From a9716bacb1f75d2f4d5aa04e31f8182322c4105d Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Thu, 29 Feb 2024 12:07:46 +0100 Subject: [PATCH] zboss: remove ZBOSS development libraries Remove ZBOSS development libraries and deprecate `ZIGBEE_LIBRARY_DEVELOPMENT` configuration. Signed-off-by: Eduardo Montoya --- zboss/CHANGELOG.rst | 8 + zboss/CMakeLists.txt | 1 - zboss/Kconfig | 4 +- zboss/README.rst | 8 +- zboss/development/CMakeLists.txt | 117 - .../include/addons/zboss_api_addons.h | 16 - .../include/addons/zboss_api_af_addons.h | 68 - .../include/addons/zboss_api_zcl_addons.h | 22 - .../include/addons/zcl/zb_zcl_basic_addons.h | 53 - .../addons/zcl/zb_zcl_color_control_addons.h | 148 - .../addons/zcl/zb_zcl_door_lock_addons.h | 25 - .../include/addons/zcl/zb_zcl_groups_addons.h | 31 - .../addons/zcl/zb_zcl_identify_addons.h | 49 - .../addons/zcl/zb_zcl_level_control_addons.h | 85 - .../include/addons/zcl/zb_zcl_on_off_addons.h | 45 - .../include/addons/zcl/zb_zcl_scenes_addons.h | 35 - .../zcl/zb_zcl_temp_measurement_addons.h | 26 - zboss/development/include/ha/zb_ha_config.h | 71 - .../include/ha/zb_ha_device_config.h | 577 -- .../development/include/ncp/ncp_common_api.h | 70 - zboss/development/include/ncp/ncp_dev_api.h | 99 - zboss/development/include/osif/build_info.h | 73 - .../include/osif/libzboss_config.ed.h | 590 -- .../include/osif/libzboss_config.h | 590 -- zboss/development/include/osif/mac_platform.h | 222 - .../include/osif/zb_config_platform.h | 61 - zboss/development/include/osif/zb_macll.h | 101 - zboss/development/include/osif/zb_osif_ext.h | 20 - .../include/osif/zb_osif_platform.h | 363 -- .../include/osif/zb_revision_r22.h | 39 - .../development/include/osif/zb_transceiver.h | 37 - zboss/development/include/osif/zb_vendor.h | 413 -- .../development/include/se/zb_se_keep_alive.h | 66 - zboss/development/include/zb_address.h | 622 -- zboss/development/include/zb_channel_page.h | 567 -- zboss/development/include/zb_config.h | 1989 ------ zboss/development/include/zb_config_common.h | 1739 ------ zboss/development/include/zb_debug.h | 261 - zboss/development/include/zb_errors.h | 151 - zboss/development/include/zb_ha.h | 147 - zboss/development/include/zb_led_button.h | 236 - zboss/development/include/zb_list_macros.h | 519 -- .../include/zb_mem_config_common.h | 331 - .../include/zb_mem_config_context.h | 321 - zboss/development/include/zb_mem_config_max.h | 106 - zboss/development/include/zb_mem_config_med.h | 94 - zboss/development/include/zb_mem_config_min.h | 98 - zboss/development/include/zb_ncp.h | 125 - zboss/development/include/zb_osif.h | 922 --- zboss/development/include/zb_pooled_list.h | 612 -- zboss/development/include/zb_ringbuffer.h | 551 -- zboss/development/include/zb_trace.h | 1246 ---- zboss/development/include/zb_types.h | 1585 ----- zboss/development/include/zb_version.h | 62 - .../include/zb_zgp_default_match_info.h | 103 - zboss/development/include/zboss_api.h | 1828 ------ zboss/development/include/zboss_api_af.h | 687 -- zboss/development/include/zboss_api_aps.h | 612 -- .../include/zboss_api_aps_interpan.h | 206 - zboss/development/include/zboss_api_buf.h | 674 -- zboss/development/include/zboss_api_core.h | 592 -- .../development/include/zboss_api_internal.h | 659 -- zboss/development/include/zboss_api_mm.h | 105 - zboss/development/include/zboss_api_nwk.h | 870 --- zboss/development/include/zboss_api_zcl.h | 2561 -------- zboss/development/include/zboss_api_zcl8.h | 147 - zboss/development/include/zboss_api_zdo.h | 3019 --------- zboss/development/include/zboss_api_zgp.h | 2087 ------- zboss/development/include/zcl/zb_zcl_alarms.h | 372 -- zboss/development/include/zcl/zb_zcl_basic.h | 586 -- .../include/zcl/zb_zcl_binary_input.h | 292 - .../include/zcl/zb_zcl_color_control.h | 3440 ----------- .../development/include/zcl/zb_zcl_commands.h | 2383 ------- zboss/development/include/zcl/zb_zcl_common.h | 2386 ------- zboss/development/include/zcl/zb_zcl_config.h | 116 - .../include/zcl/zb_zcl_control4_networking.h | 483 -- .../include/zcl/zb_zcl_custom_cluster.h | 501 -- .../include/zcl/zb_zcl_cvc_commands.h | 203 - .../include/zcl/zb_zcl_daily_schedule.h | 761 --- .../zcl/zb_zcl_dehumidification_control.h | 208 - .../include/zcl/zb_zcl_diagnostics.h | 668 -- .../include/zcl/zb_zcl_door_lock.h | 798 --- zboss/development/include/zcl/zb_zcl_drlc.h | 724 --- .../include/zcl/zb_zcl_el_measurement.h | 939 --- ..._zcl_en50523_appliance_events_and_alerts.h | 457 -- .../include/zcl/zb_zcl_fan_control.h | 178 - zboss/development/include/zcl/zb_zcl_groups.h | 786 --- .../include/zcl/zb_zcl_grpw_bed_sensor.h | 68 - .../include/zcl/zb_zcl_grpw_freq_agility.h | 58 - .../development/include/zcl/zb_zcl_ias_ace.h | 1598 ----- zboss/development/include/zcl/zb_zcl_ias_wd.h | 473 -- .../development/include/zcl/zb_zcl_ias_zone.h | 926 --- .../development/include/zcl/zb_zcl_identify.h | 466 -- .../zcl/zb_zcl_illuminance_measurement.h | 185 - .../include/zcl/zb_zcl_keep_alive.h | 165 - .../include/zcl/zb_zcl_level_control.h | 1398 ----- .../include/zcl/zb_zcl_messaging.h | 639 -- .../include/zcl/zb_zcl_meter_identification.h | 296 - .../development/include/zcl/zb_zcl_metering.h | 2547 -------- .../include/zcl/zb_zcl_occupancy_sensing.h | 330 - zboss/development/include/zcl/zb_zcl_on_off.h | 510 -- .../include/zcl/zb_zcl_on_off_switch_conf.h | 188 - .../include/zcl/zb_zcl_ota_upgrade.h | 2199 ------- .../include/zcl/zb_zcl_poll_control.h | 692 --- .../include/zcl/zb_zcl_power_config.h | 739 --- .../include/zcl/zb_zcl_pressure_measurement.h | 316 - zboss/development/include/zcl/zb_zcl_price.h | 4476 -------------- .../zcl/zb_zcl_rel_humidity_measurement.h | 181 - .../include/zcl/zb_zcl_reporting.h | 317 - zboss/development/include/zcl/zb_zcl_scenes.h | 2243 ------- .../include/zcl/zb_zcl_shade_config.h | 296 - .../include/zcl/zb_zcl_temp_measurement.h | 209 - .../include/zcl/zb_zcl_thermostat.h | 1875 ------ .../include/zcl/zb_zcl_thermostat_ui_config.h | 176 - zboss/development/include/zcl/zb_zcl_time.h | 484 -- .../zcl/zb_zcl_touchlink_commissioning.h | 2072 ------- .../include/zcl/zb_zcl_tunneling.h | 1012 --- .../include/zcl/zb_zcl_window_covering.h | 728 --- zboss/development/include/zcl/zb_zcl_wwah.h | 2617 -------- .../lib/cortex-m33/hard-float/libgppb.a | Bin 78026 -> 0 bytes .../lib/cortex-m33/hard-float/libncp-dev.a | Bin 103198 -> 0 bytes .../lib/cortex-m33/hard-float/libncp-dev.ed.a | Bin 96858 -> 0 bytes .../lib/cortex-m33/hard-float/libzboss.a | Bin 871294 -> 0 bytes .../lib/cortex-m33/hard-float/libzboss.ed.a | Bin 688254 -> 0 bytes .../lib/cortex-m4/hard-float/libgppb.a | Bin 77962 -> 0 bytes .../lib/cortex-m4/hard-float/libncp-dev.a | Bin 103058 -> 0 bytes .../lib/cortex-m4/hard-float/libncp-dev.ed.a | Bin 96730 -> 0 bytes .../lib/cortex-m4/hard-float/libzboss.a | Bin 870466 -> 0 bytes .../lib/cortex-m4/hard-float/libzboss.ed.a | Bin 687410 -> 0 bytes zboss/development/src/CMakeLists.txt | 92 - .../commissioning/bdb/bdb_finding_binding.c | 1375 ----- .../commissioning/bdb/zdo_commissioning_bdb.c | 2957 --------- .../bdb/zdo_commissioning_bdb_formation.c | 323 - .../legacy/zdo_commissioning_classic.c | 761 --- zboss/development/src/include/hw_crypto_api.h | 88 - .../development/src/include/zb_addr_globals.h | 154 - zboss/development/src/include/zb_aps.h | 601 -- .../development/src/include/zb_aps_globals.h | 615 -- .../development/src/include/zb_bdb_internal.h | 311 - zboss/development/src/include/zb_bufpool.h | 245 - .../src/include/zb_bufpool_globals.h | 153 - .../src/include/zb_commissioning.h | 195 - zboss/development/src/include/zb_common.h | 269 - zboss/development/src/include/zb_common_u.h | 100 - .../src/include/zb_error_indication.h | 72 - zboss/development/src/include/zb_g_context.h | 736 --- zboss/development/src/include/zb_hash.h | 78 - zboss/development/src/include/zb_mac.h | 3101 ---------- .../src/include/zb_mac_transport.h | 140 - zboss/development/src/include/zb_nvram.h | 1377 ----- .../src/include/zb_nvram_globals.h | 142 - zboss/development/src/include/zb_nwk.h | 2203 ------- .../development/src/include/zb_nwk_ed_aging.h | 166 - .../development/src/include/zb_nwk_globals.h | 571 -- zboss/development/src/include/zb_nwk_mm.h | 100 - .../development/src/include/zb_nwk_neighbor.h | 323 - zboss/development/src/include/zb_nwk_nib.h | 873 --- zboss/development/src/include/zb_scheduler.h | 484 -- zboss/development/src/include/zb_secur.h | 1371 ---- zboss/development/src/include/zb_secur_api.h | 86 - zboss/development/src/include/zb_sleep.h | 74 - .../development/src/include/zb_test_profile.h | 427 -- zboss/development/src/include/zb_th_dummy.h | 55 - zboss/development/src/include/zb_time.h | 168 - zboss/development/src/include/zb_watchdog.h | 111 - zboss/development/src/include/zb_zcl.h | 109 - zboss/development/src/include/zb_zdo.h | 1551 ----- .../development/src/include/zb_zdo_globals.h | 505 -- zboss/development/src/include/zb_zdo_rjb.h | 81 - .../src/include/zboss_api_buf_legacy.h | 780 --- .../development/src/include/zboss_api_error.h | 116 - .../include/zcl/zcl_ota_upgrade_commands.h | 47 - .../development/src/include/zdo_diagnostics.h | 232 - zboss/development/src/include/zdo_hubs.h | 64 - .../include/zdo_wwah_parent_classification.h | 201 - .../development/src/include/zdo_wwah_stubs.h | 137 - .../src/include/zdo_wwah_survey_beacons.h | 209 - .../src/zb_error/zb_error_to_string.c | 134 - .../src/zb_error/zb_error_to_string.h | 56 - zboss/development/src/zcl/ha_sas.c | 88 - zboss/development/src/zcl/zb_zcl_s_metering.c | 908 --- .../development/src/zcl/zcl_alarms_commands.c | 314 - zboss/development/src/zcl/zcl_attr_value.c | 215 - .../development/src/zcl/zcl_basic_commands.c | 239 - zboss/development/src/zcl/zcl_binary_input.c | 102 - .../src/zcl/zcl_c_daily_schedule.c | 456 -- zboss/development/src/zcl/zcl_c_drlc.c | 434 -- zboss/development/src/zcl/zcl_c_messaging.c | 289 - zboss/development/src/zcl/zcl_c_metering.c | 918 --- zboss/development/src/zcl/zcl_c_price.c | 387 -- zboss/development/src/zcl/zcl_c_wwah.c | 92 - .../src/zcl/zcl_color_control_commands.c | 5498 ----------------- zboss/development/src/zcl/zcl_common.c | 2495 -------- .../zcl_continuous_value_change_commands.c | 810 --- .../src/zcl/zcl_control4_networking.c | 773 --- .../development/src/zcl/zcl_dehumid_control.c | 109 - .../src/zcl/zcl_diagnostics_commands.c | 168 - zboss/development/src/zcl/zcl_door_lock.c | 407 -- .../development/src/zcl/zcl_el_measurement.c | 82 - .../zcl_en50523_appliance_events_and_alerts.c | 352 -- zboss/development/src/zcl/zcl_fan_control.c | 91 - .../src/zcl/zcl_general_commands.c | 2050 ------ zboss/development/src/zcl/zcl_groups.c | 1014 --- .../src/zcl/zcl_ias_ace_commands.c | 1066 ---- .../development/src/zcl/zcl_ias_wd_commands.c | 349 -- .../src/zcl/zcl_ias_zone_commands.c | 1106 ---- .../src/zcl/zcl_identify_commands.c | 463 -- .../src/zcl/zcl_illuminance_measurement.c | 173 - .../src/zcl/zcl_level_control_commands.c | 1507 ----- zboss/development/src/zcl/zcl_main.c | 893 --- .../src/zcl/zcl_meter_identification.c | 81 - zboss/development/src/zcl/zcl_nvram.c | 707 --- .../src/zcl/zcl_occupancy_sensing_commands.c | 175 - .../development/src/zcl/zcl_on_off_commands.c | 975 --- .../src/zcl/zcl_on_off_switch_config.c | 98 - .../src/zcl/zcl_ota_upgrade_commands.c | 1795 ------ .../src/zcl/zcl_ota_upgrade_common.c | 187 - .../src/zcl/zcl_ota_upgrade_minimal.c | 102 - .../src/zcl/zcl_ota_upgrade_srv_commands.c | 1047 ---- .../src/zcl/zcl_poll_control_client.c | 250 - .../src/zcl/zcl_poll_control_commands.c | 1263 ---- .../src/zcl/zcl_power_config_commands.c | 545 -- .../src/zcl/zcl_pressure_measurement.c | 157 - zboss/development/src/zcl/zcl_rel_humidity.c | 137 - zboss/development/src/zcl/zcl_reporting.c | 1607 ----- .../src/zcl/zcl_s_daily_schedule.c | 463 -- zboss/development/src/zcl/zcl_s_drlc.c | 386 -- zboss/development/src/zcl/zcl_s_messaging.c | 320 - zboss/development/src/zcl/zcl_s_metering.c | 949 --- zboss/development/src/zcl/zcl_s_price.c | 673 -- zboss/development/src/zcl/zcl_s_wwah.c | 3054 --------- zboss/development/src/zcl/zcl_scenes.c | 1205 ---- .../src/zcl/zcl_shade_config_commands.c | 243 - .../src/zcl/zcl_temp_measurement.c | 158 - .../src/zcl/zcl_thermostat_commands.c | 1447 ----- .../src/zcl/zcl_thermostat_ui_config.c | 91 - zboss/development/src/zcl/zcl_time.c | 548 -- .../development/src/zcl/zcl_window_covering.c | 370 -- zboss/development/src/zcl/zcl_wwah_common.c | 82 - .../trace/include/libzboss_config.ed.h | 590 -- .../trace/include/libzboss_config.h | 590 -- .../trace/lib/cortex-m33/hard-float/libgppb.a | Bin 93146 -> 0 bytes .../lib/cortex-m33/hard-float/libncp-dev.a | Bin 103846 -> 0 bytes .../lib/cortex-m33/hard-float/libncp-dev.ed.a | Bin 97498 -> 0 bytes .../lib/cortex-m33/hard-float/libzboss.a | Bin 995914 -> 0 bytes .../lib/cortex-m33/hard-float/libzboss.ed.a | Bin 779722 -> 0 bytes .../trace/lib/cortex-m4/hard-float/libgppb.a | Bin 93078 -> 0 bytes .../lib/cortex-m4/hard-float/libncp-dev.a | Bin 103706 -> 0 bytes .../lib/cortex-m4/hard-float/libncp-dev.ed.a | Bin 97370 -> 0 bytes .../trace/lib/cortex-m4/hard-float/libzboss.a | Bin 995034 -> 0 bytes .../lib/cortex-m4/hard-float/libzboss.ed.a | Bin 778822 -> 0 bytes zboss/doc/zboss_configuration.rst | 23 +- 252 files changed, 13 insertions(+), 146599 deletions(-) delete mode 100644 zboss/development/CMakeLists.txt delete mode 100644 zboss/development/include/addons/zboss_api_addons.h delete mode 100644 zboss/development/include/addons/zboss_api_af_addons.h delete mode 100644 zboss/development/include/addons/zboss_api_zcl_addons.h delete mode 100644 zboss/development/include/addons/zcl/zb_zcl_basic_addons.h delete mode 100644 zboss/development/include/addons/zcl/zb_zcl_color_control_addons.h delete mode 100644 zboss/development/include/addons/zcl/zb_zcl_door_lock_addons.h delete mode 100644 zboss/development/include/addons/zcl/zb_zcl_groups_addons.h delete mode 100644 zboss/development/include/addons/zcl/zb_zcl_identify_addons.h delete mode 100644 zboss/development/include/addons/zcl/zb_zcl_level_control_addons.h delete mode 100644 zboss/development/include/addons/zcl/zb_zcl_on_off_addons.h delete mode 100644 zboss/development/include/addons/zcl/zb_zcl_scenes_addons.h delete mode 100644 zboss/development/include/addons/zcl/zb_zcl_temp_measurement_addons.h delete mode 100644 zboss/development/include/ha/zb_ha_config.h delete mode 100644 zboss/development/include/ha/zb_ha_device_config.h delete mode 100644 zboss/development/include/ncp/ncp_common_api.h delete mode 100644 zboss/development/include/ncp/ncp_dev_api.h delete mode 100644 zboss/development/include/osif/build_info.h delete mode 100644 zboss/development/include/osif/libzboss_config.ed.h delete mode 100644 zboss/development/include/osif/libzboss_config.h delete mode 100644 zboss/development/include/osif/mac_platform.h delete mode 100644 zboss/development/include/osif/zb_config_platform.h delete mode 100644 zboss/development/include/osif/zb_macll.h delete mode 100644 zboss/development/include/osif/zb_osif_ext.h delete mode 100644 zboss/development/include/osif/zb_osif_platform.h delete mode 100644 zboss/development/include/osif/zb_revision_r22.h delete mode 100644 zboss/development/include/osif/zb_transceiver.h delete mode 100644 zboss/development/include/osif/zb_vendor.h delete mode 100644 zboss/development/include/se/zb_se_keep_alive.h delete mode 100644 zboss/development/include/zb_address.h delete mode 100644 zboss/development/include/zb_channel_page.h delete mode 100644 zboss/development/include/zb_config.h delete mode 100644 zboss/development/include/zb_config_common.h delete mode 100644 zboss/development/include/zb_debug.h delete mode 100644 zboss/development/include/zb_errors.h delete mode 100644 zboss/development/include/zb_ha.h delete mode 100644 zboss/development/include/zb_led_button.h delete mode 100644 zboss/development/include/zb_list_macros.h delete mode 100644 zboss/development/include/zb_mem_config_common.h delete mode 100644 zboss/development/include/zb_mem_config_context.h delete mode 100644 zboss/development/include/zb_mem_config_max.h delete mode 100644 zboss/development/include/zb_mem_config_med.h delete mode 100644 zboss/development/include/zb_mem_config_min.h delete mode 100644 zboss/development/include/zb_ncp.h delete mode 100644 zboss/development/include/zb_osif.h delete mode 100644 zboss/development/include/zb_pooled_list.h delete mode 100644 zboss/development/include/zb_ringbuffer.h delete mode 100644 zboss/development/include/zb_trace.h delete mode 100644 zboss/development/include/zb_types.h delete mode 100644 zboss/development/include/zb_version.h delete mode 100644 zboss/development/include/zb_zgp_default_match_info.h delete mode 100644 zboss/development/include/zboss_api.h delete mode 100644 zboss/development/include/zboss_api_af.h delete mode 100644 zboss/development/include/zboss_api_aps.h delete mode 100644 zboss/development/include/zboss_api_aps_interpan.h delete mode 100644 zboss/development/include/zboss_api_buf.h delete mode 100644 zboss/development/include/zboss_api_core.h delete mode 100644 zboss/development/include/zboss_api_internal.h delete mode 100644 zboss/development/include/zboss_api_mm.h delete mode 100644 zboss/development/include/zboss_api_nwk.h delete mode 100644 zboss/development/include/zboss_api_zcl.h delete mode 100644 zboss/development/include/zboss_api_zcl8.h delete mode 100644 zboss/development/include/zboss_api_zdo.h delete mode 100644 zboss/development/include/zboss_api_zgp.h delete mode 100644 zboss/development/include/zcl/zb_zcl_alarms.h delete mode 100644 zboss/development/include/zcl/zb_zcl_basic.h delete mode 100644 zboss/development/include/zcl/zb_zcl_binary_input.h delete mode 100644 zboss/development/include/zcl/zb_zcl_color_control.h delete mode 100644 zboss/development/include/zcl/zb_zcl_commands.h delete mode 100644 zboss/development/include/zcl/zb_zcl_common.h delete mode 100644 zboss/development/include/zcl/zb_zcl_config.h delete mode 100644 zboss/development/include/zcl/zb_zcl_control4_networking.h delete mode 100644 zboss/development/include/zcl/zb_zcl_custom_cluster.h delete mode 100644 zboss/development/include/zcl/zb_zcl_cvc_commands.h delete mode 100644 zboss/development/include/zcl/zb_zcl_daily_schedule.h delete mode 100644 zboss/development/include/zcl/zb_zcl_dehumidification_control.h delete mode 100644 zboss/development/include/zcl/zb_zcl_diagnostics.h delete mode 100644 zboss/development/include/zcl/zb_zcl_door_lock.h delete mode 100644 zboss/development/include/zcl/zb_zcl_drlc.h delete mode 100644 zboss/development/include/zcl/zb_zcl_el_measurement.h delete mode 100644 zboss/development/include/zcl/zb_zcl_en50523_appliance_events_and_alerts.h delete mode 100644 zboss/development/include/zcl/zb_zcl_fan_control.h delete mode 100644 zboss/development/include/zcl/zb_zcl_groups.h delete mode 100644 zboss/development/include/zcl/zb_zcl_grpw_bed_sensor.h delete mode 100644 zboss/development/include/zcl/zb_zcl_grpw_freq_agility.h delete mode 100644 zboss/development/include/zcl/zb_zcl_ias_ace.h delete mode 100644 zboss/development/include/zcl/zb_zcl_ias_wd.h delete mode 100644 zboss/development/include/zcl/zb_zcl_ias_zone.h delete mode 100644 zboss/development/include/zcl/zb_zcl_identify.h delete mode 100644 zboss/development/include/zcl/zb_zcl_illuminance_measurement.h delete mode 100644 zboss/development/include/zcl/zb_zcl_keep_alive.h delete mode 100644 zboss/development/include/zcl/zb_zcl_level_control.h delete mode 100644 zboss/development/include/zcl/zb_zcl_messaging.h delete mode 100644 zboss/development/include/zcl/zb_zcl_meter_identification.h delete mode 100644 zboss/development/include/zcl/zb_zcl_metering.h delete mode 100644 zboss/development/include/zcl/zb_zcl_occupancy_sensing.h delete mode 100644 zboss/development/include/zcl/zb_zcl_on_off.h delete mode 100644 zboss/development/include/zcl/zb_zcl_on_off_switch_conf.h delete mode 100644 zboss/development/include/zcl/zb_zcl_ota_upgrade.h delete mode 100644 zboss/development/include/zcl/zb_zcl_poll_control.h delete mode 100644 zboss/development/include/zcl/zb_zcl_power_config.h delete mode 100644 zboss/development/include/zcl/zb_zcl_pressure_measurement.h delete mode 100644 zboss/development/include/zcl/zb_zcl_price.h delete mode 100644 zboss/development/include/zcl/zb_zcl_rel_humidity_measurement.h delete mode 100644 zboss/development/include/zcl/zb_zcl_reporting.h delete mode 100644 zboss/development/include/zcl/zb_zcl_scenes.h delete mode 100644 zboss/development/include/zcl/zb_zcl_shade_config.h delete mode 100644 zboss/development/include/zcl/zb_zcl_temp_measurement.h delete mode 100644 zboss/development/include/zcl/zb_zcl_thermostat.h delete mode 100644 zboss/development/include/zcl/zb_zcl_thermostat_ui_config.h delete mode 100644 zboss/development/include/zcl/zb_zcl_time.h delete mode 100644 zboss/development/include/zcl/zb_zcl_touchlink_commissioning.h delete mode 100644 zboss/development/include/zcl/zb_zcl_tunneling.h delete mode 100644 zboss/development/include/zcl/zb_zcl_window_covering.h delete mode 100644 zboss/development/include/zcl/zb_zcl_wwah.h delete mode 100644 zboss/development/lib/cortex-m33/hard-float/libgppb.a delete mode 100644 zboss/development/lib/cortex-m33/hard-float/libncp-dev.a delete mode 100644 zboss/development/lib/cortex-m33/hard-float/libncp-dev.ed.a delete mode 100644 zboss/development/lib/cortex-m33/hard-float/libzboss.a delete mode 100644 zboss/development/lib/cortex-m33/hard-float/libzboss.ed.a delete mode 100644 zboss/development/lib/cortex-m4/hard-float/libgppb.a delete mode 100644 zboss/development/lib/cortex-m4/hard-float/libncp-dev.a delete mode 100644 zboss/development/lib/cortex-m4/hard-float/libncp-dev.ed.a delete mode 100644 zboss/development/lib/cortex-m4/hard-float/libzboss.a delete mode 100644 zboss/development/lib/cortex-m4/hard-float/libzboss.ed.a delete mode 100644 zboss/development/src/CMakeLists.txt delete mode 100644 zboss/development/src/commissioning/bdb/bdb_finding_binding.c delete mode 100644 zboss/development/src/commissioning/bdb/zdo_commissioning_bdb.c delete mode 100644 zboss/development/src/commissioning/bdb/zdo_commissioning_bdb_formation.c delete mode 100644 zboss/development/src/commissioning/legacy/zdo_commissioning_classic.c delete mode 100644 zboss/development/src/include/hw_crypto_api.h delete mode 100644 zboss/development/src/include/zb_addr_globals.h delete mode 100644 zboss/development/src/include/zb_aps.h delete mode 100644 zboss/development/src/include/zb_aps_globals.h delete mode 100644 zboss/development/src/include/zb_bdb_internal.h delete mode 100644 zboss/development/src/include/zb_bufpool.h delete mode 100644 zboss/development/src/include/zb_bufpool_globals.h delete mode 100644 zboss/development/src/include/zb_commissioning.h delete mode 100644 zboss/development/src/include/zb_common.h delete mode 100644 zboss/development/src/include/zb_common_u.h delete mode 100644 zboss/development/src/include/zb_error_indication.h delete mode 100644 zboss/development/src/include/zb_g_context.h delete mode 100644 zboss/development/src/include/zb_hash.h delete mode 100644 zboss/development/src/include/zb_mac.h delete mode 100644 zboss/development/src/include/zb_mac_transport.h delete mode 100644 zboss/development/src/include/zb_nvram.h delete mode 100644 zboss/development/src/include/zb_nvram_globals.h delete mode 100644 zboss/development/src/include/zb_nwk.h delete mode 100644 zboss/development/src/include/zb_nwk_ed_aging.h delete mode 100644 zboss/development/src/include/zb_nwk_globals.h delete mode 100644 zboss/development/src/include/zb_nwk_mm.h delete mode 100644 zboss/development/src/include/zb_nwk_neighbor.h delete mode 100644 zboss/development/src/include/zb_nwk_nib.h delete mode 100644 zboss/development/src/include/zb_scheduler.h delete mode 100644 zboss/development/src/include/zb_secur.h delete mode 100644 zboss/development/src/include/zb_secur_api.h delete mode 100644 zboss/development/src/include/zb_sleep.h delete mode 100644 zboss/development/src/include/zb_test_profile.h delete mode 100644 zboss/development/src/include/zb_th_dummy.h delete mode 100644 zboss/development/src/include/zb_time.h delete mode 100644 zboss/development/src/include/zb_watchdog.h delete mode 100644 zboss/development/src/include/zb_zcl.h delete mode 100644 zboss/development/src/include/zb_zdo.h delete mode 100644 zboss/development/src/include/zb_zdo_globals.h delete mode 100644 zboss/development/src/include/zb_zdo_rjb.h delete mode 100644 zboss/development/src/include/zboss_api_buf_legacy.h delete mode 100644 zboss/development/src/include/zboss_api_error.h delete mode 100644 zboss/development/src/include/zcl/zcl_ota_upgrade_commands.h delete mode 100644 zboss/development/src/include/zdo_diagnostics.h delete mode 100644 zboss/development/src/include/zdo_hubs.h delete mode 100644 zboss/development/src/include/zdo_wwah_parent_classification.h delete mode 100644 zboss/development/src/include/zdo_wwah_stubs.h delete mode 100644 zboss/development/src/include/zdo_wwah_survey_beacons.h delete mode 100644 zboss/development/src/zb_error/zb_error_to_string.c delete mode 100644 zboss/development/src/zb_error/zb_error_to_string.h delete mode 100644 zboss/development/src/zcl/ha_sas.c delete mode 100644 zboss/development/src/zcl/zb_zcl_s_metering.c delete mode 100644 zboss/development/src/zcl/zcl_alarms_commands.c delete mode 100644 zboss/development/src/zcl/zcl_attr_value.c delete mode 100644 zboss/development/src/zcl/zcl_basic_commands.c delete mode 100644 zboss/development/src/zcl/zcl_binary_input.c delete mode 100644 zboss/development/src/zcl/zcl_c_daily_schedule.c delete mode 100644 zboss/development/src/zcl/zcl_c_drlc.c delete mode 100644 zboss/development/src/zcl/zcl_c_messaging.c delete mode 100644 zboss/development/src/zcl/zcl_c_metering.c delete mode 100644 zboss/development/src/zcl/zcl_c_price.c delete mode 100644 zboss/development/src/zcl/zcl_c_wwah.c delete mode 100644 zboss/development/src/zcl/zcl_color_control_commands.c delete mode 100644 zboss/development/src/zcl/zcl_common.c delete mode 100644 zboss/development/src/zcl/zcl_continuous_value_change_commands.c delete mode 100644 zboss/development/src/zcl/zcl_control4_networking.c delete mode 100644 zboss/development/src/zcl/zcl_dehumid_control.c delete mode 100644 zboss/development/src/zcl/zcl_diagnostics_commands.c delete mode 100644 zboss/development/src/zcl/zcl_door_lock.c delete mode 100644 zboss/development/src/zcl/zcl_el_measurement.c delete mode 100644 zboss/development/src/zcl/zcl_en50523_appliance_events_and_alerts.c delete mode 100644 zboss/development/src/zcl/zcl_fan_control.c delete mode 100644 zboss/development/src/zcl/zcl_general_commands.c delete mode 100644 zboss/development/src/zcl/zcl_groups.c delete mode 100644 zboss/development/src/zcl/zcl_ias_ace_commands.c delete mode 100644 zboss/development/src/zcl/zcl_ias_wd_commands.c delete mode 100644 zboss/development/src/zcl/zcl_ias_zone_commands.c delete mode 100644 zboss/development/src/zcl/zcl_identify_commands.c delete mode 100644 zboss/development/src/zcl/zcl_illuminance_measurement.c delete mode 100644 zboss/development/src/zcl/zcl_level_control_commands.c delete mode 100644 zboss/development/src/zcl/zcl_main.c delete mode 100644 zboss/development/src/zcl/zcl_meter_identification.c delete mode 100644 zboss/development/src/zcl/zcl_nvram.c delete mode 100644 zboss/development/src/zcl/zcl_occupancy_sensing_commands.c delete mode 100644 zboss/development/src/zcl/zcl_on_off_commands.c delete mode 100644 zboss/development/src/zcl/zcl_on_off_switch_config.c delete mode 100644 zboss/development/src/zcl/zcl_ota_upgrade_commands.c delete mode 100644 zboss/development/src/zcl/zcl_ota_upgrade_common.c delete mode 100644 zboss/development/src/zcl/zcl_ota_upgrade_minimal.c delete mode 100644 zboss/development/src/zcl/zcl_ota_upgrade_srv_commands.c delete mode 100644 zboss/development/src/zcl/zcl_poll_control_client.c delete mode 100644 zboss/development/src/zcl/zcl_poll_control_commands.c delete mode 100644 zboss/development/src/zcl/zcl_power_config_commands.c delete mode 100644 zboss/development/src/zcl/zcl_pressure_measurement.c delete mode 100644 zboss/development/src/zcl/zcl_rel_humidity.c delete mode 100644 zboss/development/src/zcl/zcl_reporting.c delete mode 100644 zboss/development/src/zcl/zcl_s_daily_schedule.c delete mode 100644 zboss/development/src/zcl/zcl_s_drlc.c delete mode 100644 zboss/development/src/zcl/zcl_s_messaging.c delete mode 100644 zboss/development/src/zcl/zcl_s_metering.c delete mode 100644 zboss/development/src/zcl/zcl_s_price.c delete mode 100644 zboss/development/src/zcl/zcl_s_wwah.c delete mode 100644 zboss/development/src/zcl/zcl_scenes.c delete mode 100644 zboss/development/src/zcl/zcl_shade_config_commands.c delete mode 100644 zboss/development/src/zcl/zcl_temp_measurement.c delete mode 100644 zboss/development/src/zcl/zcl_thermostat_commands.c delete mode 100644 zboss/development/src/zcl/zcl_thermostat_ui_config.c delete mode 100644 zboss/development/src/zcl/zcl_time.c delete mode 100644 zboss/development/src/zcl/zcl_window_covering.c delete mode 100644 zboss/development/src/zcl/zcl_wwah_common.c delete mode 100644 zboss/development/trace/include/libzboss_config.ed.h delete mode 100644 zboss/development/trace/include/libzboss_config.h delete mode 100644 zboss/development/trace/lib/cortex-m33/hard-float/libgppb.a delete mode 100644 zboss/development/trace/lib/cortex-m33/hard-float/libncp-dev.a delete mode 100644 zboss/development/trace/lib/cortex-m33/hard-float/libncp-dev.ed.a delete mode 100644 zboss/development/trace/lib/cortex-m33/hard-float/libzboss.a delete mode 100644 zboss/development/trace/lib/cortex-m33/hard-float/libzboss.ed.a delete mode 100644 zboss/development/trace/lib/cortex-m4/hard-float/libgppb.a delete mode 100644 zboss/development/trace/lib/cortex-m4/hard-float/libncp-dev.a delete mode 100644 zboss/development/trace/lib/cortex-m4/hard-float/libncp-dev.ed.a delete mode 100644 zboss/development/trace/lib/cortex-m4/hard-float/libzboss.a delete mode 100644 zboss/development/trace/lib/cortex-m4/hard-float/libzboss.ed.a diff --git a/zboss/CHANGELOG.rst b/zboss/CHANGELOG.rst index f0eaf7fc48..97b1847d86 100644 --- a/zboss/CHANGELOG.rst +++ b/zboss/CHANGELOG.rst @@ -9,6 +9,14 @@ Changelog All notable changes to this project in the |NCS| are documented in this file. +nRF Connect SDK v2.6.0 +********************** + +Removed +======= + +* Precompiled development ZBOSS libraries. + nRF Connect SDK v2.3.0 ********************** diff --git a/zboss/CMakeLists.txt b/zboss/CMakeLists.txt index 27924e85e6..cc46bdfe54 100644 --- a/zboss/CMakeLists.txt +++ b/zboss/CMakeLists.txt @@ -5,4 +5,3 @@ # add_subdirectory_ifdef(CONFIG_ZIGBEE_LIBRARY_PRODUCTION production) -add_subdirectory_ifdef(CONFIG_ZIGBEE_LIBRARY_DEVELOPMENT development) diff --git a/zboss/Kconfig b/zboss/Kconfig index 53ac243767..d69f318802 100644 --- a/zboss/Kconfig +++ b/zboss/Kconfig @@ -25,8 +25,8 @@ config ZIGBEE_LIBRARY_PRODUCTION of those libraries. config ZIGBEE_LIBRARY_DEVELOPMENT - bool "Use development libraries [EXPERIMENTAL]" - select EXPERIMENTAL + bool "Use development libraries [DEPRECATED]" + select DEPRECATED help If selected, the application will be linked with newest version of ZBOSS libraries. diff --git a/zboss/README.rst b/zboss/README.rst index 4f6d101482..12298524a4 100644 --- a/zboss/README.rst +++ b/zboss/README.rst @@ -5,7 +5,7 @@ ZBOSS Zigbee stack The |NCS|'s :ref:`nrf:ug_zigbee` stack uses ZBOSS – a portable, high-performance Zigbee software protocol stack that allows for interoperability, customizing, testing, and optimizing of your Zigbee solution. -The nrfxlib repository contains the following versions of the ZBOSS libraries: +The nrfxlib repository contains the following version of the ZBOSS libraries: * *Production* version that contains the latest stable ZBOSS libraries. This version is enabled with the :kconfig:option:`CONFIG_ZIGBEE_LIBRARY_PRODUCTION` Kconfig option and its files are located in the :file:`zboss/production/` directory. @@ -13,12 +13,6 @@ The nrfxlib repository contains the following versions of the ZBOSS libraries: The production libraries fully conform to the certification, but they are not necessarily certified. -* *Development* version that contains the latest version of ZBOSS libraries, with experimental features included. - This version is enabled with the :kconfig:option:`CONFIG_ZIGBEE_LIBRARY_DEVELOPMENT` Kconfig option and its files are located in the :file:`zboss/development/` directory. - - This version might not conform to the latest Zigbee Pro R22 test specification. - There is no guarantee that the library conforms to the certification. - For information about additional configuration of these libraries and their certification status, see :ref:`zboss_configuration`. For detailed documentation of the ZBOSS API for these versions and instructions on how to use it, check the ZBOSS API documentation using the following banner. diff --git a/zboss/development/CMakeLists.txt b/zboss/development/CMakeLists.txt deleted file mode 100644 index 11295653d3..0000000000 --- a/zboss/development/CMakeLists.txt +++ /dev/null @@ -1,117 +0,0 @@ -# -# Copyright (c) 2020 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Define an interface library for Nordic's ZBOSS stack. -# This library contains official ZBOSS headers, platform-specific configuration, -# Nordic's extensions of ZBOSS API. -zephyr_interface_library_named(zboss) - -# Common includes, not related to ZBOSS source code. -target_include_directories(zboss INTERFACE - src/zb_error - include/addons -) - -# Suppress bitfield compatibility warning. -# This has to be included in all files, that uses ZBOSS headers. -# Those options will be inherited by everything that links to the ZBOSS target. -target_compile_options(zboss INTERFACE - -Wno-packed-bitfield-compat -) - -# Add compile-time definition, indicating which ZBOSS library will be linked -# This definition adjusts ZBOSS headers, by making non-applicable API for -# a given Zigbee role invisible. -# Those options will be inherited by everything that links to the ZBOSS target. -if (CONFIG_ZIGBEE_ROLE_END_DEVICE) - target_compile_definitions(zboss INTERFACE - ZB_ED_ROLE - ) -endif() - - -# Create a library for Nordic's extensions to ZBOSS stack. -# The target name is generated based on the path and is not meant to be -# explicitly linked in other modules. -# It will be pulled if the module links to the ZBOSS interface library. -zephyr_library() - -# Add source files for the Nordic's extensions to ZBOSS stack. -# Due to the fact that extensions are linked for all variants of ZBOSS builds -# (libraries, closed source), they are separate from the CMakelists.txt file -# found under the src directory. -zephyr_library_sources(src/zb_error/zb_error_to_string.c) - -# Link with ZBOSS interface library. -zephyr_library_link_libraries(zboss) - -# Precompiled libraries -only part. -# Use the CONFIG_ZBOSS_SOURCES_AVAILABLE Kconfig option is defined in ZBOSS -# platform module to check if user uses ZOI repositories for building -# application. -# If so, the user still may select libraries from nrfxlib to link with -# verified state of ZBOSS (CONFIG_ZBOSS_LIBRARY_PRECOMPILED symbol). -if ((NOT DEFINED CONFIG_ZBOSS_SOURCES_AVAILABLE) OR - (CONFIG_ZBOSS_LIBRARY_PRECOMPILED)) - - nrfxlib_calculate_lib_path(lib_path) - if (CONFIG_ZIGBEE_ENABLE_TRACES) - set(ZBOSS_LIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/trace/${lib_path}) - set(ZBOSS_LIB_CONFIG_DIR ${CMAKE_CURRENT_SOURCE_DIR}/trace/include) - else() - set(ZBOSS_LIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${lib_path}) - set(ZBOSS_LIB_CONFIG_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/osif) - endif() - if(NOT EXISTS ${ZBOSS_LIB_PATH}) - message(WARNING "This combination of SoC and floating point ABI is not supported by the ZBOSS lib." - "(${ZBOSS_LIB_PATH} doesn't exist.)") - endif() - - # Extend ZBOSS interface libraries by headers placed in nrfxlib. - target_include_directories(zboss INTERFACE - include - include/zcl - include/ha - include/se - include/osif - ) - - # Add the part of ZBOSS that is distributed in the source code. - add_subdirectory(src) - - # Resolve Zigbee role to library variant - if (CONFIG_ZIGBEE_ROLE_COORDINATOR OR CONFIG_ZIGBEE_ROLE_ROUTER) - set(LIB_VARIANT ) - else() - set(LIB_VARIANT ".ed") - endif() - - # Include the static library to the ZBOSS interface definition and select - # ZBOSS configuration header file by defining compile-time definition. - target_link_libraries(zboss INTERFACE ${ZBOSS_LIB_PATH}/libzboss${LIB_VARIANT}.a) - target_compile_definitions(zboss INTERFACE LIBZBOSS_CONFIG_FILE="${ZBOSS_LIB_CONFIG_DIR}/libzboss_config${LIB_VARIANT}.h") - - # Include the selected subset of Zigbee Green Power functionalities - if (CONFIG_ZIGBEE_ROLE_COORDINATOR OR CONFIG_ZIGBEE_ROLE_ROUTER) - if (CONFIG_ZIGBEE_GP_PB) - target_link_libraries(zboss INTERFACE ${ZBOSS_LIB_PATH}/libgppb${LIB_VARIANT}.a) - elseif (CONFIG_ZIGBEE_GP_CB) - target_link_libraries(zboss INTERFACE ${ZBOSS_LIB_PATH}/libgpcb${LIB_VARIANT}.a) - else() - message( FATAL_ERROR "Unsupported Zigbee Green Power feature set") - endif() - endif() - - # Include NCP protocol and commands implementation. - # Since the libncp-dev contains the application code, all object files has to - # be included while linking. - if (CONFIG_ZIGBEE_LIBRARY_NCP_DEV) - zephyr_library_import(zboss_libncp-dev ${ZBOSS_LIB_PATH}/libncp-dev${LIB_VARIANT}.a) - elseif (CONFIG_ZIGBEE_LIBRARY_SOC) - else() - message(FATAL_ERROR "Unsupported Zigbee platform design") - endif() -endif() diff --git a/zboss/development/include/addons/zboss_api_addons.h b/zboss/development/include/addons/zboss_api_addons.h deleted file mode 100644 index 7ceb4fcd99..0000000000 --- a/zboss/development/include/addons/zboss_api_addons.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZBOSS_API_ADDONS_H__ -#define ZBOSS_API_ADDONS_H__ - -#include "zboss_api.h" - -#include "zboss_api_zcl_addons.h" -#include "zboss_api_af_addons.h" - - -#endif /* ZBOSS_API_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zboss_api_af_addons.h b/zboss/development/include/addons/zboss_api_af_addons.h deleted file mode 100644 index e6c31c8f11..0000000000 --- a/zboss/development/include/addons/zboss_api_af_addons.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZBOSS_API_AF_ADDONS_H__ -#define ZBOSS_API_AF_ADDONS_H__ - -#include "zboss_api.h" - -/*! \addtogroup zboss_api_af_addons */ -/*! @{ */ - -/**@brief Redefinition of __CAT__ as variadic macro. - * - * @param[in] a Mandatory argument to concatenate. - * @param[in] b Mandatory argument to concatenate. - * @param[in] ... Optional argument to concatenate. - */ -#define __CAT_VA__(a, b, ...) a## __VA_ARGS__## b - -/**@brief Redefinition of ZB_AF_SIMPLE_DESC_TYPE as variadic macro. - * - * @param[in] in_num Number of input clusters. - * @param[in] out_num Number of output clusters. - * @param[in] ... Optional argument to concatenate to the type name. - */ -#define ZB_AF_SIMPLE_DESC_TYPE_VA(in_num, out_num, ...) __CAT_VA__(zb_af_simple_desc_, _t, __VA_ARGS__) - -/**@brief Redefinition of ZB_DECLARE_SIMPLE_DESC as variadic macro. - * - * @param[in] in_clusters_count Number of input clusters. - * @param[in] out_clusters_count Number of output clusters. - * @param[in] ... Optional argument to concatenate to the type name. - */ -#define ZB_DECLARE_SIMPLE_DESC_VA(in_clusters_count, out_clusters_count, ...) \ - typedef ZB_PACKED_PRE struct zb_af_simple_desc_## __VA_ARGS__## _s \ - { \ - zb_uint8_t endpoint; /* Endpoint */ \ - zb_uint16_t app_profile_id; /* Application profile identifier */ \ - zb_uint16_t app_device_id; /* Application device identifier */ \ - zb_bitfield_t app_device_version:4; /* Application device version */ \ - zb_bitfield_t reserved:4; /* Reserved */ \ - zb_uint8_t app_input_cluster_count; /* Application input cluster count */ \ - zb_uint8_t app_output_cluster_count; /* Application output cluster count */ \ - /* Application input and output cluster list */ \ - zb_uint16_t app_cluster_list[(in_clusters_count) + (out_clusters_count)]; \ - zb_uint8_t cluster_encryption[((in_clusters_count) + (out_clusters_count) + 7)/8]; \ - } ZB_PACKED_STRUCT zb_af_simple_desc_## __VA_ARGS__## _t - -/**@brief Redefinition of ZBOSS_DECLARE_DEVICE_CTX_N_EP as variadic macro. - * - * @param[in] device_ctx_name Device context variable name. - * @param[in] ... Variables holding context for endpoints. - */ -#define ZBOSS_DECLARE_DEVICE_CTX_EP_VA(device_ctx_name, ...) \ - zb_af_endpoint_desc_t *ep_list_##device_ctx_name[] = { \ - __VA_ARGS__ \ - }; \ - ZBOSS_DECLARE_DEVICE_CTX(device_ctx_name, ep_list_##device_ctx_name, \ - (ZB_ZCL_ARRAY_SIZE(ep_list_##device_ctx_name, zb_af_endpoint_desc_t*))) - - - -/** @} */ - -#endif /* ZBOSS_API_AF_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zboss_api_zcl_addons.h b/zboss/development/include/addons/zboss_api_zcl_addons.h deleted file mode 100644 index 30a815ef65..0000000000 --- a/zboss/development/include/addons/zboss_api_zcl_addons.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZBOSS_API_ZCL_ADDONS_H__ -#define ZBOSS_API_ZCL_ADDONS_H__ - -#include "zboss_api.h" - -#include "zcl/zb_zcl_basic_addons.h" -#include "zcl/zb_zcl_color_control_addons.h" -#include "zcl/zb_zcl_door_lock_addons.h" -#include "zcl/zb_zcl_groups_addons.h" -#include "zcl/zb_zcl_identify_addons.h" -#include "zcl/zb_zcl_level_control_addons.h" -#include "zcl/zb_zcl_scenes_addons.h" -#include "zcl/zb_zcl_on_off_addons.h" -#include "zcl/zb_zcl_temp_measurement_addons.h" - -#endif /* ZBOSS_API_ZCL_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zcl/zb_zcl_basic_addons.h b/zboss/development/include/addons/zcl/zb_zcl_basic_addons.h deleted file mode 100644 index 97e4e1232b..0000000000 --- a/zboss/development/include/addons/zcl/zb_zcl_basic_addons.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_ZCL_BASIC_ADDONS_H__ -#define ZB_ZCL_BASIC_ADDONS_H__ - -#include "zboss_api.h" - -/*! \addtogroup zb_zcl_basic_addons */ -/*! @{ */ - -/** @brief Basic cluster attributes according to ZCL Spec 3.2.2.2 */ -typedef struct -{ - zb_uint8_t zcl_version; - zb_uint8_t app_version; - zb_uint8_t stack_version; - zb_uint8_t hw_version; - zb_char_t mf_name[33]; - zb_char_t model_id[33]; - zb_char_t date_code[17]; - zb_uint8_t power_source; - zb_char_t location_id[17]; - zb_uint8_t ph_env; - zb_char_t sw_ver[17]; -} zb_zcl_basic_attrs_ext_t; - -/** - * @brief Declare attribute list for Basic cluster (client). - * @param attr_list - attribute list name. - */ -#define ZB_ZCL_DECLARE_BASIC_CLIENT_ATTRIB_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_BASIC) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** - * @brief Declare attribute list for Basic cluster (server). - * @param attr_list - attribute list name - * @param zcl_version - pointer to variable to store zcl version attribute value - * @param power_source - pointer to variable to store power source attribute value - */ -#define ZB_ZCL_DECLARE_BASIC_SERVER_ATTRIB_LIST(attr_list, zcl_version, power_source) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_BASIC) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID, (zcl_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, (power_source)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ - -#endif /* ZB_ZCL_BASIC_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zcl/zb_zcl_color_control_addons.h b/zboss/development/include/addons/zcl/zb_zcl_color_control_addons.h deleted file mode 100644 index 4d35c71d9f..0000000000 --- a/zboss/development/include/addons/zcl/zb_zcl_color_control_addons.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_ZCL_COLOR_CONTROL_ADDONS_H__ -#define ZB_ZCL_COLOR_CONTROL_ADDONS_H__ - -#include "zboss_api.h" - -/*! \addtogroup zb_zcl_color_control_addons */ -/*! @{ */ - -/**@brief Color information set for Color cluster attributes according to ZCL Spec 5.2.2.2.1. */ -typedef struct -{ - zb_uint8_t current_hue; - zb_uint8_t current_saturation; - zb_uint8_t color_mode; - zb_uint8_t options; - zb_uint8_t enhanced_color_mode; - zb_uint16_t color_capabilities; -} zb_zcl_color_ctrl_attrs_set_color_inf_t; - -/**@brief Color information extended set for Color cluster attributes according to ZCL Spec 5.2.2.2.1. */ -typedef struct -{ - zb_uint8_t current_hue; - zb_uint8_t current_saturation; - zb_uint16_t remaining_time; - zb_uint16_t current_X; - zb_uint16_t current_Y; - zb_uint16_t color_temperature; - zb_uint8_t color_mode; - zb_uint8_t options; - zb_uint16_t enhanced_current_hue; - zb_uint8_t enhanced_color_mode; - zb_uint8_t color_loop_active; - zb_uint8_t color_loop_direction; - zb_uint16_t color_loop_time; - zb_uint16_t color_loop_start_enhanced_hue; - zb_uint16_t color_loop_stored_enhanced_hue; - zb_uint16_t color_capabilities; - zb_uint16_t color_temp_physical_min_mireds; - zb_uint16_t color_temp_physical_max_mireds; - zb_uint16_t couple_color_temp_to_level_min_mireds; - zb_uint16_t start_up_color_temp_mireds; -} zb_zcl_color_ctrl_attrs_set_color_inf_ext_t; - -/**@brief Defined primaries information attribute set for Color cluster attributes according to ZCL Spec 5.2.2.2.2. */ -typedef struct -{ - zb_uint8_t number_primaries; -} zb_zcl_color_ctrl_attrs_set_defined_primaries_inf_t; - -/**@brief Defined primaries information extended attribute set for Color cluster attributes according to ZCL Spec 5.2.2.2.2. */ -typedef struct -{ - zb_uint8_t number_primaries; - zb_uint16_t primary_1_X; - zb_uint16_t primary_1_Y; - zb_uint8_t primary_1_intensity; - zb_uint16_t primary_2_X; - zb_uint16_t primary_2_Y; - zb_uint8_t primary_2_intensity; - zb_uint16_t primary_3_X; - zb_uint16_t primary_3_Y; - zb_uint8_t primary_3_intensity; -} zb_zcl_color_ctrl_attrs_set_defined_primaries_inf_ext_t; - -/**@brief Color cluster extended attributes according to ZCL Spec 5.2.2.2.3. */ -typedef struct -{ - zb_uint16_t primary_4_X; - zb_uint16_t primary_4_Y; - zb_uint8_t primary_4_intensity; - zb_uint16_t primary_5_X; - zb_uint16_t primary_5_Y; - zb_uint8_t primary_5_intensity; - zb_uint16_t primary_6_X; - zb_uint16_t primary_6_Y; - zb_uint8_t primary_6_intensity; -} zb_zcl_color_ctrl_attrs_set_add_prim_inf_ext_t; - -/**@brief Color cluster attributes according to ZCL Spec 5.2.2.2. */ -typedef struct -{ - zb_zcl_color_ctrl_attrs_set_color_inf_t set_color_info; - zb_zcl_color_ctrl_attrs_set_defined_primaries_inf_t set_defined_primaries_info; -} zb_zcl_color_control_attrs_t; - -/**@brief Color cluster extended attributes according to ZCL Spec 5.2.2.2. */ -typedef struct -{ - zb_zcl_color_ctrl_attrs_set_color_inf_ext_t set_color_info; - zb_zcl_color_ctrl_attrs_set_defined_primaries_inf_ext_t set_defined_primaries_info; - zb_zcl_color_ctrl_attrs_set_add_prim_inf_ext_t set_additional_defined_primaries_info; -} zb_zcl_color_control_attrs_ext_t; - -/**@brief Macro equivalent to @ref ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_HUE_SATURATION_REQ, but command is sent without APS ACK. */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_HUE_SATURATION_REQ_NO_APS_ACK(buffer, addr, dst_addr_mode,\ - dst_ep, ep, prfl_id, def_resp, cb, hue, saturation, transition_time) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SATURATION); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (hue)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (saturation)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); \ - ZB_ZCL_SEND_COMMAND_SHORT_WITHOUT_ACK((buffer), ptr, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb, 0); \ -} - -/** - * @brief Declare attribute list for Color control cluster (client). - * @param attr_list - attribute list name. - */ -#define ZB_ZCL_DECLARE_COLOR_CONTROL_CLIENT_ATTRIB_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_COLOR_CONTROL) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! - @brief Declare attribute list for Color Control cluster (extended with hue and saturation attributes) - @param attr_list - attribute list name - @param current_hue - pointer to variable to store current_hue attribute value - @param current_saturation - pointer to variable to store current_saturation attribute value - @param color_mode - pointer to variable to store color_mode attribute value - @param options - pointer to variable to store options attribute value - @param number_primaries - pointer to variable to store number_primaries attribute value - @param enhanced_color_mode - pointer to variable to store Enhanced Color Mode attribute value - @param color_capabilities - pointer to variable to store Color Capabilities attribute value -*/ -#define ZB_ZCL_DECLARE_COLOR_CONTROL_ATTRIB_LIST_HS(attr_list, current_hue, current_saturation, \ - color_mode, options, number_primaries, enhanced_color_mode, color_capabilities) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_COLOR_CONTROL) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, (current_hue)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, (current_saturation)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_MODE_ID, (color_mode)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_OPTIONS_ID, (options)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_NUMBER_OF_PRIMARIES_ID, (number_primaries)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID, (enhanced_color_mode)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_CAPABILITIES_ID, (color_capabilities)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ - -#endif /* ZB_ZCL_COLOR_CONTROL_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zcl/zb_zcl_door_lock_addons.h b/zboss/development/include/addons/zcl/zb_zcl_door_lock_addons.h deleted file mode 100644 index 06d972899a..0000000000 --- a/zboss/development/include/addons/zcl/zb_zcl_door_lock_addons.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_ZCL_DOOR_LOCK_ADDONS_H__ -#define ZB_ZCL_DOOR_LOCK_ADDONS_H__ - -#include "zboss_api.h" - -/*! \addtogroup zb_zcl_door_lock_addons */ -/*! @{ */ - -/**@brief Door Lock cluster attributes according to ZCL Spec 7.3.2.10. */ -typedef struct -{ - zb_uint8_t lock_state; - zb_uint8_t lock_type; - zb_bool_t actuator_enabled; -} zb_zcl_door_lock_attrs_t; - -/** @} */ - -#endif /* ZB_ZCL_DOOR_LOCK_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zcl/zb_zcl_groups_addons.h b/zboss/development/include/addons/zcl/zb_zcl_groups_addons.h deleted file mode 100644 index 702438b45a..0000000000 --- a/zboss/development/include/addons/zcl/zb_zcl_groups_addons.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_ZCL_GROUPS_ADDONS_H__ -#define ZB_ZCL_GROUPS_ADDONS_H__ - -#include "zboss_api.h" - -/*! \addtogroup zb_zcl_groups_addons */ -/*! @{ */ - -/**@brief Groups cluster attributes according to ZCL Spec 3.6.2.2. */ -typedef struct -{ - zb_uint8_t name_support; -} zb_zcl_groups_attrs_t; - -/** - * @brief Declare attribute list for Groups cluster (client). - * @param attr_list - attribute list name. - */ -#define ZB_ZCL_DECLARE_GROUPS_CLIENT_ATTRIB_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_GROUPS) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ - -#endif /* ZB_ZCL_GROUPS_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zcl/zb_zcl_identify_addons.h b/zboss/development/include/addons/zcl/zb_zcl_identify_addons.h deleted file mode 100644 index f179317487..0000000000 --- a/zboss/development/include/addons/zcl/zb_zcl_identify_addons.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_ZCL_IDENTIFY_ADDONS_H__ -#define ZB_ZCL_IDENTIFY_ADDONS_H__ - -#include "zboss_api.h" - -/*! \addtogroup zb_zcl_identify_addons */ -/*! @{ */ - -/**@brief Macro equivalent to @ref ZB_ZCL_IDENTIFY_SEND_TRIGGER_VARIANT_REQ, but command is sent without APS ACK. */ -#define ZB_ZCL_IDENTIFY_SEND_TRIGGER_VARIANT_REQ_NO_APS_ACK( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, def_resp, cb, effect_id, effect_var) \ -{ \ - zb_uint8_t * ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IDENTIFY_TRIGGER_EFFECT_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (effect_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (effect_var)); \ - ZB_ZCL_SEND_COMMAND_SHORT_WITHOUT_ACK((buffer), ptr, addr, dst_addr_mode, \ - dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, cb, 0); \ -} - -/** - * @brief Declare attribute list for Identify cluster (client). - * @param attr_list - attribute list name. - */ -#define ZB_ZCL_DECLARE_IDENTIFY_CLIENT_ATTRIB_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_IDENTIFY) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** - * @brief Declare attribute list for Identify cluster (server). - * @param attr_list - attribute list name - * @param identify_time - pointer to variable to store identify time attribute value - */ -#define ZB_ZCL_DECLARE_IDENTIFY_SERVER_ATTRIB_LIST(attr_list, identify_time) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_IDENTIFY) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID, (identify_time)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ - -#endif /* ZB_ZCL_IDENTIFY_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zcl/zb_zcl_level_control_addons.h b/zboss/development/include/addons/zcl/zb_zcl_level_control_addons.h deleted file mode 100644 index 010da5d27d..0000000000 --- a/zboss/development/include/addons/zcl/zb_zcl_level_control_addons.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_ZCL_LEVEL_CONTROL_ADDONS_H__ -#define ZB_ZCL_LEVEL_CONTROL_ADDONS_H__ - -#include "zboss_api.h" - -/*! \addtogroup zb_zcl_level_control_addons */ -/*! @{ */ - -/**@brief Level Control cluster attributes according to ZCL Spec 3.10.2.3. */ -typedef struct -{ - zb_uint8_t current_level; - zb_uint16_t remaining_time; -} zb_zcl_level_control_attrs_t; - -/**@brief Macro equivalent to @ref ZB_ZCL_LEVEL_CONTROL_SEND_STEP_CMD, but command is sent without APS ACK. */ -#define ZB_ZCL_LEVEL_CONTROL_SEND_STEP_CMD_NO_APS_ACK(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - cmd_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), cmd_id); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_size)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); \ - ZB_ZCL_SEND_COMMAND_SHORT_WITHOUT_ACK((buffer), ptr, \ - addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, cb, 0); \ -} - -/**@brief Macro equivalent to @ref ZB_ZCL_LEVEL_CONTROL_SEND_STEP_REQ, but command is sent without APS ACK. */ -#define ZB_ZCL_LEVEL_CONTROL_SEND_STEP_REQ_NO_APS_ACK(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_STEP_CMD_NO_APS_ACK(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - ZB_ZCL_CMD_LEVEL_CONTROL_STEP); \ -} - -/** - * @brief Declare attribute list for Level control cluster (client). - * @param attr_list - attribute list name. - */ -#define ZB_ZCL_DECLARE_LEVEL_CONTROL_CLIENT_ATTRIB_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_LEVEL_CONTROL) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ - -#endif /* ZB_ZCL_LEVEL_CONTROL_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zcl/zb_zcl_on_off_addons.h b/zboss/development/include/addons/zcl/zb_zcl_on_off_addons.h deleted file mode 100644 index 4107755252..0000000000 --- a/zboss/development/include/addons/zcl/zb_zcl_on_off_addons.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_ZCL_ON_OFF_ADDONS_H__ -#define ZB_ZCL_ON_OFF_ADDONS_H__ - -#include "zboss_api.h" - -/*! \addtogroup zb_zcl_on_off_addons */ -/*! @{ */ - -/**@brief On/Off cluster attributes with optional fields according to ZCL Spec 3.8.2.2. */ -typedef struct -{ - zb_bool_t on_off; - zb_bool_t global_scene_ctrl; - zb_uint16_t on_time; - zb_uint16_t off_wait_time; -} zb_zcl_on_off_attrs_ext_t; - -/**@brief Macro equivalent to @ref ZB_ZCL_ON_OFF_SEND_REQ, but command is sent without APS ACK. */ -#define ZB_ZCL_ON_OFF_SEND_REQ_NO_APS_ACK( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, command_id, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), command_id); \ - ZB_ZCL_SEND_COMMAND_SHORT_WITHOUT_ACK((buffer), ptr, addr, \ - dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_ON_OFF, cb, 0); \ -} - -/** - * @brief Declare attribute list for On/Off cluster (client). - * @param attr_list - attribute list name. - */ -#define ZB_ZCL_DECLARE_ON_OFF_CLIENT_ATTRIB_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_ON_OFF) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ - -#endif /* ZB_ZCL_ON_OFF_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zcl/zb_zcl_scenes_addons.h b/zboss/development/include/addons/zcl/zb_zcl_scenes_addons.h deleted file mode 100644 index e2f6cf9e7e..0000000000 --- a/zboss/development/include/addons/zcl/zb_zcl_scenes_addons.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_ZCL_SCENES_ADDONS_H__ -#define ZB_ZCL_SCENES_ADDONS_H__ - -#include "zboss_api.h" - -/*! \addtogroup zb_zcl_scenes_addons */ -/*! @{ */ - -/* Scene cluster attributes according to ZCL Spec 3.7.2.2. */ -typedef struct -{ - zb_uint8_t scene_count; - zb_uint8_t current_scene; - zb_uint8_t scene_valid; - zb_uint8_t name_support; - zb_uint16_t current_group; -} zb_zcl_scenes_attrs_t; - -/** - * @brief Declare attribute list for Scenes cluster (client). - * @param attr_list - attribute list name. - */ -#define ZB_ZCL_DECLARE_SCENES_CLIENT_ATTRIB_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_SCENES) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ - -#endif /* ZB_ZCL_SCENES_ADDONS_H__ */ diff --git a/zboss/development/include/addons/zcl/zb_zcl_temp_measurement_addons.h b/zboss/development/include/addons/zcl/zb_zcl_temp_measurement_addons.h deleted file mode 100644 index 09f9a26d68..0000000000 --- a/zboss/development/include/addons/zcl/zb_zcl_temp_measurement_addons.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_ZCL_TEMP_MEASUREMENT_ADDONS_H__ -#define ZB_ZCL_TEMP_MEASUREMENT_ADDONS_H__ - -#include "zboss_api.h" - -/*! \addtogroup zb_zcl_temp_measurement_addons */ -/*! @{ */ - -/**@brief Temperature Measurement cluster attributes according to ZCL Spec 4.4.2.1.1. */ -typedef struct -{ - zb_int16_t measure_value; - zb_int16_t min_measure_value; - zb_int16_t max_measure_value; - zb_uint16_t tolerance; -} zb_zcl_temp_measurement_attrs_t; - -/** @} */ - -#endif /* ZB_ZCL_TEMP_MEASUREMENT_ADDONS_H__ */ diff --git a/zboss/development/include/ha/zb_ha_config.h b/zboss/development/include/ha/zb_ha_config.h deleted file mode 100644 index 32e6d0b502..0000000000 --- a/zboss/development/include/ha/zb_ha_config.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: HA configuration -*/ - -#ifndef ZB_HA_CONFIG_H -#define ZB_HA_CONFIG_H 1 - -#include "zb_vendor.h" - -#if defined ZB_ENABLE_HA || defined DOXYGEN - -/** @cond DOXYGEN_HA_SECTION */ - -/* Specify a list of devices that should be supported */ -#define xZB_ALL_DEVICE_SUPPORT /* Attention! use this macro in testing purposes */ - -/* Normally startup attribute sets should be processed */ -/* TODO Re-enable HA SAS processing when appropriate */ -#define xZB_ENABLE_HA_SAS - -/* NK: why Gateway is always defined? */ -#define xZB_HA_DEFINE_DEVICE_GATEWAY - - -#include "zb_ha_device_config.h" -#include "zcl/zb_zcl_config.h" - -/** @endcond */ /* DOXYGEN_HA_SECTION */ - -#endif /* ZB_ENABLE_HA */ - -#endif /* ZB_HA_CONFIG_H */ diff --git a/zboss/development/include/ha/zb_ha_device_config.h b/zboss/development/include/ha/zb_ha_device_config.h deleted file mode 100644 index 42df1c69fa..0000000000 --- a/zboss/development/include/ha/zb_ha_device_config.h +++ /dev/null @@ -1,577 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: HA devices configuration -*/ - -#ifndef ZB_HA_DEVICE_CONFIG_H -#define ZB_HA_DEVICE_CONFIG_H 1 - -#if defined ZB_ENABLE_HA || defined DOXYGEN - -/** @cond DOXYGEN_HA_SECTION */ - -/*! @defgroup ha_config_params HA Device types */ -/*! @{ - */ - -/** @brief HA Device identifiers. */ -enum zb_ha_standard_devs_e -{ - /*! General On/Off switch */ - ZB_HA_ON_OFF_SWITCH_DEVICE_ID = 0x0000, - /*! Level Control Switch */ - ZB_HA_LEVEL_CONTROL_SWITCH_DEVICE_ID = 0x0001, - /*! General On/Off output */ - ZB_HA_ON_OFF_OUTPUT_DEVICE_ID = 0x0002, - /*! Level Controllable Output */ - ZB_HA_LEVEL_CONTROLLABLE_OUTPUT_DEVICE_ID = 0x0003, - /*! Scene Selector */ - ZB_HA_SCENE_SELECTOR_DEVICE_ID = 0x0004, - /*! Configuration Tool */ - ZB_HA_CONFIGURATION_TOOL_DEVICE_ID = 0x0005, - /*! Remote Control */ - ZB_HA_REMOTE_CONTROL_DEVICE_ID = 0x0006, - /*! Combined Interface */ - ZB_HA_COMBINED_INTERFACE_DEVICE_ID = 0x0007, - /*! Range Extender */ - ZB_HA_RANGE_EXTENDER_DEVICE_ID = 0x0008, - /*! Mains Power Outlet */ - ZB_HA_MAINS_POWER_OUTLET_DEVICE_ID = 0x0009, - /*! Door lock client */ - ZB_HA_DOOR_LOCK_DEVICE_ID = 0x000A, - /*! Door lock controller */ - ZB_HA_DOOR_LOCK_CONTROLLER_DEVICE_ID = 0x000B, - /*! Simple Sensor device */ - ZB_HA_SIMPLE_SENSOR_DEVICE_ID = 0x000C, - /*! Consumption Awareness Device */ - ZB_HA_CONSUMPTION_AWARENESS_DEVICE_ID = 0x000D, - /*! Home Gateway */ - ZB_HA_HOME_GATEWAY_DEVICE_ID = 0x0050, - /*! Smart plug */ - ZB_HA_SMART_PLUG_DEVICE_ID = 0x0051, - /*! White Goods */ - ZB_HA_WHITE_GOODS_DEVICE_ID = 0x0052, - /*! Meter Interface */ - ZB_HA_METER_INTERFACE_DEVICE_ID = 0x0053, - /* Lightning */ - /*! On/Off Light Device */ - ZB_HA_ON_OFF_LIGHT_DEVICE_ID = 0x0100, - /*! Dimmable Light Device */ - ZB_HA_DIMMABLE_LIGHT_DEVICE_ID = 0x0101, - /*! Color Dimmable Light Device */ - ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID = 0x0102, - /*! Dimmer Switch Device */ - ZB_HA_DIMMER_SWITCH_DEVICE_ID = 0x0104, - /*! Color Dimmer Switch Device */ - ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID = 0x0105, - /*! Shade */ - ZB_HA_SHADE_DEVICE_ID = 0x0200, - /*! Shade controller */ - ZB_HA_SHADE_CONTROLLER_DEVICE_ID = 0x0201, - /*! Window Covering client*/ - ZB_HA_WINDOW_COVERING_DEVICE_ID = 0x0202, - /*! Window Covering controller */ - ZB_HA_WINDOW_COVERING_CONTROLLER_DEVICE_ID = 0x0203, - /* HVAC */ - /*! Heating/Cooling Unit device */ - ZB_HA_HEATING_COOLING_UNIT_DEVICE_ID = 0x0300, - /*! Thermostat Device */ - ZB_HA_THERMOSTAT_DEVICE_ID = 0x0301, - /*! Temperature Sensor */ - ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID = 0x0302, - /* IAS */ - /*! IAS Control and Indicating Equipment */ - ZB_HA_IAS_CONTROL_INDICATING_EQUIPMENT_ID = 0x0400, - /*! IAS Ancillary Control Equipment */ - ZB_HA_IAS_ANCILLARY_CONTROL_EQUIPMENT_ID = 0x0401, - /*! IAS Zone */ - ZB_HA_IAS_ZONE_ID = 0x0402, - /*! IAS Warning Device */ - ZB_HA_IAS_WARNING_DEVICE_ID = 0x0403, - /*! Custom HA device for test */ - ZB_HA_TEST_DEVICE_ID = 0xfff0, - /*! Custom Tunnel device (should declared in private profile) */ - ZB_HA_CUSTOM_TUNNEL_DEVICE_ID = 0xfff1, - /*! Custom Attributes Device */ - ZB_HA_CUSTOM_ATTR_DEVICE_ID = 0xfff2 -}; - - -/** @cond DOXYGEN_INTERNAL_DOC */ -/* Define supported devices here */ -#ifdef ZB_ALL_DEVICE_SUPPORT - -#define ZB_HA_DEFINE_DEVICE_ON_OFF_SWITCH -#define ZB_HA_DEFINE_DEVICE_ON_OFF_OUTPUT -#define ZB_HA_DEFINE_DEVICE_DOOR_LOCK -#define ZB_HA_DEFINE_DEVICE_DOOR_LOCK_CONTROLLER -#define ZB_HA_DEFINE_DEVICE_SIMPLE_SENSOR -#define ZB_HA_DEFINE_DEVICE_COMBINED_INTERFACE -#define ZB_HA_DEFINE_DEVICE_SCENE_SELECTOR -#define ZB_HA_DEFINE_DEVICE_CONFIGURATION_TOOL -#define ZB_HA_DEFINE_DEVICE_MAINS_POWER_OUTLET -#define ZB_HA_DEFINE_DEVICE_RANGE_EXTENDER -#define ZB_HA_DEFINE_DEVICE_LEVEL_CONTROL_SWITCH -#define ZB_HA_DEFINE_DEVICE_LEVEL_CONTROLLABLE_OUTPUT -#define ZB_HA_DEFINE_DEVICE_WINDOW_COVERING -#define ZB_HA_DEFINE_DEVICE_WINDOW_COVERING_CONTROLLER -#define ZB_HA_DEFINE_DEVICE_SHADE -#define ZB_HA_DEFINE_DEVICE_SHADE_CONTROLLER - /* HVAC */ -#define ZB_HA_DEFINE_DEVICE_TEMPERATURE_SENSOR -/* IAS*/ -#define ZB_HA_DEFINE_DEVICE_IAS_CONTROL_INDICATING_EQUIPMENT -#define ZB_HA_DEFINE_DEVICE_IAS_ANCILLARY_CONTROL_EQUIPMENT -#define ZB_HA_DEFINE_DEVICE_IAS_ZONE -#define ZB_HA_DEFINE_DEVICE_IAS_WARNING_DEVICE - -#define ZB_HA_DEFINE_DEVICE_CUSTOM_ATTR -#define ZB_HA_DEFINE_DEVICE_DIMMABLE_LIGHT -#define ZB_HA_DEFINE_DEVICE_DIMMER_SWITCH - -#define ZB_HA_DEFINE_DEVICE_SMART_PLUG -#define ZB_HA_DEFINE_DEVICE_THERMOSTAT - -#define ZB_HA_DEFINE_DEVICE_TEST_DEVICE - -/************** Custom Devices ******************/ -/* Define device support for custom security sensor */ -#define ZB_HA_DEFINE_DEVICE_CUSTOM_SECURITY_SENSOR -/* this device definition - for coordinator (CIE) role, need for test - * only - remove it in release build */ -#define ZB_HA_DEFINE_DEVICE_CUSTOM_SECURITY_CONTROL -/* Define device support for Low Cost Gateway */ -#define ZB_HA_DEFINE_DEVICE_GATEWAY -#define ZB_HA_DEFINE_DEVICE_CUSTOM_DIMMABLE_LIGHT -/* Linky */ -#define ZB_HA_DEFINE_DEVICE_ERL_INTERFACE_DEVICE -#define ZB_HA_DEFINE_DEVICE_ERL_GW - - - -#define ZB_ZCL_SUPPORT_CLUSTER_DRLC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_PRICE 1 -#define ZB_ZCL_SUPPORT_CLUSTER_TUNNELING 1 -#define ZB_ZCL_SUPPORT_CLUSTER_MESSAGING 1 - -#define ZB_ZCL_SUPPORT_CLUSTER_METER_IDENTIFICATION 1 - -/* Define optional common clusters. These clusters are common to all devices - * and expected to be part of the build if ZB_ALL_DEVICE_SUPPORT is declared. - * For example, application 'multi_ep' expects "Alarms" cluster to be present. - * - * Clusters with reporting capability are omitted since common part implies - * client role which receives attribute reports. It is not necessary to enable - * ZB_ZCL_SUPPORT_* during stack build. It will be enough for applications to - * define corresponding ZB_ZCL_SUPPORT_* during application's build because - * only headers should be included, no *.c files. - * - * Also, common manufacturer-specific clusters are ignored here. - */ -#define ZB_ZCL_SUPPORT_CLUSTER_POWER_CONFIG 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ALARMS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ELECTRICAL_MEASUREMENT 1 -#define ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL 1 - -/* Define clusters which are not used by any device but expected to be - * supported in ZBOSS stack when ZB_ALL_DEVICE_SUPPORT is defined. - * - * The main intention of ZB_ALL_DEVICE_SUPPORT define is to compile in ZBOSS - * stack as much HA-related functionality as possible so declaring support for - * clusters not being used by any device but used by some sample seems to be - * fine. - */ -#define ZB_ZCL_SUPPORT_CLUSTER_DEHUMIDIFICATION_CONTROL 1 -#define ZB_ZCL_SUPPORT_CLUSTER_OCCUPANCY_SENSING 1 - -#endif /* ZB_ALL_DEVICE_SUPPORT */ - -//#define ZB_HA_DEFINE_DEVICE_SMART_PLUG - -/*********************** HA devices to cluster configuration **********************/ - -#ifdef ZB_HA_DEFINE_DEVICE_ON_OFF_SWITCH -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF_SWITCH_CONFIG 1 - -#endif /* ZB_HA_DEFINE_DEVICE_ON_OFF_OUTPUT */ - - -#ifdef ZB_HA_DEFINE_DEVICE_ON_OFF_OUTPUT -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 - -#endif /* ZB_HA_DEFINE_DEVICE_ON_OFF_OUTPUT */ - -#ifdef ZB_HA_DEFINE_DEVICE_BASIC_LIGHT -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#endif /* ZB_HA_DEFINE_DEVICE_BASIC_LIGHT */ - - -#ifdef ZB_HA_DEFINE_DEVICE_DOOR_LOCK -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_DOOR_LOCK 1 - -#endif /* ZB_HA_DEFINE_DEVICE_DOOR_LOCK */ - - -#ifdef ZB_HA_DEFINE_DEVICE_DOOR_LOCK_CONTROLLER -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_DOOR_LOCK 1 - -#endif /* ZB_HA_DEFINE_DEVICE_DOOR_LOCK_CONTROLLER */ - - -#ifdef ZB_HA_DEFINE_DEVICE_SIMPLE_SENSOR -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_BINARY_INPUT 1 -#endif /* ZB_HA_DEFINE_DEVICE_SIMPLE_SENSOR */ - - -#ifdef ZB_HA_DEFINE_DEVICE_COMBINED_INTERFACE -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF_SWITCH_CONFIG 1 -#endif /* ZB_HA_DEFINE_DEVICE_COMBINED_INTERFACE */ - - -#ifdef ZB_HA_DEFINE_DEVICE_SCENE_SELECTOR -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#endif /* ZB_HA_DEFINE_DEVICE_SCENE_SELECTOR */ - - -#ifdef ZB_HA_DEFINE_DEVICE_CONFIGURATION_TOOL -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#endif /* ZB_HA_DEFINE_DEVICE_CONFIGURATION_TOOL */ - - -#ifdef ZB_HA_DEFINE_DEVICE_MAINS_POWER_OUTLET -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 - -#endif /* ZB_HA_DEFINE_DEVICE_MAINS_POWER_OUTLET */ - - -#ifdef ZB_HA_DEFINE_DEVICE_RANGE_EXTENDER -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#endif /* ZB_HA_DEFINE_DEVICE_RANGE_EXTENDER */ - - -#ifdef ZB_HA_DEFINE_DEVICE_LEVEL_CONTROL_SWITCH -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_LEVEL_CONTROL 1 -#endif /* ZB_HA_DEFINE_DEVICE_LEVEL_CONTROL_SWITCH */ - - -#ifdef ZB_HA_DEFINE_DEVICE_LEVEL_CONTROLLABLE_OUTPUT -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_LEVEL_CONTROL 1 - -#endif /* ZB_HA_DEFINE_DEVICE_LEVEL_CONTROLLABLE_OUTPUT */ - - -#ifdef ZB_HA_DEFINE_DEVICE_WINDOW_COVERING -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_WINDOW_COVERING 1 - -#endif /* ZB_HA_DEFINE_DEVICE_WINDOW_COVERING */ - -#ifdef ZB_HA_DEFINE_DEVICE_CUSTOM_ATTR -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_WINDOW_COVERING 1 -#define ZB_ZCL_SUPPORT_CLUSTER_CUSTOM_ATTR 1 -#endif /* ZB_HA_DEFINE_DEVICE_CUSTOM_ATTR */ - -#ifdef ZB_HA_DEFINE_DEVICE_DIMMABLE_LIGHT -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_LEVEL_CONTROL 1 -#endif /* ZB_HA_DEFINE_DEVICE_DIMMABLE_LIGHT */ - -#ifdef ZB_HA_DEFINE_DEVICE_DIMMABLE_LIGHT -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_LEVEL_CONTROL 1 -#endif /* ZB_HA_DEFINE_DEVICE_DIMMER_SWITCH */ - -#ifdef ZB_HA_DEFINE_DEVICE_WINDOW_COVERING_CONTROLLER -#define ZB_HA_DEFINE_DEVICE_WINDOW_COVERING_CONTROLLER -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_WINDOW_COVERING 1 -#endif /* ZB_HA_DEFINE_DEVICE_WINDOW_COVERING_CONTROLLER */ - -#ifdef ZB_HA_DEFINE_DEVICE_SHADE -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SHADE_CONFIG 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_LEVEL_CONTROL 1 -#endif /* ZB_HA_DEFINE_DEVICE_SHADE */ - -#ifdef ZB_HA_DEFINE_DEVICE_SHADE_CONTROLLER -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_LEVEL_CONTROL 1 -#endif /* ZB_HA_DEFINE_DEVICE_SHADE_CONTROLLER */ - - /* HVAC */ - -#ifdef ZB_HA_DEFINE_DEVICE_TEMPERATURE_SENSOR -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_TEMP_MEASUREMENT 1 -#endif /* ZB_HA_DEFINE_DEVICE_TEMPERATURE_SENSOR */ - -/* IAS*/ - -#ifdef ZB_HA_DEFINE_DEVICE_IAS_CONTROL_INDICATING_EQUIPMENT -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ACE 1 -//#define ZB_ZCL_SUPPORT_CLUSTER_IAS_WD 1 -//#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#endif /* ZB_HA_DEFINE_DEVICE_IAS_CONTROL_INDICATING_EQUIPMENT */ - -#ifdef ZB_HA_DEFINE_DEVICE_IAS_ANCILLARY_CONTROL_EQUIPMENT -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE 1 -//#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ACE 1 -#endif /* ZB_HA_DEFINE_DEVICE_IAS_ANCILLARY_CONTROL_EQUIPMENT */ - -#ifdef ZB_HA_DEFINE_DEVICE_IAS_ZONE -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE 1 -#endif /* ZB_HA_DEFINE_DEVICE_IAS_ZONE */ - -#ifdef ZB_HA_DEFINE_DEVICE_IAS_WARNING_DEVICE -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_WD 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#endif /* ZB_HA_DEFINE_DEVICE_IAS_WARNING_DEVICE */ - -#ifdef ZB_HA_DEFINE_DEVICE_CUSTOM_SECURITY_SENSOR -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE 1 -#define ZB_ZCL_SUPPORT_CLUSTER_TEMP_MEASUREMENT 1 - -#define ZB_ZCL_SUPPORT_CLUSTER_POWER_CONFIG 1 -#define ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL 1 -#define ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ILLUMINANCE_MEASUREMENT 1 -#define ZB_ZCL_SUPPORT_CLUSTER_REL_HUMIDITY_MEASUREMENT 1 -#endif /* ZB_HA_DEFINE_DEVICE_CUSTOM_SECURITY_SENSOR */ - -#ifdef ZB_HA_DEFINE_DEVICE_CUSTOM_SECURITY_CONTROL -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE 1 -//#define ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL 1 -#endif /* ZB_HA_DEFINE_DEVICE_CUSTOM_SECURITY_CONTROL */ - -#ifdef ZB_HA_DEFINE_DEVICE_THERMOSTAT -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_THERMOSTAT 1 -#define ZB_ZCL_SUPPORT_CLUSTER_THERMOSTAT_UI_CONFIG 1 -#define ZB_ZCL_SUPPORT_CLUSTER_FAN_CONTROL 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ELECTRICAL_MEASUREMENT 1 -#endif /* ZB_HA_DEFINE_DEVICE_THERMOSTAT */ - -#ifdef ZB_HA_DEFINE_DEVICE_GATEWAY -/* - * Gateway supports many clusters, but in the client role and in general it's - * not necessary to define their support with ZB_ZCL_SUPPORT_CLUSTER_xxx. - * Such defines are necessary only for clusters in the server role. - * The only exception is poll control cluster for now. - */ -#define ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL 1 -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE 1 -#define ZB_ZCL_SUPPORT_CLUSTER_TIME 1 -#define ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS_CLIENT 1 -#define ZB_ZCL_SUPPORT_CLUSTER_EN50523_APPLIANCE_EVENTS_AND_ALERTS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_POWER_CONFIG 1 -#define ZB_ZCL_SUPPORT_CLUSTER_REL_HUMIDITY_MEASUREMENT 1 -#define ZB_ZCL_SUPPORT_CLUSTER_TEMP_MEASUREMENT 1 -#define ZB_ZCL_SUPPORT_CLUSTER_PRESSURE_MEASUREMENT 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_METERING 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ACE 1 -/* - * Gateway uses EZ mode only for Gemtek smartplug, which is - * currently excluded from build. - */ -/* #define ZB_HA_SUPPORT_EZ_MODE 1 */ -#endif /* ZB_HA_DEFINE_DEVICE_GATEWAY */ - -/* Custom device should not be declared as a part of HA, keep it - * here foe simplicity */ -#ifdef ZB_PROFILE_DEFINE_DEVICE_CUSTOM_TUNNEL -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_TUNNEL 1 -#endif - -#ifdef ZB_HA_DEFINE_DEVICE_SMART_PLUG -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_METERING 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -/* FIXME: Are Scenes really needed? */ -/* #define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 */ -#define ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE 1 -#endif /* ZB_HA_DEFINE_DEVICE_SMART_PLUG */ - - -#ifdef ZB_HA_DEFINE_DEVICE_CUSTOM_DIMMABLE_LIGHT -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES 1 -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF 1 -#define ZB_ZCL_SUPPORT_CLUSTER_LEVEL_CONTROL 1 -#define ZB_ZCL_SUPPORT_CLUSTER_COLOR_CONTROL 1 -#endif /* ZB_HA_DEFINE_DEVICE_CUSTOM_DIMMABLE_LIGHT */ - -#if defined ZB_HA_DEFINE_DEVICE_ERL_INTERFACE_DEVICE || defined ZB_HA_DEFINE_DEVICE_ERL_GW -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC 1 -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#define ZB_ZCL_SUPPORT_CLUSTER_TIME 1 -#define ZB_ZCL_SUPPORT_CLUSTER_METER_IDENTIFICATION 1 -#define ZB_ZCL_SUPPORT_CLUSTER_ELECTRICAL_MEASUREMENT 1 -#define ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS 1 -#define ZB_ZCL_SUPPORT_CLUSTER_METERING 1 -#define ZB_ZCL_SUPPORT_CLUSTER_MESSAGING 1 -#define ZB_ZCL_SUPPORT_CLUSTER_DAILY_SCHEDULE 1 -#endif /* defined ZB_HA_DEFINE_DEVICE_ERL_INTERFACE_DEVICE || defined ZB_HA_DEFINE_DEVICE_ERL_GW */ - -/* BDB uses identify */ -#if defined ZB_BDB_MODE && !defined ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY 1 -#endif - -/** @endcond */ - -/** @} */ /* ha_api */ - -/** @endcond */ /* DOXYGEN_HA_SECTION */ - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS -/* need to define it here because that .h file can be included after zb_config.h */ -#ifndef ZB_MAC_DIAGNOSTICS -#define ZB_MAC_DIAGNOSTICS -#endif -#ifndef ZDO_DIAGNOSTICS -#define ZDO_DIAGNOSTICS -#endif -#endif - -#endif /* ZB_ENABLE_HA */ - -#if defined ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS && ! defined ZDO_DIAGNOSTICS -#error Define ZDO_DIAGNOSTICS in vendor file if you need Diagnostic cluster! -#endif - -#endif /* ZB_HA_DEVICE_CONFIG_H */ diff --git a/zboss/development/include/ncp/ncp_common_api.h b/zboss/development/include/ncp/ncp_common_api.h deleted file mode 100644 index 37b6c448ed..0000000000 --- a/zboss/development/include/ncp/ncp_common_api.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: API shared for host and dev -*/ -#ifndef NCP_COMMON_API_H -#define NCP_COMMON_API_H 1 - -#include "zb_types.h" -#include "zb_errors.h" - -/** @cond DOXYGEN_NCP_SECTION */ - -/** @addtogroup ncp_common_api - * @{ - */ - -/** - * @brief It is used to create and read a response sent by @ref zb_ncp_custom_response - */ -typedef ZB_PACKED_PRE struct ncp_hl_custom_resp_s -{ - zb_ret_t status; - zb_uint8_t tsn; -} ZB_PACKED_STRUCT ncp_hl_custom_resp_t; - - - -/** @} */ /* ncp_common_api */ - -/** @endcond */ /* DOXYGEN_NCP_SECTION */ - -#endif /* NCP_COMMON_API_H */ diff --git a/zboss/development/include/ncp/ncp_dev_api.h b/zboss/development/include/ncp/ncp_dev_api.h deleted file mode 100644 index b8f941ca6b..0000000000 --- a/zboss/development/include/ncp/ncp_dev_api.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: NCP Dev API declarations -*/ -#ifndef NCP_DEV_API_H -#define NCP_DEV_API_H 1 - -#include "zb_types.h" -#include "ncp_common_api.h" - -/** @cond DOXYGEN_NCP_SECTION */ - -/** @addtogroup ncp_dev_api - * @{ - */ - -/** Return code which is raised if @ref zb_ncp_custom_response will be called later*/ -#define NCP_RET_LATER (255U) - - -/** The custom request callback. - * - * @param param - the buffer with request data from host and tsn (@ref zb_uint8_t) as a parameter. - * It's freed by the stack afterwards. - * - * @return The length of a response returned by @ref zb_ncp_custom_response if it is called within callback. - * @ref NCP_RET_LATER if @ref zb_ncp_custom_response is called later. - * - * @note If returned length is equal to 0, the response is generated and sent automatically. - */ -typedef zb_uint16_t (*zb_ncp_custom_request_cb_t)(zb_uint8_t param); - -/** Registers a callback, that is called once the zb_ncp_custom_request is called on the host side - * and the corresponding NCP command is received. - * - * @param cb - the callback. If NULL is passed, previously registered callback (if any) will be unregistered. - */ -void zb_ncp_custom_register_request_cb(zb_ncp_custom_request_cb_t cb); - -/** Sends the indication to the Host. - * - * @param param - the ZBOSS buffer with payload. It's freed by the stack. - */ -void zb_ncp_custom_indication(zb_uint8_t param); - -/** Sends a custom response. - * - * @param param - the ZBOSS buffer with response payload and @ref ncp_hl_custom_resp_t as a parameter. - * It's freed by the stack. - * - * @return Response length - * - * @note Should be called within @ref zb_ncp_custom_request_cb_t unless @ref NCP_RET_LATER is not returned from callback. - */ -zb_uint16_t zb_ncp_custom_response(zb_uint8_t param); - -/** @} */ /* ncp_dev_api */ - -/** @endcond */ /* DOXYGEN_NCP_SECTION */ - -#endif /* NCP_DEV_API_H */ diff --git a/zboss/development/include/osif/build_info.h b/zboss/development/include/osif/build_info.h deleted file mode 100644 index 7bd76aebe0..0000000000 --- a/zboss/development/include/osif/build_info.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -#ifndef ZBOSS_BUILD_INFO_H__ -#define ZBOSS_BUILD_INFO_H__ - -/** - * This is an autogenerated file. - * Please use release scripts to update it's contents. - * - * Repositories: - * platform_ncs 5cc5350d76b6e1abfcda44355494e58ee3c5c8fd https://projecttools.nordicsemi.no/bitbucket/scm/ZOI/platform_ncs.git - * zboss-stack-src 958ed927736f8cbcbe1270b074f738f08045f734 https://projecttools.nordicsemi.no/bitbucket/scm/zoi/zboss_stable - * zboss-stack-doc e190d4a637c3c39bdcfb0b3abbbb1425479f2a8e https://projecttools.nordicsemi.no/bitbucket/scm/zoi/zboss_doc - * nrf 0a4f29c8d141c9bb378e2693db21f3e28dcb340c https://github.com/nrfconnect/sdk-nrf - * zephyr 240c7b9a691f6bcee824d1b26a40a368a916bb05 https://github.com/nrfconnect/sdk-zephyr - * mcuboot 132a537bf94044be93240a43b7622b3040bd017e https://github.com/nrfconnect/sdk-mcuboot - * mbedtls-nrf cefdd9954bcc92c08ce2ba41d87b57c29b73482b https://github.com/nrfconnect/sdk-mbedtls - * nrfxlib 2173e3337c494d131c107e8d9ce7af095d5adc7a https://github.com/nrfconnect/sdk-nrfxlib - * trusted-firmware-m 7d4a7139009c24ffa6edfb7f24fe32090bca0583 https://github.com/nrfconnect/sdk-trusted-firmware-m - * tfm-mcuboot 4aa516e7281fc6f9a2dce0b0efda9acc580fa254 https://github.com/nrfconnect/sdk-mcuboot - * matter 80da8ab1c0aa315a6ee2ce6adf448606372b0a2d https://github.com/nrfconnect/sdk-connectedhomeip - * cjson c6af068b7f05207b28d68880740e4b9ec1e4b50a https://github.com/nrfconnect/sdk-cjson - * cmock 9d092898ef26ece140d9225e037274b64d4f851e https://github.com/ThrowTheSwitch/cmock - * unity 74cde089e65c3435ce9aa87d5c69f4f16b7f6ade https://github.com/ThrowTheSwitch/unity - * Alexa-Gadgets-Embedded-Sample-Code face92d8c62184832793f518bb1f19379538c5c1 https://github.com/alexa/Alexa-Gadgets-Embedded-Sample-Code - * zcbor 317d3c6cd6dee23a151a3e7982d8564e7e19b2e2 https://github.com/NordicSemiconductor/zcbor - * memfault-firmware-sdk b7eea3b5d8e533d04c6bedbb8148938667334b91 https://github.com/memfault/memfault-firmware-sdk - * canopennode 53d3415c14d60f8f4bfca54bfbc5d5a667d7e724 https://github.com/zephyrproject-rtos/canopennode - * civetweb 094aeb41bb93e9199d24d665ee43e9e05d6d7b1c https://github.com/zephyrproject-rtos/civetweb - * cmsis b0612c97c1401feeb4160add6462c3627fe90fc7 https://github.com/zephyrproject-rtos/cmsis - * edtt 1fc2e6f7d2a01a01074456f2ef2ccf1f3df7fac1 https://github.com/zephyrproject-rtos/edtt - * fatfs 9237454a30bcf6e14a89db174e8dbeb8f31831d2 https://github.com/zephyrproject-rtos/fatfs - * hal_nordic 626e3dd960a956993441f2ed4bf2db0b5f35f01a https://github.com/zephyrproject-rtos/hal_nordic - * hal_st 575de9d461aa6f430cf62c58a053675377e700f3 https://github.com/zephyrproject-rtos/hal_st - * libmetal f237c9d420a51cc43bc37d744e41191ad613f348 https://github.com/zephyrproject-rtos/libmetal - * littlefs 7b2cf4ba759bd530b543644e2790b07cf20cd6aa https://github.com/zephyrproject-rtos/littlefs - * loramac-node 12019623bbad9eb54fe51066847a7cbd4b4eac57 https://github.com/zephyrproject-rtos/loramac-node - * lvgl aae1c11102138cf596687e662c0d54b72f72bf9b https://github.com/zephyrproject-rtos/lvgl - * lz4 8e303c264fc21c2116dc612658003a22e933124d https://github.com/zephyrproject-rtos/lz4 - * mbedtls 3e3e58a92de76069730c63e0d524f40fea948a61 https://github.com/zephyrproject-rtos/mbedtls - * mipi-sys-t d9da086b11cda494d85f4d8a9829f505c2d5e380 https://github.com/zephyrproject-rtos/mipi-sys-t - * nanopb d148bd26718e4c10414f07a7eb1bd24c62e56c5d https://github.com/zephyrproject-rtos/nanopb - * net-tools f49bd1354616fae4093bf36e5eaee43c51a55127 https://github.com/zephyrproject-rtos/net-tools - * nrf_hw_models b8cea37dbdc8fc58cc14b4e19fa850877a9da520 https://github.com/zephyrproject-rtos/nrf_hw_models - * open-amp cfd050ff38a9d028dc211690b2ec35971128e45e https://github.com/zephyrproject-rtos/open-amp - * openthread d4d46ba94290bcf93cc849b832f0ad305c72c473 https://github.com/zephyrproject-rtos/openthread - * segger 3a52ab222133193802d3c3b4d21730b9b1f1d2f6 https://github.com/zephyrproject-rtos/segger - * tinycbor 40daca97b478989884bffb5226e9ab73ca54b8c4 https://github.com/zephyrproject-rtos/tinycbor - * tinycrypt 3e9a49d2672ec01435ffbf0d788db6d95ef28de0 https://github.com/zephyrproject-rtos/tinycrypt - * TraceRecorderSource e8ca3b6a83d19b2fc4738a0d9607190436e5e452 https://github.com/zephyrproject-rtos/TraceRecorderSource - * tf-m-tests 52814181f0fde6d1422fac204d42cde30c62e40e https://github.com/zephyrproject-rtos/tf-m-tests - * psa-arch-tests 0aab24602cbef30f6422e7ef1066a8473073e586 https://github.com/zephyrproject-rtos/psa-arch-tests - * zscilib 12bfe3f0a9fcbfe3edab7eabc9678b6c62875d34 https://github.com/zephyrproject-rtos/zscilib - */ - - -/** ZBOSS build tag */ -#define ZBOSS_BUILD_TAG "ncs_release-3.12.1.0" - -/** ZBOSS platform build tag */ -#define ZBOSS_PLATFORM_BUILD_TAG "v3.12.1.0+v5.2.0" - -/** ZBOSS build date (UTC) */ -#define ZBOSS_BUILD_DATE 20220428 - -/** ZBOSS build time (UTC) */ -#define ZBOSS_BUILD_TIME 100834 - - -#endif /* ZBOSS_BUILD_INFO_H__ */ diff --git a/zboss/development/include/osif/libzboss_config.ed.h b/zboss/development/include/osif/libzboss_config.ed.h deleted file mode 100644 index 4436b20b2c..0000000000 --- a/zboss/development/include/osif/libzboss_config.ed.h +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef LIBZBOSS_CONFIG_ED_H__ -#define LIBZBOSS_CONFIG_ED_H__ - -/** - * This is an autogenerated file. - * Please use Kconfig to change it. - */ - - -/** - * Include NCP related code in ZBOSS library. - * - * Compile NCP related code in ZBOSS library. - * This enables building NCP architecture with common ZBOSS library. - */ -#define CONFIG_ZB_NCP_MODE y - -/** - * NCP trasnport type - Serial (UART) - */ -#define CONFIG_ZB_NCP_TRANSPORT_TYPE_SERIAL y - -/** - * Enable UART serial interface for ZBOSS CLI - */ -#define CONFIG_ZB_HAVE_SERIAL y - -/** - * Serial (SPI) [UNSUPPORTED] - */ -/* #undef CONFIG_ZB_NCP_TRANSPORT_TYPE_SPI */ - -/** - * Simulator (linux pipe) [UNSUPPORTED] - */ -/* #undef CONFIG_ZB_NCP_TRANSPORT_TYPE_NSNG */ - -/** - * SDK Type (HA, SE, etc.) - Home Automation - */ -#define CONFIG_ZB_SDK_TYPE_HA y - -/** - * SDK Type (HA, SE, etc.) - Smart Energy - */ -/* #undef CONFIG_ZB_SDK_TYPE_SE */ - -/** - * ZB_SDK_TYPE - */ -#define CONFIG_ZB_SDK_TYPE 1 - -/** - * Compiled-in trace mask of ZBOSS stack logs - * - * Selectively enable Zigbee binary trace logs. - * The mask value should be a bitwise OR of values assigned to selected modules. - * - * Available modules are: - * - * - 0x04000000 Reserved - * - 0x02000000 Reserved - * - 0x01000000 Reserved - * - 0x00800000 Reserved - * - 0x00400000 Reserved - * - 0x00200000 Zigbee NCP: transport (LL) - * - 0x00100000 Zigbee NCP: command adapters (HL) - * - 0x00080000 ZCL: Over The Air firmware upgrade - * - 0x00040000 IAS zone device: battery monitoring - * - 0x00020000 Reserved - * - 0x00010000 MAC Lower Layer - * - 0x00008000 MAC layer API calls - * - 0x00004000 Zigbee Green Power - * - 0x00002000 Custom components - * - 0x00001000 Reserved - * - 0x00000800 Application - * - 0x00000400 Reserved - * - 0x00000200 Zigbee Light Link - * - 0x00000100 Zigbee Cluster Library - * - 0x00000080 Security - * - 0x00000040 Zigbee Device Object - * - 0x00000020 Zigbee Smart Energy - * - 0x00000010 Application Support layer - * - 0x00000008 Network layer - * - 0x00000004 MAC layer - * - 0x00000002 Memory management - * - 0x00000001 Common - * - * For example, in order to enable traces related to OTA DFU, - * one should set this option to 0x00080100. - * - * Note: For general debugging purposes, please use 0x00000C48. - */ -#define CONFIG_ZB_TRACE_MASK 0x0000 - -/** - * Max compiled-in log level for ZBOSS traces - Off - */ -/* #undef CONFIG_ZB_LOG_LEVEL_OFF */ - -/** - * Max compiled-in log level for ZBOSS traces - Error - */ -/* #undef CONFIG_ZB_LOG_LEVEL_ERR */ - -/** - * Max compiled-in log level for ZBOSS traces - Warning - */ -#define CONFIG_ZB_LOG_LEVEL_WRN y - -/** - * Max compiled-in log level for ZBOSS traces - Info - */ -/* #undef CONFIG_ZB_LOG_LEVEL_INF */ - -/** - * Max compiled-in log level for ZBOSS traces - Debug - */ -/* #undef CONFIG_ZB_LOG_LEVEL_DBG */ - -/** - * Off - ZB_TRACE_LOG_LEVEL - */ -#define CONFIG_ZB_TRACE_LOG_LEVEL 2 - -/** - * Initialize and flush logger directly from ZBOSS kernel - */ -/* #undef CONFIG_ZB_ASYNC_TRACE_CONTROL */ - -/** - * Enable UART test commands support - * - * Enable reception of test commands on UART interface - * (enabled in ZBOSS test configs only) - */ -#define CONFIG_ZB_NRF_TRACE_RX_ENABLE y - -/** - * Enable Zigbee test mode and features - */ -#define CONFIG_ZB_TEST_MODE y - -/** - * Enable LEDs abstract for ZBOSS OSIF - */ -#define CONFIG_ZB_USE_LEDS y - -/** - * Enable dimmable LED (PWM) abstract for ZBOSS OSIF - */ -/* #undef CONFIG_ZB_USE_DIMMABLE_LED */ - -/** - * Enable buttons abstract for ZBOSS OSIF - */ -#define CONFIG_ZB_USE_BUTTONS y - -/** - * NVRAM migration - * - * Include procedures to migrate legacy NVRAM structures - */ -#define CONFIG_ZB_NVRAM_ENABLE_VER_MIGRATION y - -/** - * Finding and Binding - * - * Enable finding and binding, as defined in BDB specification - */ -#define CONFIG_ZB_BDB_ENABLE_FINDING_BINDING y - -/** - * Distributed security - * - * Enable forming and joining Zigbee networks with distributed security - */ -#define CONFIG_ZB_DISTRIBUTED_SECURITY_ON y - -/** - * Install codes - * - * Enable commissioning with install codes - */ -#define CONFIG_ZB_SECURITY_INSTALLCODES y - -/** - * Production configuration - * - * Enable production configuration - */ -#define CONFIG_ZB_PRODUCTION_CONFIG y - -/** - * APS user frames - * - * Include API to send raw APS frames - */ -#define CONFIG_ZB_APS_USER_PAYLOAD y - -/** - * NWK security API - * - * Include API to disable NWK security - */ -#define CONFIG_ZB_LOW_SECURITY_MODE y - -/** - * APS fragmentation - * - * Enable APS fragmentation inside ZBOSS - */ -#define CONFIG_ZB_APS_FRAGMENTATION y - -/** - * PAN ID blacklist - * - * Enable PAN ID blacklisting during rejoin - */ -#define CONFIG_ZB_NWK_BLACKLIST y - -/** - * PAN ID blacklist length - */ -#define CONFIG_ZB_NWK_BLACKLIST_SIZE 16 - -/** - * Enable Control4 network support - */ -#define CONFIG_ZB_CONTROL4_NETWORK_SUPPORT y - -/** - * Enable R22 extension for for mutitple MAC interfaces support. - */ -/* #undef CONFIG_ZB_R22_MULTIMAC_MODE */ - -/** - * Enable R22 extension for for mutitple MAC interfaces support. - Enable single-MAC interface support - */ -#define CONFIG_ZB_MAC_INTERFACE_SINGLE y - -/** - * WWAH cluster - * - * Include Works With All Hubs cluster - */ -#define CONFIG_ZB_ZCL_SUPPORT_CLUSTER_WWAH y - -/** - * WWAH cluster - WWAHu client - * - * Include WWAHu cluster client implementation - */ -#define CONFIG_ZB_ZCL_ENABLE_WWAH_CLIENT y - -/** - * WWAH cluster - WWAHu server - * - * Include WWAHu cluster server implementation - */ -#define CONFIG_ZB_ZCL_ENABLE_WWAH_SERVER y - -/** - * WWAHu server - NWK retransmissions - * - * Enable retransmissions on NWK layer - */ -#define CONFIG_ZB_NWK_RETRY_COUNT y - -/** - * WWAHu server - Beacon survey - * - * Enable beacon survey - */ -#define CONFIG_ZB_BEACON_SURVEY y - -/** - * WWAHu server - Parent classification - * - * Enable parent classification - */ -#define CONFIG_ZB_PARENT_CLASSIFICATION y - -/** - * Check for Out Of Memory state - * - * If Zigbee packet buffer pool is in OOM state for a period, specified - * by ZB_OOM_THRESHOLD, then assertion is triggered. - */ -/* #undef CONFIG_ZB_CHECK_OOM_STATUS */ - -/** - * Check for Out Of Memory state - Generate NWK status frame in OOM - * - * Send broadcast frame once OOM state is detected. - */ -/* #undef CONFIG_ZB_SEND_OOM_STATUS */ - -/** - * Touchlink commissioning (experimental) - */ -/* #undef CONFIG_ZB_BDB_TOUCHLINK */ - -/** - * Enable Zigbee MAC features, used by the verification framework - Enable API for sending inter-pan packets at non default channel - */ -#define CONFIG_ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL y - -/** - * Enable Zigbee test mode and features - Enable Zigbee MAC features, used by the verification framework - */ -/* #undef CONFIG_ZB_MAC_TESTING_MODE */ - -/** - * Certification specific behavior - * - * Enable behaviors specific to golden devices used during certification - */ -#define CONFIG_ZB_CERTIFICATION_HACKS y - -/** - * MAC filtering - * - * Enables filtering frames at MAC level, based on device's short or - * long address - */ -#define CONFIG_ZB_LIMIT_VISIBILITY y - -/** - * Groups of test cases to be included - Enable both TH and DUT test cases - */ -#define CONFIG_ZB_TEST_GROUP_ALL y - -/** - * Enable Zigbee test mode and features - Enable Zigbee MAC test mode extensions - */ -/* #undef CONFIG_ZB_TEST_MODE_MAC */ - -/** - * Enable Zigbee test mode and features - Enable Zigbee PRO test mode extensions - */ -#define CONFIG_ZB_TEST_MODE_PRO y - -/** - * Groups of test cases to be included - Enable DUT test cases - */ -/* #undef CONFIG_ZB_TEST_GROUP_ALL_DUT */ - -/** - * Groups of test cases to be included - Enable TH test cases - */ -/* #undef CONFIG_ZB_TEST_GROUP_ALL_TH */ - -/** - * Enable Zigbee test mode and features - Enable Zigbee profile, used by verification framework - */ -#define CONFIG_ZB_TEST_PROFILE y - -/** - * Enable Zigbee test mode and features - Serial console RX timeout - */ -#define CONFIG_ZB_MULTITEST_CONSOLE_SLEEP_TIMEOUT 4000000 - -/** - * Disable TRACE_FILE_ID assert - * - * Disable sanity check for ZB_TRACE_FILE_ID macro definition in each file - */ -#define CONFIG_ZB_DONT_NEED_TRACE_FILE_ID y - -/** - * Use delayed TX feature of the radio driver instead of entering busy loop in GP implementation - * - * While communicating with Green Power device, ZBOSS will wait before issuing - * mcps-data.req using MAC features instead of waiting in a busy loop - */ -#define CONFIG_ZB_MAC_AUTO_DELAY_IN_MAC_GP_SEND y - -/** - * NWK requests with aliases - * - * Enables making NWK requests with aliases (see sec. 3.2.1.1.1) or - * R21 Zigbee PRO specification) - */ -/* #undef CONFIG_ZB_USEALIAS */ - -/** - * Enable MAC duty cycle monitoring - */ -/* #undef CONFIG_ZB_MAC_DUTY_CYCLE_MONITORING */ - -/** - * Enable per-device MAC TX power control - */ -/* #undef CONFIG_ZB_MAC_POWER_CONTROL */ - -/** - * Enable per-channel MAC TX power control - */ -#define CONFIG_ZB_MAC_CONFIGURABLE_TX_POWER y - -/** - * Length of the internal ZBOSS MAC TX queue - * - * The value of NRF_802154_RX_BUFFERS (ZIGBEE_RX_QUEUE_LENGTH in nRF5 SDK) - * should not be greater than ZB_MAC_QUEUE_SIZE. - * If the node is flooded with requests, that require a response to be sent, - * the node should be able to schedule responses for each buffer, - * stored inside MAC LL RX queue. - * The receiver gets disabled only if the MAC LL RX queue is full. - * The TX queue is unable to block incoming requests. - */ -#define CONFIG_ZB_MAC_QUEUE_SIZE 17 - -/** - * Acceptable noise floor (in ED units) to form a network - * - * If the MAC LL layer returns energy higher than this value for a given channel, - * the node will skip this channel after passive channel scan. - */ -#define CONFIG_ZB_NWK_CHANNEL_ACCEPT_LEVEL 200 - -/** - * Enable internal clusters through filters - */ -/* #undef CONFIG_ZB_FILTER_OUT_CLUSTERS */ - -/** - * Enable enhanced beacon support - */ -#define CONFIG_ZB_ENHANCED_BEACON_SUPPORT y - -/** - * Enable joining list support - */ -#define CONFIG_ZB_JOINING_LIST_SUPPORT y - -/** - * PAN ID translation table size - * - * NWK: size of the long-short Pan ID translation table - * - * Must be <= (packet buffer size - sizeof(*discovery_confirm)) / - * sizeof(*network_descriptor) - * That value limits number of Pan IDs visible for device during active scan. - */ -#define CONFIG_ZB_PANID_TABLE_SIZE 28 - -/** - * long addresses compression table size - * - * Size of table used for long addresses compression: 3 bytes of - * manufacturer id. - * - * ZBOSS implements long address compression: 3 bytes of manufacturer - * id are stored in the separate table; reference to manufacturer - * entry is stored in the long address giving 2 bytes economy. - * - * That is an absolute limit of number of manufacturers known to the device. - * - * Note: All that machinery will not work if instead of legal - * manufacturer ids (or illegal, but fixed ids) use random values. - */ -#define CONFIG_ZB_DEV_MANUFACTURER_TABLE_SIZE 32 - -/** - * Packet buffer wait queue size - * - * Size of queue for wait for free packet buffer - * - * Note: To prevent deadlocks ZB_BUF_Q_SIZE must be < ZB_IOBUF_POOL_SIZE/2 - */ -#define CONFIG_ZB_BUF_Q_SIZE 8 - -/** - * ZDO transactions table size - */ -#define CONFIG_ZB_ZDO_TRAN_TABLE_SIZE 16 - -/** - * number of endpoints per APS group table entry - */ -#define CONFIG_ZB_APS_ENDPOINTS_IN_GROUP_TABLE 8 - -/** - * Broadcast transaction record table size - * - * See Zigbee Specification subclause 3.6.5 - */ -#define CONFIG_ZB_NWK_BTR_TABLE_SIZE 16 - -/** - * Broadcast Retransmission table size - */ -#define CONFIG_ZB_NWK_BRR_TABLE_SIZE 16 - -/** - * Number of endpoints - * - * Maximum number of supported endpoints per device - */ -#define CONFIG_ZB_MAX_EP_NUMBER 8 - -/** - * Number of supported APS groups - */ -#define CONFIG_ZB_APS_GROUP_TABLE_SIZE 8 - -/** - * Green Power Sink table size - */ -#define CONFIG_ZB_ZGP_SINK_TBL_SIZE 24 - -/** - * Green Power Proxy table size - */ -#define CONFIG_ZB_ZGP_PROXY_TBL_SIZE 5 - -/** - * Dynamic memory configuration - * - * Enable dynamic memory configuration feature that allows to change memory - * footprint if application uses ZBOSS binaries - */ -#define CONFIG_ZB_CONFIGURABLE_MEM y - -/** - * Dynamic memory configuration - Expected overall network size - */ -#define CONFIG_ZB_CONFIG_OVERALL_NETWORK_SIZE 128 - -/** - * Expected Zigbee traffic intensity - high - */ -#define CONFIG_ZB_CONFIG_HIGH_TRAFFIC y - -/** - * Expected Zigbee traffic intensity - moderate - */ -/* #undef CONFIG_ZB_CONFIG_MODERATE_TRAFFIC */ - -/** - * Expected Zigbee traffic intensity - light - */ -/* #undef CONFIG_ZB_CONFIG_LIGHT_TRAFFIC */ - -/** - * Expected Zigbee application complexity - complex - */ -#define CONFIG_ZB_CONFIG_APPLICATION_COMPLEX y - -/** - * Expected Zigbee application complexity - moderate - */ -/* #undef CONFIG_ZB_CONFIG_APPLICATION_MODERATE */ - -/** - * Expected Zigbee application complexity - simple - */ -/* #undef CONFIG_ZB_CONFIG_APPLICATION_SIMPLE */ - -/** - * Dynamic memory configuration - Source APS binding table size - */ -/* #undef CONFIG_ZB_APS_SRC_BINDING_TABLE_SIZE */ - -/** - * Dynamic memory configuration - Destination APS binding table size - */ -/* #undef CONFIG_ZB_APS_DST_BINDING_TABLE_SIZE */ - -/** - * Dynamic memory configuration - Number of packet buffers - */ -/* #undef CONFIG_ZB_IOBUF_POOL_SIZE */ - -/** - * Dynamic memory configuration - Packet buffer wait queue size - * - * Scheduler callbacks queue size - */ -/* #undef CONFIG_ZB_SCHEDULER_Q_SIZE */ - -#endif /* LIBZBOSS_CONFIG_ED_H__ */ diff --git a/zboss/development/include/osif/libzboss_config.h b/zboss/development/include/osif/libzboss_config.h deleted file mode 100644 index f2033f98ff..0000000000 --- a/zboss/development/include/osif/libzboss_config.h +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef LIBZBOSS_CONFIG_H__ -#define LIBZBOSS_CONFIG_H__ - -/** - * This is an autogenerated file. - * Please use Kconfig to change it. - */ - - -/** - * Include NCP related code in ZBOSS library. - * - * Compile NCP related code in ZBOSS library. - * This enables building NCP architecture with common ZBOSS library. - */ -#define CONFIG_ZB_NCP_MODE y - -/** - * NCP trasnport type - Serial (UART) - */ -#define CONFIG_ZB_NCP_TRANSPORT_TYPE_SERIAL y - -/** - * Enable UART serial interface for ZBOSS CLI - */ -#define CONFIG_ZB_HAVE_SERIAL y - -/** - * Serial (SPI) [UNSUPPORTED] - */ -/* #undef CONFIG_ZB_NCP_TRANSPORT_TYPE_SPI */ - -/** - * Simulator (linux pipe) [UNSUPPORTED] - */ -/* #undef CONFIG_ZB_NCP_TRANSPORT_TYPE_NSNG */ - -/** - * SDK Type (HA, SE, etc.) - Home Automation - */ -#define CONFIG_ZB_SDK_TYPE_HA y - -/** - * SDK Type (HA, SE, etc.) - Smart Energy - */ -/* #undef CONFIG_ZB_SDK_TYPE_SE */ - -/** - * ZB_SDK_TYPE - */ -#define CONFIG_ZB_SDK_TYPE 1 - -/** - * Compiled-in trace mask of ZBOSS stack logs - * - * Selectively enable Zigbee binary trace logs. - * The mask value should be a bitwise OR of values assigned to selected modules. - * - * Available modules are: - * - * - 0x04000000 Reserved - * - 0x02000000 Reserved - * - 0x01000000 Reserved - * - 0x00800000 Reserved - * - 0x00400000 Reserved - * - 0x00200000 Zigbee NCP: transport (LL) - * - 0x00100000 Zigbee NCP: command adapters (HL) - * - 0x00080000 ZCL: Over The Air firmware upgrade - * - 0x00040000 IAS zone device: battery monitoring - * - 0x00020000 Reserved - * - 0x00010000 MAC Lower Layer - * - 0x00008000 MAC layer API calls - * - 0x00004000 Zigbee Green Power - * - 0x00002000 Custom components - * - 0x00001000 Reserved - * - 0x00000800 Application - * - 0x00000400 Reserved - * - 0x00000200 Zigbee Light Link - * - 0x00000100 Zigbee Cluster Library - * - 0x00000080 Security - * - 0x00000040 Zigbee Device Object - * - 0x00000020 Zigbee Smart Energy - * - 0x00000010 Application Support layer - * - 0x00000008 Network layer - * - 0x00000004 MAC layer - * - 0x00000002 Memory management - * - 0x00000001 Common - * - * For example, in order to enable traces related to OTA DFU, - * one should set this option to 0x00080100. - * - * Note: For general debugging purposes, please use 0x00000C48. - */ -#define CONFIG_ZB_TRACE_MASK 0x0000 - -/** - * Max compiled-in log level for ZBOSS traces - Off - */ -/* #undef CONFIG_ZB_LOG_LEVEL_OFF */ - -/** - * Max compiled-in log level for ZBOSS traces - Error - */ -/* #undef CONFIG_ZB_LOG_LEVEL_ERR */ - -/** - * Max compiled-in log level for ZBOSS traces - Warning - */ -#define CONFIG_ZB_LOG_LEVEL_WRN y - -/** - * Max compiled-in log level for ZBOSS traces - Info - */ -/* #undef CONFIG_ZB_LOG_LEVEL_INF */ - -/** - * Max compiled-in log level for ZBOSS traces - Debug - */ -/* #undef CONFIG_ZB_LOG_LEVEL_DBG */ - -/** - * Off - ZB_TRACE_LOG_LEVEL - */ -#define CONFIG_ZB_TRACE_LOG_LEVEL 2 - -/** - * Initialize and flush logger directly from ZBOSS kernel - */ -/* #undef CONFIG_ZB_ASYNC_TRACE_CONTROL */ - -/** - * Enable UART test commands support - * - * Enable reception of test commands on UART interface - * (enabled in ZBOSS test configs only) - */ -#define CONFIG_ZB_NRF_TRACE_RX_ENABLE y - -/** - * Enable Zigbee test mode and features - */ -#define CONFIG_ZB_TEST_MODE y - -/** - * Enable LEDs abstract for ZBOSS OSIF - */ -#define CONFIG_ZB_USE_LEDS y - -/** - * Enable dimmable LED (PWM) abstract for ZBOSS OSIF - */ -/* #undef CONFIG_ZB_USE_DIMMABLE_LED */ - -/** - * Enable buttons abstract for ZBOSS OSIF - */ -#define CONFIG_ZB_USE_BUTTONS y - -/** - * NVRAM migration - * - * Include procedures to migrate legacy NVRAM structures - */ -#define CONFIG_ZB_NVRAM_ENABLE_VER_MIGRATION y - -/** - * Finding and Binding - * - * Enable finding and binding, as defined in BDB specification - */ -#define CONFIG_ZB_BDB_ENABLE_FINDING_BINDING y - -/** - * Distributed security - * - * Enable forming and joining Zigbee networks with distributed security - */ -#define CONFIG_ZB_DISTRIBUTED_SECURITY_ON y - -/** - * Install codes - * - * Enable commissioning with install codes - */ -#define CONFIG_ZB_SECURITY_INSTALLCODES y - -/** - * Production configuration - * - * Enable production configuration - */ -#define CONFIG_ZB_PRODUCTION_CONFIG y - -/** - * APS user frames - * - * Include API to send raw APS frames - */ -#define CONFIG_ZB_APS_USER_PAYLOAD y - -/** - * NWK security API - * - * Include API to disable NWK security - */ -#define CONFIG_ZB_LOW_SECURITY_MODE y - -/** - * APS fragmentation - * - * Enable APS fragmentation inside ZBOSS - */ -#define CONFIG_ZB_APS_FRAGMENTATION y - -/** - * PAN ID blacklist - * - * Enable PAN ID blacklisting during rejoin - */ -#define CONFIG_ZB_NWK_BLACKLIST y - -/** - * PAN ID blacklist length - */ -#define CONFIG_ZB_NWK_BLACKLIST_SIZE 16 - -/** - * Enable Control4 network support - */ -#define CONFIG_ZB_CONTROL4_NETWORK_SUPPORT y - -/** - * Enable R22 extension for for mutitple MAC interfaces support. - */ -/* #undef CONFIG_ZB_R22_MULTIMAC_MODE */ - -/** - * Enable R22 extension for for mutitple MAC interfaces support. - Enable single-MAC interface support - */ -#define CONFIG_ZB_MAC_INTERFACE_SINGLE y - -/** - * WWAH cluster - * - * Include Works With All Hubs cluster - */ -#define CONFIG_ZB_ZCL_SUPPORT_CLUSTER_WWAH y - -/** - * WWAH cluster - WWAHu client - * - * Include WWAHu cluster client implementation - */ -#define CONFIG_ZB_ZCL_ENABLE_WWAH_CLIENT y - -/** - * WWAH cluster - WWAHu server - * - * Include WWAHu cluster server implementation - */ -#define CONFIG_ZB_ZCL_ENABLE_WWAH_SERVER y - -/** - * WWAHu server - NWK retransmissions - * - * Enable retransmissions on NWK layer - */ -#define CONFIG_ZB_NWK_RETRY_COUNT y - -/** - * WWAHu server - Beacon survey - * - * Enable beacon survey - */ -#define CONFIG_ZB_BEACON_SURVEY y - -/** - * WWAHu server - Parent classification - * - * Enable parent classification - */ -#define CONFIG_ZB_PARENT_CLASSIFICATION y - -/** - * Check for Out Of Memory state - * - * If Zigbee packet buffer pool is in OOM state for a period, specified - * by ZB_OOM_THRESHOLD, then assertion is triggered. - */ -/* #undef CONFIG_ZB_CHECK_OOM_STATUS */ - -/** - * Check for Out Of Memory state - Generate NWK status frame in OOM - * - * Send broadcast frame once OOM state is detected. - */ -/* #undef CONFIG_ZB_SEND_OOM_STATUS */ - -/** - * Touchlink commissioning (experimental) - */ -/* #undef CONFIG_ZB_BDB_TOUCHLINK */ - -/** - * Enable Zigbee MAC features, used by the verification framework - Enable API for sending inter-pan packets at non default channel - */ -#define CONFIG_ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL y - -/** - * Enable Zigbee test mode and features - Enable Zigbee MAC features, used by the verification framework - */ -/* #undef CONFIG_ZB_MAC_TESTING_MODE */ - -/** - * Certification specific behavior - * - * Enable behaviors specific to golden devices used during certification - */ -#define CONFIG_ZB_CERTIFICATION_HACKS y - -/** - * MAC filtering - * - * Enables filtering frames at MAC level, based on device's short or - * long address - */ -#define CONFIG_ZB_LIMIT_VISIBILITY y - -/** - * Groups of test cases to be included - Enable both TH and DUT test cases - */ -#define CONFIG_ZB_TEST_GROUP_ALL y - -/** - * Enable Zigbee test mode and features - Enable Zigbee MAC test mode extensions - */ -/* #undef CONFIG_ZB_TEST_MODE_MAC */ - -/** - * Enable Zigbee test mode and features - Enable Zigbee PRO test mode extensions - */ -#define CONFIG_ZB_TEST_MODE_PRO y - -/** - * Groups of test cases to be included - Enable DUT test cases - */ -/* #undef CONFIG_ZB_TEST_GROUP_ALL_DUT */ - -/** - * Groups of test cases to be included - Enable TH test cases - */ -/* #undef CONFIG_ZB_TEST_GROUP_ALL_TH */ - -/** - * Enable Zigbee test mode and features - Enable Zigbee profile, used by verification framework - */ -#define CONFIG_ZB_TEST_PROFILE y - -/** - * Enable Zigbee test mode and features - Serial console RX timeout - */ -#define CONFIG_ZB_MULTITEST_CONSOLE_SLEEP_TIMEOUT 4000000 - -/** - * Disable TRACE_FILE_ID assert - * - * Disable sanity check for ZB_TRACE_FILE_ID macro definition in each file - */ -#define CONFIG_ZB_DONT_NEED_TRACE_FILE_ID y - -/** - * Use delayed TX feature of the radio driver instead of entering busy loop in GP implementation - * - * While communicating with Green Power device, ZBOSS will wait before issuing - * mcps-data.req using MAC features instead of waiting in a busy loop - */ -#define CONFIG_ZB_MAC_AUTO_DELAY_IN_MAC_GP_SEND y - -/** - * NWK requests with aliases - * - * Enables making NWK requests with aliases (see sec. 3.2.1.1.1) or - * R21 Zigbee PRO specification) - */ -/* #undef CONFIG_ZB_USEALIAS */ - -/** - * Enable MAC duty cycle monitoring - */ -/* #undef CONFIG_ZB_MAC_DUTY_CYCLE_MONITORING */ - -/** - * Enable per-device MAC TX power control - */ -/* #undef CONFIG_ZB_MAC_POWER_CONTROL */ - -/** - * Enable per-channel MAC TX power control - */ -#define CONFIG_ZB_MAC_CONFIGURABLE_TX_POWER y - -/** - * Length of the internal ZBOSS MAC TX queue - * - * The value of NRF_802154_RX_BUFFERS (ZIGBEE_RX_QUEUE_LENGTH in nRF5 SDK) - * should not be greater than ZB_MAC_QUEUE_SIZE. - * If the node is flooded with requests, that require a response to be sent, - * the node should be able to schedule responses for each buffer, - * stored inside MAC LL RX queue. - * The receiver gets disabled only if the MAC LL RX queue is full. - * The TX queue is unable to block incoming requests. - */ -#define CONFIG_ZB_MAC_QUEUE_SIZE 17 - -/** - * Acceptable noise floor (in ED units) to form a network - * - * If the MAC LL layer returns energy higher than this value for a given channel, - * the node will skip this channel after passive channel scan. - */ -#define CONFIG_ZB_NWK_CHANNEL_ACCEPT_LEVEL 200 - -/** - * Enable internal clusters through filters - */ -/* #undef CONFIG_ZB_FILTER_OUT_CLUSTERS */ - -/** - * Enable enhanced beacon support - */ -#define CONFIG_ZB_ENHANCED_BEACON_SUPPORT y - -/** - * Enable joining list support - */ -#define CONFIG_ZB_JOINING_LIST_SUPPORT y - -/** - * PAN ID translation table size - * - * NWK: size of the long-short Pan ID translation table - * - * Must be <= (packet buffer size - sizeof(*discovery_confirm)) / - * sizeof(*network_descriptor) - * That value limits number of Pan IDs visible for device during active scan. - */ -#define CONFIG_ZB_PANID_TABLE_SIZE 28 - -/** - * long addresses compression table size - * - * Size of table used for long addresses compression: 3 bytes of - * manufacturer id. - * - * ZBOSS implements long address compression: 3 bytes of manufacturer - * id are stored in the separate table; reference to manufacturer - * entry is stored in the long address giving 2 bytes economy. - * - * That is an absolute limit of number of manufacturers known to the device. - * - * Note: All that machinery will not work if instead of legal - * manufacturer ids (or illegal, but fixed ids) use random values. - */ -#define CONFIG_ZB_DEV_MANUFACTURER_TABLE_SIZE 32 - -/** - * Packet buffer wait queue size - * - * Size of queue for wait for free packet buffer - * - * Note: To prevent deadlocks ZB_BUF_Q_SIZE must be < ZB_IOBUF_POOL_SIZE/2 - */ -#define CONFIG_ZB_BUF_Q_SIZE 8 - -/** - * ZDO transactions table size - */ -#define CONFIG_ZB_ZDO_TRAN_TABLE_SIZE 16 - -/** - * number of endpoints per APS group table entry - */ -#define CONFIG_ZB_APS_ENDPOINTS_IN_GROUP_TABLE 8 - -/** - * Broadcast transaction record table size - * - * See Zigbee Specification subclause 3.6.5 - */ -#define CONFIG_ZB_NWK_BTR_TABLE_SIZE 16 - -/** - * Broadcast Retransmission table size - */ -#define CONFIG_ZB_NWK_BRR_TABLE_SIZE 16 - -/** - * Number of endpoints - * - * Maximum number of supported endpoints per device - */ -#define CONFIG_ZB_MAX_EP_NUMBER 8 - -/** - * Number of supported APS groups - */ -#define CONFIG_ZB_APS_GROUP_TABLE_SIZE 16 - -/** - * Green Power Sink table size - */ -#define CONFIG_ZB_ZGP_SINK_TBL_SIZE 24 - -/** - * Green Power Proxy table size - */ -#define CONFIG_ZB_ZGP_PROXY_TBL_SIZE 5 - -/** - * Dynamic memory configuration - * - * Enable dynamic memory configuration feature that allows to change memory - * footprint if application uses ZBOSS binaries - */ -#define CONFIG_ZB_CONFIGURABLE_MEM y - -/** - * Dynamic memory configuration - Expected overall network size - */ -#define CONFIG_ZB_CONFIG_OVERALL_NETWORK_SIZE 128 - -/** - * Expected Zigbee traffic intensity - high - */ -#define CONFIG_ZB_CONFIG_HIGH_TRAFFIC y - -/** - * Expected Zigbee traffic intensity - moderate - */ -/* #undef CONFIG_ZB_CONFIG_MODERATE_TRAFFIC */ - -/** - * Expected Zigbee traffic intensity - light - */ -/* #undef CONFIG_ZB_CONFIG_LIGHT_TRAFFIC */ - -/** - * Expected Zigbee application complexity - complex - */ -#define CONFIG_ZB_CONFIG_APPLICATION_COMPLEX y - -/** - * Expected Zigbee application complexity - moderate - */ -/* #undef CONFIG_ZB_CONFIG_APPLICATION_MODERATE */ - -/** - * Expected Zigbee application complexity - simple - */ -/* #undef CONFIG_ZB_CONFIG_APPLICATION_SIMPLE */ - -/** - * Dynamic memory configuration - Source APS binding table size - */ -/* #undef CONFIG_ZB_APS_SRC_BINDING_TABLE_SIZE */ - -/** - * Dynamic memory configuration - Destination APS binding table size - */ -/* #undef CONFIG_ZB_APS_DST_BINDING_TABLE_SIZE */ - -/** - * Dynamic memory configuration - Number of packet buffers - */ -/* #undef CONFIG_ZB_IOBUF_POOL_SIZE */ - -/** - * Dynamic memory configuration - Packet buffer wait queue size - * - * Scheduler callbacks queue size - */ -/* #undef CONFIG_ZB_SCHEDULER_Q_SIZE */ - -#endif /* LIBZBOSS_CONFIG_H__ */ diff --git a/zboss/development/include/osif/mac_platform.h b/zboss/development/include/osif/mac_platform.h deleted file mode 100644 index 78228a5b04..0000000000 --- a/zboss/development/include/osif/mac_platform.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -/* PURPOSE: MAC platform definitions for nRF SoC. -*/ - -#ifndef ZB_MAC_PLATFORM_H__ -#define ZB_MAC_PLATFORM_H__ - -#include "zb_macll.h" - - -#define ZB_MAC_HARDWARE_PB_MATCHING -#define ZB_MAC_MANUAL_DUPS -#define ZB_MAC_SINGLE_PACKET_IN_FIFO -#define ZB_OPTIONAL_MAC_FEATURES - -#define ZB_MAC_PENDING_BIT_SOURCE_MATCHING -#define ZB_AUTO_ACK_TX -#define ZB_MAC_AUTO_ACK_RECV -#define ZB_MANUAL_ACK -#define ZB_MANUAL_ACK_TIMEOUT -#define MAC_ACK_PARSE_BY_INTR - -/* gpTxOffset should be calibrated for each HW/SW variant. - * The reason is that ZB_GPD_TX_OFFSET_US is used from ZGP stub during Green Power frame transmitting, - * and the actual TX time is not known at this level due to delays of MAC layer or transceiver. - */ -#define ZB_GPD_TX_OFFSET_US (ZB_MILLISECONDS_TO_USEC(ZB_GPD_RX_OFFSET_MS)) -#define MAC_AUTO_GPDF_RETX - -#define MAC_TIMER_QUANT_US 4 - -#define ZB_TRANSCEIVER_START_CHANNEL_NUMBER 11 -#define ZB_TRANSCEIVER_MAX_CHANNEL_NUMBER 26 -#ifndef ZB_TRANSCEIVER_ALL_CHANNELS_MASK -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK 0x07FFF800 /* 0000.0111 1111.1111 1111.1000 0000.0000*/ -#endif /* ZB_TRANSCEIVER_ALL_CHANNELS_MASK */ - - -/* Type definition required by ZBOSS transceiver API */ -typedef struct zb_transceiver_ctx_s -{ - zb_uint_t tx_status; // Required and modified by zb_mac.c -} -zb_transceiver_ctx_t; - - - -/** - Tail size for mac packet -*/ -#define ZB_TAIL_SIZE_FOR_RECEIVED_MAC_FRAME (ZB_MAC_EXTRA_DATA_SIZE) /* 2 */ - -/** - Definitions for extra information size in RX fifo packet. Packet format: - 1 byte packet length + N bytes of RX fifo data + M bytes of extra information - (LQI, RSSI, at some platforms Frame timer, Superframe counter etc) -*/ -#define ZB_MAC_PACKET_LENGTH_SIZE ZB_MACLL_PACKET_LENGTH_SIZE -#define ZB_MAC_EXTRA_DATA_SIZE ZB_MACLL_EXTRA_DATA_SIZE /* rssi & lqi - see zb_macll_metadata_t */ - -#define ZB_TRANSCEIVER_INIT_RADIO() -#define ZB_TRANSCEIVER_DEINIT_RADIO() - -/* According to BZ#14383 and J#ZB-72 this workaround is not needed, if it is needed to put - * transceiver in idle it should be done automatically in the MAC logic. */ -#define ZB_MAC_TRANSCEIVER_GO_IDLE() /* not needed */ -#define ZB_MAC_TRANSCEIVER_RESTORE() /* not needed */ -#define ZB_TRANSCEIVER_RADIO_ON_OFF() zb_macll_get_radio_on_off() - -#define zb_mac_transport_init zb_macll_init -#define ZB_RADIO_INT_DISABLE() ZB_OSIF_GLOBAL_LOCK() -#define ZB_RADIO_INT_ENABLE() ZB_OSIF_GLOBAL_UNLOCK() -#define ZB_IS_TRANSPORT_BUSY() ZB_MAC_GET_TRANS_INT_FLAG() - -#define ZB_MAC_SET_TRANS_INT() zb_macll_set_trans_int() -#define ZB_MAC_CLEAR_TRANS_INT() zb_macll_clear_trans_int() -#define ZB_MAC_GET_TRANS_INT_FLAG() zb_macll_get_trans_int() - -#define ZB_MAC_SET_RX_INT_STATUS_BIT() zb_macll_set_rx_flag() -#define ZB_MAC_CLEAR_RX_INT_STATUS_BIT() zb_macll_clear_rx_flag() -#define ZB_MAC_GET_RX_INT_STATUS_BIT() zb_macll_get_rx_flag() - -#define ZB_MAC_SET_TX_INT_STATUS_BIT() zb_macll_set_tx_flag() -#define ZB_MAC_CLEAR_TX_INT_STATUS_BIT() (zb_macll_clear_tx_flag(), ZB_TRANS_SET_TX_STATUS(0)) -#define ZB_MAC_GET_TX_INT_STATUS_BIT() zb_macll_get_tx_flag() - -#define ZB_MAC_READ_INT_STATUS_REG() /* already done by int handler */ - -#define ZB_TRANS_SET_TX_STATUS(status) (TRANS_CTX().tx_status = (status)) -#define ZB_TRANS_CHECK_CHANNEL_BUSY_ERROR() (TRANS_CTX().tx_status == ZB_TRANS_CHANNEL_BUSY_ERROR) -#define ZB_TRANS_CHECK_TX_RETRY_COUNT_EXCEEDED_ERROR() 0 -#define ZB_TRANS_CHECK_NO_ACK() (TRANS_CTX().tx_status == ZB_TRANS_NO_ACK) - -#define ZB_TRANSCEIVER_SET_COORD_SHORT_ADDR(addr) -#define ZB_TRANSCEIVER_SET_COORD_EXT_ADDR(addr) - -#define ZB_TRANSCEIVER_SET_PAN_COORDINATOR(pan_coord) zb_macll_set_pan_coord((zb_bool_t)pan_coord) - - -#ifdef ZB_MAC_HARDWARE_PB_MATCHING - -/* MAC source matching logic implemented in radio-driver v1.6.0: - * 1) Add device address in the driver's pending table if there is no indirect data for it (clear pending bit); - * 2) Remove device address from he driver's pending table if there is an indirect data for it (set pending bit); -*/ - -#define ZB_TRANSCEIVER_SRC_MATCH_SHORT_SET_PENDING_BIT(short_addr, value) \ - zb_macll_src_match_set_pending_bit((zb_uint8_t *)&(short_addr), (zb_bool_t)(value), ZB_FALSE) - -#define ZB_TRANSCEIVER_SRC_MATCH_ADD_SHORT_ADDR(index, short_addr) \ - zb_macll_src_match_set_pending_bit((zb_uint8_t *)&(short_addr), ZB_FALSE, ZB_FALSE) - -#define ZB_TRANSCEIVER_SRC_MATCH_DELETE_SHORT_ADDR(index, short_addr) \ - zb_macll_src_match_set_pending_bit((zb_uint8_t *)&(short_addr), ZB_TRUE, ZB_FALSE) - -#define ZB_TRANSCEIVER_SRC_MATCH_IEEE_SET_PENDING_BIT(ieee_addr, value) \ - zb_macll_src_match_set_pending_bit((zb_uint8_t *)(ieee_addr), (zb_bool_t)(value), ZB_TRUE) - -#define ZB_TRANSCEIVER_SRC_MATCH_ADD_IEEE_ADDR(index, ieee_addr) \ - zb_macll_src_match_set_pending_bit((zb_uint8_t *)(ieee_addr), ZB_FALSE, ZB_TRUE) - -#define ZB_TRANSCEIVER_SRC_MATCH_DELETE_IEEE_ADDR(index, ieee_addr) \ - zb_macll_src_match_set_pending_bit((zb_uint8_t *)(ieee_addr), ZB_TRUE, ZB_TRUE) - -#define ZB_TRANSCEIVER_SRC_MATCH_TBL_DROP() zb_macll_src_match_tbl_drop() - - -#else /* !ZB_MAC_HARDWARE_PB_MATCHING */ -#error Only one Pending Bit handling method is supported. - -#endif /* !ZB_MAC_HARDWARE_PB_MATCHING */ - - -#define ZB_TRANSCEIVER_SET_SHORT_ADDR(addr) zb_macll_set_short_addr(addr) -#define ZB_TRANSCEIVER_UPDATE_SHORT_ADDR() ZB_TRANSCEIVER_SET_SHORT_ADDR(MAC_PIB().mac_short_address) - -#define ZB_TRANSCEIVER_SET_PAN_ID(pan_id) zb_macll_set_pan_id(pan_id) -#define ZB_TRANSCEIVER_UPDATE_PAN_ID() ZB_TRANSCEIVER_SET_PAN_ID(MAC_PIB().mac_pan_id) - -#define ZB_TRANSCEIVER_SET_LONGMAC(long_mac) zb_macll_set_long_addr(long_mac) -#define ZB_TRANSCEIVER_UPDATE_LONGMAC() ZB_TRANSCEIVER_SET_LONGMAC((zb_uint8_t *)ZB_PIB_EXTENDED_ADDRESS()) - - -#define ZB_TRANS_SEND_FRAME(header_length, buf, wait_type) \ - { \ - ZB_DUMP_OUTGOING_DATA(buf); \ - (void)header_length; \ - zb_macll_send_packet((buf), (wait_type)); \ - } - -#define ZB_TRANS_REPEAT_SEND_FRAME(header_length, buf, wait_type) \ - (ZB_DUMP_OUTGOING_DATA(buf), \ - (void)header_length, zb_macll_resend_packet(wait_type, 0)) - -#define ZB_TRANS_GET_TX_TIMESTAMP() zb_macll_get_tx_timestamp() - -#ifdef MAC_RADIO_TX_WATCHDOG_ALARM -#error Not implemented feature -#define ZB_MAC_TX_ABORT() -#endif - - -#define ZB_TRANSCEIVER_SET_PROMISCUOUS(promiscuous_mode) - -#define ZB_TRANSCEIVER_SET_CHANNEL(page, channel_number) zb_macll_set_channel(channel_number) - -#define ZB_TRANSCEIVER_START_GET_RSSI(_scan_duration_bi) zb_macll_start_get_rssi(_scan_duration_bi); -#define ZB_TRANSCEIVER_GET_RSSI(rssi_value) zb_macll_get_rssi(rssi_value) -#define ZB_TRANSCEIVER_GET_ENERGY_LEVEL(ed_level) ZB_TRANSCEIVER_GET_RSSI(ed_level) - -#define ZB_TRANSCEIVER_SET_RX_ON_OFF(_rx_on) zb_macll_trans_set_rx_on_off(_rx_on) -#define ZB_TRANSCEIVER_GET_RX_ON_OFF() zb_macll_get_rx_on_off() - -#define ZB_TRANS_RECV_PACKET(buf) zb_macll_get_next_packet(buf) -#define ZB_MAC_TRANS_CLEAR_PENDING_BIT() -#define ZB_MAC_TRANS_SET_PENDING_BIT() - -/** - Get LQI value - @param packet - pointer to buffer -*/ -#define ZB_MAC_GET_LQI(packet) zb_macll_metadata_get_lqi(packet) - -/** - Set LQI value - @param packet - pointer to buffer - @param v - LQI value -*/ -#define ZB_MAC_SET_LQI(packet, v) zb_macll_metadata_set_lqi(packet, v) - -/** - Get RSSI value - @param packet - pointer to buffer -*/ -#define ZB_MAC_GET_RSSI(packet) zb_macll_metadata_get_power(packet) - -/** - Set RSSI value - @param packet - pointer to buffer - @param v - RSSI value -*/ -#define ZB_MAC_SET_RSSI(packet, v) zb_macll_metadata_set_power(packet, v) - - -/*PHY tests specific API. Implement for PHY tests only.*/ -#define ZB_TRANSCEIVER_PERFORM_CCA(rssi) zb_macll_cca(rssi) -#define ZB_TRANS_TX_CARRIER_DATA(channel, timeout_bi) zb_macll_tx_carrier(channel, timeout_bi) - -#define ZB_TRANSCEIVER_SET_TX_POWER(new_power) zb_macll_set_tx_power(new_power) -#define ZB_TRANSCEIVER_GET_TX_POWER(power) zb_macll_get_tx_power(power) - -/** - Cut transceiver-specific header (length byte) -*/ -#define ZB_TRANS_CUT_SPECIFIC_HEADER(zb_buffer) - - -#endif /* ZB_MAC_PLATFORM_H__ */ diff --git a/zboss/development/include/osif/zb_config_platform.h b/zboss/development/include/osif/zb_config_platform.h deleted file mode 100644 index 39bd78a86b..0000000000 --- a/zboss/development/include/osif/zb_config_platform.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -/* PURPOSE: Compiler and CPU specific configuration. -*/ - -#ifndef ZB_CONFIG_PLATFORM_H__ -#define ZB_CONFIG_PLATFORM_H__ - -#include /* memcpy */ -#include - - -#ifdef __IAR_SYSTEMS_ICC__ -#ifndef ZB_IAR -#define ZB_IAR -#endif -#endif - -/* The MAIN() macro is meant to be used only by applications and tests implemented within ZBOSS source code repository. */ -#define MAIN() int zboss_app_main(void) -#define FAKE_ARGV -#define ARGV_UNUSED -#define MAIN_RETURN(v) return (v) - -#ifdef KEIL -#define ZB_MEMCPY(dst, src, size) memcpy((void*)(dst), (void*)(src), (size)) -#define ZB_MEMSET(dst, val, size) memset((void*)(dst), (val), (size)) -#define ZB_MEMMOVE(dst, src, size) memmove((void*)(dst), (void*)(src), (size)) -#define ZB_MEMCMP(ptr1, ptr2, size) memcmp((void*)(ptr1), (void*)(ptr2), (size)) - -#else /* KEIL */ -#define ZB_MEMCPY memcpy -#define ZB_MEMSET memset -#define ZB_MEMMOVE memmove -#define ZB_MEMCMP memcmp -#endif /* KEIL */ - - -/* Enable default parameters, specific for nRF52 platform. */ -#define ZB_CONFIG_NRF52 -#define ZB_PLATFORM_NRF52 - -#define ZB_LITTLE_ENDIAN -#define ZB_NEED_ALIGN -#define ZB_VOLATILE -#define ZB_CALLBACK -#define ZB_SDCC_BANKED -#define ZB_KEIL_REENTRANT - -#define ZB_BZERO(s,l) ZB_MEMSET((char*)(s), 0, (l)) -#define ZB_BZERO2(s) ZB_BZERO(s, 2) -#define ZVUNUSED(v) (void)v - - -/* At ARM all types from 1 to 4 bytes are passed to vararg with casting to 4 bytes */ -typedef uint32_t zb_minimal_vararg_t; - -#endif /* ZB_CONFIG_PLATFORM_H__ */ diff --git a/zboss/development/include/osif/zb_macll.h b/zboss/development/include/osif/zb_macll.h deleted file mode 100644 index 5455a8470c..0000000000 --- a/zboss/development/include/osif/zb_macll.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_MACLL_H__ -#define ZB_MACLL_H__ - -#include -#include "zb_transceiver.h" - -/** The number of metadata bytes, attached to each received frame, - * at the end of ZBOSS buffer. - */ -#define ZB_MACLL_EXTRA_DATA_SIZE sizeof(zb_macll_metadata_t) - -/** The number of bytes used to pass the frame length field, - * at the beginning of ZBOSS buffer. - */ -#define ZB_MACLL_PACKET_LENGTH_SIZE 1 - -/** - Get a reference to MAC LL specific metadata structure. - @param packet - pointer to buffer -*/ -#define ZB_MACLL_GET_METADATA(packet) ((zb_macll_metadata_t *)((zb_uint8_t*)zb_buf_end(packet) - ZB_MACLL_EXTRA_DATA_SIZE)) - -/** Status code indicating that the received Data frame - * was not acknowledged with a pending bit set (indirect poll). - * - * That status should not be set directly by the transceiver implementation, - * but the zb_macll_set_received_data_status(..) API should be used. - */ -#define ZB_MACLL_NO_DATA 0xeb - - -/** Structure attached to each ZBOSS buffer used to pass additional metadata. */ -typedef struct -{ - uint8_t lqi; - int8_t power; -} ZB_PACKED_STRUCT zb_macll_metadata_t; - - -void zb_macll_init(void); - -#define zb_macll_set_trans_int() /* Transceiver interrupt is a logical or of the TX and RX interrupt flag. */ -#define zb_macll_clear_trans_int() /* Transceiver interrupt is a logical or of the TX and RX interrupt flag. */ -#define zb_macll_get_trans_int() (zb_macll_get_rx_flag() || zb_macll_get_tx_flag()) - -#define zb_macll_set_rx_flag() /* Implemented through reading RX status via zb_trans_rx_pending(). */ -#define zb_macll_clear_rx_flag() /* Implemented through reading RX status via zb_trans_rx_pending(). */ -#define zb_macll_get_rx_flag zb_trans_rx_pending - -void zb_macll_set_tx_flag(void); -void zb_macll_clear_tx_flag(void); -zb_bool_t zb_macll_get_tx_flag(void); - -zb_uint8_t zb_macll_src_match_set_pending_bit(zb_uint8_t *addr, zb_bool_t value, zb_bool_t extended); -#define zb_macll_src_match_tbl_drop zb_trans_src_match_tbl_drop - -#define zb_macll_set_short_addr zb_trans_set_short_addr -#define zb_macll_set_long_addr zb_trans_set_long_addr -#define zb_macll_set_pan_id zb_trans_set_pan_id -#define zb_macll_set_pan_coord zb_trans_set_pan_coord - -#define zb_macll_get_radio_on_off zb_trans_is_active -#define zb_macll_set_tx_power zb_trans_set_tx_power -#define zb_macll_get_tx_power zb_trans_get_tx_power -#define zb_macll_set_channel zb_trans_set_channel -#define zb_macll_start_get_rssi zb_trans_start_get_rssi -#define zb_macll_get_rssi zb_trans_get_rssi - -void zb_macll_send_packet(zb_bufid_t buf, zb_uint8_t wait_type); -void zb_macll_resend_packet(zb_uint8_t wait_type, zb_time_t tx_at); -zb_time_t zb_macll_get_tx_timestamp(void); - -void zb_macll_transmitted_raw(zb_uint8_t * p_ack); -void zb_macll_transmit_failed(zb_uint8_t error); - -void zb_macll_trans_set_rx_on_off(int rx_on); -#define zb_macll_get_rx_on_off zb_trans_is_receiving -/**@brief Pass to MAC data packet already read by radio driver layer. - * - * @param buf - ZBOSS buffer - placeholder for incoming data. - * - * @retval[0] No packets available. - * @retval[1] New packet copied to the buf. - */ -#define zb_macll_get_next_packet zb_trans_get_next_packet - -int8_t zb_macll_metadata_get_power(zb_bufid_t bufid); -void zb_macll_metadata_set_power(zb_bufid_t bufid, int8_t power); -uint8_t zb_macll_metadata_get_lqi(zb_bufid_t bufid); -void zb_macll_metadata_set_lqi(zb_bufid_t bufid, uint8_t lqi); -void zb_macll_set_received_data_status(zb_bufid_t bufid, zb_bool_t pending_bit); - -zb_ret_t zb_macll_tx_carrier(zb_uint8_t channel, zb_time_t timeout_bi); - -#endif /* ZB_MACLL_H__ */ diff --git a/zboss/development/include/osif/zb_osif_ext.h b/zboss/development/include/osif/zb_osif_ext.h deleted file mode 100644 index 0afaea8853..0000000000 --- a/zboss/development/include/osif/zb_osif_ext.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -/* PURPOSE: ZBOSS OSIF extensions/adaption layer for nRF Connect SDK -*/ - -#ifndef ZB_OSIF_EXT_H -#define ZB_OSIF_EXT_H 1 - -#include "zboss_api.h" - -/** Increase ZBOSS timer value. */ -void zb_osif_zboss_timer_tick(void); - -/** Filter out NVRAM datasets, handled by NCP host. */ -void zb_osif_ncp_set_nvram_filter(void); - -#endif /* ZB_OSIF_EXT_H */ diff --git a/zboss/development/include/osif/zb_osif_platform.h b/zboss/development/include/osif/zb_osif_platform.h deleted file mode 100644 index b5310d976b..0000000000 --- a/zboss/development/include/osif/zb_osif_platform.h +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -/* PURPOSE: Header to combine osif dependent files with stack -*/ - -#ifndef ZB_OSIF_PLATFORM_H__ -#define ZB_OSIF_PLATFORM_H__ - -#define ZB_INTERRUPT_SAFE_CALLBACKS -#define ZB_USE_NVRAM -#define ZB_NVRAM_RADIO_OFF_DURING_TRANSACTION - -/* trace */ -#define ZB_NRF_TRACE - -#ifdef ZB_TRACE_LEVEL -#define ZB_TRACE_OVER_USART -#define ZB_TRACE_TO_PORT -#define ZB_BINARY_TRACE -#define ZB_TRAFFIC_DUMP_ON -#define ZB_TRAF_DUMP_V2 -#endif /* ZB_TRACE_LEVEL */ - -#if defined ZB_TRACE_OVER_USART && defined ZB_TRACE_LEVEL -#define ZB_SERIAL_FOR_TRACE -#endif /* ZB_TRACE_OVER_USART && ZB_TRACE_LEVEL */ - -#ifdef ZB_SERIAL_FOR_TRACE -void zb_osif_serial_flush(void); -#if defined(ZB_NRF_TRACE) && (defined CONFIG_ZB_ASYNC_TRACE_CONTROL || defined ZB_MULTI_TEST) -#define ZB_OSIF_SERIAL_FLUSH() zb_osif_serial_flush() -#elif !defined(ZBOSS_BUILD) -#define ZB_OSIF_SERIAL_FLUSH() zb_osif_serial_flush() -#else /* ZB_NRF_TRACE && (CONFIG_ZB_ASYNC_TRACE_CONTROL || defined ZB_MULTI_TEST) */ -#define ZB_OSIF_SERIAL_FLUSH() -#endif /* ZB_NRF_TRACE && (CONFIG_ZB_ASYNC_TRACE_CONTROL || defined ZB_MULTI_TEST) */ -#else /* ZB_SERIAL_FOR_TRACE */ -#define ZB_OSIF_SERIAL_FLUSH() -#endif /* ZB_SERIAL_FOR_TRACE */ - - -#define ZB_SOFT_SECURITY -#define ZB_HW_ZB_AES128 - -#ifdef ZB_HW_ZB_AES128 -void zb_osif_aes128_hw_encrypt(zb_uint8_t *key, zb_uint8_t *msg, zb_uint8_t *c); -#define hw_aes128 zb_osif_aes128_hw_encrypt -#endif /* ZB_HW_ZB_AES128 */ - - -void zb_osif_init(void); -#define ZB_PLATFORM_INIT() zb_osif_init() - -void zb_osif_abort(void); -#define ZB_ABORT zb_osif_abort - -#define ZB_GO_IDLE() - -/* Read the NCP firmware version. This function may be redefined by the application. */ -zb_uint32_t zb_osif_get_fw_version(void); -#define NCP_FW_VERSION zb_osif_get_fw_version() - -/* Read the ZBOSS stack version in NCP firmware. This value is defined in zb_vendor.h. */ -#define NCP_STACK_VERSION ZB_STACK_VERSION - -/* Read the NCP protocol version. This function may be redefined by the application. */ -zb_uint32_t zb_osif_get_ncp_protocol_version(void); -#define NCP_PROTOCOL_VERSION zb_osif_get_ncp_protocol_version() - - -void zb_osif_timer_init(void); -zb_uint32_t zb_osif_timer_get(void); - -void zb_osif_timer_stop(void); -#define ZB_STOP_HW_TIMER() zb_osif_timer_stop() - -void zb_osif_timer_start(void); -#define ZB_START_HW_TIMER() zb_osif_timer_start() - -zb_bool_t zb_osif_timer_is_on(void); -#define ZB_CHECK_TIMER_IS_ON() zb_osif_timer_is_on() - - -void zb_osif_enable_all_inter(void); -void zb_osif_disable_all_inter(void); - -/* Redefine ZBOSS scheduler API only inside Zephyr application. */ -#ifndef ZBOSS_BUILD -#define ZB_SCHEDULE_APP_CALLBACK(func, param) \ - zigbee_schedule_callback(func, param) - -#define ZB_SCHEDULE_APP_CALLBACK2(func, param, user_param) \ - zigbee_schedule_callback2(func, param, user_param) - -#define ZB_SCHEDULE_APP_ALARM(func, param, timeout_bi) \ - zigbee_schedule_alarm(func, param, timeout_bi) - -#define ZB_SCHEDULE_APP_ALARM_CANCEL(func, param) \ - zigbee_schedule_alarm_cancel(func, param) - -#define zb_buf_get_out_delayed(func) \ - zigbee_get_out_buf_delayed(func) - -#define zb_buf_get_in_delayed(func) \ - zigbee_get_in_buf_delayed(func) - -#define zb_buf_get_out_delayed_ext(func, param, max_size) \ - zigbee_get_out_buf_delayed_ext(func, param, max_size) - -#define zb_buf_get_in_delayed_ext(func, param, max_size) \ - zigbee_get_in_buf_delayed_ext(func, param, max_size) - -/**@brief Schedule single-param callback execution. - * - * This API is thread- and ISR- safe. - * It performs all necessary actions: - * - Forwards request from ISR to thread context - * - Schedules the callback in ZBOSS scheduler queue - * - Wakes up the Zigbee task. - * - * @param func function to execute - * @param param - callback parameter - usually ref to packet buffer - * - * @return RET_OK or RET_OVERFLOW. - */ -zb_ret_t zigbee_schedule_callback(zb_callback_t func, zb_uint8_t param); - -/**@brief Schedule two-param callback execution. - * - * This API is thread- and ISR- safe. - * It performs all necessary actions: - * - Forwards request from ISR to thread context - * - Schedules the callback in ZBOSS scheduler queue - * - Wakes up the Zigbee task. - * - * @param func function to execute - * @param param zb_uint8_t callback parameter - usually, - * ref to packet buffer - * @param user_param zb_uint16_t additional user parameter - * - * @return RET_OK or RET_OVERFLOW. - */ -zb_ret_t zigbee_schedule_callback2(zb_callback2_t func, zb_uint8_t param, - zb_uint16_t user_param); - - -/**@brief Schedule alarm - callback to be executed after timeout. - * - * Function will be called via scheduler after timeout expired, with possible - * delays due to locking/unlocking and scheduling mechanism. - * Timer resolution depends on implementation and is limited to a single - * Beacon Interval (15.36 msec). - * Same callback can be scheduled for execution more then once. - * - * This API is thread- and ISR- safe. - * It performs all necessary actions: - * - Forwards request from ISR to thread context - * - Schedules the callback in ZBOSS scheduler queue - * - Wakes up the Zigbee task. - * - * @param func function to call via scheduler - * @param param parameter to pass to the function - * @param timeout_bi timeout, in beacon intervals - * - * @return RET_OK or RET_OVERFLOW - */ -zb_ret_t zigbee_schedule_alarm(zb_callback_t func, zb_uint8_t param, - zb_time_t run_after); - -/**@brief Cancel previously scheduler alarm. - * - * This API cancels alarms scheduled via zigbee_schedule_alarm() API - * - * This API is thread- and ISR- safe. - * It performs all necessary actions: - * - Forwards request from ISR to thread context - * - Schedules the callback in ZBOSS scheduler queue - * - Wakes up the Zigbee task. - * - * @param func - function to call via scheduler - * @param param - parameter to pass to the function - * - * @return RET_OK or RET_OVERFLOW - */ -zb_ret_t zigbee_schedule_alarm_cancel(zb_callback_t func, zb_uint8_t param); - -/**@brief Allocate OUT buffer, call a callback when the buffer is available. - * - * Use default buffer size _func(alloc single standard buffer). - * If buffer is available, schedules callback for execution immediately. - * If no buffers are available now, schedule callback later, - * when buffer will be available. - * - * This API is thread- and ISR- safe. - * It performs all necessary actions: - * - Forwards request from ISR to thread context - * - Schedules the callback in ZBOSS scheduler queue - * - Wakes up the Zigbee task. - * - * @param func - function to execute. - * @return RET_OK or RET_OVERFLOW - */ -zb_ret_t zigbee_get_out_buf_delayed(zb_callback_t func); - -/**@brief Allocate IN buffer, call a callback when the buffer is available. - * - * Use default buffer size _func(alloc single standard buffer). - * If buffer is available, schedules callback for execution immediately. - * If no buffers are available now, schedule callback later, - * when buffer will be available. - * - * This API is thread- and ISR- safe. - * It performs all necessary actions: - * - Forwards request from ISR to thread context - * - Schedules the callback in ZBOSS scheduler queue - * - Wakes up the Zigbee task. - * - * @param func - function to execute. - * @return RET_OK or RET_OVERFLOW - */ -zb_ret_t zigbee_get_in_buf_delayed(zb_callback_t func); - -/**@brief Allocate OUT buffer, call a callback when the buffer is available. - * - * If buffer is available, schedules callback for execution immediately. - * If no buffers are available now, schedule callback later, - * when buffer will be available. - * - * This API is thread- and ISR- safe. - * It performs all necessary actions: - * - Forwards request from ISR to thread context - * - Schedules the callback in ZBOSS scheduler queue - * - Wakes up the Zigbee task. - * - * @param func function to execute. - * @param param second parameter to pass to the function - * @param max_size required maximum buffer payload size (in bytes). - * It can be bigger or smaller than the default buffer size. - * Depending on the specific value, the buffer pool may decide - * to use a fraction of buffer or long buffers. - * Special value 0 means "single default buffer". - * @return RET_OK or RET_OVERFLOW - */ -zb_ret_t zigbee_get_out_buf_delayed_ext(zb_callback2_t func, zb_uint16_t param, - zb_uint16_t max_size); - -/**@brief Allocate IN buffer, call a callback when the buffer is available. - * - * If buffer is available, schedules callback for execution immediately. - * If no buffers are available now, schedule callback later, - * when buffer will be available. - * - * @param func function to execute. - * @param param second parameter to pass to the function - * @param max_size required maximum buffer payload size (in bytes). - * It can be bigger or smaller than the default buffer size. - * Depending on the specific value, the buffer pool may decide - * to use a fraction of buffer or long buffers. - * Special value 0 means "single default buffer". - * @return RET_OK or error code. - */ -zb_ret_t zigbee_get_in_buf_delayed_ext(zb_callback2_t func, zb_uint16_t param, - zb_uint16_t max_size); - -#endif /* ZBOSS_BUILD */ - -#ifdef ZB_STACK_REGRESSION_TESTING_API - -#define ZB_ENABLE_ALL_INTER() \ - ZB_REGRESSION_TESTS_API().osif_interrupts_balance++; \ - zb_osif_enable_all_inter() -#define ZB_DISABLE_ALL_INTER() \ - ZB_REGRESSION_TESTS_API().osif_interrupts_balance--; \ - zb_osif_disable_all_inter() - -#else /* ZB_STACK_REGRESSION_TESTING_API */ - -#define ZB_ENABLE_ALL_INTER() zb_osif_enable_all_inter() -#define ZB_DISABLE_ALL_INTER() zb_osif_disable_all_inter() - -#endif /* ZB_STACK_REGRESSION_TESTING_API */ - -#define ZB_OSIF_GLOBAL_LOCK() ZB_DISABLE_ALL_INTER() -#define ZB_OSIF_GLOBAL_UNLOCK() ZB_ENABLE_ALL_INTER() - - -#ifdef ZB_USE_SLEEP -void zb_osif_sleep_init(void); -zb_uint32_t zb_osif_sleep(zb_uint32_t sleep_tmo); -zb_bool_t zb_osif_is_sleeping(void); -#endif /* ZB_USE_SLEEP */ - - - -#ifdef ZB_MACSPLIT_TRANSPORT_USERIAL -#define ZB_TRANSPORT_NONBLOCK_ITERATION() (zb_macsplit_transport_recv_bytes(),0) -#else /* ZB_MACSPLIT_TRANSPORT_USERIAL */ -#define ZB_TRANSPORT_NONBLOCK_ITERATION() 0 -#endif /* ZB_MACSPLIT_TRANSPORT_USERIAL */ - - -#ifdef CONFIG_ZB_HAVE_SERIAL -#define ZB_HAVE_SERIAL -#define ZB_HAVE_ASYNC_SERIAL -#endif /* CONFIG_ZB_HAVE_SERIAL */ - -#ifdef CONFIG_ZB_USE_LEDS -#define ZB_USE_LEDS -#define ZB_N_LEDS 4 -#endif /* CONFIG_ZB_USE_LEDS */ - -#ifdef CONFIG_ZB_USE_DIMMABLE_LED -#define ZB_USE_DIMMABLE_LED -#endif /* CONFIG_ZB_USE_DIMMABLE_LED */ - -#ifdef CONFIG_ZB_USE_BUTTONS -#define ZB_USE_BUTTONS -#define ZB_N_BUTTONS 4 -#endif /* CONFIG_ZB_USE_BUTTONS */ - - -/** @addtogroup special_nordic_functions - * @{ - */ - -/** - * @brief Read IEEE long address from FICR registers. - * - * @param[out] ieee_eui64 Pointer to a long address structure to be filled. - * @cond NORDIC_NCS_SPECIAL_FUNCTIONS - * This structure is filled with the EUI-64 assigned by Nordic Semiconductor. Refer to the Configuring Zigbee in nRF Connect SDK ("IEEE 802.15.4 EUI-64 configuration" section) if you want to change it. - * @endcond - * @cond NORDIC_NRF5_SPECIAL_FUNCTIONS - * The 24 oldest bits are filled in by the ZIGBEE_VENDOR_OUI macro and the remainder is taken from the FICR register. - * @endcond - */ -void zb_osif_get_ieee_eui64(zb_ieee_addr_t ieee_eui64); - - -/**@brief Function which tries to put the device into deep sleep mode, caused by an empty Zigbee stack scheduler queue. - * - * Function is defined as weak; to be redefined if someone wants to implement their own - * going-to-deep-sleep policy. - */ -zb_uint32_t zb_osif_sleep(zb_uint32_t sleep_tmo); - -/**@brief Function which is called after zb_osif_sleep - * finished and ZBOSS timer is reenabled. - * - * Function is defined as weak; to be redefined if someone - * wants to implement their own going-to-deep-sleep policy/share resources - * between Zigbee stack and other components. - */ -void zb_osif_wake_up(void); - -/** - * @} - */ - -#endif /* ZB_OSIF_PLATFORM_H__ */ diff --git a/zboss/development/include/osif/zb_revision_r22.h b/zboss/development/include/osif/zb_revision_r22.h deleted file mode 100644 index 21ca8f4a27..0000000000 --- a/zboss/development/include/osif/zb_revision_r22.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - * - * This file implements mappings of Kconfig options enabling and configuring ZBOSS features. - */ - -/** - * Revision number of ZBOSS. It is defined as a sequential number of the commit, - * starting from the latest tagged revision on the master branch. - * - * Note: This value is automatically updated by the release script. - */ -#define ZBOSS_SDK_REVISION 0U - -/** - * Major version number of the ZBOSS platform for NCS. - */ -#define ZBOSS_PLATFORM_MAJOR 5U - -/** - * Minor version number of the ZBOSS platform for NCS. - */ -#define ZBOSS_PLATFORM_MINOR 2U - -/** - * Patch version number of the ZBOSS platform for NCS. - * - * Note: This value is automatically updated by the release script. - */ -#define ZBOSS_PLATFORM_PATCH 0U - -/** - * Patch version number of the ZBOSS core. - * - * Note: This value is automatically updated by the release script. - */ -#define ZBOSS_PATCH 1U diff --git a/zboss/development/include/osif/zb_transceiver.h b/zboss/development/include/osif/zb_transceiver.h deleted file mode 100644 index e134699446..0000000000 --- a/zboss/development/include/osif/zb_transceiver.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef ZB_TRANSCEIVER_H__ -#define ZB_TRANSCEIVER_H__ - -void zb_trans_hw_init(void); -void zb_trans_set_pan_id(zb_uint16_t pan_id); -void zb_trans_set_long_addr(zb_ieee_addr_t long_addr); -void zb_trans_set_short_addr(zb_uint16_t addr); -void zb_trans_start_get_rssi(zb_uint8_t scan_duration_bi); -void zb_trans_get_rssi(zb_uint8_t *rssi_value_p); -void zb_trans_set_channel(zb_uint8_t channel_number); -void zb_trans_set_tx_power(zb_int8_t power); -void zb_trans_get_tx_power(zb_int8_t *power); -void zb_trans_set_pan_coord(zb_bool_t pan_coord); -void zb_trans_set_auto_ack(zb_bool_t enabled); -void zb_trans_set_promiscuous_mode(zb_bool_t enabled); -void zb_trans_enter_receive(void); -void zb_trans_enter_sleep(void); -zb_bool_t zb_trans_is_receiving(void); -zb_bool_t zb_trans_is_active(void); -zb_bool_t zb_trans_transmit(zb_uint8_t wait_type, zb_time_t tx_at, zb_uint8_t *tx_buf, zb_uint8_t current_channel); -void zb_trans_buffer_free(zb_uint8_t *p_buf); -zb_bool_t zb_trans_set_pending_bit(zb_uint8_t *addr, zb_bool_t value, zb_bool_t extended); -void zb_trans_src_match_tbl_drop(void); -zb_time_t osif_sub_trans_timer(zb_time_t t2, zb_time_t t1); -zb_bool_t zb_trans_rx_pending(void); -zb_uint8_t zb_trans_get_next_packet(zb_bufid_t buf); -zb_ret_t zb_trans_cca(void); -zb_ret_t zb_trans_continuous_carrier(void); -void zb_trans_set_crcpoly(zb_uint32_t iv, zb_uint32_t polynomial); - -#endif /* ZB_TRANSCEIVER_H__ */ diff --git a/zboss/development/include/osif/zb_vendor.h b/zboss/development/include/osif/zb_vendor.h deleted file mode 100644 index 8acef98daf..0000000000 --- a/zboss/development/include/osif/zb_vendor.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - * - * This file implements mappings of Kconfig options enabling and configuring ZBOSS features. - */ - -#ifndef ZB_VENDOR_H__ -#define ZB_VENDOR_H__ - -/** - * Include additional configuration file, which usually contains the set of - * symbols defined by ZBOSS source code Kconfig, which can be found in NCS - * platform repository. - */ -#ifdef LIBZBOSS_CONFIG_FILE -#include LIBZBOSS_CONFIG_FILE -#endif - -#include "zb_config_platform.h" -#include "zb_version.h" -#include "zb_revision_r22.h" - -#ifdef CONFIG_ZB_NCP_MODE -#define NCP_MODE -#endif - -#ifdef CONFIG_ZB_NCP_TRANSPORT_TYPE_SERIAL -#define ZB_NCP_TRANSPORT_TYPE_SERIAL -#endif - -#ifdef CONFIG_ZB_NCP_TRANSPORT_TYPE_SPI -#define ZB_NCP_TRANSPORT_TYPE_SPI -#endif - -#ifdef CONFIG_ZB_NCP_TRANSPORT_TYPE_NSNG -#define ZB_NCP_TRANSPORT_TYPE_NSNG -#endif - -#ifdef CONFIG_ZB_SDK_TYPE -#define ZBOSS_SDK_TYPE (CONFIG_ZB_SDK_TYPE - 1) -#endif - -#ifdef CONFIG_ZB_TRACE_LOG_LEVEL -#define ZB_TRACE_LEVEL CONFIG_ZB_TRACE_LOG_LEVEL -#endif - -#ifdef CONFIG_ZB_TRACE_MASK -#define ZB_TRACE_MASK CONFIG_ZB_TRACE_MASK -#endif - -#ifdef CONFIG_ZB_NVRAM_ENABLE_VER_MIGRATION -#define ZB_NVRAM_ENABLE_VER_MIGRATION -#else -#define ZB_NO_NVRAM_VER_MIGRATION -#endif - -#ifdef CONFIG_ZB_BDB_ENABLE_FINDING_BINDING -#define ZB_BDB_ENABLE_FINDING_BINDING -#endif - -#ifdef CONFIG_ZB_DISTRIBUTED_SECURITY_ON -#define ZB_DISTRIBUTED_SECURITY_ON -#endif - -#ifdef CONFIG_ZB_SECURITY_INSTALLCODES -#define ZB_SECURITY_INSTALLCODES -#endif - -#ifdef CONFIG_ZB_PRODUCTION_CONFIG -#define ZB_PRODUCTION_CONFIG -#endif - -#ifdef CONFIG_ZB_APS_USER_PAYLOAD -#define ZB_APS_USER_PAYLOAD -#endif - -#ifdef CONFIG_ZB_LOW_SECURITY_MODE -#define ZB_LOW_SECURITY_MODE -#endif - -#ifdef CONFIG_ZB_APS_FRAGMENTATION -#define APS_FRAGMENTATION -#endif - -#ifdef CONFIG_ZB_NWK_BLACKLIST -#define ZB_NWK_BLACKLIST - -#ifdef CONFIG_ZB_NWK_BLACKLIST_SIZE -#define ZB_NWK_BLACKLIST_SIZE CONFIG_ZB_NWK_BLACKLIST_SIZE -#endif - -#endif /* CONFIG_ZB_NWK_BLACKLIST */ - -#ifdef CONFIG_ZB_CONTROL4_NETWORK_SUPPORT -#define ZB_CONTROL4_NETWORK_SUPPORT -#endif - -#ifdef CONFIG_ZB_R22_MULTIMAC_MODE -#define ZB_R22_MULTIMAC_MODE -#endif - -#ifdef CONFIG_ZB_MAC_INTERFACE_SINGLE -#define ZB_MAC_INTERFACE_SINGLE -#endif - -#ifdef CONFIG_ZB_MAC_TESTING_MODE -#define ZB_MAC_TESTING_MODE -#define ZB_MAC_API_TRACE_PRIMITIVES -#endif - -#ifdef CONFIG_ZB_MAC_DUTY_CYCLE_MONITORING -#define ZB_MAC_DUTY_CYCLE_MONITORING -#endif - -#ifdef CONFIG_ZB_MAC_POWER_CONTROL -#define ZB_MAC_POWER_CONTROL -#endif - -#ifdef CONFIG_ZB_MAC_CONFIGURABLE_TX_POWER -#define ZB_MAC_CONFIGURABLE_TX_POWER -#endif - -#ifdef CONFIG_ZB_MAC_QUEUE_SIZE -#define ZB_MAC_QUEUE_SIZE CONFIG_ZB_MAC_QUEUE_SIZE -#endif - -#ifdef CONFIG_ZB_NWK_CHANNEL_ACCEPT_LEVEL -#define ZB_NWK_CHANNEL_ACCEPT_LEVEL CONFIG_ZB_NWK_CHANNEL_ACCEPT_LEVEL -#endif - -#ifdef CONFIG_ZB_FILTER_OUT_CLUSTERS -#define ZB_FILTER_OUT_CLUSTERS -#endif - -#ifdef CONFIG_ZB_ENHANCED_BEACON_SUPPORT -#define ZB_ENHANCED_BEACON_SUPPORT -#endif - -#ifdef CONFIG_ZB_JOINING_LIST_SUPPORT -#define ZB_JOINING_LIST_SUPPORT -#endif - -#ifdef CONFIG_ZB_ZCL_SUPPORT_CLUSTER_WWAH -#define ZB_ZCL_SUPPORT_CLUSTER_WWAH - -#ifdef CONFIG_ZB_ZCL_ENABLE_WWAH_CLIENT -#define ZB_ZCL_ENABLE_WWAH_CLIENT -#endif - -#ifdef CONFIG_ZB_ZCL_ENABLE_WWAH_SERVER -#define ZB_ZCL_ENABLE_WWAH_SERVER - -#ifdef CONFIG_ZB_NWK_RETRY_COUNT -#define ZB_NWK_RETRY_COUNT -#endif - -#ifdef CONFIG_ZB_BEACON_SURVEY -#define ZB_BEACON_SURVEY -#endif - -#ifdef CONFIG_ZB_PARENT_CLASSIFICATION -#define ZB_PARENT_CLASSIFICATION -#endif - -#elif defined(CONFIG_ZB_NWK_RETRY_COUNT) || defined(CONFIG_ZB_BEACON_SURVEY) || defined(CONFIG_ZB_PARENT_CLASSIFICATION) -#error ZBOSS configuration mismatch: You have to enable WWAHu cluster server implementation to use additional WWAHu features. - -#endif /* ZB_ZCL_ENABLE_WWAH_SERVER */ - -#endif /* CONFIG_ZB_ZCL_SUPPORT_CLUSTER_WWAH */ - -#ifdef CONFIG_ZB_CHECK_OOM_STATUS -#define ZB_CHECK_OOM_STATUS -#endif - -#ifdef CONFIG_ZB_SEND_OOM_STATUS -#define ZB_SEND_OOM_STATUS -#endif - -#ifdef CONFIG_ZB_PROMISCUOUS_MODE -#define ZB_PROMISCUOUS_MODE -#endif - -#ifdef CONFIG_ZB_CERTIFICATION_HACKS -#define ZB_CERTIFICATION_HACKS -#endif - -#ifdef CONFIG_ZB_TEST_PROFILE -#define ZB_TEST_PROFILE -#endif - -#ifdef CONFIG_ZB_MULTITEST_CONSOLE_SLEEP_TIMEOUT -#define ZB_MULTITEST_CONSOLE_SLEEP_TIMEOUT CONFIG_ZB_MULTITEST_CONSOLE_SLEEP_TIMEOUT -#endif - -#ifdef CONFIG_ZB_DONT_NEED_TRACE_FILE_ID -#define ZB_DONT_NEED_TRACE_FILE_ID -#endif - -#ifdef CONFIG_ZB_MAC_AUTO_DELAY_IN_MAC_GP_SEND -#define MAC_AUTO_DELAY_IN_MAC_GP_SEND -#endif - -#ifdef CONFIG_ZB_USEALIAS -#define ZB_USEALIAS -#endif - -#ifdef CONFIG_ZB_LIMIT_VISIBILITY -#define ZB_LIMIT_VISIBILITY -#endif - -#ifdef CONFIG_ZB_BDB_TOUCHLINK -#define ZB_ENABLE_INTER_PAN_EXCHANGE -#define ZB_ENABLE_ZLL -#define ZB_BDB_TOUCHLINK -#endif - -#ifdef CONFIG_ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL -#define ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL -#endif - -#ifdef CONFIG_ZB_CONFIGURABLE_MEM -#define ZB_CONFIGURABLE_MEM -#endif - -/* Default memory storage configuration, used while dynamic memory configuration features is enabled. */ -#ifdef ZB_CONFIG_DEFAULT_KERNEL_DEFINITION - -/* Select memory configuration according to the implemented Zigbee role. */ -#ifndef ZB_ED_ROLE -#define ZB_CONFIG_ROLE_ZC -#else -#define ZB_CONFIG_ROLE_ZED -#endif - -#ifdef CONFIG_ZB_CONFIG_OVERALL_NETWORK_SIZE -#define ZB_CONFIG_OVERALL_NETWORK_SIZE CONFIG_ZB_CONFIG_OVERALL_NETWORK_SIZE -#endif - -#ifdef CONFIG_ZB_CONFIG_HIGH_TRAFFIC -#define ZB_CONFIG_HIGH_TRAFFIC -#endif - -#ifdef CONFIG_ZB_CONFIG_MODERATE_TRAFFIC -#define ZB_CONFIG_MODERATE_TRAFFIC -#endif - -#ifdef CONFIG_ZB_CONFIG_LIGHT_TRAFFIC -#define ZB_CONFIG_LIGHT_TRAFFIC -#endif - -#ifdef CONFIG_ZB_CONFIG_APPLICATION_COMPLEX -#define ZB_CONFIG_APPLICATION_COMPLEX -#endif - -#ifdef CONFIG_ZB_CONFIG_APPLICATION_MODERATE -#define ZB_CONFIG_APPLICATION_MODERATE -#endif - -#ifdef CONFIG_ZB_CONFIG_APPLICATION_SIMPLE -#define ZB_CONFIG_APPLICATION_SIMPLE -#endif - -#endif /* ZB_CONFIG_DEFAULT_KERNEL_DEFINITION */ - -/* Compile-time parameters, affecting memory usage in all configurations. */ -#define ZB_PANID_TABLE_SIZE CONFIG_ZB_PANID_TABLE_SIZE -#define ZB_DEV_MANUFACTORER_TABLE_SIZE CONFIG_ZB_DEV_MANUFACTURER_TABLE_SIZE -#define ZB_BUF_Q_SIZE CONFIG_ZB_BUF_Q_SIZE -#define ZDO_TRAN_TABLE_SIZE CONFIG_ZB_ZDO_TRAN_TABLE_SIZE -#define ZB_APS_ENDPOINTS_IN_GROUP_TABLE CONFIG_ZB_APS_ENDPOINTS_IN_GROUP_TABLE -#define ZB_NWK_BTR_TABLE_SIZE CONFIG_ZB_NWK_BTR_TABLE_SIZE -#define ZB_NWK_BRR_TABLE_SIZE CONFIG_ZB_NWK_BRR_TABLE_SIZE -#define ZB_MAX_EP_NUMBER CONFIG_ZB_MAX_EP_NUMBER -#define ZB_APS_GROUP_TABLE_SIZE CONFIG_ZB_APS_GROUP_TABLE_SIZE -#define ZB_ZGP_SINK_TBL_SIZE CONFIG_ZB_ZGP_SINK_TBL_SIZE -#define ZB_ZGP_PROXY_TBL_SIZE CONFIG_ZB_ZGP_PROXY_TBL_SIZE - -#ifdef CONFIG_ZB_APS_SRC_BINDING_TABLE_SIZE -#define ZB_APS_SRC_BINDING_TABLE_SIZE CONFIG_ZB_APS_SRC_BINDING_TABLE_SIZE -#endif - -#ifdef CONFIG_ZB_APS_DST_BINDING_TABLE_SIZE -#define ZB_APS_DST_BINDING_TABLE_SIZE CONFIG_ZB_APS_DST_BINDING_TABLE_SIZE -#endif - -#ifdef CONFIG_ZB_IOBUF_POOL_SIZE -#define ZB_IOBUF_POOL_SIZE CONFIG_ZB_IOBUF_POOL_SIZE -#endif - -#ifdef CONFIG_ZB_SCHEDULER_Q_SIZE -#define ZB_SCHEDULER_Q_SIZE CONFIG_ZB_SCHEDULER_Q_SIZE -#endif - -#ifndef ZB_CONFIGURABLE_MEM -#define ZB_CHILD_HASH_TABLE_SIZE (((ZB_IEEE_ADDR_TABLE_SIZE + ZB_IEEE_ADDR_TABLE_SIZE / 3) + 31) / 32 * 32) -#endif /* ZB_CONFIGURABLE_MEM */ - -/* ZBOSS stack options non-configurable via Kconfig. */ - -/* Include Zigbee BDB implementation (always defined, except macsplit). */ -#define ZB_BDB_MODE - -#if defined NCP_MODE && !defined NCP_MODE_HOST -/* Enable NCP SoC -specific BDB signal generation and handler. */ -#define ZB_NCP_SOC_BDB -/* Include additional API, that allows to write any dataset structure into the ZBOSS NVRAM. */ -#define ZB_NVRAM_ENABLE_DIRECT_API -/* Include NCP commands for entering bootloader. */ -#define ZB_NCP_ENABLE_OTA_CMD -#endif /* NCP_MODE && !NCP_MODE_HOST */ - -/* Include Zigbee HA clusters implementation (always defined, except macsplit). */ -#define ZB_ENABLE_HA - -/* Include all ZCL clusters. */ -#define ZB_ZCL_SUPPORT_CLUSTER_ALARMS -#define ZB_ZCL_SUPPORT_CLUSTER_BASIC -#define ZB_ZCL_SUPPORT_CLUSTER_BINARY_INPUT -#define ZB_ZCL_SUPPORT_CLUSTER_COLOR_CONTROL -#define ZB_ZCL_SUPPORT_CLUSTER_DEHUMIDIFICATION_CONTROL -#define ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS -#define ZB_ZCL_SUPPORT_CLUSTER_DOOR_LOCK -#define ZB_ZCL_SUPPORT_CLUSTER_DRLC -#define ZB_ZCL_SUPPORT_CLUSTER_EN50523_APPLIANCE_EVENTS_AND_ALERTS -#define ZB_ZCL_SUPPORT_CLUSTER_FAN_CONTROL -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS -#define ZB_ZCL_SUPPORT_CLUSTER_GROUPS_CLIENT -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ACE -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_WD -#define ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE -#define ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY -#define ZB_ZCL_SUPPORT_CLUSTER_ILLUMINANCE_MEASUREMENT -#define ZB_ZCL_SUPPORT_CLUSTER_LEVEL_CONTROL -#define ZB_ZCL_SUPPORT_CLUSTER_MESSAGING -#define ZB_ZCL_SUPPORT_CLUSTER_METER_IDENTIFICATION -#define ZB_ZCL_SUPPORT_CLUSTER_METERING -#define ZB_ZCL_SUPPORT_CLUSTER_OCCUPANCY_SENSING -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF -#define ZB_ZCL_SUPPORT_CLUSTER_ON_OFF_SWITCH_CONFIG -#define ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE -#define ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL -#define ZB_ZCL_SUPPORT_CLUSTER_POWER_CONFIG -#define ZB_ZCL_SUPPORT_CLUSTER_PRESSURE_MEASUREMENT -#define ZB_ZCL_SUPPORT_CLUSTER_PRICE -#define ZB_ZCL_SUPPORT_CLUSTER_REL_HUMIDITY_MEASUREMENT -#define ZB_ZCL_SUPPORT_CLUSTER_SCENES -#define ZB_ZCL_SUPPORT_CLUSTER_SHADE_CONFIG -#define ZB_ZCL_SUPPORT_CLUSTER_TEMP_MEASUREMENT -#define ZB_ZCL_SUPPORT_CLUSTER_THERMOSTAT -#define ZB_ZCL_SUPPORT_CLUSTER_THERMOSTAT_UI_CONFIG -#define ZB_ZCL_SUPPORT_CLUSTER_TIME -#define ZB_ZCL_SUPPORT_CLUSTER_TUNNELING -#define ZB_ZCL_SUPPORT_CLUSTER_WINDOW_COVERING -#define ZB_ZCL_SUPPORT_CLUSTER_WWAH - -/* Include rejoin backoff procedure (always included, except macsplit). */ -#define ZB_REJOIN_BACKOFF - -/* Enable ZGP profile (always defined, except macsplit). */ -#define ZB_ENABLE_ZGP - -/* Enable Green Power Combo implementation. */ -#if defined(CONFIG_ZIGBEE_GP_CB) && !defined(ZB_ENABLE_ZGP_COMBO) -#define ZB_ENABLE_ZGP_COMBO -#endif - -/* Enable sleepy behaviour on all devices. The sleep signal will allow other, lower-priority task to take over. */ -#ifndef ZB_USE_SLEEP -#define ZB_USE_SLEEP -#endif - -/* Enter TX mode directly from radio sleep sate. */ -#define ZB_TRANSCEIVER_ON_BEFORE_TX 0 - -/* Start Energy Detection from radio sleep state. */ -#define ZB_TRANSCEIVER_ON_BEFORE_ED 0 - -/* Include test cases in the certification firmware builds. */ -#ifdef CONFIG_ZB_TEST_GROUP_ALL -#define ZB_TEST_GROUP_ALL -#endif - -#ifdef CONFIG_ZB_TEST_GROUP_ALL_DUT -#ifndef ZB_ED_ROLE -#define ZB_TEST_GROUP_ALL_DUT -#else -/* The zed_test_table.h doe not divide test cases into TH and DUT roles. */ -#define ZB_TEST_GROUP_ALL -#endif /* ZB_ED_ROLE */ -#endif /* CONFIG_ZB_TEST_GROUP_ALL_DUT */ - -#ifdef CONFIG_ZB_TEST_GROUP_ALL_TH -#define ZB_TEST_GROUP_ALL_TH -#endif - - -/* Set the ZBOSS buffer size according to the set of enabled MAC features. */ -#ifdef ZB_MAC_SECURITY -#define ZB_IO_BUF_SIZE 164 -#else /* ZB_MAC_SECURITY */ -#define ZB_IO_BUF_SIZE 152 -#endif /* ZB_MAC_SECURITY */ - -/* ZBOSS stack version, represented as an unit32 number. */ -#define ZB_STACK_VERSION ((ZBOSS_MAJOR << 24) | (ZBOSS_MINOR << 16) | (ZBOSS_PATCH << 8) | (ZBOSS_SDK_REVISION)) - -/* ZBOSS NCP protocol version. */ -#define ZB_NCP_PROTOCOL_VERSION 0x0115 - -#endif /* ZB_VENDOR_H__ */ diff --git a/zboss/development/include/se/zb_se_keep_alive.h b/zboss/development/include/se/zb_se_keep_alive.h deleted file mode 100644 index 8d283ebfed..0000000000 --- a/zboss/development/include/se/zb_se_keep_alive.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Deprecated Definitions of SE's Keep-Alive cluster (SE spec, Annex A.3) -*/ - -#ifndef ZB_SE_KEEP_ALIVE_H -#define ZB_SE_KEEP_ALIVE_H 1 - -/** @cond DOXYGEN_SE_SECTION */ - -/** @addtogroup ZB_ZCL_KEEP_ALIVE_HEADER_DEPRECATED - * @{ - * @details - * Using of this SE cluster header is deprecated. The header was moved from SE to ZCL in ZCL8. Use ZCL Keep Alive Cluster instead (include/zcl/zb_zcl_keep_alive.h). - * @deprecated - * This cluster header as a part of SE will be removed in February 2023 in favor of its heir ZCL Keep Alive Cluster. - * - */ - -/* Deprecated header ZB_SE_KEEP_ALIVE_H */ - -/*! @} */ /* SE Keep-Alive cluster definitions */ - -/** @endcond */ /* DOXYGEN_SE_SECTION */ - -#include "zcl/zb_zcl_keep_alive.h" - -#endif /* ZB_SE_KEEP_ALIVE_H */ diff --git a/zboss/development/include/zb_address.h b/zboss/development/include/zb_address.h deleted file mode 100644 index ec394b4beb..0000000000 --- a/zboss/development/include/zb_address.h +++ /dev/null @@ -1,622 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Zigbee address management -*/ - -#ifndef ZB_ADDRESS_H -#define ZB_ADDRESS_H 1 - -/*! \addtogroup ZB_NWK_ADDR */ -/*! @{ */ - - -/*! @cond internals_doc */ - -#define ZB_UNKNOWN_SHORT_ADDR 0xFFFFU - -#ifdef ZB_DEBUG_ADDR -#define TRACE_ADDR_PROTO_VOID zb_uint16_t from_file, zb_uint16_t from_line -#define TRACE_ADDR_CALL_VOID ZB_TRACE_FILE_ID, __LINE__ -#define TRACE_ADDR_FORWARD_VOID from_file, from_line -#define TRACE_ADDR_PROTO TRACE_ADDR_PROTO_VOID , -#define TRACE_ADDR_CALL TRACE_ADDR_CALL_VOID , -#define TRACE_ADDR_FORWARD TRACE_ADDR_FORWARD_VOID , -#else -#define TRACE_ADDR_PROTO_VOID -#define TRACE_ADDR_CALL_VOID -#define TRACE_ADDR_FORWARD_VOID -#define TRACE_ADDR_PROTO -#define TRACE_ADDR_CALL -#define TRACE_ADDR_FORWARD -#endif /* ZB_DEBUG_ADDR */ - -/** - Compressed IEEE address. One byte device manufacturer - reference to - \see zb_dev_manufacturer_t array. -*/ -typedef ZB_PACKED_PRE struct zb_ieee_addr_compressed_s -{ - zb_uint8_t dev_manufacturer; /*!< Index from dev manufacturer array */ - zb_uint8_t device_id[5]; /*!< Device ID */ -} -ZB_PACKED_STRUCT -zb_ieee_addr_compressed_t; - -/*! @endcond */ - - -/** - Pan ID reference - - Should be used inside protocol tables instead of 64-bit Pan ID -*/ -typedef zb_uint8_t zb_address_pan_id_ref_t; - - -/** - IEEE address reference - - Should be used inside protocol tables instead of 64/16-bit IEEE. -*/ -typedef zb_uint8_t zb_address_ieee_ref_t; - -/*! @cond internals_doc */ - -/** - 64-bit / 16-bit address map -*/ -typedef ZB_PACKED_PRE struct zb_address_map_s -{ - zb_ieee_addr_compressed_t ieee_addr; /*!< Compressed IEEE address */ - zb_uint16_t addr; /*!< 16-bit device address */ - zb_address_ieee_ref_t redirect_ref; /*!< Reference to redirected or regular record */ - - zb_bitfield_t lock_cnt:8; /*!< lock counter. not locked if 0 */ - zb_bitfield_t used:1; /*!< if 0, this entry is free (never used) */ - zb_bitfield_t has_address_conflict:1; /*!< Set to 1 if device discovers address conflict - * Cleared when conflict is resolved: - * - Device that discovers conflict sending Network Status - * - or another Network Status with identical payload was received */ - zb_bitfield_t padding:2; /*!< Explicit padding bits */ - zb_bitfield_t clock:1; /*!< clock value for the clock usage algorithm */ - zb_bitfield_t redirect_type:2; /*!< redirect type @ref addr_redirect_type */ - zb_bitfield_t pending_for_delete:1; /*!< record is pending for deletion */ - -} ZB_PACKED_STRUCT zb_address_map_t; - - -/** - \par work with compressed addresses - */ - -/* - * AS: Fixed wrong division 64-bit extended address into - * manufacturer specific and device unique parts. -*/ -#define ZB_ADDRESS_DECOMPRESS(address, compressed_address) \ -do \ -{ \ - if (ZB_ADDRESS_COMPRESSED_IS_UNKNOWN(compressed_address)) \ - { \ - ZB_64BIT_ADDR_UNKNOWN(address); \ - } \ - else \ - { \ - ZB_MEMCPY(&((address)[5]), \ - &(ZG->addr.dev_manufacturer[(compressed_address).dev_manufacturer].device_manufacturer[0]), \ - (sizeof((address)[0]) * 3U)); \ - ZB_MEMCPY(&((address)[0]), &((compressed_address).device_id[0]), (sizeof((address)[0]) * 5U)); \ - \ - } \ -} \ -while (0) - -/* -#define ZB_ADDRESS_COMPRESSED_CMP(one, two) ( \ - (one).dev_manufacturer == (two).dev_manufacturer \ - && (one).device_id[0] == (two).device_id[0] \ - && (one).device_id[1] == (two).device_id[1] \ - && (one).device_id[2] == (two).device_id[2] \ - && (one).device_id[3] == (two).device_id[3] \ - && (one).device_id[4] == (two).device_id[4] ) -*/ -zb_bool_t zb_address_compressed_cmp(zb_ieee_addr_compressed_t *one, zb_ieee_addr_compressed_t *two); -#define ZB_ADDRESS_COMPRESSED_CMP(one, two) zb_address_compressed_cmp(&one, &two) - -#define ZB_ADDRESS_COMPRESSED_COPY(dest, src) \ - ZB_MEMCPY(&(dest).dev_manufacturer, &(src).dev_manufacturer, sizeof(zb_ieee_addr_compressed_t)) - - /* g_zero_addr is declared as ZB_CONST which allows IAR to place it in CODE memory. - Compiled this by IAR 7.60 for 8051. - This placement changes pointer type making it unusable - Is this cast needed here? - */ -#define ZB_ADDRESS_COMPRESSED_IS_ZERO(dest) \ - (ZB_MEMCMP(&(dest).dev_manufacturer, (void const *)g_zero_addr, sizeof(zb_ieee_addr_compressed_t)) == 0) - -#define ZB_ADDRESS_COMPRESSED_IS_UNKNOWN(dest) \ - (ZB_MEMCMP(&(dest).dev_manufacturer, (void const *)g_unknown_ieee_addr, sizeof(zb_ieee_addr_compressed_t)) == 0) - -#define ZB_ADDRESS_COMPRESS_UNKNOWN(dest) \ - (ZB_MEMCPY(&(dest).dev_manufacturer, (void const *)g_unknown_ieee_addr, sizeof(zb_ieee_addr_compressed_t))) - -/** - Add Pan ID to address storage and return reference. - - @param short_pan_id - 16-bit Pan ID identifier - @param pan_id - 64-bit Pan ID identifier - @param ref - (output) reference to Pan ID. - - @return RET_OK - when success, error code otherwise. - - @b Example -@code - zb_address_pan_id_ref_t panid_ref; - zb_ret_t ret; - - ret = zb_address_set_pan_id(mhr.src_pan_id, beacon_payload->extended_panid, &panid_ref); - if (ret == RET_ALREADY_EXISTS) - { - ret = RET_OK; - } -@endcode - - */ -zb_ret_t zb_address_set_pan_id(zb_uint16_t short_pan_id, zb_ext_pan_id_t pan_id, zb_address_pan_id_ref_t *ref); - - -/** - Get extended Pan ID with reference. - - @param pan_id_ref - reference to Pan ID - @param pan_id - (output) Pan ID. - - @return nothing - - @b Example -@code - zb_uint8_t i; - ZB_BUF_INITIAL_ALLOC((zb_bufid_t )ZB_BUF_FROM_REF(param), - sizeof(*discovery_confirm) + sizeof(*network_descriptor) * ZB_PANID_TABLE_SIZE, - discovery_confirm); - zb_nlme_network_descriptor_t *network_descriptor = (zb_nlme_network_descriptor_t *)(discovery_confirm + 1); - for (i = 0 ; i < ZG->nwk.neighbor.ext_neighbor_used ; ++i) - { - zb_address_get_pan_id(ZG->nwk.neighbor.ext_neighbor[i].panid_ref, network_descriptor[j].extended_pan_id); - network_descriptor[j].logical_channel = ZG->nwk.neighbor.ext_neighbor[i].logical_channel; - ... - n_nwk_dsc++; - } - discovery_confirm->network_count = n_nwk_dsc; - discovery_confirm->status = (zb_mac_status_t)((zb_bufid_t )ZB_BUF_FROM_REF(param))->u.hdr.status; - ZB_SCHEDULE_CALLBACK(zb_nlme_network_discovery_confirm, param); -@endcode - - */ -void zb_address_get_pan_id(zb_address_pan_id_ref_t pan_id_ref, zb_ext_pan_id_t pan_id); - -/** - Clears Pan ID table except own pan_id. - - @param pan_id - (our) Pan ID. - - @return nothing - - */ -void zb_address_clear_pan_id_table(zb_ext_pan_id_t pan_id); - -/** - Clears whole Pan ID table - - @return nothing - - */ -void zb_address_reset_pan_id_table(void); - -/*! @endcond */ - -/** - Get Pan ID reference with extended Pan ID. - - @param pan_id - Pan ID - @param ref - (output) reference to Pan ID - - @return RET_OK - when success, error code otherwise. - - @b Example -@code - zb_address_pan_id_ref_t my_panid_ref; - if ( zb_address_get_pan_id_ref(ZB_NIB_EXT_PAN_ID(), &my_panid_ref) != RET_OK ) - { - TRACE_MSG(TRACE_NWK1, "Pan ID " TRACE_FORMAT_64 " not in Pan ID arr - ?", (FMT__A, - TRACE_ARG_64(ZB_NIB_EXT_PAN_ID()))); - } -@endcode - */ -zb_ret_t zb_address_get_pan_id_ref(zb_ext_pan_id_t pan_id, zb_address_pan_id_ref_t *ref); - -/** - Get short Pan ID with reference. - - @param pan_id_ref - reference to Pan ID - @param pan_id_p - (output) Pan ID. - - - @b Example -@code - zb_uint16_t nt_panid; - zb_address_get_short_pan_id(ZG->nwk.neighbor.ext_neighbor[i].panid_ref, &nt_panid); - if (nt_panid == pan_id) - { - TRACE_MSG(TRACE_NWK1, "pan_id %d is on ch %hd", (FMT__D_H, pan_id, channel)); - unique_pan_id = 0; - } -@endcode - */ -void zb_address_get_short_pan_id(zb_address_pan_id_ref_t pan_id_ref, zb_uint16_t *pan_id_p); - - -/** - Compare Pan ID in the source form with Pan ID reference. - - @param pan_id_ref - Pan ID ref - @param pan_id - Pan ID (64-bit) - - @return ZB_TRUE if addresses are equal, ZB_FALSE otherwise - - @b Example -@code - for (i = 0 ; i < ZG->nwk.neighbor.ext_neighbor_used ; ++i) - { - for (j = 0 ; j < n_nwk_dsc && - !zb_address_cmp_pan_id_by_ref(ZG->nwk.neighbor.ext_neighbor[i].panid_ref, network_descriptor[j].extended_pan_id) ; - ++j) - { - ... - } - } -@endcode - */ -zb_bool_t zb_address_cmp_pan_id_by_ref(zb_address_pan_id_ref_t pan_id_ref, zb_ext_pan_id_t pan_id); - -/** - Update long/short address pair. Create the pair if not exist. Optionally, lock. - Reaction on device announce etc. Long and short addresses are present. Must - synchronize the address translation table with this information. - - @note Never call zb_address_update() with empty (zero) ieee_address or empty - (-1) short_address. - - @param ieee_address - long address - @param short_address - short address - @param lock - if TRUE, lock address entry - @param ref_p - (out) address reference - - @return RET_OK or error code - - @b Example -@code - zb_address_ieee_ref_t addr_ref; - zb_uint16_t nwk_addr; - zb_zdo_nwk_addr_resp_head_t *resp = (zb_zdo_nwk_addr_resp_head_t*)zb_buf_begin(buf); - if (resp->status == ZB_ZDP_STATUS_SUCCESS) - { - ZB_LETOH64(ieee_addr, resp->ieee_addr); - ZB_LETOH16(&nwk_addr, &resp->nwk_addr); - zb_address_update(ieee_addr, nwk_addr, ZB_TRUE, &addr_ref); - } -@endcode - - */ -zb_ret_t zb_address_update(zb_ieee_addr_t ieee_address, zb_uint16_t short_address, zb_bool_t lock, zb_address_ieee_ref_t *ref_p); - -void zb_long_address_update_by_ref(zb_ieee_addr_t ieee_address, zb_address_ieee_ref_t ref); - -/** - Get address with address reference. - - Get existing IEEE (long) and short addresses with address reference. Update address alive - time if it not locked. - - @param ieee_address - (out) long address - @param short_address_p - (out) short address - @param ref - address reference - - @b Example -@code - zb_address_ieee_ref_t addr_ref; - zb_nlme_join_indication_t *resp = ZB_BUF_GET_PARAM((zb_bufid_t )ZB_BUF_FROM_REF(param), zb_nlme_join_indication_t); - zb_address_by_ref(resp->extended_address, &resp->network_address, addr_ref); -@endcode - - */ -void zb_address_by_ref(zb_ieee_addr_t ieee_address, zb_uint16_t *short_address_p, zb_address_ieee_ref_t ref); - -/** - Get IEEE address with address reference. - - Get existing IEEE address(long address) with address reference. Update address alive time if it not locked. - - @param ieee_address - (out) long address - @param ref - address reference - - @b Example -@code -void func(zb_neighbor_tbl_ent_t *nbt) -{ - zb_ieee_addr_t ieee_addr; - zb_address_ieee_by_ref(ieee_addr, nbt->addr_ref); - ... -} -@endcode - - */ -void zb_address_ieee_by_ref(zb_ieee_addr_t ieee_address, zb_address_ieee_ref_t ref); - - -/** - Get short address by address reference. - - Get existing short address with address reference. Update address alive time if it not locked. - - @param short_address_p - (out) short address - @param ref - address reference - - @b Example -@code - zb_neighbor_tbl_ent_t *nbt; - if(zb_nwk_neighbor_with_address_conflict(&nbt)==RET_OK) - { - zb_uint16_t addr; - zb_address_short_by_ref(&addr, nbt->addr_ref); - func(addr); - } -@endcode - - */ -void zb_address_short_by_ref(zb_uint16_t *short_address_p, zb_address_ieee_ref_t ref); - -/** - Get address ref by long address, optionally create if not exist, optionally lock. - Update address alive time if not locked. - @param ieee - IEEE device address - @param create - if TRUE, create address entry if it does not exist - @param lock - if TRUE, lock address entry - @param ref_p - (out) address reference - - @note: never call zb_address_by_ieee() with empty (zero) ieee_address - - @return RET_OK or error code - - @b Example -@code - void test_get_short_addr(zb_uint8_t param) - { - zb_address_ieee_ref_t ref_p; - zb_bufid_t buf = ZB_BUF_FROM_REF(param); - - if (zb_address_by_ieee(g_ieee_addr_r2, ZB_TRUE, ZB_FALSE, &ref_p) == RET_OK) - { - ... - } - } -@endcode - - */ -zb_ret_t zb_address_by_ieee(const zb_ieee_addr_t ieee, zb_bool_t create, zb_bool_t lock, zb_address_ieee_ref_t *ref_p); - - -/** - Get short address by IEEE address (long). - - @param ieee_address - long address - - @return short address if ok, -1 otherwise. - - @par Example - @snippet thermostat/thermostat_zc/thermostat_zc.c default_short_addr - @snippet thermostat/thermostat_zc/thermostat_zc.c address_short_by_ieee - @par - - */ -zb_uint16_t zb_address_short_by_ieee(zb_ieee_addr_t ieee_address); - - -/** - Get IEEE address (long) with short address. - - @param short_addr - short address - @param ieee_address - (out)long address - - @return RET_OK or RET_NOT_FOUND - - @b Example - @snippet light_sample_HA_1_2_bulb/light_coordinator_HA_1_2_bulb/light_zc_HA_1_2_bulb.c address_ieee_by_short - - */ -zb_ret_t zb_address_ieee_by_short(zb_uint16_t short_addr, zb_ieee_addr_t ieee_address); - - -/** - Get address reference with long address. Create the reference if it does not exist. - Optionally, lock the address. Update address alive time if not locked. - @param short_address - 16bit device address - @param create - if TRUE, create address entry if it does not exist - @param lock - if TRUE, lock address entry - @param ref_p - (out) address reference - - @note Never call zb_address_by_short() with empty (-1) short_address - - @return RET_OK or error code - - @b Example - @snippet simple_gw/simple_gw.c address_by_short - - */ -zb_ret_t zb_address_by_short(zb_uint16_t short_address, zb_bool_t create, zb_bool_t lock, zb_address_ieee_ref_t *ref_p); - - -/*! @cond internals_doc */ -/** - Get address ref by index from short_sorted table. - @param index - index address short_sorted table - @param ref_p - (out) address reference - - @return RET_OK or error code - - @b Example -@code - zb_address_ieee_ref_t ref_p; - if( ZG->nwk.neighbor.base_neighbor_used > 0 && - zb_address_by_sorted_table_index(ZG->nwk.neighbor.send_link_status_index, &ref_p)==RET_OK - ) - { - ... - } -@endcode - */ -zb_ret_t zb_address_by_sorted_table_index(zb_ushort_t index, zb_address_ieee_ref_t *ref_p); -/*! @endcond */ - -/** - Check that address is locked (has lock counter > 0) - - @param ref - IEEE/network address pair reference - - @return ZB_TRUE if address is locked - */ -zb_bool_t zb_address_is_locked(zb_address_ieee_ref_t ref); - - -/** - - Increase address lock counter, when it used in some table. - Address must be already locked. - - @param ref - IEEE/network address pair reference - - @return RET_OK or RET_ERROR - */ -#define zb_address_lock(ref) zb_address_lock_func(TRACE_ADDR_CALL ref) - -zb_ret_t zb_address_lock_func(TRACE_ADDR_PROTO zb_address_ieee_ref_t ref); - - -/** - - Unlock address counter. Decrease lock counter. - - @param ref - IEEE/network address pair reference - */ -#define zb_address_unlock(ref) zb_address_unlock_func(TRACE_ADDR_CALL ref) - -void zb_address_unlock_func(TRACE_ADDR_PROTO zb_address_ieee_ref_t ref); - -/** - Delete address. - - @return RET_OK or RET_ERROR - - @param ref - IEEE/network address pair reference - */ -zb_ret_t zb_address_delete(zb_address_ieee_ref_t ref); - - -/*! @cond internals_doc */ - -/** - Compress long address: store manufacturer address part elsewhere - - This routine packs 8 bytes address to 6 bytes - - @param address - uncompressed address - @param compressed_address - (out) compressed address - - @b Example -@code - void func(zb_address_pan_id_ref_t panid_ref, zb_ieee_addr_t long_addr, zb_ext_neighbor_tbl_ent_t **enbt) - { - zb_ieee_addr_compressed_t compressed_addr; - zb_ieee_addr_compress(long_addr, &compressed_addr); - - for (i = 0 ; i < ZG->nwk.neighbor.ext_neighbor_used ; ++i) - { - if (ZG->nwk.neighbor.ext_neighbor[i].panid_ref == panid_ref - && ZB_ADDRESS_COMPRESSED_CMP(ZG->nwk.neighbor.ext_neighbor[i].long_addr, compressed_addr)) - { - *enbt = &ZG->nwk.neighbor.ext_neighbor[i]; - } - } - } -@endcode - */ -void zb_ieee_addr_compress(const zb_ieee_addr_t address, zb_ieee_addr_compressed_t *compressed_address); - - -/** - Decompress compressed long address. - - This routine unpacks 6 bytes address to 8 bytes - - @param address - (out) uncompressed address - @param compressed_address - compressed address - - @b Example -@code - zb_ieee_addr_t long_address; - if (ZG->nwk.neighbor.ext_neighbor[i].short_addr != (zb_uint16_t)~0) - { - if (!ZB_ADDRESS_COMPRESSED_IS_UNKNOWN(ZG->nwk.neighbor.ext_neighbor[i].long_addr)) - { - zb_ieee_addr_decompress(long_address, &ZG->nwk.neighbor.ext_neighbor[i].long_addr); - zb_address_update(long_address, ZG->nwk.neighbor.ext_neighbor[i].short_addr, ZB_FALSE, &addr_ref); - } - } -@endcode - */ -void zb_ieee_addr_decompress(zb_ieee_addr_t address, zb_ieee_addr_compressed_t *compressed_address); - -/*! @endcond */ - -/*! @} */ - - -#endif /* ZB_ADDRESS_H */ diff --git a/zboss/development/include/zb_channel_page.h b/zboss/development/include/zb_channel_page.h deleted file mode 100644 index 097e803bc1..0000000000 --- a/zboss/development/include/zb_channel_page.h +++ /dev/null @@ -1,567 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Channel page header file. All channel-related stuff. -*/ -#ifndef ZB_CHANNEL_PAGE_H -#define ZB_CHANNEL_PAGE_H 1 - -#include "zb_config.h" -#include "zb_types.h" -#include "zb_errors.h" - -/*! \addtogroup channel_page */ -/*! @{ */ - -#define ZB_CHANNEL_PAGE_PAGE_BITMASK 0xF8000000u -#define ZB_CHANNEL_PAGE_MASK_BITMASK 0x07FFFFFFu - -/** - * Represents the fields of the Channel Page structure (binary encoded channel - * page and channels mask). - */ -typedef zb_uint32_t zb_channel_page_t; - -/** - * Channel list structure (ZBOSS internal) - */ -typedef zb_channel_page_t zb_channel_list_t[ZB_CHANNEL_PAGES_NUM]; - -/* Private API */ -#define ZB_CHANNEL_LIST_PAGE0_IDX 0U -#define ZB_CHANNEL_LIST_PAGE23_IDX 1U -#define ZB_CHANNEL_LIST_PAGE24_IDX 2U -#define ZB_CHANNEL_LIST_PAGE25_IDX 3U -#define ZB_CHANNEL_LIST_PAGE26_IDX 4U -#define ZB_CHANNEL_LIST_PAGE27_IDX 5U -#define ZB_CHANNEL_LIST_PAGE28_IDX 6U -#define ZB_CHANNEL_LIST_PAGE29_IDX 7U -#define ZB_CHANNEL_LIST_PAGE30_IDX 8U -#define ZB_CHANNEL_LIST_PAGE31_IDX 9U - -#define ZB_PAGE0_2_4_GHZ_CHANNEL_FROM 11U -#define ZB_PAGE0_2_4_GHZ_CHANNEL_TO 26U - -#define ZB_PAGE23_SUB_GHZ_CHANNEL_FROM 0U -#define ZB_PAGE23_SUB_GHZ_CHANNEL_TO 24U - -#define ZB_PAGE24_SUB_GHZ_CHANNEL_FROM 56U -#define ZB_PAGE24_SUB_GHZ_CHANNEL_TO 76U - -#define ZB_PAGE25_SUB_GHZ_CHANNEL_FROM 0U -#define ZB_PAGE25_SUB_GHZ_CHANNEL_TO 26U - -#define ZB_PAGE26_SUB_GHZ_CHANNEL_FROM 27U -#define ZB_PAGE26_SUB_GHZ_CHANNEL_TO 34U - -#define ZB_PAGE27_SUB_GHZ_CHANNEL_FROM 35U -#define ZB_PAGE27_SUB_GHZ_CHANNEL_TO 55U - -#define ZB_PAGE28_SUB_GHZ_CHANNEL_FROM 0U -#define ZB_PAGE28_SUB_GHZ_CHANNEL_TO 26U - -#define ZB_PAGE29_SUB_GHZ_CHANNEL_FROM 27U -#define ZB_PAGE29_SUB_GHZ_CHANNEL_TO 34U - -#define ZB_PAGE30_SUB_GHZ_CHANNEL_FROM 35U -#define ZB_PAGE30_SUB_GHZ_CHANNEL_TO 61U - -#define ZB_PAGES_28_29_30_SUG_GHZ_CHANNEL_FROM ZB_PAGE28_SUB_GHZ_CHANNEL_FROM -/** - * NR: Adding one more channel since page 29 takes channels (27-34) and 62 - */ -#define ZB_PAGES_28_29_30_SUG_GHZ_CHANNEL_TO 62U -#define ZB_PAGE29_SUB_GHZ_CHANNEL_62 62U - -#define ZB_PAGE31_SUB_GHZ_CHANNEL_FROM 0U -#define ZB_PAGE31_SUB_GHZ_CHANNEL_TO 26U - -#define ZB_CHANNEL_PAGE_TO_IDX(channel_page) (((channel_page) > 0U) ? ((channel_page) - 22U) : 0U) -#define ZB_CHANNEL_PAGE_FROM_IDX(channel_page_idx) (((channel_page_idx) > 0U) ? ((channel_page_idx) + 22U) : 0U) - -#ifdef ZB_PAGES_REMAP_TO_2_4GHZ -/** - The following remap stuff allows to remap Sub GHz pages/channel to 2.4GHz. - This is used to test Sub GHz without getting out from the town to desert - island due to wide range of Sub GHz. - - Remap is based on using of channels range of 2.4GHz to imitate working with - Sub GHz. The main idea is to divide channels range of 2.4GHz, where each - channels area corresponds to particular channel page. We have 5 channel - pages, so the range of channel numbers of 2.4GHz is divided into 5 areas: - - * 0-2 - PAGE0 - * 3-5 - PAGE28 - * 6-8 - PAGE29 - * 9-11 - PAGE30 - * 12-14 - PAGE31 - - So whole range of used channel numbers starts from 0 and ends with 14 - (15 channels of 2.4GHz are used). - - The following formula is used to remap channel number into 2.4GHz channel number. - * remap_channel_number = (channel_number % 3) + page_shift - */ - -#define ZB_PAGES_REMAP_PAGE_CHANNELS_NUM 3U - -#define ZB_PAGES_REMAP_PAGE0_SHIFT 0U -#define ZB_PAGES_REMAP_PAGE28_SHIFT (ZB_PAGES_REMAP_PAGE0_SHIFT + ZB_PAGES_REMAP_PAGE_CHANNELS_NUM) -#define ZB_PAGES_REMAP_PAGE29_SHIFT (ZB_PAGES_REMAP_PAGE28_SHIFT + ZB_PAGES_REMAP_PAGE_CHANNELS_NUM) -#define ZB_PAGES_REMAP_PAGE30_SHIFT (ZB_PAGES_REMAP_PAGE29_SHIFT + ZB_PAGES_REMAP_PAGE_CHANNELS_NUM) -#define ZB_PAGES_REMAP_PAGE31_SHIFT (ZB_PAGES_REMAP_PAGE30_SHIFT + ZB_PAGES_REMAP_PAGE_CHANNELS_NUM) - -#define ZB_PAGES_REMAP_CHANNEL_PAGE ZB_CHANNEL_PAGE0_2_4_GHZ -#define ZB_PAGES_REMAP_CHANNEL_NUMBER(page, channel_number) (((channel_number % ZB_PAGES_REMAP_PAGE_CHANNELS_NUM)) + ZB_PAGE0_2_4_GHZ_START_CHANNEL_NUMBER + \ - (page == ZB_CHANNEL_PAGE28_SUB_GHZ ? ZB_PAGES_REMAP_PAGE28_SHIFT : \ - (page == ZB_CHANNEL_PAGE29_SUB_GHZ ? ZB_PAGES_REMAP_PAGE29_SHIFT : \ - (page == ZB_CHANNEL_PAGE30_SUB_GHZ ? ZB_PAGES_REMAP_PAGE30_SHIFT : \ - (page == ZB_CHANNEL_PAGE31_SUB_GHZ ? ZB_PAGES_REMAP_PAGE31_SHIFT : \ - ZB_PAGES_REMAP_PAGE0_SHIFT))))) - -/** - Remaps logical channel into corresponding logical channel in 2.4GHz range. - - @param channel_page - original channel page - @param logical_channel - original logical channel in scope of original channel page - @param remap_logical_channel [out] - remapped logical channel in scope of 2.4GHz - - @return remapped channel if success - 0xff in case of error -*/ -zb_uint8_t zb_pages_remap_logical_channel(zb_uint8_t channel_page, - zb_uint8_t logical_channel); - -#define ZB_PAGES_REMAP_LOGICAL_CHANNEL(page, lchannel_number) zb_pages_remap_logical_channel(page, lchannel_number) - -#else - -#define ZB_PAGES_REMAP_LOGICAL_CHANNEL(page, lchannel_number) (lchannel_number) - -#endif - -/** - * Gets channel page field from Channel page structure - * - * @param channel_page - binary encoded channel page and channels mask - */ -#define ZB_CHANNEL_PAGE_GET_PAGE(channel_page) (((channel_page) & ZB_CHANNEL_PAGE_PAGE_BITMASK) >> 27U) - -/** - * Gets channels mask field from Channel page structure - * - * @param channel_page - binary encoded channel page and channels mask - */ -#define ZB_CHANNEL_PAGE_GET_MASK(channel_page) ((channel_page) & ZB_CHANNEL_PAGE_MASK_BITMASK) - -/** - * Sets channel page field for Channel page structure - * - * @param channel_page - binary encoded channel page and channels mask - * @param page - channel page to set - */ -#define ZB_CHANNEL_PAGE_SET_PAGE(channel_page, page) (channel_page) = ((channel_page) & ZB_CHANNEL_PAGE_MASK_BITMASK) | (((zb_uint32_t)(page)) << 27U) - -/** - * Sets channels mask field for Channel page structure - * - * @param channel_page - binary encoded channel page and channels mask - * @param mask - channels mask to set - */ -#define ZB_CHANNEL_PAGE_SET_MASK(channel_page, mask) (channel_page) = ((channel_page) & ZB_CHANNEL_PAGE_PAGE_BITMASK) | ((mask) & ZB_CHANNEL_PAGE_MASK_BITMASK) - -/* Numbers [23 - 31] have common first bit - * - * 23 = 0b10111 - * 24 = 0b11000 - * 25 = 0b11001 - * 26 = 0b11010 - * 27 = 0b11011 - * 28 = 0b11100 - * 29 = 0b11101 - * 30 = 0b11110 - * 31 = 0b11111 - * - * So, it is enough to compare it with 0b10111 mask = 0x17 = 23 (dec). - */ -#define ZB_LOGICAL_PAGE_SUB_GHZ_PAGE_MASK ZB_CHANNEL_PAGE23_SUB_GHZ - -#define ZB_LOGICAL_PAGE_IS_SUB_GHZ(logical_page) \ - (ZB_U2B((logical_page) & ZB_LOGICAL_PAGE_SUB_GHZ_PAGE_MASK)) - -#define ZB_LOGICAL_PAGE_IS_SUB_GHZ_NA_FSK(logical_page) \ - ((logical_page) == ZB_CHANNEL_PAGE23_SUB_GHZ) - -#define ZB_LOGICAL_PAGE_IS_SUB_GHZ_EU_FSK(logical_page) \ - ((logical_page) >= ZB_CHANNEL_PAGE24_SUB_GHZ && (logical_page) <= ZB_CHANNEL_PAGE27_SUB_GHZ) - -#define ZB_LOGICAL_PAGE_IS_SUB_GHZ_GB_FSK(logical_page) \ - ((logical_page) >= ZB_CHANNEL_PAGE28_SUB_GHZ && (logical_page) <= ZB_CHANNEL_PAGE31_SUB_GHZ) - -#define ZB_LOGICAL_PAGE_IS_2_4GHZ(logical_page) \ - ((logical_page) == ZB_CHANNEL_PAGE0_2_4_GHZ) - -#define ZB_CHANNEL_PAGE_IS_SUB_GHZ(channel_page) \ - (ZB_LOGICAL_PAGE_IS_SUB_GHZ(ZB_CHANNEL_PAGE_GET_PAGE(channel_page))) - -#define ZB_CHANNEL_PAGE_IS_SUB_GHZ_NA_FSK(channel_page) \ - (ZB_LOGICAL_PAGE_IS_SUB_GHZ_NA_FSK(ZB_CHANNEL_PAGE_GET_PAGE(channel_page))) - -#define ZB_CHANNEL_PAGE_IS_SUB_GHZ_EU_FSK(channel_page) \ - (ZB_LOGICAL_PAGE_IS_SUB_GHZ_EU_FSK(ZB_CHANNEL_PAGE_GET_PAGE(channel_page))) - -#define ZB_CHANNEL_PAGE_IS_SUB_GHZ_GB_FSK(channel_page) \ - (ZB_LOGICAL_PAGE_IS_SUB_GHZ_GB_FSK(ZB_CHANNEL_PAGE_GET_PAGE(channel_page))) - -#define ZB_CHANNEL_PAGE_IS_2_4GHZ(channel_page) \ - (ZB_LOGICAL_PAGE_IS_2_4GHZ(ZB_CHANNEL_PAGE_GET_PAGE(channel_page))) - -#define ZB_CHANNEL_PAGE_IS_MASK_EMPTY(channel_page) \ - (ZB_CHANNEL_PAGE_GET_MASK(channel_page) == 0U) - -/** - * @brief Copies source channel page list to the destination. Destination list - * must be allocated. - * - * @note Number of elements in both lists must be equal to ZB_CHANNEL_PAGES_NUM. - * - * @param dst - destination channel page list - * @param src - source channel page list - */ -void zb_channel_page_list_copy(zb_channel_list_t dst, - zb_channel_list_t src); - -/** - * @brief Sets channels mask for specified element of channel page list. - * - * @param list - channel page list - * @param idx - index of the list element - * @param mask - channels mask to set - */ -void zb_channel_page_list_set_mask(zb_channel_list_t list, - zb_uint8_t idx, - zb_uint32_t mask); - -/** - * @brief Gets channels mask of specified element of channel page list. - * - * @param list - channel page list - * @param idx - index of the list element - * - * @return Channels mask. - */ -zb_uint32_t zb_channel_page_list_get_mask(zb_channel_list_t list, - zb_uint8_t idx); - -/** - * @brief Sets channel page for specified element of channel page list. - * - * @param list - channel page list - * @param idx - index of the list element - * @param page - channel page to set - */ -void zb_channel_page_list_set_page(zb_channel_list_t list, - zb_uint8_t idx, - zb_uint8_t page); - -/** - * @brief Gets channel page of specified element of channel page list. - * - * @param list - channel page list - * @param idx - index of the list element - * - * @return Channel page. - */ -zb_uint8_t zb_channel_page_list_get_page(zb_channel_list_t list, - zb_uint8_t idx); - - -/** - * @brief Gets channel page index in channel lists. - * - * @param page - channel page - * @param idx [out] - index of the channel page in channel lists - * - * @return RET_OK or RET_NOT_FOUND. - */ -zb_ret_t zb_channel_page_list_get_page_idx(zb_uint8_t page, zb_uint8_t *idx); - - -/** - * @brief Gets page number by channel page index. - * - * @param idx - index of the channel page in channel lists - * @param page[out] - channel page - * - * @return RET_OK or RET_NOT_FOUND. - */ -zb_ret_t zb_channel_page_get_page_by_idx(zb_uint8_t idx, zb_uint8_t *page); - -/** - * @brief Gets all channels mask by a page number - * - * @param page - channel page - * - * @return the all channels mask for a certain page - */ -zb_uint32_t zb_channel_page_get_all_channels_mask_by_page(zb_uint8_t page); - -/** - * @brief Sets channels mask for the list element of channel page list that - * corresponds to 2.4GHz. - * - * @param list - channel page list - * @param mask - channels mask to set - */ -void zb_channel_page_list_set_2_4GHz_mask(zb_channel_list_t list, - zb_uint32_t mask); - -/** - * @brief Gets channels mask of the list element of channel page list that - * corresponds to 2.4GHz. - * - * @param list - channel page list - * - * @return 2.4GHz channels mask. - */ -zb_uint32_t zb_channel_page_list_get_2_4GHz_mask(zb_channel_list_t list); - -/* - * @brief Gets the first filled page index of channel page list. - * - * @param list - channel page list - * - * @return Page index of the first used page or number of pages if all list is empty. - */ -zb_uint8_t zb_channel_page_list_get_first_filled_page(zb_channel_list_t list); - -/** - * @brief Sets channels mask for specified element of the AIB channel page list. - * - * @param idx - index of the list element - * @param mask - channels mask to set - */ -void zb_aib_channel_page_list_set_mask(zb_uint8_t idx, - zb_uint32_t mask); - -/** - * @brief Gets channels mask of specified element of the AIB channel page list. - * - * @param idx - index of the list element - * - * @return Channels mask. - */ -zb_uint32_t zb_aib_channel_page_list_get_mask(zb_uint8_t idx); - -/** - * @brief Sets channel page for specified element of the AIB channel page list. - * - * @param idx - index of the list element - * @param page - channel page to set - */ -void zb_aib_channel_page_list_set_page(zb_uint8_t idx, - zb_uint8_t page); - -/** - * @brief Gets channels page of specified element of the AIB channel page list. - * - * @param idx - index of the list element - * - * @return Channel page. - */ -zb_uint8_t zb_aib_channel_page_list_get_page(zb_uint8_t idx); - -/** - * @brief Sets channels mask for the list element of the AIB channel page list that - * corresponds to 2.4GHz. - * - * @param mask - channels mask to set - */ -void zb_aib_channel_page_list_set_2_4GHz_mask(zb_uint32_t mask); - -/** - * @brief Gets channels mask of the list element of the AIB channel page list that - * corresponds to 2.4GHz. - * - * @return 2.4GHz channels mask. - */ -zb_uint32_t zb_aib_channel_page_list_get_2_4GHz_mask(void); - -/* - * @brief Gets the first filled page index of the AIB channel page list. - * - * @return Page index of the first used AIB channel page or number of pages if all list is empty. - */ -zb_uint8_t zb_aib_channel_page_list_get_first_filled_page(void); - -/** - * @brief Gets the first channel number for specified channel page. - * - * @note The channel number is returned in inner representation as channels bits - * stored in channel mask internally, it may differ from real channel numbers - * specified by spec. - * - * @param page - channel page - * @param channel_number [out] - channel number - * - * @return RET_OK or RET_NOT_FOUND. - */ -zb_ret_t zb_channel_page_get_start_channel_number(zb_uint8_t page, zb_uint8_t *channel_number); - -/** - * @brief Gets the last channel number for specified channel page. - * - * @note The channel number is returned in inner representation as channels bits - * stored in channel mask internally, it may differ from real channel numbers - * specified by spec. - * - * @param page - channel page - * @param channel_number [out] - channel number - * - * @return RET_OK or RET_NOT_FOUND. - */ -zb_ret_t zb_channel_page_get_max_channel_number(zb_uint8_t page, zb_uint8_t *channel_number); - -/** - * @brief Converts logical channel to channel number within channel mask for - * specified channel page. For example: - * - page [in] = 30 - * - logical channel [in] = 36 - * - channel number [out] = 1 - * - * @param page [in] - channel page - * @param logical_channel [in] - logical channel (e.g. simply channel) - * @param channel_number [out] - channel number within channel mask (inner representation) - * - * @return RET_OK - success, - * RET_NOT_FOUND - unknown channel page, - * RET_INVALID_PARAMETER - unacceptable logical channel for specified channel page. - */ -zb_ret_t zb_channel_page_channel_logical_to_number(zb_uint8_t page, - zb_uint8_t logical_channel, - zb_uint8_t *channel_number); - -/** - * @brief Converts channel number within channel mask to logical channel for - * specified channel page. For example: - * - page [in] = 30 - * - channel number [in] = 1 - * - logical channel [out] = 36 - * - * @param page - channel page - * @param channel_number - channel number within channel mask (inner representation) - * @param logical_channel [out] - logical channel (e.g. simply channel) - * - * @return RET_OK - success, - * RET_NOT_FOUND - unknown channel page, - * RET_INVALID_PARAMETER - unacceptable logical channel for specified channel page. - */ -zb_ret_t zb_channel_page_channel_number_to_logical(zb_uint8_t page, - zb_uint8_t channel_number, - zb_uint8_t *logical_channel); - -/** - * @brief Sets bit in channel mask corresponding to specified channel number. - * - * @param list - channel list - * @param idx - index of channel page which channel mask will be modified - * @param channel_number - channel number within channel mask (inner representation) - * - * @return RET_OK - success, - * RET_INVALID_PARAMETER - unacceptable channel number for specified channel page. - */ -zb_ret_t zb_channel_page_list_set_channel(zb_channel_list_t list, - zb_uint8_t idx, - zb_uint8_t channel_number); - -/** - * @brief Sets bit in channel mask corresponding to specified channel number. - * - * @param list - channel list - * @param page - logicl page number - * @param channel_number - logical channel number - * - * @return RET_OK - success, - * RET_INVALID_PARAMETER - unacceptable channel number for specified channel page. - */ -zb_ret_t zb_channel_page_list_set_logical_channel(zb_channel_list_t list, - zb_uint8_t page, - zb_uint8_t channel_number); - - - -/** - * @brief Unsets bit in channel mask corresponding to specified channel number. - * - * @param list - channel list - * @param idx - index of channel page which channel mask will be modified - * @param channel_number - channel number within channel mask (inner representation) - * - * @return RET_OK - success, - * RET_INVALID_PARAMETER - unacceptable channel number for specified channel page. - */ -zb_ret_t zb_channel_page_list_unset_channel(zb_channel_list_t list, - zb_uint8_t idx, - zb_uint8_t channel_number); - -zb_uint8_t zb_channel_page_list_get_channels_num(zb_channel_list_t list, - zb_uint8_t idx); - - -#ifdef ZB_MAC_CONFIGURABLE_TX_POWER -/** - * @brief Get offsets for MAC TX power stored in the production config for - * specified channel and page - * - * @param page - logicl page number - * @param channel_number - logical channel number - * @param array_idx [out] - pointer to store array id. The value -1 is an invalid value. - * @param array_ofs [out] - pointer to store array offset. The value -1 is an invalid value. - * - */ -void zb_channel_get_tx_power_offset(zb_uint8_t page, zb_uint8_t channel, - zb_uint8_t *array_idx, zb_uint8_t *array_ofs); - -#endif /* ZB_MAC_CONFIGURABLE_TX_POWER */ - - -/*! @} */ - -#endif /* ZB_CHANNEL_PAGE_H */ diff --git a/zboss/development/include/zb_config.h b/zboss/development/include/zb_config.h deleted file mode 100644 index a18fa4d34e..0000000000 --- a/zboss/development/include/zb_config.h +++ /dev/null @@ -1,1989 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Configuration file: configuration- and platform-specific definitions, -constants etc. -*/ - -#ifndef ZB_CONFIG_H -#define ZB_CONFIG_H 1 - -/** - Load vendor specific configurations -*/ - -/* \defgroup buildconfig Build Configurations - @{ */ -#include "zb_vendor.h" -/** - Load common ZBOSS definitions -*/ -#include "zb_config_common.h" - -/* - * ZC/ZR - GPPB role library (default) (implementation of Basic Proxy is mandatory for Zigbee 3.0 ZR) - * ZC/ZR - GPCB role library (Options file shall use ZB_ENABLE_ZGP_COMBO define) - * ZC/ZR - GP Commissioning Tool (Options file shall use ZGP_COMMISSIONING_TOOL define) - * ZED - Target role library (default) (Options file shall use ZB_ENABLE_ZGP_TARGET define) - * ZED - Target+ role library (Options file shall use ZB_ENABLE_ZGP_TARGET_PLUS define) - * - * To enable advanced features (not covered by the current version of GP specification) please - * define ZB_ENABLE_ZGP_ADVANCED, so in this case the GPPB/GPCB/GPCT basic libs will be re-compiled - * to GPP/GPC/GPCT advanced libs - * - * GP infrastructure devices: - * - * A.3.2.1 GP Target device ability: - * - ability to receive any GP frame in tunneled mode - * - * A.3.2.2 GP Target+ device ability: - * - ability to receive any GP frame both in direct mode and in tunneled mode - * - * A.3.2.3 GP Proxy device ability: - * - ability to receive any GP frame in direct mode when the proxy is in the radio range of the - * GPD - * - ability to send to the registered sink devices a GP Notification command with the received - * GP frame - * - ability to maintain a Proxy Table at commissioning time to register sink devices which are - * asking for GP frame forwarding service - * - ability to update the Proxy Table based on the observed GP traffic in order to enable GP - * device mobility in the network - * - ability to drop scheduled tunneling of GP frame, based on received GP commands related to - * the same GP frame - * - * A.3.2.4 GP Combo device - * - ability to receive any GP frame both in direct mode and in tunneled mode - * - */ - -#ifdef ZB_ZGPD_ROLE -#define ZB_ENABLE_ZGP_DIRECT -#define ZB_ENABLE_ZGP_SECUR -#define APP_ONLY_NVRAM -#define ZB_MAC_INTERFACE_SINGLE -#elif defined ZB_ENABLE_ZGP && !defined ZB_ENABLE_ZGP_TARGET && defined ZB_ED_ROLE -#undef ZB_ENABLE_ZGP -#endif - - -#if defined ZB_ENABLE_ZGP && !defined ZB_ZGPD_ROLE - -/* -#define ZB_ENABLE_ZGP_ADVANCED -*/ - -#define ZB_ENABLE_ZGP_CLUSTER -#define ZB_ENABLE_ZGP_SECUR -#define ZB_USEALIAS - -#ifndef ZB_ED_ROLE -/* ZED can only be implemented as GP Target/Target+ */ -#define ZB_ENABLE_ZGP_PROXY -#endif - -#ifndef ZB_ENABLE_ZGP_TARGET -#define ZB_ENABLE_ZGP_DIRECT -#define ZB_ENABLE_ZGP_TX_QUEUE -#endif - -#if (defined ZB_ENABLE_ZGP_COMBO || defined ZB_ENABLE_ZGP_TARGET || defined ZB_ENABLE_ZGP_TARGET_PLUS || defined ZGP_COMMISSIONING_TOOL) -#define ZB_ENABLE_ZGP_SINK - -/* Old implementation of 8 bit vector handling on ZGP Sink Side is deprecated now. - * Let's keep it until SC will decide to discontinue it - * All the code under this define should be removed once it will be discontinued */ -#ifndef ZB_ZGP_SINK_SUPPORT_LEGACY_8BIT_VECTOR_HANDLING -#define ZB_ZGP_SINK_SUPPORT_LEGACY_8BIT_VECTOR_HANDLING -#endif - -/**< ZGP Sink Match Info is legacy and is deprecated now. - * Let's keep it until SC will decide to discontinue it - * All the code under this define should be removed once it will be discontinued */ -#ifndef ZB_ZGP_SINK_SUPPORT_LEGACY_MATCH_INFO -#define ZB_ZGP_SINK_SUPPORT_LEGACY_MATCH_INFO -#endif - -#ifdef ZB_ZGP_SINK_SUPPORT_LEGACY_MATCH_INFO -/** Max number of command identifiers in one - * functionality matching table entry */ -#define ZB_ZGP_MATCH_TBL_MAX_CMDS_FOR_MATCH 5U - -/** Max number of cluster identifiers in one - * functionality matching table entry */ -#define ZB_ZGP_TBL_MAX_CLUSTERS 5U -#endif /* ZB_ZGP_SINK_SUPPORT_LEGACY_MATCH_INFO */ - -#endif - -/** Sink table size */ -#ifndef ZB_ZGP_SINK_TBL_SIZE -#define ZB_ZGP_SINK_TBL_SIZE 32U -#endif /* ZB_ZGP_SINK_TBL_SIZE */ - - -/* 5.1.2.3.2 test specification - The default value for DUT-GPP being a Basic Combo pr a Basic Proxy - * is "ZigBeeAlliance09", i.e. {0x5A 0x69 0x67 0x42 0x65 0x65 0x41 0x6C 0x6C 0x69 0x61 0x6E - * 0x63 0x65 0x30 0x39}. */ -#define ZB_ZGP_DEFAULT_LINK_KEY "ZigBeeAlliance09" - -/* 5.1.2.3.2 test specification - The default value for DUT-GPP being a Basic Proxy or Basic Combo - * is 0b000. */ -#define ZB_ZGP_DEFAULT_SHARED_SECURITY_KEY_TYPE ZB_ZGP_SEC_KEY_TYPE_NO_KEY - -/* A.3.3.2.5 The default value is 180 seconds. */ -#ifndef ZB_ZGP_DEFAULT_COMMISSIONING_WINDOW -#define ZB_ZGP_DEFAULT_COMMISSIONING_WINDOW 180U -#endif - -/* in bytes */ -#define ZB_ZGP_MIN_PROXY_TABLE_ENTRY_SIZE 7U - -#ifndef ZB_ZGP_PROXY_COMMISSIONING_DEFAULT_COMMUNICATION_MODE -#define ZB_ZGP_PROXY_COMMISSIONING_DEFAULT_COMMUNICATION_MODE ZGP_PROXY_COMM_MODE_UNICAST -#endif - -#define ZB_ZGP_DEFAULT_COMMISSIONING_EXIT_MODE ZGP_COMMISSIONING_EXIT_MODE_ON_GP_PROXY_COMMISSIONING_MODE_EXIT - -#define ZB_ZGP_DEFAULT_SEC_LEVEL_PROTECTION_WITH_GP_LINK_KEY 0U -#define ZB_ZGP_DEFAULT_SEC_LEVEL_INVOLVE_TC 0U -#define ZB_ZGP_MAX_TEMP_MASTER_COUNT 0x03U -#define ZB_ZGP_DMAX_FOR_ACCUMULATE_TEMP_MASTER_INFO 100U -#define ZB_ZGP_MIN_SINK_TABLE_ENTRY_SIZE 8U -#ifndef MAX_ZGP_CLUSTER_GPDF_PAYLOAD_SIZE -#define MAX_ZGP_CLUSTER_GPDF_PAYLOAD_SIZE 65U /* (64 for APP_000 + 1 byte header size) */ -#endif -#define ZB_GP_DMIN_U_MS 5U -#define ZB_GP_DMIN_D_MS 32U - -#ifndef ZB_ZGP_DEFAULT_COMMUNICATION_MODE -#define ZB_ZGP_DEFAULT_COMMUNICATION_MODE ZGP_COMMUNICATION_MODE_LIGHTWEIGHT_UNICAST -#endif - -#define ZB_ZGP_DEFAULT_SECURITY_LEVEL ZB_ZGP_SEC_LEVEL_NO_SECURITY - -#ifdef ZB_ENABLE_ZGP_PROXY -#ifndef ZB_ZGP_PROXY_TBL_SIZE -#define ZB_ZGP_PROXY_TBL_SIZE 16U -#endif /* ZB_ZGP_PROXY_TBL_SIZE */ -#endif /* ZB_ENABLE_ZGP_PROXY */ - -#endif /* !ZB_ZGPD_ROLE */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -/** - ZB_ENABLE_SE_MIN_CONFIG - enables CBKE-related structures and functionality - can be defined in vendor file directly, or enabled, when ZB_ENABLE_SE is defined -*/ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -#if defined ZB_ENABLE_SE_MIN_CONFIG -#ifndef ZB_SECURITY_INSTALLCODES -#define ZB_SECURITY_INSTALLCODES -#endif -/* ZB_ENABLE_SE could be set to enable only CBKE but not SE commissioning */ -#ifndef ZB_NO_SE_COMMISSIONING -#define ZB_SE_COMMISSIONING -#endif -#ifndef APS_FRAGMENTATION -#define APS_FRAGMENTATION -#endif - -#ifndef ZB_SE_DISABLE_TIME_SYNC -#define ZB_ENABLE_TIME_SYNC -#endif - -#ifdef ZB_SE_KE_WHITELIST -#ifndef ZB_SE_KE_WHITELIST_MAX_SIZE -#define ZB_SE_KE_WHITELIST_MAX_SIZE 32U -#endif -#endif - -#endif /* if defined ZB_ENABLE_SE_MIN_CONFIG */ - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_WWAH -#define ZB_ENABLE_NWK_RETRANSMIT -/* #ifdef ZB_ENABLE_SE */ -/* #pragma error SE inconsistent with WWAH. Disable ZB_ENABLE_SE */ -/* #endif */ -#endif /* ZB_ZCL_SUPPORT_CLUSTER_WWAH */ - -/* - * Use vendor file to define build for the desired band: - * - * ZB_R22_MULTIMAC_MODE - 2.4GHz band and Sub-GHz band supported - * ZB_SUBGHZ_ONLY_MODE - only Sub-GHz band supported - * Nothing of above - only 2.4GHz band supported - */ - -#if defined ZB_SUBGHZ_ONLY_MODE || defined ZB_R22_MULTIMAC_MODE -/* Sub-GHz is used without reference to 2.4GHz band enabled */ -#define ZB_SUBGHZ_BAND_ENABLED - -/* Current Sub-GHz properties */ -#define ZB_MAC_DUTY_CYCLE_MONITORING -#define ZB_MAC_POWER_CONTROL -#define ZB_SUB_GHZ_LBT -#define ZB_ENHANCED_BEACON_SUPPORT -#define ZB_JOINING_LIST_SUPPORT -#define ZB_SUB_GHZ_ZB30_SUPPORT -#define ZB_FILTER_OUT_CLUSTERS -#if !defined SNCP_MODE -#define ZB_ZCL_SUPPORT_CLUSTER_SUBGHZ -#endif -#define ZB_MGMT_NWK_ENHANCED_UPDATE_ENABLED - -#endif /* ZB_SUBGHZ_ONLY_MODE || ZB_R22_MULTIMAC_MODE */ - -/** - Number of frames in GPFS (repeated frames with same mac seq number) - - For debug purposes set it to 1 -*/ - -#ifndef ZB_ZGP_TX_QUEUE_SIZE -#define ZB_ZGP_TX_QUEUE_SIZE 10U -#endif - -#ifdef ZB_ZGP_IMMED_TX -/** Number of zb_zgp_tx_pinfo_t in zb_zgp_tx_packet_info_q_t. */ -#define ZB_ZGP_TX_PACKET_INFO_COUNT ZB_ZGP_TX_QUEUE_SIZE + (ZB_IOBUF_POOL_SIZE / 4U) -/** Value with which immed_tx_frame_counter is incremented upon a reboot. */ -#define ZB_GP_IMMED_TX_FRAME_COUNTER_UPDATE_INTERVAL 1000U -#define ZGP_INCLUDE_DST_LONG_ADDR -#else -#define ZB_ZGP_TX_PACKET_INFO_COUNT ZB_ZGP_TX_QUEUE_SIZE -#endif /* ZB_ZGP_IMMED_TX */ -/** Maximum payload length in outgoing ZGP frames */ -#ifndef ZB_ZGP_TX_CMD_PLD_MAX_SIZE -#define ZB_ZGP_TX_CMD_PLD_MAX_SIZE 64U /* Maximum payload size of APP_0000 packet */ -#endif - -#define ZB_ZGP_LED_COMMISSIONING_PARAMS ZB_LED_ARG_CREATE(0, ZB_LED_BLINK_HALF_SEC) - -/* some preconditions and dependencies */ -#ifdef ZB_BDB_TOUCHLINK -#define ZB_ENABLE_ZLL -#define ZB_ENABLE_INTER_PAN_EXCHANGE -#endif - -/* Add dependency to the Inter-Pan exchange */ -#ifdef ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL -#ifndef ZB_ENABLE_INTER_PAN_EXCHANGE -#define ZB_ENABLE_INTER_PAN_EXCHANGE -#endif -#endif - - -/* - Features to be specified in vendor config: - - - ZB_ENABLE_HA - - ZB_ENABLE_ZLL - - ENABLE_ZGP_TARGET_PLUS - - HA specific: - -ZB_ALL_DEVICE_SUPPORT - -*/ - -/* BDB uses HA clusters */ -#if defined ZB_BDB_MODE && !defined ZB_ENABLE_HA -#define ZB_ENABLE_HA -#endif - -/** - Size of table used for long addresses compression: 3 bytes of manufacturer ID. - - ZBOSS implements long address compression: 3 bytes of manufacturer - ID are stored in the separate table; reference to manufacturer - entry is stored in the long address giving 2 bytes economy. - - That is an absolute limit of numbers of manufacturers known to the device. - - @note All that machinery will not work if instead of legal - manufacturer IDs (or illegal, but fixed IDs) use random values. - */ -#ifndef ZB_DEV_MANUFACTURER_TABLE_SIZE -#define ZB_DEV_MANUFACTURER_TABLE_SIZE 32U -#endif - -/* There were configuration options for different platforms. - Since in ZOI we are separating stack and platform making not all platforms visible, - include here current platform-specific stuff. - - Now every platform has its own platform/include/zb_config_platform.h where we moved stuff like -#if (defined ZB_CONFIG_LINUX_NSNG || defined ZB_CONFIG_SGW_NSNG) -#define ZB_NSNG -#define ZB_DSR_MAC -... - - -Ideally should rework the whole zb_config.h to suit better for that new concept. - - */ -#include "zb_config_platform.h" - -#ifndef ZB_ZGPD_GPFS_SIZE -#define ZB_ZGPD_GPFS_SIZE 4U -#endif - - - -/* #define ZB_TRANSCEIVER_ALL_CHANNELS_MASK (0xffff << 11) */ /* 0000.0111 1111.1111 1111.1000 0000.0000*/ -/* C51 doesn't like long shifts, it just cut last two bytes. (11-26) */ -/* TODO: Remove old subgig definitions */ -#if defined ZB_SUBGHZ_BAND_ENABLED -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK 0x07FFF800U /* 11-26 for compatibility with 2.4Ghz*/ -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK_PAGE23 0xB9FFFFFFU -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK_PAGE24 0xC01FFFFFU -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK_PAGE25 0xCFFFFFFFU -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK_PAGE26 0xD00000FFU -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK_PAGE27 0xD81FFFFFU -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK_PAGE28 0xE7FFFFFFU -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK_PAGE29 0xE80001FFU -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK_PAGE30 0xF7FFFFFFU -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK_PAGE31 0xFFFFFFFFU -#else -#define ZB_TRANSCEIVER_ALL_CHANNELS_MASK 0x07FFF800U /* 0000.0111 1111.1111 1111.1000 0000.0000*/ -#endif /* !ZB_SUBGHZ_BAND_ENABLED */ - -#define MAC_DEVICE_TABLE_SIZE 4U - -#if defined ZB_ENABLE_INTER_PAN_EXCHANGE && ! defined ZB_MAC_EXT_DATA_REQ -#define ZB_MAC_EXT_DATA_REQ -#endif /* defined ZB_ENABLE_INTER_PAN_EXCHANGE && ! defined ZB_MAC_EXT_DATA_REQ */ - - - - - -/* MAC transport in Linux, line NSNG, uart/macsplit etc */ - -/***********************************************************************/ -/****************************General stack options**********************/ -/***********************************************************************/ - -#define ZB_VERSION "0.2.0.1" - -/*! \addtogroup ZB_CONFIG */ -/*! @{ */ - -/** Network Selection Stack Profile ID*/ -#define STACK_NETWORK_SELECT 0x00U -/** 2007 Stack Profile ID */ -#define STACK_2007 0x01U -/** Pro Stack Profile ID */ -#define STACK_PRO 0x02U - -/** - This define switches PRO version on or off. -*/ -#define ZB_PRO_STACK - -/** - If defined, 2007 stack profile is implemented -*/ -//#define ZB_STACK_PROFILE_2007 - -/** - * If defined, NVRAM is used - * Create *.nvram file - * - * To be used near always to prevent flash damage (flash can do ~1000 rewrites only) - * - * For certification test need comment. - * Else change Assignment to Rejoin for second and last runs - * - */ -//#define NVRAM_NOT_AVAILABLE - -#if !defined NVRAM_NOT_AVAILABLE && !defined ZB_USE_NVRAM -#define ZB_USE_NVRAM -#endif -/*! @} */ /* ZB_CONFIG */ - -/** - Use 32-bit timer -*/ -#define ZB_TIMER_32 - -#ifndef ZB_CB_QUANT -#define ZB_CB_QUANT 1U -#endif /* !ZB_CB_QUANT */ - -/*! \addtogroup ZB_CONFIG */ -/*! @{ */ - -/* MMDEVQ: what to do??? */ -/** - Zigbee channel selection. - Default value of ZB_AIB().aps_channel_mask - Channels to be used for discovery and join. - If a single channel is selected, there is no need to perform energy scan. - - @note ZLL, HA, ZLL tests can redefine this mask with the means of other constants. -*/ - -/* ZB_DEFAULT_APS_CHANNEL_MASK can be redefined in zb_vendor.h */ -#ifndef ZB_DEFAULT_APS_CHANNEL_MASK -//#define ZB_DEFAULT_APS_CHANNEL_MASK ((1l<<11)) -/* Change that place if you want to set channel for internal tests */ -//#define ZB_DEFAULT_APS_CHANNEL_MASK ((1l<<11)) -/* #define ZB_DEFAULT_APS_CHANNEL_MASK ((1l<<16)) */ -#define ZB_DEFAULT_APS_CHANNEL_MASK (ZB_TRANSCEIVER_ALL_CHANNELS_MASK) -#endif /* ZB_DEFAULT_APS_CHANNEL_MASK */ -/** @} */ /* ZB_CONFIG */ - - -/* PRO stack specific details */ -/** - NWK: If defined, use stochastic address assignment (Zigbee PRO). -*/ -#define ZB_NWK_STOCHASTIC_ADDRESS_ASSIGN - -/*! Source routing path length, also called nwkMaxSourceRoute */ -#define ZB_NWK_MAX_PATH_LENGTH 5U -/*! Source route table capacity */ -/* 10/21/2019 EE CR:MINOR Isn't it too many? Can we handle situation when source route table is not big enough? */ -#define ZB_NWK_MAX_SRC_ROUTES ZB_NEIGHBOR_TABLE_SIZE -/* 10/21/2019 EE CR:MINOR Better indicate in const name that this is time in seconds by adding _S suffix */ -/*! Expiration time of the source route table (300 sec) */ -#define ZB_NWK_SRC_ROUTE_TABLE_EXPIRY 60U - - - -#if defined ZB_MAC_PENDING_BIT_SOURCE_MATCHING - -#if !defined ZB_MAC_SWITCHABLE_PB_MATCHING && defined ZB_MAC_SOFTWARE_PB_MATCHING && defined ZB_MAC_HARDWARE_PB_MATCHING -#error "Do not define SW and HW pending bit matching at the same time! Use ZB_MAC_SWITCHABLE_PB_MATCHING instead of it!" -#endif /* !ZB_MAC_SWITCHABLE_PB_MATCHING && ZB_MAC_SOFTWARE_PB_MATCHING && ZB_MAC_HARDWARE_PB_MATCHING */ - -#if defined ZB_MAC_SWITCHABLE_PB_MATCHING -#ifndef ZB_MAC_SOFTWARE_PB_MATCHING -#define ZB_MAC_SOFTWARE_PB_MATCHING -#endif - -#ifndef ZB_MAC_HARDWARE_PB_MATCHING -#define ZB_MAC_HARDWARE_PB_MATCHING -#endif -#endif /* ZB_MAC_SWITCHABLE_PB_MATCHING */ - -#endif /* ZB_MAC_PENDING_BIT_SOURCE_MATCHING */ - - -#if defined ZB_MAC_SWITCHABLE_PB_MATCHING || defined ZB_MAC_SOFTWARE_PB_MATCHING || defined ZB_MAC_HARDWARE_PB_MATCHING - -#ifndef ZB_MAC_PENDING_BIT_SOURCE_MATCHING -#error "ZB_MAC_PENDING_BIT_SOURCE_MATCHING must be defined in your vendor or platform config file either!" -#endif /* !ZB_MAC_PENDING_BIT_SOURCE_MATCHING */ - -#endif /* ZB_MAC_SWITCHABLE_PB_MATCHING || ZB_MAC_SOFTWARE_PB_MATCHING || ZB_MAC_HARDWARE_PB_MATCHING */ - - -/****************************Zigbee Roles*******************************/ - -/* -# Device roles per build. - -We usually have ZC and ZR combined. -We can have ZR which can be switched to ZED (via reset to factory defaults), or ZR which is "just ZR". -It could be useful to have ZC-only and ZR-only libraries. -ZED rx-on-when-idle can be configurable at runtime or at compile time. - -To better divide ZC an ZR define functionality groups: - -- routing & parent srv (zc & zr) - ZB_ROUTER_ROLE (name is not perfect, but keep it to minimize code change) -- centralized TC - ZB_COORDINATOR_ROLE (name is not perfect, but keep it to minimize code change) -- joiner client functionality (zr & zed) - ZB_JOIN_CLIENT -- formation functionality - ZB_FORMATION == ZB_COORDINATOR_ROLE || ZB_ROUTER_ROLE && ZB_DISTRIBUTED_SECURITY_ON. Also in request key etc -- distributed-only ZR build (do not link router's update device etc) - ZB_DISTRIBUTED_ONLY -- distributed security - ZB_ROUTER_ROLE & ZB_DISTRIBUTED_SECURITY_ON - - ZR (link if enabled?) -- router security (upd dev send etc) ZB_ROUTER_SECURITY == ZB_ROUTER_ROLE && !ZB_COORDINATOR_ROLE && !ZB_DISTRIBUTED_ONLY -- By default - -- panid conflict resolution (TBD) - - ZC part - always, or if enabled - - ZR part - if enabled - -- address conflict resolution (TBD) - - in ZR role - - in ZC role (recheck: is it so?) - -- ZED functionality (either ZED or ZR) - ZB_ED_FUNC. Can be present in ED-only or ZR build. - -ZB_ED_ROLE == ZB_ED_FUNC && !ZB_ROUTER_ROLE && !ZB_COORDINATOR_ROLE - -ZB_ED_FUNC is polling and ED aging. - -ZB_ROUTER_ROLE, ZB_COORDINATOR_ROLE, ZB_ED_ROLE defines exists for the very beginning. Let's keep it in the code where it is appropriate. - -In general, define ZB_COORDINATOR_ROLE to compile ZC-only build, ZB_ROUTER_ROLE to compile ZR+ZED build, ZB_ED_ROLE to compile ZED-only build. - */ - -#if !defined ZB_ED_ROLE && !defined ZB_ZGPD_ROLE && !defined ZB_COORDINATOR_ROLE && !defined ZB_ROUTER_ROLE -/** - If no any role defined, let it be max possible roles set: ZC + ZR switchable to ZED at runtime -*/ -#define ZB_COORDINATOR_ROLE -#define ZB_ROUTER_ROLE -/** - * If ZB_ROUTER_NO_ED defined, ZR library has no ZED functionality. - * ZR can't switch to ZED mode from application or implicitly join as ZED. - */ -#ifndef ZB_ROUTER_NO_ED -/*! Define Zigbee end device functionality */ -#define ZB_ED_FUNC -#endif -#endif - -#if defined ZB_ED_ROLE || defined ZB_ROUTER_ROLE -/*! Define joiner client functionality */ -#define ZB_JOIN_CLIENT -#endif - -#if defined ZB_COORDINATOR_ROLE && !defined ZB_ROUTER_ROLE -/** - If only ZB_COORDINATOR_ROLE is defined, only ZC role is compiled. -*/ -#define ZB_ROUTER_ROLE -#define ZB_COORDINATOR_ONLY -#endif /*defined ZB_COORDINATOR_ROLE && !defined ZB_ROUTER_ROLE*/ - -#if defined ZB_ROUTER_ROLE && !defined ZB_COORDINATOR_ONLY && !defined ZB_ROUTER_NO_ED - -/* By default ZR can be switched to ZED at runtime. */ -/*! ZB end device functionality */ -#ifndef ZB_ED_FUNC -#define ZB_ED_FUNC -#endif - -#endif - -/* -Related defines -ZB_LITE_ROUTER_ONLY_ROLE -ZB_ED_RX_OFF_WHEN_IDLE - */ - -#if defined ZB_COORDINATOR_ROLE || (defined ZB_ROUTER_ROLE && defined ZB_DISTRIBUTED_SECURITY_ON) - -/*! Formation is supported by ZC or ZR in Distributed mode */ -#define ZB_FORMATION -#endif - -#if defined ZB_ROUTER_ROLE && !defined ZB_COORDINATOR_ONLY && !defined ZB_DISTRIBUTED_ONLY -/*! Defines router security */ -#define ZB_ROUTER_SECURITY -#endif - -#if defined ZB_ED_ROLE && (defined ZB_ROUTER_ROLE || defined ZB_COORDINATOR_ROLE) -#error Conflicting defines: ZB_ED_ROLE excludes ZB_ROUTER_ROLE/ZB_COORDINATOR_ROLE -#endif - -#ifdef ZB_ED_ROLE -/* ED functionality is implemented by ZED-only build or ZR switchable to ZED */ -#define ZB_ED_FUNC -#endif -/** @addtogroup ZB_CONFIG */ -/** @{ */ -/** - * NWK: size of the neighbor table - * - * @note This is a default value of the define. This value can be changed by user. - */ -#ifndef ZB_NEIGHBOR_TABLE_SIZE - -#if defined ZB_COORDINATOR_ROLE -#define ZB_NEIGHBOR_TABLE_SIZE 32U - -#elif defined ZB_ROUTER_ROLE -#define ZB_NEIGHBOR_TABLE_SIZE 32U - -#elif defined ZB_ED_ROLE -#define ZB_NEIGHBOR_TABLE_SIZE 32U - -#elif defined ZB_ZGPD_ROLE -/* zcl_common.zgpd.o won't be built without any ZB_NEIGHBOR_TABLE_SIZE definition. */ -#define ZB_NEIGHBOR_TABLE_SIZE 1U - -#else -#error No any role defined -#endif /* roles */ - -#endif /* ZB_NEIGHBOR_TABLE_SIZE */ - -#if ZB_NEIGHBOR_TABLE_SIZE > 255U -#error ZB_NEIGHBOR_TABLE_SIZE should be less than 255 (fit into 1 byte) -#endif - -/** - * Scheduler callbacks queue size. Usually not need to change it. - * - * @note This is a default value of the define. This value can be changed by user. -*/ -#ifndef ZB_SCHEDULER_Q_SIZE -#ifdef ZB_ED_ROLE -#define ZB_SCHEDULER_Q_SIZE 16U -#else -/* @note: If set ZB_SCHEDULER_Q_SIZE > 32 is set, change alarms bitmask in the scheduler */ -#define ZB_SCHEDULER_Q_SIZE 32U -#endif -#endif /*ZB_SCHEDULER_Q_SIZE*/ -/** @} */ /* ZB_CONFIG */ -#if defined ZB_ED_ROLE -/** - End device idle time-out -*/ -#define ZB_TIME_ED_IDLE ZB_MILLISECONDS_TO_BEACON_INTERVAL(7500) -#endif - - -#if defined ZB_ROUTER_ROLE -/** - NWK: If defined, enable routing functionality -*/ -#define ZB_NWK_ROUTING - -/** - Number of secure materials to store -*/ -#define N_SECUR_MATERIAL 3U - - -#ifndef ZB_NWK_STOCHASTIC_ADDRESS_ASSIGN -/** - If not defined, implement tree routing -*/ -#define ZB_NWK_TREE_ROUTING -#endif /*ZB_NWK_STOCHASTIC_ADDRESS_ASSIGN*/ - -/** - NWK: if defined, implement mesh routing -*/ -#define ZB_NWK_MESH_ROUTING - -#else - -#define N_SECUR_MATERIAL 1U - -#endif /* coordinator or router */ - - -/****************************APS layer options**************************/ -/** @addtogroup ZB_CONFIG */ -/** @{ */ -#ifndef ZB_MAX_EP_NUMBER -/* max supported EP number, increase if needed */ -/** Maximum number of supported endpoints per device */ -#define ZB_MAX_EP_NUMBER 5U -#endif -/* APS binding */ - -#ifndef ZB_MEMORY_COMPACT - -#ifndef ZB_APS_SRC_BINDING_TABLE_SIZE -/** - * APS: SRC binding table size - * - * @note This is a default value of the define. This value can be changed by user. -*/ -#define ZB_APS_SRC_BINDING_TABLE_SIZE 32U -#endif - - -#ifndef ZB_APS_DST_BINDING_TABLE_SIZE -/** - * APS: DST binding table size - * - * @note This is a default value of the define. This value can be changed by user. -*/ -#define ZB_APS_DST_BINDING_TABLE_SIZE 32U -#endif - - -#ifndef ZB_APS_GROUP_TABLE_SIZE -/** - APS: max number of groups in the system -*/ -#define ZB_APS_GROUP_TABLE_SIZE 16U -#endif - - -#ifndef ZB_APS_ENDPOINTS_IN_GROUP_TABLE -/** - APS: max number of endpoints per group table entry -*/ -#define ZB_APS_ENDPOINTS_IN_GROUP_TABLE 8U -#endif - -/** - APS: size of queue to be used to pass - incoming group addresses packets up -*/ -#define ZB_APS_GROUP_UP_Q_SIZE 8U - -#else /* ZB_MEMORY_COMPACT */ - -#ifndef ZB_APS_SRC_BINDING_TABLE_SIZE -#define ZB_APS_SRC_BINDING_TABLE_SIZE 8U -#endif - - -#ifndef ZB_APS_DST_BINDING_TABLE_SIZE -/** - APS: DST binding table size -*/ -#define ZB_APS_DST_BINDING_TABLE_SIZE 8U -#endif - - -#ifndef ZB_APS_GROUP_TABLE_SIZE -/** - APS: max number of groups in the system -*/ -#define ZB_APS_GROUP_TABLE_SIZE 4U -#endif - - -#ifndef ZB_APS_ENDPOINTS_IN_GROUP_TABLE -/** - APS: max number of endpoints per group table entry -*/ -#define ZB_APS_ENDPOINTS_IN_GROUP_TABLE 4U -#endif - -/** - APS: size of queue to be used to pass - incoming group addresses packets up -*/ -#define ZB_APS_GROUP_UP_Q_SIZE 4U - -#endif /* ZB_MEMORY_COMPACT */ - - -#ifndef ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE -/** - * APS: maximum number of tables with key-pair information - * - * @note This is a default value of the define. This value can be changed by user. -*/ -#ifdef ZB_ED_ROLE -#define ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE 5U -#else -/* [EE] 05/25/2016 CR:MINOR Set it to some big value - say, 128. This is total # - * of devices in the network, not neighbor table size */ -#define ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE ZB_NEIGHBOR_TABLE_SIZE -#endif -#endif - -/** - If the joining device does not receive any of - the keys within apsSecurityTimeOutPeriod, of receiving the NLME-JOIN. - confirm primitive, it shall reset - - apsSecurityTimeOutPeriod value is not defined by specification and should be defined in stack - profile. For ZB_PRO_STACK this value equal to 1.7 seconds on 2.4 GHz. - - See Zigbee specification revision 22 subclause 4.4.11 -*/ -#define ZB_APS_SECURITY_TIME_OUT_PERIOD ZB_MILLISECONDS_TO_BEACON_INTERVAL(1700U) - -/** - APS: Get APS ACK wait time for the device depending on its receiver on when idle -*/ -/* WARNING: Generally, it is not according to spec. There are some nwk and APS routines that should - * correlate to this interval, for these we will use ZB_N_APS_ACK_WAIT_DURATION_FROM_SLEEPY. */ -#if !(defined ZB_ED_RX_OFF_WHEN_IDLE && defined ZB_ED_ROLE) -#define ZB_N_APS_ACK_WAIT_DURATION(_rx_on_when_idle) \ - ((_rx_on_when_idle) ? \ - ZB_N_APS_ACK_WAIT_DURATION_FROM_NON_SLEEPY : ZB_N_APS_ACK_WAIT_DURATION_FROM_SLEEPY) -#else -#define ZB_N_APS_ACK_WAIT_DURATION(_rx_on_when_idle) \ - (ZB_N_APS_ACK_WAIT_DURATION_FROM_SLEEPY) -#endif - -/****************************NWK layer options**************************/ - -/* - If defined, NWK and upper layers can access PIB directly. - - Usually, can be defined when using our MAC. - Undef it to separate MAC and upper layers IB spaces for debug purposes. - - #define ZB_DIRECT_PIB_ACCESS - -*/ -/** - * NWK: size of the long-short address translation table - * - * @note This is a default value of the define. This value can be changed by user. -*/ -#ifndef ZB_MEMORY_COMPACT -#define ZB_IEEE_ADDR_TABLE_SIZE 101U -#else -#define ZB_IEEE_ADDR_TABLE_SIZE 32U -#endif - -#ifndef ZB_PANID_TABLE_SIZE -/** - NWK: size of the long-short Pan ID translation table - - Must be <= (packet buffer size - sizeof(*discovery_confirm)) / sizeof(*network_descriptor) - - That value limits number of Pan IDs visible for device during active scan. -*/ -#define ZB_PANID_TABLE_SIZE 16U -#endif -/** @cond DOXYGEN_INTERNAL_DOC */ -/** - If defined, add jitter to broadcast transmits etc. - - @note It adds zb_random() and breaks some tests that are supposed to know - next generated address by setting random generator start. -*/ -#define ZB_NWK_USE_SEND_JITTER -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -/* Some defaults for ZDO startup */ - -#ifndef ZB_TRACE_LEVEL -/** - NWK: default energy/active scan duration -*/ -#define ZB_DEFAULT_SCAN_DURATION 4U - -#ifdef ZB_SUBGHZ_BAND_ENABLED -/** @cond DOXYGEN_SUBGHZ_FEATURE */ -/* as defined in D.7 of Zigbee/r22 */ -#define ZB_DEFAULT_SCAN_DURATION_SUB_GHZ 7U -/** @endcond */ /* DOXYGEN_SUBGHZ_FEATURE */ -#else -#define ZB_DEFAULT_SCAN_DURATION_SUB_GHZ ZB_DEFAULT_SCAN_DURATION -#endif /* !ZB_SUBGHZ_BAND_ENABLED */ - -#else /* ZB_TRACE_LEVEL */ - -/* SNCP release build has enabled trace and in the same time requires to have scan duration value set to 3 */ -#ifdef SNCP_MODE -#define ZB_DEFAULT_SCAN_DURATION 3U -#else -#define ZB_DEFAULT_SCAN_DURATION 5U -#endif /* SNCP_MODE */ - -#if defined ZB_SUBGHZ_BAND_ENABLED -#define ZB_DEFAULT_SCAN_DURATION_SUB_GHZ 7U -#else -#define ZB_DEFAULT_SCAN_DURATION_SUB_GHZ ZB_DEFAULT_SCAN_DURATION -#endif /* !ZB_SUBGHZ_BAND_ENABLED */ - -#endif /*ZB_TRACE_LEVEL*/ - - -#if ZB_ZDO_NWK_SCAN_ATTEMPTS == 1U -/** - Integer value representing the - * number of scan attempts to make - * before the NWK layer decides - * which Zigbee coordinator or - * router to associate with - */ - -#define ZB_NWK_ONE_SCAN_ATTEMPT -#endif /*ZB_ZDO_NWK_SCAN_ATTEMPTS == 1*/ - - -/** - Number of pending Mgmt_Leave requests allowed -*/ -#ifndef ZB_MEMORY_COMPACT -#define ZB_ZDO_PENDING_LEAVE_SIZE 4U -#else -#define ZB_ZDO_PENDING_LEAVE_SIZE 2U -#endif /*ZB_MEMORY_COMPACT*/ -/** @cond DOXYGEN_INTERNAL_DOC */ -#ifndef ZB_COORDINATOR_ONLY -/* Enables PAN blacklisting. Note: it was under ifdef - * ZB_COORDINATOR_ROLE. But ZBOSS usually built with ZR & ZC, so - * blacklist is useful for ZR. */ -/** Enables PAN blacklisting */ -#define ZB_NWK_BLACKLIST -#ifndef ZB_NWK_BLACKLIST_SIZE -/** Size of PAN IDs blacklist */ -#define ZB_NWK_BLACKLIST_SIZE 16U -#endif -#endif - -/** - * NWK Mesh route: routing table size - * - * @note This is a default value of the define. This value can be changed by user. -*/ -#ifndef ZB_MEMORY_COMPACT -#define ZB_NWK_ROUTING_TABLE_SIZE ZB_NEIGHBOR_TABLE_SIZE -#else -#define ZB_NWK_ROUTING_TABLE_SIZE 5U -#endif -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** - Size of channel list structure -*/ -#if defined ZB_SUBGHZ_BAND_ENABLED -#define ZB_CHANNEL_PAGES_NUM 10U -#else -#define ZB_CHANNEL_PAGES_NUM 1U -#endif /* !ZB_SUBGHZ_BAND_ENABLED */ - -/** @cond DOXYGEN_SE_SECTION */ -/** Maximum channel pages number according to the Zigbee revision 22 specification */ -#define ZB_CHANNEL_PAGES_MAX_NUM 5U -/** @endcond */ - -/*! @cond DOXYGEN_INTERNAL_DOC */ -/** -The minimum value of the -backoff exponent (BE) in the -CSMA-CA algorithm. See -7.5.1.4 for a detailed -explanation of the backoff -exponent. - */ -/* As defined in D.6 Zigbee/r22 spec */ -#define ZB_MAC_MIN_BE 5U - - /** -The maximum value of the -backoff exponent, BE, in the -CSMA-CA algorithm. See -7.5.1.4 for a detailed -explanation of the backoff -exponent. - */ -/* As defined in D.6 Zigbee/r22 spec */ -#define ZB_MAC_MAX_BE 8U - -/*! @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -#ifdef ZB_MAC_POLL_INDICATION_CALLS_REDUCED -#ifndef ZB_MAC_POLL_INDICATION_CALL_MAX_TIMEOUT -/** - Default maximum value of Poll Indication calls timeout (in sec) - */ -#define ZB_MAC_POLL_INDICATION_CALL_MAX_TIMEOUT 3600U -#endif -#endif /* ZB_MAC_POLL_INDICATION_CALLS_REDUCED */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -#ifndef ZB_NWK_NEIGHBOUR_PATH_COST_RSSI_BASED -/** - Neighbor path cost calculation method. - By default, calculate neighbor path cost from LQI value as described in ZB - spec(section 3.6.3.1). But for some special cases (e.g. LCGW) we need to calculate path cost - from RSSI value. - */ -#define ZB_NWK_NEIGHBOUR_PATH_COST_LQI_BASED -#endif /* ZB_NWK_NEIGHBOUR_PATH_COST_RSSI_BASED */ - -/*! Reserved space for routing on a parent when a device in ZED role. - * - * ZED doesn't have information about routing, so we need to reserve - * some space in a packet during APSDE data request processing. - * In this case our parent will be able to use at least 7 hops. - * - * If destination is not ZC, it is possible that packet - * can be routed via ZC, and ZC will use source routing. - * - * Use that 24 bytes for either long addresses in nwk hdr with 3 hops - * or 11 hops of source routing. -*/ -#define ZB_NWK_RESERVED_SPACE_FOR_PARENT_ROUTING 24U -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/***********************************************************************/ -/***************************ZBOSS FEATURES SECTION**********************/ -/***********************************************************************/ - -/***************************STACK FEATURES**********************/ - -/** @cond DOXYGEN_INTERNAL_DOC *//* Current stack profile */ -#define ZB_STACK_PROFILE STACK_PRO - -/** - Protocol version selection: see table 1.1(pro-specification) -*/ -#if ZB_STACK_PROFILE == STACK_PRO || ZB_STACK_PROFILE == STACK_2007 -#define ZB_PROTOCOL_VERSION 0x02U -#else -#define ZB_PROTOCOL_VERSION 0x01U -#endif -/** @endcond */ /* DOXYGEN_INTERNAL_DOC ZB_STACK_PROFILE */ - - -#ifndef ZB_BUF_Q_SIZE -/* @note To prevent deadlocks ZB_BUF_Q_SIZE must be < ZB_IOBUF_POOL_SIZE/2 */ -/** - Size of queue for wait for free packet buffer -*/ -#define ZB_BUF_Q_SIZE 8U -#endif /*ZB_BUF_Q_SIZE*/ - -/** - Size, in bytes, of the packet buffer - - @internal Be sure keep it multiple of 4 to exclude alignment problems at ARM -*/ -#ifndef ZB_IO_BUF_SIZE -/* Set the ZBOSS buffer size according to the set of enabled MAC features. */ -#ifdef ZB_MAC_SECURITY -#define ZB_IO_BUF_SIZE 164U -#else /* ZB_MAC_SECURITY */ -#define ZB_IO_BUF_SIZE 152U -#endif /* ZB_MAC_SECURITY */ -#endif /* ZB_IO_BUF_SIZE */ - -/** - Buffer tail portion alignment - 4. - - Note: not sizeof(zb_size_t) because at 64-bit build it is 8 which we don't want. - */ -#define ZB_BUF_ALLOC_ALIGN (4U) - - -/** - Number of fragmented packets which ZBOSS can receive in parallel - */ -#define ZB_APS_MAX_IN_FRAGMENT_TRANSMISSIONS 3U - -/** - * Number of packet buffers. More buffers - more memory. Less buffers - risk to be blocked due to buffer absence. - * - * @note This is a default value of the define. This value can be changed by user. -*/ -#ifndef ZB_IOBUF_POOL_SIZE -#if defined ZB_MEMORY_COMPACT && defined ZB_ED_ROLE -#define ZB_IOBUF_POOL_SIZE 20U -#else -#define ZB_IOBUF_POOL_SIZE 26U -#endif -#endif - -/** @cond DOXYGEN_INTERNAL_DOC */ -/* - If enabled, real int24 and uint48 types will work. Else, int24 and uint48 is mapped to - int32 and uint32. - See include/zb_uint48.h. -*/ -/** Enable support for int24 and uint48 data types */ -#ifndef ZB_NO_UINT24_48_SUPPORT -#define ZB_UINT24_48_SUPPORT -#endif /* !ZB_NO_UINT24_48_SUPPORT */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** Should expire in this number of attempts if failure*/ -#define ZB_NWK_ROUTING_FAILURE_ATTEMPTS_NUM 1U - -/** Calculate routing expiry step interval based on timer initiation value and number of attempts*/ -#define ZB_NWK_ROUTING_FAILURE_EXPIRY_STEP (ZB_NWK_ROUTING_TABLE_EXPIRY / ZB_NWK_ROUTING_FAILURE_ATTEMPTS_NUM) - -/** - Number of times device fails to send packet to the parent before rejoin -*/ -#define ZB_ZDO_PARENT_LINK_FAILURE_CNT 12U - -/** @cond DOXYGEN_INTERNAL_DOC */ -//#define ZB_ZDO_CHECK_FAILS_NWK_UPDATE_NOTIFY_LIMIT 4 -#define ZB_ZDO_CHECK_FAILS_CLEAR_TIMEOUT (30U * ZB_TIME_ONE_SECOND) - -#define ZB_PREDEFINED_ROUTER_ADDR 0x3344U -#define ZB_PREDEFINED_ED_ADDR 0x3344U -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -#if defined ZB_LITTLE_ENDIAN && defined ZB_BIG_ENDIAN -#error Enable only 1 profile support: ZB_LITTLE_ENDIAN or ZB_BIG_ENDIAN -#endif /* defined ZB_LITTLE_ENDIAN && defined ZB_BIG_ENDIAN */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -/* DA: network status with OUT_OF_MEMORY custom value */ -#if !defined ZB_CHECK_OOM_STATUS && !defined xZB_CHECK_OOM_STATUS && !defined ZB_MACSPLIT_DEVICE && !defined ZB_LITE_NO_OOM_DETECTION -/** Enable check whether the ZBOSS stack is out of memory */ -#define ZB_CHECK_OOM_STATUS -#endif -//#define ZB_SEND_OOM_STATUS - -#ifdef ZB_CHECK_OOM_STATUS -/** If bufpool is in out of memory state for a period, specified by ZB_OOM_THRESHOLD, - * then assertion is triggered. */ -#define ZB_OOM_THRESHOLD (120U * ZB_TIME_ONE_SECOND) -#ifdef ZB_SEND_OOM_STATUS -#define ZB_SEND_OOM_DELAY (5U * ZB_TIME_ONE_SECOND) -#endif /* ZB_SEND_OOM_STATUS */ -#endif /* ZB_CHECK_OOM_STATUS */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -#if defined ZB_JOINING_LIST_SUPPORT -/** @cond DOXYGEN_JOINING_LIST_SECTION */ -#define ZB_JOINING_LIST_Q_SIZE 5U -#define ZB_JOINING_LIST_RESP_ITEMS_LIMIT 9U -#define ZB_JOINING_LIST_DELAY_STEP ZB_TIME_ONE_SECOND -/* default value for mibIeeeExpiryInterval, in minutes */ -#define ZB_JOINING_LIST_DEFAULT_EXPIRY_INTERVAL 5U -/** @endcond */ /* DOXYGEN_JOINING_LIST_SECTION */ -#endif /* ZB_JOINING_LIST_SUPPORT */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -/** The necessity of radio interrupt disabling/enabling when MAC gets RX/TX interrupt statuses is platform-dependent. - * This protection is not needed only if the platform guarantees that getting a 4-byte aligned variable is an atomic operation. - * If platform allows do it without this protection, ZB_GET_RADIO_FLAG_UNPROTECTED macro should be defined for this feature in platform. - * Otherwise, radio interrupts disabling/enabling for the case will be switched on. - */ -#ifndef ZB_GET_RADIO_FLAG_UNPROTECTED -#define ZB_GET_RADIO_FLAG_INT_DISABLE() ZB_RADIO_INT_DISABLE() -#define ZB_GET_RADIO_FLAG_INT_ENABLE() ZB_RADIO_INT_ENABLE() -#else -#define ZB_GET_RADIO_FLAG_INT_DISABLE() -#define ZB_GET_RADIO_FLAG_INT_ENABLE() -#endif -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/***************************HA and ZLL FEATURES**********************/ -/** @cond DOXYGEN_INTERNAL_DOC */ -#if defined ZB_ENABLE_HA || defined ZB_ENABLE_ZLL -#define ZB_ENABLE_ZCL - -#if defined ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS -#ifndef ZB_MAC_DIAGNOSTICS -#define ZB_MAC_DIAGNOSTICS -#endif -#ifndef ZDO_DIAGNOSTICS -#define ZDO_DIAGNOSTICS -#endif -#endif /* ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS */ - -#endif /* defined ZB_ENABLE_HA || ZB_ENABLE_ZLL */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/* Enable only 1 profile support: ZLL or HA */ -/** @cond DOXYGEN_TOUCHLINK_FEATURE */ -#if defined ZB_ENABLE_ZLL || defined DOXYGEN -/** @brief Controls inter-PAN exchange feature */ -#define ZB_ENABLE_INTER_PAN_EXCHANGE -/* only ZLL uses AES128 decoding */ -#define ZB_NEED_AES128_DEC -#define ZB_ZLL_ENABLE_COMMISSIONING_CLIENT -#define ZB_ZLL_ENABLE_COMMISSIONING_SERVER -#ifdef ZB_ZLL_ENABLE_COMMISSIONING_CLIENT -/* Client device should be address assignment capable */ -#define ZB_ZLL_ADDR_ASSIGN_CAPABLE -#endif -#define ZB_ZLL_PRIMARY_CHANNELS {11, 15, 20, 25} -#endif /* defined ZB_ENABLE_ZLL || defined DOXYGEN */ -/** @endcond */ /* DOXYGEN_TOUCHLINK_FEATURE */ - -/*************************Serial and UDP trace**********************/ -#ifndef ZB_PLATFORM_LINUX /* Uncomment for binary logs! */ -#if defined ZB_SERIAL_FOR_TRACE || defined ZB_TRACE_OVER_JTAG || defined ZB_NET_TRACE -/* binary trace: optimize traffic size. need special win_com_dump */ -#define ZB_BINARY_TRACE -/* #define ZB_TRAFFIC_DUMP_ON */ -/* #define ZB_TRAF_DUMP_V2 */ -#endif /*ZB_SERIAL_FOR_TRACE || defined ZB_TRACE_OVER_JTAG || defined ZB_NET_TRACE*/ -#endif /*ZB_PLATFORM_LINUX*/ - -/** @cond DOXYGEN_INTERNAL_DOC */ -#ifdef ZB_PLATFORM_LINUX - -/* NSNG run in the single thread */ -#define ZB_THREADS -#ifndef ZB_INIT_HAS_ARGS -#define ZB_INIT_HAS_ARGS -#endif -#ifndef ZB_HAVE_FILE -#define ZB_HAVE_FILE -#endif -#ifndef ZB_TRACE_TO_FILE -#define ZB_TRACE_TO_FILE -#endif -#ifndef ZB_TMP_FILE_PATH_PREFIX -#define ZB_TMP_FILE_PATH_PREFIX "" -#endif -#ifndef ZB_BINARY_FILE_PATH_PREFIX -#define ZB_BINARY_FILE_PATH_PREFIX "" -#endif -#ifndef ZB_USERDATA_FILE_PATH_PREFIX -#define ZB_USERDATA_FILE_PATH_PREFIX "" -#endif -#ifndef ZB_LOG_FILE_PATH_PREFIX -#define ZB_LOG_FILE_PATH_PREFIX ZB_TMP_FILE_PATH_PREFIX -#endif - -#ifdef ZB_USE_LOGFILE_ROTATE -#ifndef LOG_ROTATE_1K -#define LOG_ROTATE_1K 1024 -#endif -#ifndef ZB_DEFAULT_MAX_LOGFILE_SIZE -#define ZB_DEFAULT_MAX_LOGFILE_SIZE (720 * LOG_ROTATE_1K) -#endif -#ifndef ZB_DEFAULT_TOTAL_LOGS_SIZE -#define ZB_DEFAULT_TOTAL_LOGS_SIZE (2160 * LOG_ROTATE_1K) -#endif -#ifndef ZB_DEFAULT_MAX_LOGFILE_CNT -#define ZB_DEFAULT_MAX_LOGFILE_CNT (ZB_DEFAULT_TOTAL_LOGS_SIZE / ZB_DEFAULT_MAX_LOGFILE_SIZE) -#endif -#endif /* ZB_USE_LOGFILE_ROTATE */ - -/* # define ZB_BINARY_TRACE */ -/* # define ZB_NET_TRACE */ -/* # define ZB_TRAFFIC_DUMP_ON */ -#if (ZB_STACK_SPEC_VERSION < 23U) -#define ZB_TRAFFIC_DUMP_V3 -#endif -#endif - -#ifndef ZB_MEMTRACE_BUF_SIZE -#define ZB_MEMTRACE_BUF_SIZE 4080U -#endif - -/* Tune trace portion to fit HTTPS body into single Ethernet frame. Align to 3 - * because base64 packs 3 bytes into 4 chars. */ -#ifndef ZB_NET_TRACE_PORTION -#define ZB_NET_TRACE_PORTION 1020U -#endif - - -/** - If defined, transport calls traffic dump by itself, generic MAC not need to do it -*/ -//#define ZB_TRANSPORT_OWN_TRAFFIC_DUMP_ON - -//#define ZB_DUMP_TRAF - -/** - Name for trace off switch file - - If file of this name exists in the current directory, switch off both trace - and traffic dump. -*/ -#define ZB_TRACE_SWITCH_OFF_FILE_NAME "trace_off" -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/************************Hardware watchdog******************/ - - -#ifndef ZB_WATCHDOG_SCHED_QUANT -/** - *Check watchdogs once per 20 sec. - *The hardware watchdog timer is set to 30 seconds, - *it should be initiated even if there is no job for it -*/ -#define ZB_WATCHDOG_SCHED_QUANT (20U * ZB_TIME_ONE_SECOND) -#endif - - -/** @cond DOXYGEN_INTERNAL_DOC */ -/* membuffers debug: */ -/* extra buffers trace and debug */ -/* WARNING: Disabled by default. It costs too many ROM size! */ -#if ZB_TRACE_LEVEL && ZB_TRACE_MASK -/* #define ZB_DEBUG_BUFFERS */ -#endif - -/* Assert when already freed memory buffer is accessed. Useful for debugging */ -#ifdef ZB_DEBUG_BUFFERS -#define ZB_BUF_SHIELD -/* extended membuffers debug*/ -#ifdef ZB_DEBUG_BUFFERS_EXT -#define ZB_DEBUG_BUFFERS_EXT_USAGES_COUNT 1U -#endif -#endif /*ZB_DEBUG_BUFFERS*/ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/************************Special modes for testing*******************/ - -#if defined DEBUG && defined ZB_CERTIFICATION_HACKS - -/** - * This define turns on/off test profile - */ -#if !defined ZB_TEST_PROFILE -#define ZB_TEST_PROFILE -#endif - -#endif /* DEBUG && ZB_CERTIFICATION_HACKS */ - - -/* Testing mode for some pro certification tests */ -/** @cond DOXYGEN_INTERNAL_DOC */ - -/* See: certification test TP_PRO_BV-11 */ -#ifdef ZB_CERTIFICATION_HACKS -#if !defined ZB_LIMIT_VISIBILITY && !defined ZB_MEMORY_COMPACT -#define ZB_LIMIT_VISIBILITY -#endif /*!ZB_LIMIT_VISIBILITY && !ZB_MEMORY_COMPACT */ -#endif /* ZB_CERTIFICATION_HACKS */ - -#ifdef ZB_LIMIT_VISIBILITY -/** - Maximum number of addresses in the visibility limit arrays -*/ -#define ZB_N_VISIBLE_ADDRESSES 6U -#endif - -#if defined ZB_ROUTER_ROLE -/* See: certification test 13.66_Commissioning_the_short_address */ -#define ZB_PRO_ADDRESS_ASSIGNMENT_CB -#endif /*defined ZB_COORDINATOR_ROLE || defined ZB_ROUTER_ROLE*/ - -/* Compatibility tests (with Ember Zigbee platform ISA3)*/ - -/* Ember + ZBOSS stack with ZLL Profile*/ - -/* Ember + ZBOSS Core Pro stack */ -//#define ZB_EMBER_TESTS - -/* Send messages with empty payload without APS-security */ -#define ZB_SEND_EMPTY_DATA_WITHOUT_APS_ENCRYPTION - - -//* Definitions for 802.15.4 certification hacks */ - -//#define MAC_CERT_TEST_HACKS - -//* -// This define turns on/off channel error mode (set errors while data sending) -//*/ -//#define ZB_CHANNEL_ERROR_TEST - -//#define TP_PRO_BV_31 - -//#define TP_PRO_BV_38 - -/* Put radio into RX mode before transmitting. */ -#ifndef ZB_TRANSCEIVER_ON_BEFORE_TX -#define ZB_TRANSCEIVER_ON_BEFORE_TX 1 -#endif /* ZB_TRANSCEIVER_ON_BEFORE_TX */ - -/* Put radio into RX mode before starting Energy Detection. */ -#ifndef ZB_TRANSCEIVER_ON_BEFORE_ED -#define ZB_TRANSCEIVER_ON_BEFORE_ED 1 -#endif /* ZB_TRANSCEIVER_ON_BEFORE_ED */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/* Certification defines */ - -#if 0 -/** - Disabling of processing of bind_req and end_device_bind_req for certification purposes -*/ -#define ZB_DISABLE_BIND_REQ -#endif - - -#if 0 -/** - Disabling of processing of end device bind requests -*/ -#define ZB_DISABLE_ED_BIND_REQ -#endif - -/*PRO STACK COMPATIBILITY, it is better to turn it on only when needed */ -/* #AT disable compatible mode with 2007 stack version */ -#if 0 -#define ZB_PRO_COMPATIBLE -#endif - -/** - Default value for mac frame version subfield -*/ -#define MAC_FRAME_VERSION MAC_FRAME_IEEE_802_15_4_2003 -/** @cond DOXYGEN_INTERNAL_DOC */ -/** - Block sleepy end devices (devices with rx-on-when-idle == false) from receiving broadcasts (drop it at MAC level) -*/ -#define ZB_BLOCK_BROADCASTS_SLEEPY_ED -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -/* MAC */ -/* TODO: add MAC properties here */ - -#if defined ZB_JOINING_LIST_SUPPORT -/** @cond DOXYGEN_JOINING_LIST_SECTION */ -#ifndef MAC_JOINING_LIST_SIZE_LIMIT -#define MAC_JOINING_LIST_SIZE_LIMIT 16U -#endif -/** @endcond */ /* DOXYGEN_JOINING_LIST_SECTION */ -#endif /* ZB_JOINING_LIST_SUPPORT */ - -/***** GREEN POWER *****/ - -#ifdef ZB_ZGPD_ROLE -#define ZB_MAC_ONLY_STACK -#undef ZB_CHECK_OOM_STATUS -#undef APS_FRAME_SECURITY -#undef ZB_ENABLE_ZCL -#undef ZB_ENABLE_ZLL -#undef ZB_ENABLE_HA -#undef ZB_USE_NVRAM -/* Temporarily disabled for ZGPD MAC library build. */ -/* #undef ZB_DIRECT_MODE_WITH_ZGPD */ -#define ZB_ENABLE_ZGPD_ATTR_REPORTING -/* - * The OperationalChannel sub-field can take the following values: 0b0000: channel 11, - * 0b0001: channel 12, , 0b1111: channel 26. - * 26-11+1 = 12. Let's use 3 series of 4 channels each. - * @note that channelsdiapason must be multiple of series. - */ -#define ZB_ZGPD_CH_SERIES 3U - -#define ZB_GPD_COMMISSIONING_RETRY_INTERVAL ZB_MILLISECONDS_TO_BEACON_INTERVAL(500) -#endif /* ZB_ZGPD_ROLE */ - -#ifdef ZB_ENABLE_ZGP_DIRECT -/* Old GP GPD sensors (until May, 2014) use - * 5 ms offset. New sensors use 20 ms offset.*/ -//#define ZB_GPD_RX_OFFSET_MS 5 -#define ZB_GPD_RX_OFFSET_MS 20U - -/* Old platforms require gpTxOffset calibration. It put into zb_config_platform.h. At new DSR platforms DSR MAC has a call "tx at specified time" so GP TX delay calibrating is not required. */ -#ifndef ZB_GPD_TX_OFFSET_US -#define ZB_GPD_TX_OFFSET_US \ - (ZB_MILLISECONDS_TO_USEC(ZB_GPD_RX_OFFSET_MS)) -#endif - -/** - gpdMinRxWindow - The gpdMinRxWindow is minimal duration of the reception window of an Rx-capable GPD. - It has the value of 0.576 ms that corresponds to the Channel Configuration GPDF of 18B. - GPD vendors shall implement reception window duration that corresponds to the actual GPD frame - size to be received by this GPD, which may never be shorter than - gpdMinRxWindow. - - A.1.6.3.2 gpdMinRxWindow -*/ -#define ZB_GPD_MIN_RX_WINDOW_MS 50U -#endif /* ZB_ENABLE_ZGP_DIRECT */ -/** @} */ /* ZB_CONFIG */ -/************************NVRAM SUPPORT*******************/ - -#if defined ZB_USE_NVRAM - -/** - Interval in which counter is stored -*/ -#define ZB_LAZY_COUNTER_INTERVAL 0x400U -#endif /*ZB_USE_NVRAM*/ - -/** - Migration datasets when page overflow in NVRAM -*/ -#define ZB_NVRAM_DATASET_MIGRATION - -/** Save address map in the NVRAM */ -#define ZB_STORE_ADDR_MAP - -/** Save neighbor table in the NVRAM */ -#define ZB_STORE_NEIGHBOR_TBL - - -/* Check for old GP definitions and produce a error */ -#if defined ENABLE_ZGP_TARGET_PLUS || defined ZB_ENABLE_ZGP_EP || defined ZB_DIRECT_MODE_WITH_ZGPD -#error Old ZGP define detected! -#endif - -/* ZBOSS Lite defines */ - -/* - If defined maximum possible features cut - */ - -#ifdef ZB_ZBOSS_LITE_MAX -#ifndef ZB_LITE_NO_SOURCE_ROUTING -/** - Disable source routing - */ -#define ZB_LITE_NO_SOURCE_ROUTING -#endif - -#ifndef ZB_LITE_NO_NLME_ROUTE_DISCOVERY -/** - Disable route discovery API (but keep implicit route discovery) - */ -#define ZB_LITE_NO_NLME_ROUTE_DISCOVERY -#endif - -#ifndef ZB_NO_NWK_MULTICAST -/** - Disable NWK multicast. Use APS groups and NWK broadcast instead. - */ -#define ZB_NO_NWK_MULTICAST -#endif - -#ifndef ZB_LITE_NO_PANID_CONFLICT_DETECTION -/** - Disable Pan ID conflict detection - */ -#define ZB_LITE_NO_PANID_CONFLICT_DETECTION -#endif - -#ifndef ZB_LITE_NO_PANID_CONFLICT_RECEIVING -/** - Disable Pan ID conflict command receiving - */ -#define ZB_LITE_NO_PANID_CONFLICT_RECEIVING -#endif - - -#ifdef ZB_LITE_NO_LINK_COST -/** - Disable nwk link cost based on lqi - - See 3.6.3.1 Routing Cost - */ -///not sure this is good idea #define ZB_LITE_NO_LINK_COST -#endif - -#ifndef ZB_LITE_NO_ORPHAN_SCAN -//#define ZB_LITE_NO_ORPHAN_SCAN -#endif - - -#ifndef ZB_LITE_NO_APS_DATA_ENCRYPTION -/** - Do not encrypt data at APS level - */ -#define ZB_LITE_NO_APS_DATA_ENCRYPTION -#endif - -#ifndef ZB_LITE_NO_STORE_APS_COUNTERS -/** - Do not store APS security frame counters in nvram - */ -#define ZB_LITE_NO_STORE_APS_COUNTERS -#endif - -#ifndef SNCP_MODE -/** - Do not check for APS security counters inconsistency at unsecure - */ -#ifndef ZB_NO_CHECK_INCOMING_SECURE_APS_FRAME_COUNTERS -#define ZB_NO_CHECK_INCOMING_SECURE_APS_FRAME_COUNTERS -#endif -#endif - -#ifdef ZB_DISTRIBUTED_SECURITY_ON -#undef ZB_DISTRIBUTED_SECURITY_ON -#endif - -#ifdef ZB_SECURITY_INSTALLCODES -#undef ZB_SECURITY_INSTALLCODES -#endif - -#ifdef ZB_CERTIFICATION_HACKS -#undef ZB_CERTIFICATION_HACKS -#endif - - -#ifndef ZB_LITE_NO_UNICAST_SWITCH_KEY -/** - Do not send switch key unicast - */ -#define ZB_LITE_NO_UNICAST_SWITCH_KEY -#endif - - -#ifndef ZB_LITE_NO_GLOBAL_VS_UNIQUE_KEYS -/** - Treat all APS keys as Unique. -(Unique vs Global is brain-damaging flag to define encryption/non encryption at -APS of some APS commands, like Update Device. It was introduced in r20 probably for -compatibility with some old code. */ -//#define ZB_LITE_NO_GLOBAL_VS_UNIQUE_KEYS -#endif - - -#ifndef ZB_LITE_NO_TRUST_CENTER_REQUIRE_KEY_EXCHANGE -/** - Never require unique keys exchange on join - */ -#define ZB_LITE_NO_TRUST_CENTER_REQUIRE_KEY_EXCHANGE -#endif - -#ifndef ZB_LITE_NO_ZDO_SYSTEM_SERVER_DISCOVERY -/** - Exclude ZDO System Server Discovery - */ -#define ZB_LITE_NO_ZDO_SYSTEM_SERVER_DISCOVERY -#endif - -#ifndef ZB_LITE_NO_ZDO_MGMT_RTG -#define ZB_LITE_NO_ZDO_MGMT_RTG -#endif - -#ifndef ZB_LITE_NO_FULL_FUNCLIONAL_MGMT_NWK_UPDATE -#define ZB_LITE_NO_FULL_FUNCLIONAL_MGMT_NWK_UPDATE -#endif - -/** - Do not try to inject LEAVE on data request from ZED which we already timed out. - - That define removes some r21 feature which requires from us to always set - pending bit in any our real devices (just because we are a) not so fast to check - _absence_ of device in the neighbor table and replay with MAC ACK and b) want - to use auto-ack feature of radio which support it - like TI devices). - */ -#ifndef ZB_LITE_NO_LEAVE_INJECTION -#define ZB_LITE_NO_LEAVE_INJECTION -#endif -#ifdef ZB_LITE_NO_LEAVE_INJECTION -#ifdef ZB_MAC_STICKY_PENDING_BIT -#undef ZB_MAC_STICKY_PENDING_BIT -#endif -#endif - -#ifndef ZB_LITE_NO_CONFIGURABLE_LINK_STATUS -#define ZB_LITE_NO_CONFIGURABLE_LINK_STATUS -#endif - -#ifdef ZB_COORDINATOR_ONLY -#ifdef ZB_DISTRIBUTED_SECURITY_ON -#undef ZB_DISTRIBUTED_SECURITY_ON -#endif -#endif - -#ifndef ZB_LITE_NO_INDIRECT_MGMT_LEAVE -/** - Disable mgmt leave with requires sending leave to third device. - */ -#define ZB_LITE_NO_INDIRECT_MGMT_LEAVE -/* Need to store only one entry - about leave myself */ -#ifdef ZB_ZDO_PENDING_LEAVE_SIZE -#undef ZB_ZDO_PENDING_LEAVE_SIZE -#define ZB_ZDO_PENDING_LEAVE_SIZE 1U -#endif -#endif - -#ifndef ZB_LITE_APS_DONT_TX_PACKET_TO_MYSELF -/** - Don't pass from APS up packet which is sent to myself - either directly or - via group. - */ -#define ZB_LITE_APS_DONT_TX_PACKET_TO_MYSELF -#endif - - -#ifndef ZB_LITE_BDB_ONLY_COMMISSIONING -/** - Allow only BDB commissioning and disallow old ZBOSS start sequence - */ -#define ZB_LITE_BDB_ONLY_COMMISSIONING -#endif -#if defined ZB_LITE_BDB_ONLY_COMMISSIONING && !defined ZB_BDB_MODE -#define ZB_BDB_MODE -#endif - - -#ifndef ZB_LITE_LIMIT_PIB_ACCESS -/** - Limit access to PIB to values really used by the stack - */ -#define ZB_LITE_LIMIT_PIB_ACCESS -#endif - -#ifndef ZB_LITE_ALWAYS_SECURE -/** - No ability to switch off security - */ -#define ZB_LITE_ALWAYS_SECURE -#endif - -#ifndef ZB_LITE_DONT_STORE_RSSI -/** - Do not store rssi in the neighbor - */ -//#define ZB_LITE_DONT_STORE_RSSI -//#define ZB_LITE_DONT_STORE_RSSI -#endif - -/** - Disable end device bind - */ -#ifndef ZB_LITE_NO_END_DEVICE_BIND -#define ZB_LITE_NO_END_DEVICE_BIND -#endif - -#ifdef ZB_TEST_PROFILE -#undef ZB_TEST_PROFILE -#endif - -#endif /* ZB_ZBOSS_LITE_MAX */ - - -#ifdef ZB_COORDINATOR_ONLY -#undef ZB_DISTRIBUTED_SECURITY_ON -#endif - -#if defined ZB_TRAFFIC_DUMP_OFF && defined ZB_TRAFFIC_DUMP_ON -#undef ZB_TRAFFIC_DUMP_ON -#endif - - -#ifndef ZB_NO_NWK_MULTICAST -/** - Disable NWK multicast. Deprecated in R21. - Use APS groups and NWK broadcast instead. - */ -#define ZB_NO_NWK_MULTICAST -#endif - - -#ifdef ZB_CONFIGURABLE_MEM - -/* - Huge feature if configuring RAM usage without ZBOSS library recompiling. - Instead of normal static declarations use pointers. - At init time set pointers to be used instead of static arrays used normally. - Keep possibility to compile in a normal way; also keep code mergeable. - Undefine here array size constants and define it to be variables. See zb_g_context.h for details. -*/ -#ifdef ZB_IOBUF_POOL_SIZE -#undef ZB_IOBUF_POOL_SIZE -#endif -#ifdef ZB_SCHEDULER_Q_SIZE -#undef ZB_SCHEDULER_Q_SIZE -#endif -#ifdef ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE -#undef ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE -#endif -#ifdef ZB_IEEE_ADDR_TABLE_SIZE -#undef ZB_IEEE_ADDR_TABLE_SIZE -#endif -#ifdef ZB_NEIGHBOR_TABLE_SIZE -#undef ZB_NEIGHBOR_TABLE_SIZE -#endif -#ifdef ZB_NWK_ROUTING_TABLE_SIZE -#undef ZB_NWK_ROUTING_TABLE_SIZE -#endif -#ifdef ZB_APS_DUPS_TABLE_SIZE -#undef ZB_APS_DUPS_TABLE_SIZE -#endif -#ifdef ZB_APS_SRC_BINDING_TABLE_SIZE -#undef ZB_APS_SRC_BINDING_TABLE_SIZE -#endif -#ifdef ZB_APS_DST_BINDING_TABLE_SIZE -#undef ZB_APS_DST_BINDING_TABLE_SIZE -#endif -#ifdef ZB_APS_BIND_TRANS_TABLE_SIZE -#undef ZB_APS_BIND_TRANS_TABLE_SIZE -#endif -#ifdef ZB_SINGLE_TRANS_INDEX_SIZE -#undef ZB_SINGLE_TRANS_INDEX_SIZE -#endif -/* 10/21/2019 EE CR:MINOR There was #undef ZB_SCHEDULER_Q_SIZE_PROTECTED_STACK_POOL. Was its removal intended? */ -#ifdef ZB_NWK_MAX_SRC_ROUTES -#undef ZB_NWK_MAX_SRC_ROUTES -#endif - -#else -/** - The purpose of the define. Ret code handling implementation on the application side - (via ZB_SCHEDULE_USER_APP_ALARM and ZB_SCHEDULE_USER_APP_CALLBACK) implies that we have some part - of the callback and alarm queues which can not be used from the user app and always should be reserved - for stack schedule purposes. So, let's define this part as 10 (for both immediate callbacks and alarms) - for all configurations. - */ - -#define ZB_SCHEDULER_Q_SIZE_PROTECTED_STACK_POOL 10U -#if (ZB_SCHEDULER_Q_SIZE - ZB_SCHEDULER_Q_SIZE_PROTECTED_STACK_POOL) < 6U -#error The size of application scheduler queue is very small! Please, change ZB_SCHEDULER_Q_SIZE_PROTECTED_STACK_POOL, ZB_SCHEDULER_Q_SIZE to set it at least 6 -#endif -#endif /* ZB_CONFIGURABLE_MEMORY */ - -/* pending bit source matching intended for ZB_ROUTER_ROLE only */ -#ifndef ZB_ROUTER_ROLE -#ifdef ZB_MAC_PENDING_BIT_SOURCE_MATCHING -#undef ZB_MAC_PENDING_BIT_SOURCE_MATCHING -#endif -#ifdef ZB_MAC_SOFTWARE_PB_MATCHING -#undef ZB_MAC_SOFTWARE_PB_MATCHING -#endif -#ifdef ZB_MAC_HARDWARE_PB_MATCHING -#undef ZB_MAC_HARDWARE_PB_MATCHING -#endif -#ifdef ZB_MAC_SWITCHABLE_PB_MATCHING -#undef ZB_MAC_SWITCHABLE_PB_MATCHING -#endif -#endif - -#ifdef ZB_COORDINATOR_ONLY -/* ZLL/Touchlink can be only ZR and ZED */ -#ifdef ZB_BDB_TOUCHLINK -#undef ZB_BDB_TOUCHLINK -#endif -#ifdef ZB_ENABLE_INTER_PAN_EXCHANGE -#undef ZB_ENABLE_INTER_PAN_EXCHANGE -#endif -#ifdef ZB_REJOIN_BACKOFF -#undef ZB_REJOIN_BACKOFF -#endif -#ifdef ZB_DISTRIBUTED_SECURITY_ON -#undef ZB_DISTRIBUTED_SECURITY_ON -#endif -#endif - -#ifdef ZB_ED_ROLE -#define ZB_USE_SLEEP -#endif - -#ifdef ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL -/* Lock queues size to temporarily store packets when inter-pan procedure is in progress */ -#define NWK_INTRP_LOCK_QUEUE_SIZE 5U -#define APS_LOCK_QUEUE_SIZE 5U -#endif - -/*! \addtogroup ZB_CONFIG */ -/*! @{ */ -/** Maximum buffer index. Buffer indexing starts from one. */ -#define ZB_N_BUF_IDS (ZB_IOBUF_POOL_SIZE + 1U) - -#ifdef ZB_PRODUCTION_CONFIG -#define ZB_PRODUCTION_CONFIG_MAX_SIZE 128 - -/** - * @name Production configuration version - * @anchor production_config_version - * - * Note: These values were members of `enum zb_production_config_version_e` type but were converted - * to a set of macros due to MISRA violations. - * - * Versions description: - * v1: - * stack compatibility: R21 - * supported channels: only 2.4Ghz 11-26 - * features: R21 compatible, its own crc `zb_crc32_next_v2`, supports tx_power settings for 2.4GHz - * v2: - * stack compatibility: R22 - * supported channels: - * 1. 2.4 GHz 11-26 - * 2. Subghz page 28 channels 0-26 - * 2. Subghz page 29 channels 27-34, 62 - * 2. Subghz page 30 channels 35-61 - * 2. Subghz page 31 channels 0-26 - * features: not compatible with R21, normal crc, less memory consumed, - * most devices in fields support it, supports tx_power settings for 2.4GHz and 4 subghz pages - * - * v3: - * stack compatibility: R22 - * supported channels: - * 1. 2.4 GHz 11-26 - * 2. Subghz page 23 channels 0-24 - * 2. Subghz page 24 channels 56-76 - * 2. Subghz page 25 channels 0-26 - * 2. Subghz page 26 channels 27-34 - * 2. Subghz page 27 channels 35-55 - * 2. Subghz page 28 channels 0-26 - * 2. Subghz page 29 channels 27-34, 62 - * 2. Subghz page 30 channels 35-61 - * 2. Subghz page 31 channels 0-26 - * features: not compatible with R21, normal crc, supports tx_power for 2.4 GHz and 9 subghz pages. - */ -/** @{ */ -#define ZB_PRODUCTION_CONFIG_VERSION_1_0 0x01U -#define ZB_PRODUCTION_CONFIG_VERSION_2_0 0x02U -#define ZB_PRODUCTION_CONFIG_VERSION_3_0 0x03U -/** @} */ - -#define ZB_PRODUCTION_CONFIG_CURRENT_VERSION ZB_PRODUCTION_CONFIG_VERSION_2_0 -#endif /*ZB_PRODUCTION_CONFIG*/ -/*! @} */ - -/* Note: MAC split SoC doesn't sleep on hardware, but can sleep on Linux platform */ -#if defined USE_ZB_WATCHDOG || (defined(ZB_MACSPLIT_DEVICE) && !defined(ZB_PLATFORM_LINUX)) -#define ZB_NEVER_STOP_TIMER -#endif - -#ifdef ZB_DISABLE_BIN_TRACE_DUMP_EXPOSE_KEYS -#ifdef DEBUG_EXPOSE_KEYS -#warning undefining DEBUG_EXPOSE_KEYS for release build -#undef DEBUG_EXPOSE_KEYS -#endif - -#ifdef DEBUG_EXPOSE_ALL_KEYS -#warning undefining DEBUG_EXPOSE_ALL_KEYS for release build -#undef DEBUG_EXPOSE_ALL_KEYS -#endif - -#ifdef ZB_BINARY_TRACE -#warning undefining ZB_BINARY_TRACE for release build -#undef ZB_BINARY_TRACE -#endif - -#ifdef ZB_TRAFFIC_DUMP_ON -#warning undefining ZB_TRAFFIC_DUMP_ON for release build -#undef ZB_TRAFFIC_DUMP_ON -#define ZB_TRAFFIC_DUMP_OFF -#endif - -#endif /* ZB_DISABLE_BIN_TRACE_DUMP_EXPOSE_KEYS */ - -#if defined NCP_MODE_HOST && !defined SNCP_MODE -#define HAVE_TOP_LEVEL_ERROR_HANDLER -#endif /* NCP_MODE_HOST && !SNCP_MODE */ - -#ifndef ZB_APS_USER_PAYLOAD -#define ZB_APS_USER_PAYLOAD -#endif - -#ifndef ZB_DEPRECATED_API -/* Note: we don't use deprecated API in SNCP */ -#ifndef SNCP_MODE -#define ZB_DEPRECATED_API -#endif -#endif - -/** @cond DOXYGEN_MULTIMAC_SECTION */ -/* Monolithic MAC is a default interface and used when enabled interfaces are not specified in vendors */ -#if !defined(ZB_MAC_MONOLITHIC) && !defined(ZB_MACSPLIT_HOST) && !defined(ZB_MACSPLIT_DEVICE) && !defined(ZB_MAC_SUBGHZ) && !defined(NCP_MODE_HOST) && !defined (ZB_EXTMAC) - #define ZB_MAC_MONOLITHIC -#endif /* !ZB_MAC_MONOLITHIC && !ZB_MACSPLIT_HOST && !ZB_MACSPLIT_DEVICE && !ZB_MAC_SUBGHZ && */ - -#if (defined(ZB_MAC_MONOLITHIC) || defined(ZB_MACSPLIT_DEVICE)) && !defined(ZB_ALIEN_MAC) - #define ZB_COMPILE_MAC_MONOLITHIC -#endif -/** @endcond */ /* DOXYGEN_MULTIMAC_SECTION */ - -#endif /* ZB_CONFIG_H */ diff --git a/zboss/development/include/zb_config_common.h b/zboss/development/include/zb_config_common.h deleted file mode 100644 index d1bcafac12..0000000000 --- a/zboss/development/include/zb_config_common.h +++ /dev/null @@ -1,1739 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Common constants and definitions, mainly related to Zigbee protocol. -*/ -#ifndef ZB_CONFIG_COMMON_H -#define ZB_CONFIG_COMMON_H 1 - -/* -Note: that file included form the very beginning of zb_config.h -Do not put there ifdefs depending on defines made in the middle of zb_config.h! - */ - -/*! \addtogroup ZB_CONFIG */ -/*! @{ */ -/**@cond internals_doc*/ -/* To compile MAC only build; - TODO: Fix it. there should probably be another way to build without security -*/ -/** @endcond *//* internals_doc */ -/****************************Security options**************************/ - -/****************************Security keys***************************/ - -/* Always security on (both NWK and APS). Remove all special security configs */ - -/* -4.6.3.2.2.1 Standard Security Mode - -A default global trust center link key must be supported by the device if no other -link key is specified by the application at the time of joining. This default link key -shall have a value of 5A 69 67 42 65 65 41 6C 6C 69 61 6E 63 65 30 39 -(ZigbeeAlliance09).44 - */ -/*! Define a default global trust center link key */ -#define ZB_STANDARD_TC_KEY {0x5A, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6C, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0x30, 0x39 }; - - -/** - In ZLL specification this is ZLL Certification pre-installed link key - see - 8.7.2 Transfer ring the network key during classical Zigbee commissioning. - - - The distributed security global link key is used to join a distributed security - network. This link key is provided to a company as a result of a successful - certification of a product. For testing, this key SHALL have this default value. - - - See Base Device Behaviour Specification subclause 6.3.2 Distributed security global link key - */ -#define ZB_DISTRIBUTED_GLOBAL_KEY {0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf}; - -/** @cond touchlink */ - -/** -6.3.4 Touchlink preconfigured link key - -The touchlink preconfigured link key is used to join a network via -touchlink. This link key is provided to a company as a result of a -successful certification of a product. For testing, this key SHALL have the -value of: - -In ZLL specification this is 8.7.5.1.2 Certification key (key index 15) - -In BDB 8.7.1.2 Key index and encrypted network key fields. -"This value SHALL be set to 0x04 during certification testing or 0x0f at all -other times." -In ZLL Table 67 Key encryption algorithms: 4 is Master key, 0xf is Certification -key. They use same algorithm. - - */ -#define ZB_TOUCHLINK_PRECONFIGURED_KEY {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf}; - -/** @endcond */ /* touchlink */ - -/* BDB does not mention using of Development ZLL key, so skip it. */ -/** @cond internals_doc */ -/** - SECUR: if defined, implement Standard security - - @note High Security is obsolete and will never be implemented. -*/ -#define ZB_STANDARD_SECURITY - -/** - SECUR: If defined, generate random keys at Trust Center at start of pre-configured key is not set. -*/ -#define ZB_TC_GENERATES_KEYS - -/* (currently - always)*/ -/** - SECUR: If defined, trust Center is at ZC -*/ -#define ZB_TC_AT_ZC -/** @endcond */ /* internals_doc */ -/** - SECUR: CCM key size. Hard-coded -*/ -#define ZB_CCM_KEY_SIZE 16U - -/** - SECUR: CCM key CRC size -*/ -#define ZB_CCM_KEY_CRC_SIZE 2U - -#ifndef ZB_SECUR_N_SECUR_MATERIAL -/* NLS5 - All devices shall maintain at least 2 NWK keys with the frame - counters consistent with the security mode of the network (Standard or High).*/ -/*! Define number of network keys with the frame counter */ -#define ZB_SECUR_N_SECUR_MATERIAL 3U -#endif - -/* parameters for security level 5 - the only security level supported */ -/** - SECUR: security level. Now fixed to be 5 -*/ -#define ZB_SECURITY_LEVEL 5U -/** @cond internals_doc */ -/*! - CCM L parameter for security level 5. -*/ -#define ZB_CCM_L 2U - -/*! - CCM nonce length. -*/ -#define ZB_CCM_NONCE_LEN (15U - ZB_CCM_L) - -/*! - CCM M parameter for security level 5 -*/ -#define ZB_CCM_M 4U - -/*! - Value of nwk packets counter which trigger nwk key switch -*/ -#define ZB_SECUR_NWK_COUNTER_LIMIT ((zb_uint32_t)(~0u) - 128U) - -//#define ZB_DEFAULT_SECURE_ALL_FRAMES 0 -/*! - Default value for nib.secure_all_frames -*/ -#define ZB_DEFAULT_SECURE_ALL_FRAMES 1 - -/*! - Include long address into APS security header - */ -#define ZB_APS_SECUR_APS_USE_EXT_NONCE - -/*! - This macro defines total number of NWK frame unsecure attempts before NWK decides that - frame can not be processed. Made as Workaround. - If frame was not unsecured, cut 1 byte of buffer end and try to unsecure frame again. - */ -//#define ZB_NWK_SECUR_UNSECURE_FRAME_ATTEMPTS 4 - - -/****************************APS layer options**************************/ - - - -/* APS */ - -/* - APS: dup check timeout. - - APS dup checks resolution is 1 sec, so dup timeout is 21 sec. This - interval guaranties total APS retransmission interval (1 original + 2 retransmits). -*/ -/*! Dup check timeout */ -#define ZB_APS_DUP_INITIAL_CLOCK 21U -/*! Sets APS dup checks time out. By default it is 21 sec. This -* interval guaranties total APS retransmission interval (1 original + 2 retransmits). -*/ -#define ZB_APS_DUP_CHECK_TIMEOUT ZB_MILLISECONDS_TO_BEACON_INTERVAL(1000) - -#ifndef ZB_APS_DUPS_TABLE_SIZE -/** - * APS dups table size. - * - * @note This is a default value of the define. This value can be changed by user. - */ -#define ZB_APS_DUPS_TABLE_SIZE 32U -#endif - -/** @endcond *//* internals_doc */ -/*! - Maximum MAC packet waiting time to expire - */ - #define ZB_MAC_INDIRECT_POLL_EXPIRE_TMO ZB_MILLISECONDS_TO_BEACON_INTERVAL(7680U) - - - -/** - APS retransmissions - */ - -/* - APS: max number of packets waiting for APS ACK - - Derive it from the pool size. Keep some free buffers in the pool, remember some - buffers are reserved at start (I see 4 out buffers reserved). -*/ -#ifndef ZB_CONFIGURABLE_MEM -/** - * APS: maximum number of packets waiting for APS ACK - * - * @note This is a default value of the define. This value can be changed by user. - */ - #define ZB_N_APS_RETRANS_ENTRIES ((ZB_IOBUF_POOL_SIZE / 3U) > 0U ? (ZB_IOBUF_POOL_SIZE / 3U) : (ZB_IOBUF_POOL_SIZE / 2U)) -#endif - -/** - * APS maximum of apscMaxFrameRetries times - * - * See Zigbee specification revision 22 section 2.2.7.1 APS Constants -*/ - #define ZB_N_APS_MAX_FRAME_RETRIES 3U - - -/*! - APS: APS ACK wait time from Sleepy devices. After this timeout resend APS packet - see Zigbee specification revision 22 section 2.2.7.1 APS Constants -*/ - #define ZB_N_APS_ACK_WAIT_DURATION_FROM_SLEEPY (10U*ZB_TIME_ONE_SECOND) -/** @cond internals_doc */ -/*! - APS: The base amount of delay before each broadcast parent announce is sent. - */ -#define ZB_APS_PARENT_ANNOUNCE_BASE_TIMER (ZB_SECONDS_TO_BEACON_INTERVAL(10U)) - -/*! -The max amount of jitter that is added to the apsParentAnnounceBaseTimer before each broadcast parent announce is sent. -*/ -#define ZB_APS_PARENT_ANNOUNCE_JITTER_MAX (ZB_SECONDS_TO_BEACON_INTERVAL(10U) - 2U) -/** @endcond */ /*internals_doc*/ - -/** - * APS: APS ACK wait time from Non Sleepy devices. After this timeout resend APS packet - * - * See Zigbee specification revision 22 section 2.2.7.1 APS Constants -*/ - /* Some devices send APS_ACK to AF and ZDO commands after sending appropriate response or - * DefaultResponse. For example, ZCL On/Off command can be done within 5-7 seconds, - * so 2 seconds for wail duration is insufficiently. */ - #define ZB_N_APS_ACK_WAIT_DURATION_FROM_NON_SLEEPY (3U*ZB_TIME_ONE_SECOND) - -/** - APS: maximum number of tables with information from a binding table to be sent to the devices -*/ - #define ZB_N_APS_BINDTRANS_ARR_MAX_SIZE 5U - -/** - * APS: maximum number of elements in array with index from dst array in bind table -*/ - #define ZB_N_APS_BINDTRANS_DST_INDEX_ARR_MAX_SIZE ZB_APS_DST_BINDING_TABLE_SIZE - -/** @cond internals_doc */ -/* Origin of this tweak is R21 version of core stack */ -/* Also it is a kind of "everybody knows" issue */ -/** - Disable APS acknowledgement request bit in APS commands. -*/ -#define ZB_APS_DISABLE_ACK_IN_COMMANDS -/** @endcond *//*internals_doc*/ - -/* EE: wrong place for that constant in zb_aps.h (this is not public APS API!) and wrong - * calculation! - * BTW that constant used at 1 place only. - * ZB_ZDO_MAX_PAYLOAD_SIZE in zb_zdo.h is hard-coded! - * And, zb_zdo.h is also bad place for it. - * - * Let's count supposing no APS security. - * MAC header - 10 with fcf (suppose Pan ID compression) - * NWK header - 24 unicast, but 16 broadcast - * NWK ZB security header + MIC - cf 1 + fcnt 4 + ext src 8 + key seq 1 mic 4 = 18 - * APS hdr 8b - * Totally for broadcast - 127 - (11+16+18+8) = 74 - * For unicast 74-8 = 66 - -Fixed that size for the certification test TP/R21/BV-24. -We actually fit 5 parent annce records into 127 bytes only for broadcast tx, -with Pan ID compression. - -At the worst case our NWK can skip long address at tx: 8 bytes of reserve. - - */ -/**@cond internals_doc*/ -/** - Maximal frame size - */ -#define MAX_PHY_FRM_SIZE 127U - -/** - MAC overhead for unicast frame with Pan ID compression (normal case when - sending via nwk), including FCS bytes -*/ -#define MAX_MAC_OVERHEAD_SHORT_ADDRS 11U - -/* ZB packet length must not exceed 127 bytes - * - * Old calculation by Maxim: - * - * MAC header (total: 11 bytes) - * - FCF: 2 bytes - * - Sequence number: 1 bytes - * - PAN: 2 bytes - * - Destination address: 2 bytes - * - Source address: 2 bytes - * - * NWK header (total: 24 bytes) - * - FCF: 2 bytes - * - Destination short address: 2 bytes - * - Source short address: 2 bytes - * - Radius: 1 byte - * - Sequence number: 1 byte - * - Destination long address: 8 bytes - * - Source long address: 8 bytes - * - * ZB security header (total: 31 bytes) - * - * APS header (total: 8 bytes) - * - FCF: 1 byte - * - Destination endpoint: 1 byte - * - Cluster ID: 2 bytes - * - Profile ID: 2 bytes - * - Source endpoint: 1 byte - * - Counter: 1 byte - * - * APS payload (total: variable length) - * - * MAC footer (total: 2 bytes) - * - FCS: 2 bytes - * - * Total length w/o APS payload: 127-(11+24+31+8+2)= 51 bytes, - * consequently APS payload max size is 51 bytes. - */ -/* - * MAC (short source, short destination): MAX_MAC_OVERHEAD_SHORT_ADDRS bytes - * NWK (broadcast, no destination IEEE): 16 bytes header + 18 bytes security - * Total length: 127-(11+16+18) = 82 bytes */ - /* nwk hdr include source IEEE address */ - -/** - * NWK base header: 8b - * 2b - fcf - * 2b - dst short addr - * 2b - src short addr - * 1b - radius - * 1b - seq num - */ -#define ZB_NWK_BASE_HDR_SIZE 8U - -/*! Maximum broadcast NWK header size */ -#define ZB_NWK_MAX_BROADCAST_HDR_SIZE 16U -/*! Maximum security NWK header size */ -#define ZB_NWK_MAX_SECURITY_HDR_SIZE 18U -/*! Maximum broadcast NWK payload size */ -#define ZB_NWK_MAX_BROADCAST_PAYLOAD_SIZE (MAX_PHY_FRM_SIZE - (MAX_MAC_OVERHEAD_SHORT_ADDRS + \ - ZB_NWK_MAX_BROADCAST_HDR_SIZE + ZB_NWK_MAX_SECURITY_HDR_SIZE)) -/** @endcond */ /* internals_doc */ - -/** @cond internals_doc */ -/*! The size of the MAC header used by the Zigbee NWK layer. */ -#define ZB_NWKC_MAC_FRAME_OVERHEAD 0xBU -/*! The minimum number of octets added by the NWK layer to an NSDU. */ -#define ZB_NWKC_MIN_HEADER_OVERHEAD 0x8U - -/*! - * The number of network layer retries on unicast messages that are attempted before - * reporting the result to the higher layer. It must be at least 3. - * Value: 3 - */ -#define ZB_NWKC_UNICAST_RETRIES 3U - -/*! - * The delay between network layer retries. - * Value: 50 ms - */ -#define ZB_NWKC_UNICAST_RETRY_DELAY ZB_MILLISECONDS_TO_BEACON_INTERVAL(50U) - -/* max nsdulength = aMaxPHYFrameSize -(nwkcMACFrameOverhead + nwkcMinHeaderOverhead) (D.4 aMaxMACFrameSize) */ -/*! Maximum NSDU(Network Service Data Unit) length */ -#define ZB_NSDU_MAX_LEN (MAX_PHY_FRM_SIZE - (ZB_NWKC_MAC_FRAME_OVERHEAD + ZB_NWKC_MIN_HEADER_OVERHEAD)) -/*! The minimum number of octets added by the APS sub-layer to an ASDU. */ -#define ZB_APSC_MIN_HEADER_OVERHEAD 0x0CU -/* max asdu length 256*(NsduLength - apscMinHeaderOverhead); currently fragmentation - * is not supported */ -/*! Maximum ASDU(APS service data unit) length*/ -#define ZB_ASDU_MAX_LEN (ZB_NSDU_MAX_LEN - ZB_APSC_MIN_HEADER_OVERHEAD) - -/* 06/20/2017 EE CR:MAJOR can't always count extra header bytes when calculating max packet length. It is not optimal, and we even may not pass tests checking for max payload length */ -/* NK: Agree, but this define is called MAX_LEN, and includes maximum possible data. Better to - * calculate maximum payload length dynamically (based on fragmentation, destination addr, - * security mode etc). - * Anyway, there are not too many cases where we use ZB_APS_HEADER_MAX_LEN or - * ZB_APS_PAYLOAD_MAX_LEN. - * EE: Can't we assert in zb_zdo_nwk_upd_notify()? You can define 2 constants: fragmented and not. - */ - -/*! Maximum broadcast APS payload size */ -#define ZB_APS_MAX_BROADCAST_PAYLOAD_SIZE 74U -/** - Maximum broadcast APS payload size supposing NWK encryption only, no long - address in NWK header. That means definitely the largest possible size. - */ -#define ZB_APS_MAX_MAX_BROADCAST_PAYLOAD_SIZE (74U + 8U) - -/** - * APS base header: 8b - * 1b - FCF - * 1b - dst ep - * 2b - cluster id - * 2b - profile id - * 1b - src ep - * 1b - counter - */ -#define ZB_APS_BASE_HDR_SIZE 8U - -/** - Ext frame control: 1 byte - Block number: 1 byte - ACK bitfield: 1 byte - for acks only; for data packets it doesn't matter - */ -#define ZB_APS_EXT_HDR_SIZE_DATA_PKT 2U - -#define ZB_APS_EXT_HDR_SIZE_ACK_PKT ((ZB_APS_EXT_HDR_SIZE_DATA_PKT) + 1U) - -/** - MAC hdr: 9 - 3 (hdr, seq num) + 2 * 3 (short dst and src; dst panid) - NWK hdr: 8 - 4 + 2*2 (dst, src short) - NWK security: 18 - APS hdr: 8 (max, without ext header and security) - MAC footer: 2 - - Total: 9 + 8 + 18 + 8 + 2 = 45 bytes - So we can send: 127 - 45 = 82 bytes -*/ -#define ZB_APS_GUARANTEED_PAYLOAD_SIZE_WO_SECURITY \ - ((MAX_PHY_FRM_SIZE) \ - - ((MAX_MAC_OVERHEAD_SHORT_ADDRS) \ - + (ZB_NWK_BASE_HDR_SIZE) \ - + (ZB_NWK_MAX_SECURITY_HDR_SIZE) \ - + (ZB_APS_BASE_HDR_SIZE))) - -/** - * 1b - sec control field - * 4b - frame counter - * 4b - message integrity code - */ -#define ZB_APS_MIN_APS_SECURITY_SIZE 9U - -/** - * ext src addr when ext nonce flag is true - */ -#define ZB_APS_SECURITY_EXT_SRC_SIZE ((zb_uint8_t)sizeof(zb_ieee_addr_t)) - -/** - * Maximum number of bytes that is additionally occupied by APS security (in case of extended nonce) - */ -#define ZB_APS_MAX_APS_SECURITY_SIZE ((ZB_APS_MIN_APS_SECURITY_SIZE) + (ZB_APS_SECURITY_EXT_SRC_SIZE)) - -/* APS base header: 8b - * 1b - FCF - * 1b - dst ep - * 2b - cluster id - * 2b - profile id - * 1b - src ep - * 1b - counter - * - * ext FC: 2b - * 1b - fragmentation - * 1b - block number - * 1b - ACK bitfield - it doesn't matter for data packets - * - * security: 17b - * 1b - control field - * 4b - frame counter - * 4b - message integrity code - * 8b - ieee addr - * - * total: 8b + 2b + 17b = 27b - */ -/*! Maximum length of APS header */ -#define ZB_APS_HEADER_MAX_LEN \ - ((ZB_APS_BASE_HDR_SIZE) \ - + (ZB_APS_EXT_HDR_SIZE_DATA_PKT) \ - + (ZB_APS_MAX_APS_SECURITY_SIZE)) - -/*! Maximum length of an APS payload.*/ -#define ZB_APS_PAYLOAD_MAX_LEN ((ZB_ASDU_MAX_LEN) - (ZB_APS_HEADER_MAX_LEN)) - -/* 01/24/2018 EE CR:MINOR Better move it out of zb_config.common.h */ -/* Value 3 in this define comes for fragmentation and ext header */ -/*Take into account that ZB_ASDU_MAX_LEN counts minimum overhead, but it is sometimes -* impossible to send pkt with these conditions; add 10 more bytes for nwk security etc -*/ -/*! - * Length of an APS payload fragment - * @param short_addr - address of the buffer containing APS fragment - */ -#define ZB_APS_FRAG_PAYLOAD_LEN(short_addr) ((zb_aps_get_max_buffer_size(short_addr)>40+ZB_APS_HEADER_MAX_LEN)?\ - (zb_aps_get_max_buffer_size(short_addr) - ZB_APS_HEADER_MAX_LEN \ - - 3 \ - - 37 ):21) -/*! - * Maximum number of APS fragments - * See Zigbee specification revision 22 section 2.2.8.4.5 Fragmented Transmissions - */ -#define ZB_APS_MAX_FRAGMENT_NUM 8U - -/*! -* Maximum number of fragments which can be -* transmitted/received during one APS frame window. -* -* See Zigbee specification revision 22 section 2.2.8.4.5 Fragmented Transmissions -*/ -#define ZB_APS_MAX_FRAGMENT_NUM_IN_WINDOW 8U -/** @endcond *//* internals_doc */ - -/*! - * Maximum unicast APS payload size, if no APS encryption is provided - */ -#define ZB_APS_MAX_PAYLOAD_SIZE ZB_APS_GUARANTEED_PAYLOAD_SIZE_WO_SECURITY - -/** Maximum buffer size for APS fragmentation. Bigger buffer will not be created for APS fragmentation */ -#define APS_IN_FRAG_MAX_BUF_SIZE 1500U - -/** @cond internals_doc */ -/*! Maximum ZDO payload size */ -#define ZB_ZDO_MAX_PAYLOAD_SIZE (ZB_APS_MAX_PAYLOAD_SIZE-1U) -/** @endcond *//* internals_doc */ - -/****************************NWK layer options**************************/ -/** @cond internals_doc */ -/*! - Define maximum number of children per node. - - This value should be defined in stack profile. - - See Zigbee specification revision 22 subclause 3.5.2 -*/ -#define ZB_NWK_MAX_CHILDREN 4U - -/*! - Define maximum number of routers per node. - - This value should be defined in stack profile. - - See Zigbee specification revision 22 subclause 3.5.2. -*/ -#define ZB_NWK_MAX_ROUTERS 4U - -/** - Define maximum network depth for a tree routing -*/ -#define ZB_NWK_TREE_ROUTING_DEPTH 5U - -/** - Define maximum network depth in stochastic addressing mode (NLF90) -*/ -#define ZB_NWK_STOCH_DEPTH 15U - - -/*! - NWK Mesh route stuff: route discovery table size -*/ -#ifndef ZB_NWK_ROUTE_DISCOVERY_TABLE_SIZE -#define ZB_NWK_ROUTE_DISCOVERY_TABLE_SIZE 6U -#endif - -/* nwkcRouteDiscoveryTime == 0x2710 ms == 10 sec. Expiry function called once - * per second */ -/*! Time period for calling route discovery expiry function */ -#define ZB_NWK_ROUTE_DISCOVERY_EXPIRY 10U -/*! Length of the route discovery function */ -#define ZB_NWK_EXPIRY_ROUTE_DISCOVERY (ZB_N_APS_ACK_WAIT_DURATION_FROM_SLEEPY / ZB_NWK_ROUTE_DISCOVERY_EXPIRY) - -/*#define ZB_NWK_RREQ_TABLE_SIZE 5*/ - -/*! -* The number of times the first broadcast -* transmission of a route request command -* frame is retried. -* -* Correspond to nwkcInitialRREQRetries in Zigbee Specification revision 22 subclause 3.5.1 NWK -* Constants -* -* The value is defined by specification. -*/ -#define ZB_NWK_INITIAL_RREQ_RETRIES 3U -/*! - * The number of times the broadcast - * transmission of a route request command - * frame is retried on relay by an intermediate - * Zigbee router or Zigbee coordinator. - * - * Correspond to nwkcRREQRetries in Zigbee Specification revision 22 subclause 3.5.1 NWK Constants - * The value defined by specification. - */ -#define ZB_NWK_RREQ_RETRIES 2U - -#ifndef ZB_NWK_PENDING_TABLE_SIZE -/*! Pending table size */ -#define ZB_NWK_PENDING_TABLE_SIZE 5U -#endif - -/*! Pending entry expiry during route request */ -#define ZB_NWK_PENDING_ENTRY_EXPIRY 2U -/*! Network static path cost */ -#define ZB_NWK_STATIC_PATH_COST 7U - -/*! -* Delay to wait before sending packet after receiving route replay. -* -* Used only if ZB_CERT_HACKS().delay_pending_tx_on_rresp is 1. -* Useful for test TP_PRO_BV-04. -* Normally ZBOSS sends NWK immediately after receiving any route. -*/ -#define ZB_NWK_SEND_AFTER_RRESP_RECV_DELAY_MS 1000U - - -#ifndef ZB_NWK_BTR_TABLE_SIZE -/*! -* Broadcast transaction record table size -* See Zigbee Specification subclause 3.6.5 -*/ -#define ZB_NWK_BTR_TABLE_SIZE 16U -#endif - -#ifndef ZB_NWK_BRR_TABLE_SIZE -/*! Broadcast Retransmission table size */ -#define ZB_NWK_BRR_TABLE_SIZE 8U -#endif - -/* 01/15/2019 EE CR:MINOR Can't it be better to keep ZB_NWK_MAX_BROADCAST_JITTER_INTERVAL define but internally define it using octets? - In such case you minimize code modifications. same for all similar cases. Why move "octets" to the upper layer? */ -/* nwkcMaxBroadcastJitter */ -/* 01/15/2019 EE CR:MINOR Add reference to the specification: here and in similar cases */ -#define ZB_NWKC_MAX_BROADCAST_JITTER_OCTETS 0x7d0U - -/* nwkcMinRREQJitter */ -#define ZB_NWKC_MIN_RREQ_JITTER_OCTETS 0x3fU - -/* nwkcMaxRREQJitter */ -#define ZB_NWKC_MAX_RREQ_JITTER_OCTETS 0xfa0U - -/* nwkcRREQRetryInterval */ -#define ZB_NWKC_RREQ_RETRY_INTERVAL 0x1f02U - -/*! Expiration time of pending period */ -#define ZB_NWK_EXPIRY_PENDING (ZB_N_APS_ACK_WAIT_DURATION_FROM_SLEEPY / 2U) /* 5 seconds */ - -/* 9 seconds */ -/* According to 2013 PICS, it should be 9 sec. - According to spec, it should be converted from broadcastDeliveryTime */ -/** See Zigbee specification revision 22 section 3.5.2 NWK Information Base - * nwkBroadcastDeliveryTime */ -#define ZB_NWK_EXPIRY_BROADCAST 9U - -/* Check if it is really should be so long. According to r21 spec, 3.6.3.2 - it is out of - * the scope of this spec. */ -/* Should correspond to ( 5 * minutes = 300 seconds / ZB_NWK_EXPIRY_PENDING ) */ -/*! Expiration time of the network routing table */ -#define ZB_NWK_ROUTING_TABLE_EXPIRY 60U - -/*! - * The maximum number of retries allowed after a broadcast transmission failure. - * - * See PICS NDF4. -*/ -#define ZB_NWK_MAX_BROADCAST_RETRIES 0x02U - -/*! - * The maximum time duration in milliseconds allowed for the parent and all - * child devices to retransmit a broadcast message. - * - * See PICS NDF4. - */ -#define ZB_NWK_PASSIVE_ACK_TIMEOUT_OCTETS 0x3D09U - -/*! - NWK Broadcast delivery time See 3.5.2.1 -nwkBroadcastDeliveryTime = 2*nwkMaxDepth* ((0.05+(nwkcMaxBroadcastJitter/2))+ nwkPassiveAckTimeout*nwkBroadcastRetries/1000 -nwkcMaxBroadcastJitter and nwkPassiveAckTimeout are measured in OctetDurations (!). - -In PICS NDF4 for PRO: - -nwkBroadcastDeliveryTime = 0x44AA2 Octet -durations (9 seconds on -2.4 GHz) -nwkPassiveAckTimeout = -0x3D09 Octet -Durations9 (500 ms on -2.4 GHz) maximum -nwkMaxBroadcastRetries -= 2 - */ -#define ZB_NWK_BROADCAST_DELIVERY_TIME_OCTETS 0x44AA2U -/** @endcond *//* internals_doc */ - -/*! - * The time in seconds between link status command frames. - * - * Correspond to nwkLinkStatusPeriod in Zigbee Specification revision 22 subclause 3.5.1 NWK Constants - * The value defined by specification. - */ -#define ZB_NWK_LINK_STATUS_PERIOD 0xfU - -/*! - * The number of missed link status command frames before - * resetting the link costs to zero. - * - * Correspond to nwkRouterAgeLimit in Zigbee Specification revision 22 subclause 3.5.1 NWK Constants - * The value defined by specification. -*/ -#define ZB_NWK_ROUTER_AGE_LIMIT 3U -/** @cond internals_doc */ -/*! - Maximum number of rejoin requests in progress -*/ -#define ZB_NWK_REJOIN_REQUEST_TABLE_SIZE 1U -/** @endcond */ /* internals_doc */ -/*! Rejoin timeout length */ -#define ZB_NWK_REJOIN_TIMEOUT (ZB_TIME_ONE_SECOND * 5U) - -/*! -* The rejoining sleeping end-device shall not poll before the response timeout (500ms), such that -* the parent has enough time to process the rejoin request and put a response frame in its indirect -* queue (same as for association response). Depending on the implementation, once a rejoining device -* has performed an active scan and selected a new parent router, it sends a rejoin request (and at -* that time considers this router to be its new parent, otherwise it cannot accept the rejoin -* response), and polls for a response 500ms later. - */ -#define ZB_NWK_REJOIN_FIRST_POLL_DELAY (ZB_TIME_ONE_SECOND / 2U) - -/*! Number of poll attempts during rejoin */ -#define ZB_NWK_REJOIN_POLL_ATTEMPTS 3U -//#define ZB_NWK_REJOIN_POLL_ATTEMPTS 6 //TEST - -/** @cond internals_doc */ -#ifndef ZB_NWK_CHANNEL_ACCEPT_LEVEL -/*! - * Acceptable energy level on channel - */ -#define ZB_NWK_CHANNEL_ACCEPT_LEVEL 0x60U -#endif - -/** - Devices which sends broadcast packets with rssi lower than this value will not be added - to the neighbor table. - */ -#ifndef ZB_NWK_NEIGHBOR_RSSI_FILTER -#define ZB_NWK_NEIGHBOR_RSSI_FILTER (-80) -#endif - -#ifndef ZB_DEFAULT_PERMIT_JOINING_DURATION -/*! - Default duration to permit joining. Set to infinite by default. -*/ -#define ZB_DEFAULT_PERMIT_JOINING_DURATION 0xffU -#endif -/** @endcond *//* internals_doc */ - -/*! - * Default value of nib.max_children - max number of children which can join to this device - * - * See Zigbee Specification revision 22 section 3.5.2 NWK Information Base -*/ -#define ZB_DEFAULT_MAX_CHILDREN 32U -/**@cond internals_doc */ -/* Old feature from pre-3.0 (HA) era */ -/* If there was an error in NWK security processing of incoming packet from parent, - * then device tries to rejoin. This define disables this behavior */ - -/* By default device is rejoined if network key switch failed */ -/* #define ZB_DISABLE_REJOIN_AFTER_KEY_SWITCH_FAIL */ - -/*! -* The default value of zb_tc_rejoin flag. Allows ZED to rejoin using Trust Center -* rejoin procedure -*/ -#define ZB_TC_REJOIN_ENABLE - - /*! - Define policy of ignoring assoc. permit and corresponding flags during rejoin - */ -#define ZB_REJOIN_IGNORES_FLAGS - -/*! -Workaround for secure rejoin -*/ -#define xZB_NO_KEY_AFTER_REJOIN - -//#define ZB_MULTILEAVE_HACK - - /*! If the macro is defined, the device leaves the network according to application callback*/ -#define ZB_LEAVE_USE_APP_CALLBACK -/** @endcond *//* internals_doc */ -/**@cond DOXYGEN_MULTIMAC_SECTION */ -/*! -* The rate, in seconds, of how often a Link Power Delta request is generated. -* In bands where this is optional, it should be set to 0, disabling the -* function. The default value should be 16. - */ -#define ZB_NWK_LINK_POWER_DELTA_TRANSMIT_RATE 16U - -/*! A Link Power Delta request rate jitter */ -#define ZB_NWK_LINK_POWER_DELTA_TRANSMIT_RATE_JITTER 10U /* 10 seconds */ -/** @endcond *//* DOXYGEN_MULTIMAC_SECTION */ -/********************ZDO layer options*********************************/ -/**@cond internals_doc*/ - /*! - ZDO Indirect poll timer - */ -#define ZB_ZDO_INDIRECT_POLL_TIMER (5U*ZB_TIME_ONE_SECOND) /* ZB_TIME_ONE_SECOND*10 */ - -/*! - ZDO Max parent threshold retry - */ -#define ZB_ZDO_MAX_PARENT_THRESHOLD_RETRY 10U - -/*! - Min scan duration for mgmt_nwk_update_req -*/ -#define ZB_ZDO_MIN_SCAN_DURATION 0U -/*! - Max scan duration for mgmt_nwk_update_req -*/ -#define ZB_ZDO_MAX_SCAN_DURATION 5U -/*! - Max scan count for mgmt_nwk_update_freq -*/ -#define ZB_ZDO_MAX_SCAN_COUNT_PARAM 1U -/*! - * Special value of the ScanDuration for Mgmt_NWK_Update_req for channel change. - * - * See Zigbee Specification revision 22 Table 2.88, field ScanDuration. - */ -#define ZB_ZDO_NEW_ACTIVE_CHANNEL 0xFEU -/*! - * Special value of the ScanDuration for Mgmt_NWK_Update_req for channel mask change. - * - * See Zigbee Specification revision 22 Table 2.88, field ScanDuration. -*/ -#define ZB_ZDO_NEW_CHANNEL_MASK 0xFFU - - -/** - * @todo{OLD_DESCRIPTION} Old (2015) and strange define - * A countdown timer (in minutes) indicating the time to the next - * permitted frequency agility channel change - */ -#define ZB_ZDO_APS_CHANEL_TIMER (1U * 60U) - -/*! - 1 minute timer to measure large timeouts -*/ -#define ZB_ZDO_1_MIN_TIMEOUT (ZB_TIME_ONE_SECOND * 60U) - -/* Default values: see HA spec 9.6.4.2 Attribute Settings and Battery Life Considerations */ -/** @endcond *//* internals_doc */ -/*! - Default fast poll timeout - */ -#define ZB_PIM_DEFAULT_FAST_POLL_TIMEOUT (ZB_TIME_ONE_SECOND * 10U) - -/*! - Default fast poll interval - */ -#define ZB_PIM_DEFAULT_FAST_POLL_INTERVAL ZB_QUARTERECONDS_TO_BEACON_INTERVAL(2U) - -/*! - Default long poll interval - */ -#define ZB_PIM_DEFAULT_LONG_POLL_INTERVAL (ZB_TIME_ONE_SECOND * 5U) - -/*! - Minimum long poll interval in quarterseconds - */ -#define ZB_PIM_MINIMUM_LONG_POLL_INTERVAL_IN_QS 0x04U - -/*! - Default long poll interval in quarterseconds - */ -#define ZB_PIM_DEFAULT_LONG_POLL_INTERVAL_IN_QS 0x0014U - -/*! - Maximum long poll interval in quarterseconds - */ -#define ZB_PIM_MAXIMUM_LONG_POLL_INTERVAL_IN_QS 0x6e0000U - -/*! - Minimum short poll interval in quarterseconds - */ -#define ZB_PIM_MINIMUM_SHORT_POLL_INTERVAL_IN_QS 0x01U - -/*! - Default short poll interval in quarterseconds - */ -#define ZB_PIM_DEFAULT_SHORT_POLL_INTERVAL_IN_QS 0x02U - -/*! - Maximum short poll interval in quarterseconds - */ -#define ZB_PIM_MAXIMUM_SHORT_POLL_INTERVAL_IN_QS 0xffffU - -/*! - Default turbo poll interval - */ -#if defined ZB_SUBGHZ_ONLY_MODE || defined ZB_R22_MULTIMAC_MODE -/* For the Sub-GHz bands the minimum and default turbo polling intervals are increased, - because the LBT mechanism periodically blocks the radio */ -#define ZB_PIM_DEFAULT_TURBO_POLL_INTERVAL ZB_MILLISECONDS_TO_BEACON_INTERVAL(250U) -#else -#define ZB_PIM_DEFAULT_TURBO_POLL_INTERVAL ZB_MILLISECONDS_TO_BEACON_INTERVAL(100U) -#endif - -/*! - Minimal possible turbo poll interval - */ -#if defined ZB_SUBGHZ_ONLY_MODE || defined ZB_R22_MULTIMAC_MODE && !defined SNCP_MODE -#define ZB_PIM_DEFAULT_MIN_TURBO_POLL_INTERVAL ZB_MILLISECONDS_TO_BEACON_INTERVAL(250U) -#else -#define ZB_PIM_DEFAULT_MIN_TURBO_POLL_INTERVAL ZB_MILLISECONDS_TO_BEACON_INTERVAL(100U) -//#define ZB_PIM_DEFAULT_MIN_TURBO_POLL_INTERVAL ZB_MILLISECONDS_TO_BEACON_INTERVAL(60) -#endif - -/*! - Maximal possible turbo poll interval - */ -#define ZB_PIM_DEFAULT_MAX_TURBO_POLL_INTERVAL ZB_MILLISECONDS_TO_BEACON_INTERVAL(3000U) - -/*! - Timeout for turbo poll - */ -#define ZB_PIM_TURBO_POLL_PACKETS_TIMEOUT (ZB_TIME_ONE_SECOND * 15U) - -/*! - Timeout for turbo poll - */ -#define ZB_PIM_TURBO_POLL_LEAVE_TIMEOUT (ZB_TIME_ONE_SECOND / 3U) -/**@cond internals_doc*/ -/*! - Timeout for poll buffer allocation retry - */ -#define ZB_PIM_POLL_ALLOC_TIMEOUT ZB_MILLISECONDS_TO_BEACON_INTERVAL(500U) -/** @endcond *//* internals_doc */ -/*! - Integer value representing the - time duration (in milliseconds) -*/ -#define ZB_ZDO_NWK_TIME_BTWN_SCANS 30U -/**@cond internals_doc*/ -/*! - Timeout value in seconds - employed in End Device - Binding */ -#define ZB_ZDO_ENDDEV_BIND_TIMEOUT 60U - - -#ifndef ZDO_TRAN_TABLE_SIZE -/*! - Transactions table size -*/ -#define ZDO_TRAN_TABLE_SIZE 16U -#endif - -/*! Number of packets with "no ack" status before removing unreachable device from nbt. */ -#define ZB_ZDO_NEIGHBOR_FAILURE_PKT_THRESHOLD 5U -/* 60 seconds */ -/*! Timeout before removing unreachable device from nbt. */ -#define ZB_ZDO_NEIGHBOR_UNREACHABLE_TIMEOUT 60U - -/*! Checking channel timeout*/ -#define ZB_ZDO_CHECK_CHANNEL_TIMEOUT (24U * 60U * 60U * ZB_TIME_ONE_SECOND) -/** @endcond *//* internals_doc */ -/* Before r22 this value could be only 1, because scan attempts routine work - * wrong. Rewritten/fixed in r22. */ -/*! -* Integer value representing the number of scan attempts to make before the NWK layer decides -* which Zigbee coordinator or router to associate with. -* -* See Zigbee Specification revision 22 section 2.5.51 Configuration Attribute Definitions -* -* Table 2-154 of Zigbee Specification revision 22 : Config_NWK_Scan_Attempts default value is 5. -*/ -#define ZB_ZDO_NWK_SCAN_ATTEMPTS 5U -/** @cond internals_doc */ -/*! Delay for sending the end device request command. */ -#define ZB_ZDO_SEND_ED_TIMEOUT_REQ_DELAY ZB_MILLISECONDS_TO_BEACON_INTERVAL(100U) -/** @endcond *//*internals_doc*/ -/**********************************************************************/ -/************************** MAC SECTION********************************/ -/**********************************************************************/ -/*! @cond internals_doc */ -/* -IEEE 802.15.4g p.7 - -Table 0 - MR-FSK symbol duration used for MAC and PHY timing parameters -Frequency band (MHz) MR-FSK symbol duration used for MAC - and PHY timing parameters (us) --------------------------------------------------------------------------- -169.400-169.475 (Europe) 208+1/3 -450-470 (US FCC Part 22/90) 104+1/6 -470-510 (China) 20 -779-787 (China) 20 -863-870 (Europe) 20 -896-901 (US FCC Part 90) 100 -901-902 (US FCC Part 24) 100 -902-928 (US ISM) 20 -917-923.5 (Korea) 20 -928-960 (US FCC Part 22/24/90/101) 100 -920-928 (Japan) 20 -950-958 (Japan) 20 -1427-1518 (US FCC Part 90)/(Canada 100 - SRSP 301.4) -2400-2483.5 (Worldwide) 20 -*/ - -#if defined(ZB_SUB_GHZ_EU1) || defined(ZB_SUB_GHZ_EU2) || defined(ZB_SUB_GHZ_EU3) -#define ZB_SYMBOL_DURATION_USEC 20U -#elif defined(ZB_SUB_GHZ_US) -#define ZB_SYMBOL_DURATION_USEC 20U -#elif defined ZB_SUB_GHZ_JP -#define ZB_SYMBOL_DURATION_USEC 20U -#elif defined ZB_SUB_GHZ_CN -#else - -/*! - * @brief Symbol duration - * @see 6.5.3.2 Symbol rate - * The 2450 MHz PHY symbol rate shall be 62. - * 5 ksymbol/s 40 ppm. - */ -#define ZB_SYMBOL_DURATION_USEC 16U /* 1 symbol = 16e-6 sec (mac spec 6.5.3.2 Symbol rate) */ -#endif - -/*! - * @brief Symbol duration for O-QPSK (2.4 GHz) - * @see 12.3 section of 802.15.4-2015 - */ -#define ZB_O_QPSK_2_4_GHZ_SYMBOL_DURATION_USEC 16U -#define ZB_O_QPSK_2_4_GHZ_PHY_SYMBOLS_PER_OCTET 2U - -#define ZB_2_4_GHZ_OCTET_DURATION_USEC (ZB_O_QPSK_2_4_GHZ_SYMBOL_DURATION_USEC * ZB_O_QPSK_2_4_GHZ_PHY_SYMBOLS_PER_OCTET) - -/*! - \par Time measurement unit is beacon interval. - It is both internal representation and value used in API. - It is still possible to convert it to/from msec. - aBaseSuperframeDuration = aBaseSlotDuration * aNumSuperframeSlots - aBaseSlotDuration = 60 - aNumSuperframeSlots = 16 -*/ -#define ZB_ABASE_SUPERFRAME_DURATION 960U - - -/*! -RX-to-TX or TX-to-RX maximum turnaround time -(in symbol periods) (see 6.9.1 and 6.9.2) - */ -#define ZB_MAC_A_TURNAROUND_TIME_SYM 12U - - -/* @note: All packet tx timings are for 2.4 GHz radio. */ - -/* - -6.3.1 Preamble field, octets -Table 19Preamble field length - -24002483.5 MHz O-QPSK 4 octets 8 symbols - */ -/*! Preamble field length */ -#define ZB_MAC_PREAMBLE_LEN 4U - - -/* - PHY hdr len, octets - - -6.3 PPDU format -This subclause specifies the - */ -/*! PHY header length */ -#define ZB_MAC_PHR_LEN 1U - - -/* - -The SFD is a field indicating the end of the SHR and the start of the packet data. - - -6.3.2 SFD field - */ -/*! Start of length delimiter field length */ -#define ZB_MAC_SFD_LEN 1U - - - -/** - MAC frame preamble length, octets. - -Each PPDU consists of the following basic components: - + A synchronization header (SHR), which allows a receiving device to synchronize and lock onto the -bit stream - + A PHY header (PHR), which contains frame length information - + A variable length payload, which carries the MAC sublayer frame - -See IEEE Standard for Low-Rate Wireless Networks, section 5.7.3 Frame structure. - */ -/* MAC frame preamble length, octets. */ -#define ZB_MAC_FRAME_PPDU_HDR_LEN (ZB_MAC_PREAMBLE_LEN + ZB_MAC_SFD_LEN + ZB_MAC_PHR_LEN) - - - /* See D.10.1.1 PPDU Format for European Sub-GHz FSK */ - /*! MAC SUB GHZ preamble length */ -#define ZB_MAC_SUBG_PREAMBLE_LEN 8U -/*! MAC SUB GHZ start of frame delimiter length*/ -#define ZB_MAC_SUBG_SFD_LEN 2U -/*! MAC SUB GHZ PHY header length */ -#define ZB_MAC_SUBG_PHR_LEN 2U -/*! MAC SUB GHZ PHY protocol data unit frame header length */ -#define ZB_MAC_SUBG_FRAME_PPDU_HDR_LEN (ZB_MAC_SUBG_PREAMBLE_LEN + ZB_MAC_SUBG_SFD_LEN + ZB_MAC_SUBG_PHR_LEN) -/*! MAC SUB GHZ PHY protocol data unit frame footer length */ -#define ZB_MAC_SUBG_FRAME_PPDU_FOOTER_LEN 2U -/*! MAC SUB GHZ symbol duration in microseconds */ -#define ZB_MAC_SUBG_SYMBOL_DURATION_USEC 10U -/*! MAC SUB GHZ transition octet to symbol */ -#define ZB_MAC_SUBG_OCTET_TO_SYMBOL(octets) ((octets) * 8U) -/* aRxTxTurnAround - see Table D-23 LBT MAC Sublayer Constants - Implementation */ -/*! -* Time for radio to switch between receive and transmit -* -* See Table D-23 LBT MAC Sublayer Constants - Implementation -*/ -#define ZB_MAC_SUBG_TURNAROUND_TIME_SYM 100U - -/* - Define how many symbols used to transmit given number of octets - -6.5.2.2 Bit-to-symbol mapping -All binary data contained in the PPDU shall be encoded using the modulation and spreading functions -shown in Figure 18. This subclause describes how binary information is mapped into data symbols. -The 4 LSBs (b0, b1, b2, b3) of each octet shall map into one data symbol, and the 4 MSBs (b4, b5, b6, b7) of -each octet shall map into the next data symbol. Each octet of the PPDU is processed through the modulation -and spreading functions (see Figure 18) sequentially, beginning with the Preamble field and ending with the -last octet of the PSDU. - */ -/*! Define how many symbols used to transmit given number of octets */ -#define ZB_MAC_OCTET_TO_SYMBOL(octets) ((octets) * 2U) - -/*! -The maximum number of -backoffs the CSMA-CA -algorithm will attempt before -declaring a channel access -failure. - */ -#define ZB_MAC_MAX_CSMA_BACKOFFS 4U - -/*! -The number of symbols forming the basic time period -used by the CSMA-CA algorithm. - -See 7.4.1 MAC constants -*/ -#define ZB_MAC_A_UNIT_BACKOFF_PERIOD 20U - -/*! -6.9.9 Clear channel assessment (CCA) -The CCA detection time shall be equal to 8 symbol periods. - */ -/*! Clear channel assessment period */ -#define ZB_MAC_CCA_PERIOD 8U - -/*! Number of times performed in slotted CSMA-CA by CCA */ -#define ZB_MAC_NUM_CCA 2U -/*! Total transmission attempts */ -#define ZB_TX_TOTAL_THRESHOLD 20U -/* TODO: check it */ -/*! Endpoint busy state value */ -#define ZB_CHANNEL_BUSY_ED_VALUE 0x60U -/* TODO: check it */ -/*! Endpoint free state value */ -#define ZB_CHANNEL_FREE_ED_VALUE 0x60U -/* use it as divider, 25% */ -/*! Percentage of failures. Use it as divider to get 25 % */ -#define ZB_FAILS_PERCENTAGE 4U -/*! MAC queue size */ -/* Since the ZB_MAC_RX_QUEUE_CAP can be configured by the Vendor, the ZB_MAC_QUEUE_SIZE - * should be configurable too. - * - * If ZB_MAC_RX_QUEUE_CAP is larger than ZB_MAC_QUEUE_SIZE and the node is flooded - * with requests, that require a response to be sent, the node enters a weird state: - * - For each request a response is generated. - * - Each response is scheduled. - * - Part of the responses are not sent and the error -774 is returned in the callback for the response packet. - * This is a totally valid behavior, but there is no clean way of handling this case - * in the application logic. - * - * If the ZB_MAC_RX_QUEUE_CAP is smaller than ZB_MAC_QUEUE_SIZE this situation is avoided, - * since the node stops sending MAC ACKs for frames that it cannot send a response to immediately. - */ -#ifndef ZB_MAC_QUEUE_SIZE -#if defined ZB_SUBGHZ_ONLY_MODE || defined ZB_R22_MULTIMAC_MODE -/* Increased MAC queue size for Sub-GHz because the LBT mechanism periodically blocks the radio */ -#define ZB_MAC_QUEUE_SIZE 7U -#else -#define ZB_MAC_QUEUE_SIZE 5U -#endif -#endif /* ZB_MAC_QUEUE_SIZE */ - -/* -The maximum time, in -multiples of -aBaseSuperframeDuration, a -device shall wait for a -response command frame to -be available following a -request command frame. -*/ -/*! - Maximum time to wait for a response command frame, range 2-64 - Default is 32, 64 set for better compatibility -*/ -#define ZB_MAC_RESPONSE_WAIT_TIME 32U - -/*! Make all MAC PIB attributes configurable */ -#define ZB_CONFIGURABLE_MAC_PIB - -/* Zigbee IEEE 802.15.4 Test Spec (Zigbee Doc. 14-0332-01), TP/154/MAC/DATA-04 test: - macMaxFrameTotalWaitTime for 2.4 GHz 802.15.4-2003 Zigbee/PRO/RF4CE device is - 1220 symbols (or 20 msec) - minimal WaitTime to pass the test. - - Previous value was 500 msec, looks like it is too big. Big WaitTime values bring additional - battery drain for ED devices. - - The value should be at least 1 beacon interval higher than in specs: - ZBOSS timer resolution is 1 beacon interval, so there is a chance that 2 BI may correspond to - 16 ms of real time -- too low (especially for nsng). - */ -/*! -* Maximum time to wait for indirect data. -* -* See IEEE Standard for Low-Rate Wireless Networks 2006, section 7.4.2 MAC PIB attributes. -* -* @note Make sure the time value is not too big. -*/ -#define ZB_MAX_FRAME_TOTAL_WAIT_TIME_2_4_GHZ (ZB_MILLISECONDS_TO_BEACON_INTERVAL(40U) + 1U) -/*! -* Maximum time to wait for indirect data for SUB GHZ. -* -* IEEE Standard for Low-Rate Wireless Networks 2006, section 7.4.2 MAC PIB attributes. -* -* @note Make sure the time value is not too big. -* There is no defined value for sub-ghz now. In case of aLBTTxMinOff frame can be sent with a -* delay in case of it's own transmission right before Received Date Req. This value calculated -* taking into account this possible situation. -*/ -#define ZB_MAX_FRAME_TOTAL_WAIT_TIME_SUB_GHZ (ZB_MILLISECONDS_TO_BEACON_INTERVAL(136U) + 1U) - - -/*! -* The maximum number of retries allowed after a transmission failure 0-7 -*/ -#define ZB_MAC_MAX_FRAME_RETRIES 3U - - -/* (currently - all platforms)*/ -/*! -* Sets MAC address at start -*/ -#define ZB_SET_MAC_ADDRESS - -#ifndef ZB_SEND_BEACON_IMMEDIATELY -/*! -* Replay to the beacon request after a jitter (meaningful for DSR MAC only). - */ -#define ZB_SEND_BEACON_AFTER_RANDOM_DELAY -#endif /* ZB_SEND_BEACON_IMMEDIATELY */ - -/*! -* External MAC - */ -#define ZB_MAC_EXT_DATA_REQ - -/* Was 3, seems like it is too small when there are >7-10 beacons. - Also it seems like we need some bottom line for this - it should not be 1 etc. */ -/*! MAC beacon request timeout length (high bound of the random value) */ -#ifndef ZB_MAC_HANDLE_BEACON_REQ_HI_TMO -/*! Default MAC beacon request timeout length */ -#define ZB_MAC_HANDLE_BEACON_REQ_HI_TMO_DEFAULT 8U -/*! Extended MAC beacon request timeout length */ -#define ZB_MAC_HANDLE_BEACON_REQ_HI_TMO_EXTENDED 20U - -#ifdef ZB_CERTIFICATION_HACKS -/* Choose exact value depending on cert hack flags */ -/*! Default MAC beacon request timeout length depending on certification hack flags */ -#define ZB_MAC_HANDLE_BEACON_REQ_HI_TMO (ZB_CERT_HACKS().extended_beacon_send_jitter ? ZB_MAC_HANDLE_BEACON_REQ_HI_TMO_EXTENDED : ZB_MAC_HANDLE_BEACON_REQ_HI_TMO_DEFAULT) -#else -/* Otherwise use the default value*/ -/*! Default MAC beacon request timeout length */ -#define ZB_MAC_HANDLE_BEACON_REQ_HI_TMO ZB_MAC_HANDLE_BEACON_REQ_HI_TMO_DEFAULT -#endif - -#endif /* ZB_MAC_HANDLE_BEACON_REQ_HI_TMO */ - -/*! MAC beacon request timeout length (low bound of the random value) */ -#ifndef ZB_MAC_HANDLE_BEACON_REQ_LOW_TMO -/*! Default MAC beacon request timeout length */ -#define ZB_MAC_HANDLE_BEACON_REQ_LOW_TMO_DEFAULT 1U -/*! Extended MAC beacon request timeout length */ -#define ZB_MAC_HANDLE_BEACON_REQ_LOW_TMO_EXTENDED 12U - -#ifdef ZB_STACK_REGRESSION_TESTING_API -/** Choose exact value depending on regression tests flags */ -#define ZB_MAC_HANDLE_BEACON_REQ_LOW_TMO (ZB_REGRESSION_TESTS_API().extended_beacon_send_delay ? ZB_MAC_HANDLE_BEACON_REQ_LOW_TMO_EXTENDED : ZB_MAC_HANDLE_BEACON_REQ_LOW_TMO_DEFAULT) -#else -/** Otherwise use the default value */ -#define ZB_MAC_HANDLE_BEACON_REQ_LOW_TMO ZB_MAC_HANDLE_BEACON_REQ_LOW_TMO_DEFAULT -#endif - -#endif /* ZB_MAC_HANDLE_BEACON_REQ_LOW_TMO */ -/*! @endcond */ /* internals_doc */ -/** @cond DOXYGEN_MULTIMAC_SECTION */ -/*! -* European Sub-GHz FSK reverence sensitivity level, in dBm -* D.10.2.2.1.2. Sensitivity Requirement, -* Reference document 05-3474-22 Zigbee Specification R22 -* - */ -#define ZB_EU_FSK_REFERENCE_SENSITIVITY -99 -#define ZB_NA_FSK_REFERENCE_SENSITIVITY -91 - -/* - * 02/01/2021: After discussions in ZigBee Sub-GHz task group, agreed that - * end device can close it's receiver if it hasn't received first bit of the MAC header between - * aLBTAckWindowStart (450us) and aLBTAckWindow (1ms). - * - * TODO: Clarify this after official specification will be available - */ -#define ZB_MAC_PIB_ACK_WAIT_DURATION_HW_GB_EU_FSK_SYMBOLS 100U -#define ZB_MAC_PIB_ACK_WAIT_DURATION_HW_NA_FSK_SYMBOLS 500U - -/*! - * @brief Symbol duration for European FSK Sub-GHz - * @see D.11.2 MAC Support for Listen Before Talk (LBT) - */ -#define ZB_GB_EU_FSK_SYMBOL_DURATION_USEC 10UL - -/*! - * @brief Symbol duration for North America FSK Sub-GHz - */ -#define ZB_NA_FSK_SYMBOL_DURATION_USEC 2UL - -#define ZB_SUB_GHZ_PHY_SYMBOLS_PER_OCTET 8U - -/*! - * @brief Synchronization header for Sub-GHz PHY - * @see D.10.1.1.1 SHR for European Sub-GHz FSK - * synchronization header: 8 bytes preamble + 2 bytes SFD - */ -#define ZB_MAC_SUB_GHZ_SHR_LEN_BYTES 10U - -/*! - * @brief PHY header for Sub-GHz PHY - * @see D.10.1.1.2 PHR for European Sub-GHz FSK - * PHY header: 2 bytes - */ -#define ZB_MAC_SUB_GHZ_PHR_LEN_BYTES 2U - -/* @brief CCA period for Sub-GHz PHY in symbols */ -#define ZB_MAC_SUB_GHZ_CCA_PERIOD_SYMBOLS 16U - -/* IMPORTANT!!! - * As mentioned in section D.11.2 MAC Support for Listen Before Talk - * of Zigbee Specification R22, document 05-3474-22, page 543 - * - * Quote: "The UK have adopted the same values for ALL channel pages as defined - * for pages 28 & 29. Other regions may use different values for pages 30 & 31 - * which as yet have not been defined or verified." - * - */ -/* aLBTTxMinOff */ -/* 100 ms */ -/*! The minimum permitted off time between a device's own transmissions. */ -#define ZB_MAC_LBT_TX_MIN_OFF_SYMBOLS 10000UL - -/* aLBTTxMaxPKT */ -/* 1 second */ -/*! The maximum permitted off time between a device's own transmissions. */ -#define ZB_MAC_LBT_TX_MAX_PKT_SYMBOLS 100000U - -/* aLBTMinFree */ -/*! The minimum duration a channel should be free for different Sub-GHz pages */ -#define ZB_MAC_GB_EU_FSK_LBT_MIN_FREE_SYMBOLS 500U -#define ZB_MAC_NA_FSK_LBT_MIN_FREE_SYMBOLS 32U - -/* aLBTMaxRandom */ -/*! The maximum period of the backoff for different Sub-GHz pages */ -#define ZB_MAC_GB_EU_FSK_LBT_MAX_RANDOM_SYMBOLS 500UL -#define ZB_MAC_NA_FSK_LBT_MAX_RANDOM_SYMBOLS 2200UL - -/* aLBTMinRandom */ -/*! The minimum period of the backoff for different Sub-GHz pages */ -#define ZB_MAC_GB_EU_FSK_LBT_MIN_RANDOM_SYMBOLS 0U -#define ZB_MAC_NA_FSK_LBT_MIN_RANDOM_SYMBOLS 500U - -/* aLBTGranularity */ -/*! The granularity in the random backoff for different Sub-GHz pages */ -#define ZB_MAC_GB_EU_FSK_LBT_GRANULARITY_SYMBOLS 50U -#define ZB_MAC_NA_FSK_LBT_GRANULARITY_SYMBOLS 200U - -/* aLBTAckWindowStart */ -/* 450 us */ -/*! -* The minimum pause before acknowledging a received packet. -* This is to allow a transmitting device to change from -* transmit to receive mode. Starting an ACK before this time -* may result in the transmitter missing the ACK. -*/ -#define ZB_MAC_GB_EU_FSK_LBT_ACK_WINDOW_START_SYMBOLS 45U -#define ZB_MAC_NA_FSK_LBT_ACK_WINDOW_START_SYMBOLS 225U - -/* aLBTAckWindow */ -/* 1ms */ -/*! -* The maximum wait time before acknowledging a received -* packet (includes @ref ZB_MAC_LBT_ACK_WINDOW_START_SYMBOLS). -* This time MUST be shorter than @ref ZB_MAC_LBT_MIN_FREE_SYMBOLS otherwise other -* devices could interpret the quiet as an opportunity to transmit. -*/ -#define ZB_MAC_GB_EU_FSK_LBT_ACK_WINDOW_SYMBOLS 100U -#define ZB_MAC_NA_FSK_LBT_ACK_WINDOW_SYMBOLS 500U - -/*aTxRxTurnAround */ -/*! -* Time for radio to switch between transmit and receive -*/ -#define ZB_MAC_GB_EU_FSK_LBT_TX_RX_SWITCH_TIME_SYMBOLS 45U -#define ZB_MAC_NA_FSK_LBT_TX_RX_SWITCH_TIME_SYMBOLS 225U - -/* aLBTTimeout */ -/* 6 ms */ -/*! -* Time before aborting LBT if it cannot find a free slot. -* This value should be set to at least -* [@ref ZB_MAC_LBT_MIN_FREE_SYMBOLS + @ref ZB_MAC_LBT_MAX_TX_RETRIES * (@ref ZB_MAC_LBT_MIN_FREE_SYMBOLS + @ref ZB_MAC_LBT_MAX_RANDOM_SYMBOLS) + @ref ZB_MAC_LBT_TX_RX_SWITCH_TIME_SYMBOLS )] -* to ensure that all re-tries can occur. -*/ -#define ZB_MAC_GB_EU_FSK_LBT_TIMEOUT_SYMBOLS 6000UL -#define ZB_MAC_NA_FSK_LBT_TIMEOUT_SYMBOLS 30000U - - -/* aLBTThresholdLevelLp */ -/*! -* The level (in dBm) at which the receiver determines whether there -* is activity in a low power channel (+14 dBm Tx). -*/ -#define ZB_MAC_LBT_GB_THRESHOLD_LEVEL_LP (-87) -#define ZB_MAC_LBT_EU_THRESHOLD_LEVEL_LP (-87) -#define ZB_MAC_LBT_NA_THRESHOLD_LEVEL_LP (-79) /* 08/25/2020: see TP/154/PHYRFS1/RECEIVER-07 test */ - -/* aLBTThresholdLevelHp */ -/*! -* The level (in dBm) at which the receiver determines whether -* there is activity in a high power channel (+27 dBm Tx). -*/ -#define ZB_MAC_LBT_GB_THRESHOLD_LEVEL_HP (-91) -#define ZB_MAC_LBT_EU_THRESHOLD_LEVEL_HP (-91) -#define ZB_MAC_LBT_NA_THRESHOLD_LEVEL_HP ZB_MAC_LBT_NA_THRESHOLD_LEVEL_LP - -/* aLBTMaxTxRetries */ -/*! The maximum number of retries allowed while looking for a clear channel. - * - * See Zigbee Specification revision 22 Table D-23 LBT MAC Sublayer Constants - Implementation. -*/ -#define ZB_MAC_LBT_MAX_TX_RETRIES 3U - -/* Tuned to fit to 2 beacon intervals */ -/*! LBT transmission wait period in ms */ -#define ZB_MAC_LBT_TX_WAIT_QUANT_MS 33U - -/* aDUTYCYCLEMeasurementPeriod */ -/*! The period over which the duty cycle is calculated. */ -#define ZB_MAC_DUTY_CYCLE_MEASUREMENT_PERIOD_SYMBOLS 360000000U - -/* aDUTYCYCLERampUp */ -#ifndef ZB_MAC_DUTY_CYCLE_RAMP_UP_SYMBOLS -/*! Time transmitter is transmitting carrier prior to start of data */ -#define ZB_MAC_DUTY_CYCLE_RAMP_UP_SYMBOLS 0U -#endif /* ZB_MAC_DUTY_CYCLE_RAMP_UP_SYMBOLS */ - -/* aDUTYCYCLERampDown */ -#ifndef ZB_MAC_DUTY_CYCLE_RAMP_DOWN_SYMBOLS -/*! Time transmitter is transmitting carrier after end of data */ -#define ZB_MAC_DUTY_CYCLE_RAMP_DOWN_SYMBOLS 0U -#endif /* ZB_MAC_DUTY_CYCLE_RAMP_DOWN_SYMBOLS */ - - - -#ifndef ZB_USE_DUTY_CYCLE_PERCENT_ENABLE - -/*! MAC duty cycle of limited threshold length */ -#define ZB_MAC_DUTY_CYCLE_LIMITED_THRESHOLD_SYMBOLS 5400000U -/*! MAC duty cycle of critical threshold length */ -#define ZB_MAC_DUTY_CYCLE_CRITICAL_THRESHOLD_SYMBOLS 7500000U - -/*! MAC duty cycle of limited threshold length */ -/*! Length of regulated MAC duty cycle pages 29 and 29 */ -#define ZB_MAC_DUTY_CYCLE_REGULATED_SYMBOLS_PAGES_28_29 10000000U -/*! Length of regulated MAC duty cycle pages 30 and 31 */ -#define ZB_MAC_DUTY_CYCLE_REGULATED_SYMBOLS_PAGES_30_31 9000000U - -#endif /* ZB_USE_DUTY_CYCLE_PERCENT_ENABLE */ - -/* aDUTYCYCLEBuckets */ -/*! Number of buckets used for duty cycle monitoring */ -#define ZB_MAC_DUTY_CYCLE_BUCKETS 13U - -/*! -* MAC power control information table size -* -* See reference document 05-3474-22 section D.9.2 Zigbee Specification R22 - */ -#define ZB_MAC_POWER_CONTROL_INFO_TABLE_SIZE 10U -/*! MAC power control expiration time out */ -#define ZB_MAC_POWER_CONTROL_EXPIRATION_TIMEOUT (10U * ZB_TIME_ONE_SECOND) - -#ifndef ZB_MAC_DEFAULT_TX_POWER_GB_EU_SUB_GHZ -/*! Default MAC transmission power for GB and EU Sub-GHz PHY */ -#define ZB_MAC_DEFAULT_TX_POWER_GB_EU_SUB_GHZ +14 -#endif - -#ifndef ZB_MAC_DEFAULT_TX_POWER_GB_EU_SUB_GHZ -/*! Default MAC transmission power for GB and EU Sub-GHz PHY */ -#define ZB_MAC_DEFAULT_TX_POWER_GB_EU_SUB_GHZ +14 -#endif -#ifndef ZB_MAC_DEFAULT_TX_POWER_NA_SUB_GHZ -/*! Default MAC transmission power for NA Sub-GHz PHY */ -#define ZB_MAC_DEFAULT_TX_POWER_NA_SUB_GHZ +30 -#endif - -/** @endcond */ /* DOXYGEN_MULTIMAC_SECTION */ -/** @cond internals_doc */ -#ifndef ZB_MAC_DEFAULT_TX_POWER_24_GHZ -/*! Default MAC transmission power for 2.4 GHZ */ -#define ZB_MAC_DEFAULT_TX_POWER_24_GHZ +20 -#endif -/*! MAC diagnostic filter size */ -#define ZB_MAC_DIAGNOSTICS_FILTER_SIZE 4U -/*! MAC diagnostic time period in minutes */ -#define ZB_MAC_DIAGNOSTICS_TIME_PERIOD_MIN 10U -/*! MAC diagnostic time period in seconds */ -#define ZB_MAC_DIAGNOSTICS_TIME_PERIOD_SEC \ - (ZB_MAC_DIAGNOSTICS_TIME_PERIOD_MIN * 60U * ZB_TIME_ONE_SECOND) - -#ifndef ZB_MAC_ASSOCIATION_DATA_REQUEST_COUNT -/*! Count of MAC data association */ -#define ZB_MAC_ASSOCIATION_DATA_REQUEST_COUNT 1U -#endif -/* Base Device */ - -/** -* See about bdbTrustCenterNodeJoinTimeout in Base Device Specification subclause 5.3.16. -* -* The bdbTrustCenterNodeJoinTimeout attribute specifies a timeout in seconds -* for the Trust Center to remove the Trust Center link key of the newly joined -* node that did not successfully establish a new link key. This attribute -* is used by Zigbee coordinator nodes. - */ -/*! Timeout in seconds for the Trust Center to remove the Trust Center link key of the newly joined - node that did not successfully establish a new link key. This attribute - is used by Zigbee coordinator nodes.*/ -#define ZB_DEFAULT_BDB_TRUST_CENTER_NODE_JOIN_TIMEOUT ZB_MILLISECONDS_TO_BEACON_INTERVAL(0xfU * 1000U) -/*! Timeout in seconds for the Trust Center to exchange link keys with the newly joined node */ -#define ZB_BDBC_TCLINK_KEY_EXCHANGE_TIMEOUT ZB_MILLISECONDS_TO_BEACON_INTERVAL(5000U) -/*! Minimum commissioning period */ -#define ZB_BDBC_MIN_COMMISSIONING_TIME_S 180U -/*! Number of Trust Center link attempts to exchange link keys with the newly joined node. */ -#define ZB_DEFAULT_BDB_TCLINK_KEY_EXCHANGE_ATTEMPTS_MAX 3U -/** @endcond *//*internals_doc*/ -/*! Specification version of the specification */ -#define ZB_STACK_SPEC_VERSION 22U - - -/*! @cond touchlink */ -/* Table 2 Constants used by nodes supporting touchlink */ -#define ZB_BDBC_TL_INTER_PANTRANS_ID_LIFETIME ZB_MILLISECONDS_TO_BEACON_INTERVAL(8000U) -#define ZB_BDBC_TL_MIN_STARTUP_DELAY_TIME ZB_MILLISECONDS_TO_BEACON_INTERVAL(2000U) -/* used for a non-extended touchlink scan */ -#define ZB_BDBC_TL_PRIMARY_CHANNEL_SET 0x02108800 -#define ZB_BDBC_TL_RX_WINDOW_DURATION ZB_MILLISECONDS_TO_BEACON_INTERVAL(5000U) -#define ZB_BDBC_TL_SCAN_TIME_BASE_DURATION ZB_MILLISECONDS_TO_BEACON_INTERVAL(250U) -/* used for an extended touchlink scan after the bdbcTLPrimaryChannelSet - * channels have been scanned. */ -#define ZB_BDBC_TL_SECONDARY_CHANNEL_SET (0x07fff800U ^ ZB_BDBC_TL_PRIMARY_CHANNEL_SET) -/*! @endcond */ /* touchlink */ - - -/* Green Power */ - -/** @cond DOXYGEN_ZGP_SECTION */ -/*! - * zgpDuplicateTimeout value - * - * The time the EPP of the ZGPS and ZGPP keeps the information on the received - * GPDF with random sequence number, in order to filter out duplicates. - * - * The default value of 2 seconds can be modified by the application profile - * - * @see ZGP spec, A.3.6.1.2.1 */ -#define ZB_ZGP_DUPLICATE_TIMEOUT (1U * ZB_TIME_ONE_SECOND) - -/* - The OperationalChannel sub-field can take the following values: 0b0000: channel 11, 0b0001: channel - 12, , 0b1111: channel 26. -*/ -/*! First Zigbee green power device channel value */ -#define ZB_ZGPD_FIRST_CH 11U -/*! Last Zigbee green power device channel value */ -#define ZB_ZGPD_LAST_CH 26U - -/* ZGP spec, A.3.9.1: - * If no Channel Request is received on channel TransmitChannel for 5sec, - * the TempMaster removes the Channel Configuration GPDF from its - * gpTxQueue and returns to the operational channel in commissioning mode - */ -/*! Timeout of Zigbee Green Power Device channel transition request */ -#define ZB_ZGP_CHANNEL_REQ_ON_TX_CH_TIMEOUT (5U * ZB_TIME_ONE_SECOND) - -/*! - * If commissioning on the last stage, then it determines time to wait - * until commissioning is complete. If commissioning is not completed - * during this time, then commissioning cancel procedure is started. - */ -/*! -* Timeout before completing commissioning if -* the last stage is successful or, -* otherwise, start the cancel procedure. -*/ -#define ZB_ZGP_TIMEOUT_BEFORE_FORCE_CANCEL (3U * ZB_TIME_ONE_SECOND) - -/*! Unspecified Zigbee Green Power device manufacturer ID */ -#define ZB_ZGPD_MANUF_ID_UNSPEC 0xFFFFU -/*! Default Zigbee Green Power device manufacturer ID */ -#define ZB_ZGPD_DEF_MANUFACTURER_ID 0x10d0U -/*! Maximum number of lightweight unicast address per Green Power device. */ -#define ZB_ZGP_MAX_LW_UNICAST_ADDR_PER_GPD 2U -/*! Maximum number of SINK groups per Green Power device */ -#define ZB_ZGP_MAX_SINK_GROUP_PER_GPD 2U -/*! Maximum number of paired endpoints*/ -#define ZB_ZGP_MAX_PAIRED_ENDPOINTS 2U -/*! Maximum number of paired Green Power devices commands */ -#define ZB_ZGP_MAX_PAIRED_CONF_GPD_COMMANDS 2U -/*! Maximum number of paired configuration clusters */ -#define ZB_ZGP_MAX_PAIRED_CONF_CLUSTERS 2U -/** @endcond */ /* DOXYGEN_ZGP_SECTION */ -/*! @} */ - -/* ****************** Smart Energy parameters ******************* */ -/* 5.3.8 APS Fragmentation Parameters - For the Smart Energy Profile the default value shall be set to 128 bytes. */ -#define ZB_APS_MSG_MAX_SIZE 1536U -#define ZB_ASDU_MAX_LEN_MULTIPLIER ((ZB_APS_MSG_MAX_SIZE + sizeof(zb_apsde_data_indication_t) + ZB_APS_HEADER_MAX_LEN)/ZB_IO_BUF_SIZE + 1U) -#define ZB_ASDU_MAX_FRAG_LEN (ZB_ASDU_MAX_LEN_MULTIPLIER*ZB_IO_BUF_SIZE - sizeof(zb_apsde_data_indication_t) - ZB_APS_HEADER_MAX_LEN) -#define ZB_APS_MAX_WINDOW_SIZE 1U -#define ZB_APS_INTERFRAME_DELAY 50U /* milliseconds */ - - -#define ZB_SE_STEADY_STATE_CLUSTER_MATCH_DESC_TIME (ZB_TIME_ONE_SECOND * 20U) -#define ZB_SE_STEADY_STATE_MAX_FAILURE_CNT 3U - -#define ZB_SE_PARTNER_LK_SETUP_TIMEOUT (ZB_TIME_ONE_SECOND * 30U) - -#define ZB_SE_HI_FREQ_MSG_TIMEOUT (ZB_TIME_ONE_SECOND * 30U) -#define ZB_SE_HI_FREQ_MSG_N_SLOTS 4U - -/*! @cond internals_doc */ -/* No need to set manufacturer code in node descriptor directly. - * zb_set_node_descriptor should select the right one depending on defined platform and/or radio - * For other codes see docs-05-3874-26-0csg-database-of-manufacturer-codes-for-use-in-the-node-descriptor.pdf */ -#define ZB_MANUFACTURER_CODE_DSR 0x1234U -/* That is not a joke, our manufacturer code is really 1234! */ -/*! @endcond */ /* internals_doc */ - -#define ZB_DEFAULT_MANUFACTURER_CODE ZB_MANUFACTURER_CODE_DSR - -#ifndef ZB_MULTITEST_HW_INIT_WAIT_ITERATIONS -#define ZB_MULTITEST_HW_INIT_WAIT_ITERATIONS 0U -#endif - -#ifndef ZB_MULTITEST_CONSOLE_SLEEP_TIMEOUT -#define ZB_MULTITEST_CONSOLE_SLEEP_TIMEOUT 4000000U -#endif - - -#endif /* ZB_CONFIG_COMMON_H */ diff --git a/zboss/development/include/zb_debug.h b/zboss/development/include/zb_debug.h deleted file mode 100644 index 1b34affffc..0000000000 --- a/zboss/development/include/zb_debug.h +++ /dev/null @@ -1,261 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Tests and debug macros -*/ -#ifndef ZB_DEBUG_H -#define ZB_DEBUG_H 1 - -/*! \addtogroup ZB_ASSERT_DYNAMIC */ -/*! @{ */ - -#if (defined USE_ASSERT) -/** - Trace current location, abort current program execution, with core dump if possible. - - @param caller_file - source file name - @param caller_line - line in the source - */ -void zb_abort(char *caller_file, int caller_line); - -#ifndef ZB_BINARY_TRACE -/** @cond internals_doc */ -/** - Assert: print diagnostic and force core dump - - @param file_name - source file name - @param line_number - line in the source -*/ -ZB_NORETURN void zb_assert(const zb_char_t *file_name, zb_int_t line_number); -/** @endcond */ -/** - Check for expression in runtime and call zb_assert() if it is false. - - Compiled to nothing if USE_ASSERT is not defined. - - @param expr expression to check -*/ -#define ZB_ASSERT(expr) {if(!(expr)){zb_assert(__FILE__, __LINE__);}} -/** @cond internals_doc */ -#define ZB_INLINE_ASSERT_SIMPLE(expr) ((expr) ? 1 : (zb_assert(__FILE__, __LINE__), 1)) -/** @endcond */ - -#else /* !ZB_BINARY_TRACE */ -/** - Assert: print diagnostic and force core dump - - @param file_id - source file id - @param line_number - line in the source -*/ -ZB_NORETURN void zb_assert(zb_uint16_t file_id, zb_int_t line_number); -/** - Check for expression in runtime and call zb_assert() if it is false. - - Compiled to nothing if USE_ASSERT is not defined. - - @param expr expression to check -*/ -#define ZB_ASSERT(expr) {if(!(expr)) { zb_assert(ZB_TRACE_FILE_ID, __LINE__);} } -/** @cond internals_doc */ -#define ZB_INLINE_ASSERT_SIMPLE(expr) ((expr) ? 1 : (zb_assert(ZB_TRACE_FILE_ID, __LINE__), 1)) -/** @endcond */ - -#endif /* !ZB_BINARY_TRACE */ - -/** @cond internals_doc */ -void lwip_zb_assert(zb_uint16_t file_id, zb_int_t line_number); -/** @endcond */ - -/** - Assert which can be used inside an expression. - - @param expr - expression to check. - @return always 1 (true) - */ -#define ZB_INLINE_ASSERT(expr) ZB_INLINE_ASSERT_SIMPLE((expr)), - -#else /* release */ - -#define ZB_ASSERT(expr) ((void)(expr)) -#define ZB_INLINE_ASSERT_SIMPLE(expr) -1 -#define ZB_INLINE_ASSERT(expr) - -#endif - -/*! @} */ - -/** \addtogroup ZB_ASSERT_STATIC */ -/** @{ */ - -/** @cond internals_doc */ -/* Tricks to force preprocessor to substitute __LINE__ in macros */ -#define ZB_ASSERT_CAT_(a, b) a##_##b -#define ZB_ASSERT_CAT(a, b) ZB_ASSERT_CAT_(a, b) -/** @endcond */ - -/** - Check condition at compile time in the code (not declaration block) - - @param expr - expression to check. - */ -#if defined SDCC || defined KEIL -#define ZB_ASSERT_COMPILE_TIME(expr) -#else -#define ZB_ASSERT_COMPILE_TIME(expr) ((void)(zb_int_t (*)[(expr) ? 1 : -1])0) -#endif -/** - Check condition at compile time in the code (not declaration block), return 0 - To be used inside an expressions. - - @param expr - expression to check. - */ -#define ZB_ASSERT_COMPILE_TIME_EXPR(expr) ((zb_int_t)((zb_int_t (*)[(expr) ? 1 : -1])0)) - -/** - Check condition at compile time in the declaration block - - @param expr - expression to check. - */ -#ifdef __cplusplus -#define ZB_ASSERT_COMPILE_DECL(expr) __extension__ static_assert(expr, "Assert at line __LINE__") -#elif (defined __GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -#define ZB_ASSERT_COMPILE_DECL(expr) __extension__ _Static_assert(expr, "Assert at line __LINE__") -#elif defined(__COUNTER__) -#define ZB_ASSERT_COMPILE_DECL(expr) typedef zb_int_t ZB_ASSERT_CAT(assert, ZB_ASSERT_CAT(__LINE__, __COUNTER__))[(expr) ? 1 : -1] -#else -#define ZB_ASSERT_COMPILE_DECL(expr) -#endif - - -/** - Ensures, that size of type `type' is not greater than `limit'. If it is not, - compilation is aborted. - - @param type - type name - @param limit - size limit - */ -#define ZB_ASSERT_TYPE_SIZE_NOT_GREATER(type, limit) ZB_ASSERT_COMPILE_DECL(sizeof(type) <= (limit)) - -/** - Ensures, that size of type `type' is not less than `limit'. If it is not, - compilation is aborted. - - @param type - type name - @param limit - size limit - */ -#define ZB_ASSERT_TYPE_SIZE_NOT_LESS(type, limit) ZB_ASSERT_COMPILE_DECL(sizeof(type) >= (limit)) - -/** - Ensures, that size of type `type' is equal to the `limit'. If it is not, - compilation is aborted. - - @param type - type name - @param limit - size limit - */ -#define ZB_ASSERT_TYPE_SIZE_EQ(type, limit) ZB_ASSERT_COMPILE_DECL(sizeof(type) == (limit)) - -/*! @} */ - -#ifdef ZB_ARRAYS_CHECK -/** - Address all array elements. Use this macro to test that array really inited - by valgrind in Linux - */ -#define ZB_CHK_ARR(arr, len) \ - do \ - { \ - zb_ushort_t _ii; \ - zb_ushort_t n = 0; \ - for (_ii = 0 ; _ii < (len) ; ++_ii) \ - { \ - if ((arr)[_ii] < 2) \ - { \ - n++; \ - } \ - else \ - { \ - n--; \ - } \ - } \ - } \ -while (0) - -#else -#define ZB_CHK_ARR(arr, len) -#endif /* ZB_ARRAYS_CHECK */ - - -#define ZB_P3_ON() -#define ZB_P3_OFF() -#define ZB_P4_ON() -#define ZB_P4_OFF() - -#if defined ZB_TRAFFIC_DUMP_ON -/** - Dump array of byte - - @param buf - array of byte - @param len - size of array - */ -void dump_traf(zb_uint8_t *buf, zb_ushort_t len); -#endif /* DEBUG */ - -#ifdef ZB_TRAFFIC_DUMP_ON -void dump_usb_traf(zb_uint8_t *buf, zb_ushort_t len); -#else -#define dump_usb_traf(buf, len) -#endif - -#define DUMP_TRAF(comment, buf, len, total) - -#ifdef DEBUG -void dump_hex_data(zb_uint_t trace_mask, zb_uint8_t trace_level, zb_uint8_t *buf, zb_ushort_t len); - -void trace_hex_data_func(zb_uint8_t *ptr, zb_short_t size, zb_bool_t format); -#define trace_8hex_per_line(ptr, size) trace_hex_data_func((ptr), (size), ZB_FALSE) -#define trace_16hex_per_line(ptr, size) trace_hex_data_func((ptr), (size), ZB_TRUE) -#else -#define dump_hex_data(trace_mask, trace_level, buf, len) - -#define trace_8hex_per_line(ptr, size) -#define trace_16hex_per_line(ptr, size) -#endif /* DEBUG */ - -#endif /* ZB_DEBUG_H */ diff --git a/zboss/development/include/zb_errors.h b/zboss/development/include/zb_errors.h deleted file mode 100644 index 43a51568a0..0000000000 --- a/zboss/development/include/zb_errors.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Error codes -*/ - -#ifndef ZB_ERRORS_H -#define ZB_ERRORS_H 1 - -/** - * @addtogroup base_types - * @{ - */ -/** @brief Return type for ZB functions returning execution status. @see ::RET_OK. */ -typedef zb_int32_t zb_ret_t; -/** @} */ - -/*! @cond internals_doc */ - -/* categories */ - -#define ERROR_CATEGORY_INTERVAL 256 - -#define ERROR_CATEGORY_GENERIC 0 -#define ERROR_CATEGORY_SYSTEM 1 -#define ERROR_CATEGORY_MAC 2 -#define ERROR_CATEGORY_NWK 3 -#define ERROR_CATEGORY_APS 4 -#define ERROR_CATEGORY_ZDO 5 -#define ERROR_CATEGORY_CBKE 6 -#define ERROR_CATEGORY_WATCHDOG 7 -#define ERROR_CATEGORY_SERIAL 8 -#define ERROR_CATEGORY_NVRAM 9 -#define ERROR_CATEGORY_MACSPLIT 10 -#define ERROR_CATEGORY_NCP 11 - -/* Let's always return 0 for RET_OK - in any category. */ -#define ERROR_CODE(category, code) ((zb_ret_t)(((zb_ret_t)code) != 0 ? -(((category) * ERROR_CATEGORY_INTERVAL) + ((zb_ret_t)code)) : 0)) -#define GENERIC_ERROR_CODE(code) ERROR_CODE(ERROR_CATEGORY_GENERIC, code) -#define SYSTEM_ERROR_CODE(code) ERROR_CODE(ERROR_CATEGORY_SYSTEM, code) - -#define ERROR_GET_CATEGORY(err) (((-(zb_int_t)(err))) / ERROR_CATEGORY_INTERVAL) -#define ERROR_GET_CODE(err) ((-(zb_int_t)(err)) % ERROR_CATEGORY_INTERVAL) - -/** @endcond */ /* internals_doc */ - -/** - * @addtogroup error_codes - * @{ - */ - -/** - * @brief Error codes for non-void stack functions. - * In general, function can return OK, BLOCKED or some error. Errors are negative. - * - * Error can be "generic" or some additional error code. - */ - -/* Most common return types: ok, generic error, BLOCKED, thread exit indication. */ -#define RET_OK 0 -#define RET_ERROR ERROR_CODE(ERROR_CATEGORY_GENERIC, 1) /* -1 indeed */ -#define RET_BLOCKED ERROR_CODE(ERROR_CATEGORY_GENERIC, 2) -#define RET_EXIT ERROR_CODE(ERROR_CATEGORY_GENERIC, 3) -#define RET_BUSY ERROR_CODE(ERROR_CATEGORY_GENERIC, 4) -#define RET_EOF ERROR_CODE(ERROR_CATEGORY_GENERIC, 5) -#define RET_OUT_OF_RANGE ERROR_CODE(ERROR_CATEGORY_GENERIC, 6) -#define RET_EMPTY ERROR_CODE(ERROR_CATEGORY_GENERIC, 7) -#define RET_CANCELLED ERROR_CODE(ERROR_CATEGORY_GENERIC, 8) - - -#define RET_INVALID_PARAMETER_1 ERROR_CODE(ERROR_CATEGORY_GENERIC, 10) -#define RET_INVALID_PARAMETER_2 ERROR_CODE(ERROR_CATEGORY_GENERIC, 11) -#define RET_INVALID_PARAMETER_3 ERROR_CODE(ERROR_CATEGORY_GENERIC, 12) -#define RET_INVALID_PARAMETER_4 ERROR_CODE(ERROR_CATEGORY_GENERIC, 13) -#define RET_INVALID_PARAMETER_6 ERROR_CODE(ERROR_CATEGORY_GENERIC, 15) -#define RET_PENDING ERROR_CODE(ERROR_CATEGORY_GENERIC, 21) -#define RET_NO_MEMORY ERROR_CODE(ERROR_CATEGORY_GENERIC, 22) -#define RET_INVALID_PARAMETER ERROR_CODE(ERROR_CATEGORY_GENERIC, 23) -#define RET_OPERATION_FAILED ERROR_CODE(ERROR_CATEGORY_GENERIC, 24) -#define RET_BUFFER_TOO_SMALL ERROR_CODE(ERROR_CATEGORY_GENERIC, 25) -#define RET_END_OF_LIST ERROR_CODE(ERROR_CATEGORY_GENERIC, 26) -#define RET_ALREADY_EXISTS ERROR_CODE(ERROR_CATEGORY_GENERIC, 27) -#define RET_NOT_FOUND ERROR_CODE(ERROR_CATEGORY_GENERIC, 28) -#define RET_OVERFLOW ERROR_CODE(ERROR_CATEGORY_GENERIC, 29) -#define RET_TIMEOUT ERROR_CODE(ERROR_CATEGORY_GENERIC, 30) -#define RET_NOT_IMPLEMENTED ERROR_CODE(ERROR_CATEGORY_GENERIC, 31) -#define RET_NO_RESOURCES ERROR_CODE(ERROR_CATEGORY_GENERIC, 32) -#define RET_UNINITIALIZED ERROR_CODE(ERROR_CATEGORY_GENERIC, 33) -#define RET_INVALID_STATE ERROR_CODE(ERROR_CATEGORY_GENERIC, 35) -#define RET_CONNECTION_FAILED ERROR_CODE(ERROR_CATEGORY_GENERIC, 37) -#define RET_CONNECTION_LOST ERROR_CODE(ERROR_CATEGORY_GENERIC, 38) -#define RET_UNAUTHORIZED ERROR_CODE(ERROR_CATEGORY_GENERIC, 40) -#define RET_CONFLICT ERROR_CODE(ERROR_CATEGORY_GENERIC, 41) -#define RET_INVALID_FORMAT ERROR_CODE(ERROR_CATEGORY_GENERIC, 42) -#define RET_NO_MATCH ERROR_CODE(ERROR_CATEGORY_GENERIC, 43) -#define RET_PROTOCOL_ERROR ERROR_CODE(ERROR_CATEGORY_GENERIC, 44) -#define RET_VERSION ERROR_CODE(ERROR_CATEGORY_GENERIC, 45) -#define RET_FILE_NOT_FOUND ERROR_CODE(ERROR_CATEGORY_GENERIC, 48) -#define RET_CONVERSION_ERROR ERROR_CODE(ERROR_CATEGORY_GENERIC, 50) -#define RET_FILE_CORRUPTED ERROR_CODE(ERROR_CATEGORY_GENERIC, 56) -#define RET_PAGE_NOT_FOUND ERROR_CODE(ERROR_CATEGORY_GENERIC, 57) -#define RET_ILLEGAL_REQUEST ERROR_CODE(ERROR_CATEGORY_GENERIC, 62) -#define RET_INVALID_GROUP ERROR_CODE(ERROR_CATEGORY_GENERIC, 64) -#define RET_TABLE_FULL ERROR_CODE(ERROR_CATEGORY_GENERIC, 65) -#define RET_IGNORE ERROR_CODE(ERROR_CATEGORY_GENERIC, 69) -#define RET_AGAIN ERROR_CODE(ERROR_CATEGORY_GENERIC, 70) -#define RET_DEVICE_NOT_FOUND ERROR_CODE(ERROR_CATEGORY_GENERIC, 71) -#define RET_OBSOLETE ERROR_CODE(ERROR_CATEGORY_GENERIC, 72) -#define RET_INTERRUPTED ERROR_CODE(ERROR_CATEGORY_GENERIC, 73) -#define RET_NULL_POINTER ERROR_CODE(ERROR_CATEGORY_GENERIC, 74) - -/** @} */ /* Error codes */ - -#endif /* ZB_ERRORS_H */ diff --git a/zboss/development/include/zb_ha.h b/zboss/development/include/zb_ha.h deleted file mode 100644 index faebc1dbd4..0000000000 --- a/zboss/development/include/zb_ha.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: HA global definitions -*/ - -#ifndef ZB_HA_H -#define ZB_HA_H 1 - -#ifdef ZB_ENABLE_HA -#include "ha/zb_ha_config.h" - -#ifdef ZB_ENABLE_HA_SAS -#include "ha/zb_ha_sas.h" -#endif - -#ifdef ZB_HA_DEFINE_DEVICE_DOOR_LOCK -#include "ha/zb_ha_door_lock.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_DOOR_LOCK_CONTROLLER -#include "ha/zb_ha_door_lock_controller.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_ON_OFF_OUTPUT -#include "ha/zb_ha_on_off_output.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_ON_OFF_SWITCH -#include "ha/zb_ha_on_off_switch.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_SIMPLE_SENSOR -#include "ha/zb_ha_simple_sensor.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_COMBINED_INTERFACE -#include "ha/zb_ha_combined_interface.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_SCENE_SELECTOR -#include "ha/zb_ha_scene_selector.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_CONFIGURATION_TOOL -#include "ha/zb_ha_configuration_tool.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_MAINS_POWER_OUTLET -#include "ha/zb_ha_mains_power_outlet.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_RANGE_EXTENDER -#include "ha/zb_ha_range_extender.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_LEVEL_CONTROL_SWITCH -#include "ha/zb_ha_level_control_switch.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_LEVEL_CONTROLLABLE_OUTPUT -#include "ha/zb_ha_level_controllable_output.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_WINDOW_COVERING -#include "ha/zb_ha_window_covering.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_WINDOW_COVERING_CONTROLLER -#include "ha/zb_ha_window_covering_controller.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_SHADE -#include "ha/zb_ha_shade.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_SHADE_CONTROLLER -#include "ha/zb_ha_shade_controller.h" -#endif - -#ifdef ZB_HA_DEFINE_DEVICE_TEMPERATURE_SENSOR -#include "ha/zb_ha_temperature_sensor.h" -#endif - -#ifdef ZB_HA_DEFINE_DEVICE_IAS_CONTROL_INDICATING_EQUIPMENT -#include "ha/zb_ha_ias_control_indicating_equipment.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_IAS_ANCILLARY_CONTROL_EQUIPMENT -#include "ha/zb_ha_ias_ancillary_control_equipment.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_IAS_ZONE -#include "ha/zb_ha_ias_zone.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_IAS_WARNING_DEVICE -#include "ha/zb_ha_ias_warning_device.h" -#endif - -#ifdef ZB_HA_DEFINE_DEVICE_CUSTOM_ATTR -#include "ha/zb_ha_custom_attr.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_DIMMABLE_LIGHT -#include "ha/zb_ha_dimmable_light.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_DIMMER_SWITCH -#include "ha/zb_ha_dimmer_switch.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_SMART_PLUG -#include "ha/zb_ha_smart_plug.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_THERMOSTAT -#include "ha/zb_ha_thermostat.h" -#endif - -#ifdef ZB_HA_DEFINE_DEVICE_TEST_DEVICE -#include "ha/zb_ha_test_device.h" -#endif - -#ifdef ZB_HA_DEFINE_DEVICE_ERL_INTERFACE_DEVICE -#include "ha/zb_ha_erl_device_interface.h" -#endif -#ifdef ZB_HA_DEFINE_DEVICE_ERL_GW -#include "ha/zb_ha_erl_gw_device.h" -#endif -#endif -#endif /* ZB_HA_H */ diff --git a/zboss/development/include/zb_led_button.h b/zboss/development/include/zb_led_button.h deleted file mode 100644 index f603da2c88..0000000000 --- a/zboss/development/include/zb_led_button.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Common definitions for leds and buttons functionality -*/ - -#ifndef ZB_LED_H -#define ZB_LED_H 1 - -#include "zb_vendor.h" -#include "zboss_api_core.h" - -/*! @addtogroup leds_buttons */ -/*! @{ */ - -/** - * @name LED - * @{ - */ - -#ifdef ZB_DEPRECATED_API -/* This function is not used anywhere and seems its objective is not different from - * 'zb_osif_led_button_init()' which is currently used. It will be removed in a future - * release. */ -/** - * Prepare LEDs for usage - */ -void zb_led_init(void) ZB_DEPRECATED; -#endif /* ZB_DEPRECATED_API */ - -/** - * Stop blinking on given LED - * - * See ZB_LED_ARG_CREATE() for constructing led_arg - */ -void zb_led_blink_off(zb_uint8_t led_arg); - -/** - * Start blinking on given LED - * - * See ZB_LED_ARG_CREATE() for constructing led_arg - */ -void zb_led_blink_on(zb_uint8_t led_arg); - -/** - * Quant size for intervals passed to ZBOSS LED functions. - * - * See ZB_LED_ARG_CREATE() - */ -#define ZB_LED_PERIOD_MULTIPLIER ZB_MILLISECONDS_TO_BEACON_INTERVAL(250U) - -/** - * Conveniency constants to be used with ZB_LED_ARG_CREATE() macro - */ -typedef enum zb_led_blink_frequency_e -{ - ZB_LED_BLINK_QUATER_SEC = 1, /*!< Blink four times per second */ - ZB_LED_BLINK_HALF_SEC = 2, /*!< Blink twice per second */ - ZB_LED_BLINK_PER_SEC = 4, /*!< Blink every second */ - ZB_LED_BLINK_PER_2SEC = 8, /*!< Blink every two seconds */ -} zb_led_blink_frequency_t; - -/** @cond internals_doc */ - -/** - * @brief get period argument value (in beacon intervals) from led_arg. - * To be used in ZBOSS led functions - */ -#define ZB_LED_ARG_PERIOD(led_arg) (((led_arg) >> 4U) * ZB_LED_PERIOD_MULTIPLIER) - -/** - * @brief get LED number from led_arg - * To be used in ZBOSS led functions - */ -#define ZB_LED_ARG_NUMBER(led_arg) ((led_arg) & 0xfU) - -/** @endcond */ - -/** - * @brief Construct argument to pass to LEd functions line zb_led_blink_on() - * @param num - number of LED for which command is meant - * @param period - interval between LED state changes. - * see @ref ZB_LED_PERIOD_MULTIPLIER for quant size. - * @note period should not exceed value of 16 - */ -#define ZB_LED_ARG_CREATE(num, period) ((num) | (period << 4U)) - -/** @} */ - -/** - * @name Buttons - * @{ - */ - -/** - * @brief Set state of given button to on - * - * @param butt_no - number of button being pressed - */ -void zb_button_on_cb(zb_uint8_t butt_no); - -/** - * @brief Set state of given button to off and invoke button handler. - * - * Handler to invoke is chosen by button and duration of button press. - * See @ref zb_button_register_handler() for how to setup button handlers - * - * @param butt_no - number of button being released - */ -void zb_button_off_cb(zb_uint8_t butt_no); - -/** - * @brief Register handler to be called on button release - * - * Several handlers can be set for one button (see ZB_BUTT_N_CBS for maximum number of callbacks) - * Each handler is associated with handler press duration, and only one will be called, - * it depends on how long button was pressed which one. - * - * @param butt_no - number of button with which handler is associated - * @param pressed_sec_pow2 - duration with which handler is associated. - * calculated as given power of 2 (in sec): 1-2-4-8... sec - * @param cb - pointer to handler functions - */ -void zb_button_register_handler(zb_uint8_t butt_no, zb_uint8_t pressed_sec_pow2, zb_callback_t cb); - -/** @cond internals_doc */ -void zb_osif_led_button_init(void); -/** @endcond */ - -/** - * @brief Set state of given LED to "On" - */ -void zb_osif_led_on(zb_uint8_t led_no); - -/** - * @brief Set state of given LED to "Off" - */ -void zb_osif_led_off(zb_uint8_t led_no); - -/** @cond internals_doc */ -zb_bool_t zb_setup_buttons_cb(zb_callback_t cb); -void zb_osif_button_cb(zb_uint8_t arg); -zb_bool_t zb_osif_button_state(zb_uint8_t arg); -/** @endcond */ - -/* Button indexes utilized by applications - * note: more can be used/defined depending on target HW - */ -#define ZB_BOARD_BUTTON_0 0U -#define ZB_BOARD_BUTTON_1 1U -#define ZB_BOARD_BUTTON_2 2U -#define ZB_BOARD_BUTTON_3 3U - -/** - * Number of handler that can be associated with a button. - * - * Each of those handlers corresponds to its own press duration - */ -#define ZB_BUTT_N_CBS 5U - -#ifndef ZB_N_BUTTONS - -/** - * Number of button utilized by application - */ -#define ZB_N_BUTTONS 1U - -#endif - -#ifndef ZB_N_LEDS - -/** - * Number of leds utilized by application - */ -#define ZB_N_LEDS 1U - -#endif - -/** @cond internals_doc */ -typedef struct zb_button_ctl_s -{ - zb_bool_t is_on; - zb_time_t on_time; - zb_callback_t handlers[ZB_BUTT_N_CBS]; -} zb_button_ctl_t; - - -typedef struct zb_buttons_global_s -{ - zb_button_ctl_t buttons[ZB_N_BUTTONS]; -} zb_buttons_global_t; - -/** @endcond */ - -/*! @} */ - -/*! @} */ - -#endif /* ZB_LED_H */ diff --git a/zboss/development/include/zb_list_macros.h b/zboss/development/include/zb_list_macros.h deleted file mode 100644 index 5ed326ed42..0000000000 --- a/zboss/development/include/zb_list_macros.h +++ /dev/null @@ -1,519 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Very simple lists operations (macros). -*/ -#ifndef LIST_H -#define LIST_H 1 - -/*! @cond internals_doc */ -/** - @addtogroup ZB_BASE - @{ -*/ - - -/** - \par Double linked list - - Usage sample: - - declare some structure, include list field into it: - struct xxx { - ... - ZB_LIST_FIELD(struct xxx *, next1); - }; - - declare list head in some other place: - struct xxx * list_head; - - - insert into the list - ZB_LIST_INSERT_HEAD(list_head, next1, ent) - ZB_LIST_INSERT_TAIL(list_head, next1, ent) - ZB_LIST_INSERT_AFTER(list_head, next1, old_ent, new_ent) - - - iterate (for loop): - ZB_LIST_ITERATE(list_head, next1, ent) - { - do something with ent - } - - - iterate back (for loop) - ZB_LIST_ITERATE_BACK(list_head, next1, ent) - { - do something with ent - } - - - iterate (manual) - struct xxx *ent = ZB_LIST_GET_HEAD(list_head, next1) - while (ent) - { - ... - ent = ZB_LIST_NEXT(ent, next1); - } - - - iterate back (manual) - struct xxx *ent = ZB_LIST_GET_TAIL(list_head, next1) - while (ent) - { - ... - ent = ZB_LIST_PREV_FOR_ITER(ent, next1); - } - - - remove - ZB_LIST_REMOVE_HEAD(list_head, next1) - ZB_LIST_REMOVE_TAIL(list_head, next1) - ZB_LIST_REMOVE(list_head, next1, ent) - - - check that item is already in list - ZB_LIST_ITEM_IN_LIST(ent, next1) - */ - - -/** - * List control fields declaration. To be put into the structure - * definition. - * - * _prev field has special meaning for the list head: this is pointer - * to the list tail. - */ -#define ZB_LIST_FIELD(type, name) type name ## _next; type name ## _prev - -#if defined DEBUG && defined __GNUC__ -#define ZB_LIST_CHECK_ENT(list, name, ent) do { \ - { \ - typeof(ent) tmp; \ - ZB_LIST_ITERATE(list, name, tmp) \ - { \ - ZB_ASSERT(tmp != ent); \ - } \ - } \ -} while(0) -#else -#define ZB_LIST_CHECK_ENT(list, name, ent) do{}while(0) -#endif - -/* Macro for debugging adding duplicates to the list */ -#define ZB_LIST_CHECK_ENT1(list, name, ent, type) do{ \ - type * tmp; \ - ZB_LIST_ITERATE(list, name, tmp) \ - { \ - ZB_ASSERT(tmp != ent); \ - } \ -}while(0) - -#define ZB_LIST_SIZE(type) (2 * sizeof(type)) - -#define ZB_LIST_DEFINE(type, list) type list -#define ZB_LIST_ARRAY_DEFINE(type, list, n) type list[n] -#define ZB_LIST_INIT(list) (list) = NULL - - -#define ZB_LIST_IS_EMPTY(list) ((list) == NULL) -#define ZB_LIST_IS_NOT_EMPTY(list) ((list) != NULL) -#define ZB_LIST_NEXT(ent, name) (ent)->name ## _next -#define ZB_LIST_PREV_RAW(ent, name) (ent)->name ## _prev -#define ZB_LIST_ZERO(ent, name) (ent)->name ## _prev = (ent)->name ## _next = 0 - -/** - * Like ZB_LIST_PREV(), but check for going over list head - */ -#define ZB_LIST_PREV(ent, name) ((((ent)->name ## _prev)->name ## _next) ? (ent)->name ## _prev : 0) -#define ZB_LIST_GET_HEAD(list, name) (list) -#define ZB_LIST_GET_TAIL(list, name) ((list) ? (list)->name ## _prev : 0) -#define ZB_LIST_ITEM_IN_LIST(t, name) (((t)->name ## _prev) != NULL) - - -/* - * Remove from the list head, and store it in ent - */ -#define ZB_LIST_CUT_HEAD(list, name, ent) do \ -{ \ - ent = list; \ - if ((list)) \ - { \ - if (((list)->name ## _next)) \ - { \ - ((list)->name ## _next)->name ## _prev = (list)->name ## _prev; \ - } \ - (list)->name ## _prev = 0; \ - (list) = (list)->name ## _next; \ - } \ -} while (0) - - - -/* - * Insert to the list head - */ -#define ZB_LIST_INSERT_HEAD(list, name, ent) do \ -{ \ - ZB_LIST_CHECK_ENT(list, name, ent); \ - (ent)->name ## _next = (list); \ - if ((list)) \ - { \ - (ent)->name ## _prev = (list)->name ## _prev; \ - (list)->name ## _prev = (ent); \ - } \ - else \ - { \ - (ent)->name ## _prev = (ent); \ - } \ - (list) = (ent); \ -} while(0) - - -/* - * Insert to the list tail - */ -#define ZB_LIST_INSERT_TAIL(list, name, ent) do \ -{ \ - ZB_LIST_CHECK_ENT(list, name, ent); \ - (ent)->name ## _next = 0; \ - if ((list)) \ - { \ - (ent)->name ## _prev = (list)->name ## _prev; \ - ((list)->name ## _prev)->name ## _next = (ent); \ - (list)->name ## _prev = (ent); \ - } \ - else \ - { \ - (ent)->name ## _prev = (ent); \ - (list) = (ent); \ - } \ -} while (0) - - -/* - * Insert after existed entry - */ -#define ZB_LIST_INSERT_AFTER(list, name, ent, new_ent) do \ -{ \ - ZB_LIST_CHECK_ENT(list, name, new_ent); \ - if ((ent)) \ - { \ - if ((ent) == ZB_LIST_GET_TAIL(list, name)) \ - { \ - ZB_LIST_INSERT_TAIL(list, name, new_ent); \ - } \ - else \ - { \ - (new_ent)->name ## _next = (ent)->name ## _next; \ - (new_ent)->name ## _prev = (ent); \ - ((ent)->name ## _next)->name ## _prev = (new_ent); \ - (ent)->name ## _next = (new_ent); \ - } \ - } \ -} while(0) - - -/* - * Remove from the list head - */ -#define ZB_LIST_REMOVE_HEAD(list, name) do \ -{ \ - if ((list)) \ - { \ - if (((list)->name ## _next)) \ - { \ - ((list)->name ## _next)->name ## _prev = (list)->name ## _prev; \ - } \ - (list)->name ## _prev = 0; \ - (list) = (list)->name ## _next; \ - } \ -} while (0) - -/* - * Remove from the list tail - */ -#define ZB_LIST_REMOVE_TAIL(list, name) do \ -{ \ - if ((list)) \ - { \ - if ((list)->name ## _prev == (list)) /* made an empty list */ \ - { \ - (list)->name ## _prev = 0; \ - (list) = 0; \ - } \ - else \ - { \ - (((list)->name ## _prev)->name ## _prev)->name ## _next = 0; \ - /* This is a bit tricky: we need to assign list->prev and set \ - * tail->prev to 0, but we can't use temporary variable because \ - * we have no type here. Use _next as temporary variable. */ \ - ((list)->name ## _prev)->name ## _next = ((list)->name ## _prev)->name ## _prev; \ - ((list)->name ## _prev)->name ## _prev = 0; \ - (list)->name ## _prev = ((list)->name ## _prev)->name ## _next; \ - } \ - } \ -} while (0) - -#define ZB_LIST_ITERATE(list, name, ent) \ -for ((ent) = (list) ; (ent) != 0 ; (ent) = (ent)->name ## _next) - -#define ZB_LIST_ITERATE_BACK(list, name, ent) \ -for ((ent) = (list) ? (list)->name ## _prev : 0 ; (ent) ; (ent) = (((ent)->name ## _prev)->name ## _next) ? (ent)->name ## _prev : 0) - -#define ZB_LIST_NULL_INIT 0,0 - -#define ZB_LIST_REMOVE(list, name, ent) \ -do \ -{ \ - if ((ent)->name ## _prev != 0) \ - { \ - if ((ent)->name ## _next) /* this is not a tail */ \ - { \ - ((ent)->name ## _next)->name ## _prev = (ent)->name ## _prev; \ - } \ - else /* this is a tail */ \ - { \ - (list)->name ## _prev = (ent)->name ## _prev; \ - } \ - if ((ent) == (list)) /* this is a head */ \ - { \ - (list) = (ent)->name ## _next; \ - } \ - else /* this is not a head */ \ - { \ - ((ent)->name ## _prev)->name ## _next = (ent)->name ## _next; \ - } \ - (ent)->name ## _prev = 0; \ - } \ -} \ -while (0) - -/** - \par Single-linked list (stack and FIFO). - - Use same name ## _next field of the double linked list, so can coexist with it. - */ - -/** - Define single-linked list head/tail pointer - - @param type - type of the pointer to the list element - @param list - list head/tail name prefix - - @b Example: -@code - ZB_SL_LIST_DEFINE (struct work_file_page0_s *, f); -@endcode - */ -#define ZB_SL_LIST_DEFINE(type, list) type list ## _head; type list ## _tail - -#define ZB_SL_LIST_INIT(list) list ## _head = list ## _tail = 0 - - -/** - Define field in the single-linked list element - - @param type - type of the pointer to the list element - @param name - list name (to be able to put element to more then one list) - - @b Example: -@code - ZB_SL_LIST_FIELD (struct work_file_page0_s *, f); -@endcode - */ -#define ZB_SL_LIST_FIELD(type, name) type name ## _next - -/** - Insert into single-linked list head - - @param list - list header pointer (sample: some_ptr->some_list) - @param name - list name - @param ent - element for insert - */ -#define ZB_SL_LIST_INSERT_HEAD(list, name, ent) \ -do \ -{ \ - (ent)->name ## _next = (list ## _head); \ - if (!(list ## _head)) \ - { \ - (list ## _tail) = (ent); \ - } \ - (list ## _head) = (ent); \ -} \ -while (0) - - -#define ZB_SL_LIST_INSERT_TAIL(list, name, ent) \ -do \ -{ \ - (ent)->name ## _next = 0; \ - if (list ## _tail) \ - { \ - (list ## _tail)->name ## _next = (ent); \ - list ## _tail = (ent); \ - } \ - else \ - { \ - (list ## _head) = (ent); \ - (list ## _tail) = (ent); \ - } \ -} \ -while (0) - - - -#define ZB_SL_LIST_REMOVE_HEAD(list, name) \ -do \ -{ \ - if ((list ## _head)) \ - { \ - (list ## _head) = (list ## _head)->name ## _next; \ - if (!(list ## _head)) \ - { \ - (list ## _tail) = 0; \ - } \ - } \ -} \ -while (0) - -#define ZB_SL_LIST_CUT_HEAD(list, name, ent) \ -do \ -{ \ - if ((list ## _head)) \ - { \ - ent = (list ## _head); \ - (list ## _head) = (list ## _head)->name ## _next; \ - if (!(list ## _head)) \ - { \ - (list ## _tail) = 0; \ - } \ - } \ - else \ - { \ - (ent) = 0; \ - } \ -} \ -while (0) - -#define ZB_SL_LIST_REMOVE(type, list, name, ent) \ -do \ -{ \ - type p; \ - type prev = 0; \ - for (p = (list ## _head) ; p ; prev = p, p = p->name ## _next) \ - { \ - if (p == (ent)) \ - { \ - if (prev) \ - { \ - prev->name ## _next = p->name ## _next; \ - if ((list ## _tail) == ent) \ - { \ - (list ## _tail) = prev; \ - } \ - } \ - else \ - { \ - (list ## _head) = p->name ## _next; \ - } \ - if (!(list ## _head)) \ - { \ - (list ## _tail) = 0; \ - } \ - break; \ - } \ - } \ -} \ -while (0) - - -#define ZB_SL_LIST_ITERATE(list, name, ent) for ((ent) = (list ## _head) ; (ent) ; (ent) = (ent)->name ## _next) - -#define ZB_SL_LIST_NEXT(ent, name) ((ent)->name ## _next) - -#define ZB_SL_LIST_GET_HEAD(list) (list ## _head) - - -/* FIFO compatible with double-linked list macros */ - -#define ZB_FIFO_DEFINE ZB_SL_LIST_DEFINE -#define ZB_FIFO_FIELD ZB_SL_LIST_FIELD -#define ZB_FIFO_INIT ZB_SL_LIST_INIT -#define ZB_FIFO_PUT ZB_SL_LIST_INSERT_TAIL -#define ZB_FIFO_PUT_TAIL ZB_SL_LIST_INSERT_HEAD -#define ZB_FIFO_GET ZB_SL_LIST_CUT_HEAD -#define ZB_FIFO_PEEK ZB_SL_LIST_GET_HEAD -#define ZB_FIFO_REMOVE ZB_SL_LIST_REMOVE_HEAD -#define ZB_FIFO_ITERATE_FROM_TAIL ZB_SL_LIST_ITERATE - - -/* Stack compatible with double-linked list macros */ - -#define ZB_STK_DEFINE(type, list) type list ## _head - -#define ZB_STK_INIT(list) list ## _head = 0 - -#define ZB_STK_FIELD ZB_SL_LIST_FIELD - -#define ZB_STK_FIELD_INIT(field) field ## _next = 0 - -#define ZB_STK_PUSH(list, name, ent) \ -do \ -{ \ - (ent)->name ## _next = (list ## _head); \ - (list ## _head) = (ent); \ -} \ -while (0) - -#define ZB_STK_POP(list, name, ent) \ -do \ -{ \ - if ((list ## _head)) \ - { \ - (ent) = (list ## _head); \ - (list ## _head) = (list ## _head)->name ## _next; \ - } \ - else \ - { \ - (ent) = 0; \ - } \ -} \ -while (0) - -#define ZB_STK_PEEK ZB_SL_LIST_GET_HEAD -#define ZB_STK_ITERATE ZB_SL_LIST_ITERATE -#define ZB_STK_NEXT ZB_SL_LIST_NEXT - -/*! @} */ -/*! @endcond */ - -#endif /* LIST_H */ diff --git a/zboss/development/include/zb_mem_config_common.h b/zboss/development/include/zb_mem_config_common.h deleted file mode 100644 index 7c0a155692..0000000000 --- a/zboss/development/include/zb_mem_config_common.h +++ /dev/null @@ -1,331 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Common rules for ZBOSS application-side memory configuring - -That file is to be included from zb_mem_config_xxxx.h after basic -selectors defined. - -Do not include that file directly into the application source! -*/ -#ifndef ZB_MEM_CONFIG_COMMON_H -#define ZB_MEM_CONFIG_COMMON_H 1 - -/* - That file is useful only for ZBOSS build with memory configurable by the user without ZBOSS lib recompile. - */ -#ifdef ZB_CONFIGURABLE_MEM - -#ifdef ZB_ED_ROLE -/* If ZBOSS library is compiled for ZED only, force ZED config role. */ -#ifndef ZB_CONFIG_ROLE_ZED -#define ZB_CONFIG_ROLE_ZED -#endif -#ifdef ZB_CONFIG_ROLE_ZC -#undef ZB_CONFIG_ROLE_ZC -#endif -#ifdef ZB_CONFIG_ROLE_ZR -#undef ZB_CONFIG_ROLE_ZR -#endif -#endif - -/* - Rules of deriving parameters from generic settings. - -## device role ZC/ZR/ZED -### Parameters depending on it: -ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE: set 4 for ZR / OVERALL_NETWORK_SIZE for ZC - -## Overall Zigbee network size: -OVERALL_NETWORK_SIZE 16 to 200 - -### Parameters depending on it: -- ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE: set = OVERALL_NETWORK_SIZE -- ZB_IEEE_ADDR_TABLE_SIZE - set = OVERALL_NETWORK_SIZE + reserve for redirected entries -- ZB_NEIGHBOR_TABLE_SIZE - set = ZB_IEEE_ADDR_TABLE_SIZE - -## Total network traffic -HIGH_TRAFFIC / MODERATE_TRAFFIC / LIGHT_TRAFFIC - -### Parameters depending on it: -- ZB_IOBUF_POOL_SIZE: 18 LITE / 32 MODERATE / 48 HIGH -- ZB_NWK_ROUTING_TABLE_SIZE ZB_NEIGHBOR_TABLE_SIZE if MODERATE or HIGH, 8 if LITE -- ZB_MAC_PENDING_QUEUE_SIZE (ZB_IOBUF_POOL_SIZE / 4) -- ZB_APS_BIND_TRANS_TABLE_SIZE function of ZB_IOBUF_POOL_SIZE - -## Complexity of application relationships -APPLICATION_SIMPLE / APPLICATION_MODERATE / APPLICATION_COMPLEX - -### Parameters depending on it: -- ZB_IOBUF_POOL_SIZE: same constants as for net traffic; use bigger one if have a choice -- ZB_N_APS_RETRANS_ENTRIES: derived from ZB_IOBUF_POOL_SIZE -- ZB_APS_DUPS_TABLE_SIZE: 8 SIMPLE / 16 MODERATE / 32 COMPLEX -- ZB_SCHEDULER_Q_SIZE 20 SIMPLE / 32 MODERATE / 48 COMPLEX - */ - -/* - Total network size: set at upper level, just a verification here. - */ -#ifndef ZB_CONFIG_OVERALL_NETWORK_SIZE -#error Define ZB_CONFIG_OVERALL_NETWORK_SIZE! -#elif ZB_CONFIG_OVERALL_NETWORK_SIZE < 2U || ZB_CONFIG_OVERALL_NETWORK_SIZE > 200U -#error ZB_CONFIG_OVERALL_NETWORK_SIZE must be between 2 and 200! -#else -/* Derive constands from the network size */ - -#endif /* ZB_CONFIG_OVERALL_NETWORK_SIZE */ - - /* Reserve in address translation table for aliases: 1/4, at least - * 4. Table size must be < 255, so let's limit net size to 200 */ -#define ZB_IEEE_ADDR_TABLE_SIZE_RESERVE(n) ((n + 15U)/16U * 4U) - -/* - Device role -*/ -#ifdef ZB_CONFIG_ROLE_ZC - -#if defined ZB_CONFIG_ROLE_ZR || defined ZB_CONFIG_ROLE_ZED -#error Only one ZB_CONFIG_ROLE_xxx can be defined! -#endif - -/* ZC need to store one TCLK per device in the overall network */ -#define ZB_CONFIG_N_APS_KEY_PAIR_ARR_MAX_SIZE ZB_CONFIG_OVERALL_NETWORK_SIZE -/* Address table for entire network + reserve */ -#define ZB_CONFIG_IEEE_ADDR_TABLE_SIZE (ZB_CONFIG_OVERALL_NETWORK_SIZE + ZB_IEEE_ADDR_TABLE_SIZE_RESERVE(ZB_CONFIG_OVERALL_NETWORK_SIZE)) -/* Let's have enough space to have the entire network in neighbors - Star topology */ -#define ZB_CONFIG_NEIGHBOR_TABLE_SIZE ZB_CONFIG_OVERALL_NETWORK_SIZE -#define ZB_CONFIG_NWK_MAX_SOURCE_ROUTES ZB_CONFIG_OVERALL_NETWORK_SIZE - -#elif defined ZB_CONFIG_ROLE_ZR - -#if defined ZB_CONFIG_ROLE_ZC || defined ZB_CONFIG_ROLE_ZED -#error Only one ZB_CONFIG_ROLE_xxx can be defined! -#endif - -/* Only own keys need to be stored */ -#define ZB_CONFIG_N_APS_KEY_PAIR_ARR_MAX_SIZE 4U -/* The same as ZC: let's be able to work in Star. */ -#define ZB_CONFIG_IEEE_ADDR_TABLE_SIZE (ZB_CONFIG_OVERALL_NETWORK_SIZE + ZB_IEEE_ADDR_TABLE_SIZE_RESERVE(ZB_CONFIG_OVERALL_NETWORK_SIZE)) -#define ZB_CONFIG_NEIGHBOR_TABLE_SIZE ZB_CONFIG_OVERALL_NETWORK_SIZE -/* 10/21/2019 EE CR:MINOR Why we ever need that constant for ZR? Only ZC is a concentrator. */ -#define ZB_CONFIG_NWK_MAX_SOURCE_ROUTES ZB_CONFIG_OVERALL_NETWORK_SIZE - -#elif defined ZB_CONFIG_ROLE_ZED - -#if defined ZB_CONFIG_ROLE_ZC || defined ZB_CONFIG_ROLE_ZR -#error Only one ZB_CONFIG_ROLE_xxx can be defined! -#endif - -/* 2 is needed to perform BDB TCLK, 1 more is needed to request new TCLK */ -#define ZB_CONFIG_N_APS_KEY_PAIR_ARR_MAX_SIZE 4 -/* Set it here big enough; may decrease it later */ -#define ZB_CONFIG_IEEE_ADDR_TABLE_SIZE ZB_CONFIG_OVERALL_NETWORK_SIZE - -/* ZED needs neighbor table at join time only. More devices and nets around - bigger nbt required. Let's use some heuristics. */ -#if ZB_CONFIG_OVERALL_NETWORK_SIZE < 8U -#define ZB_CONFIG_NEIGHBOR_TABLE_SIZE 8U -#elif ZB_CONFIG_OVERALL_NETWORK_SIZE < 32U -#define ZB_CONFIG_NEIGHBOR_TABLE_SIZE 16U -#else -#define ZB_CONFIG_NEIGHBOR_TABLE_SIZE 32U -#endif - -#else - -#error Define exactly one ZB_CONFIG_ROLE_xxx! - -#endif /* ZB_CONFIG_ROLE_ZC */ - - -/* - Total network traffic (including NWK routing) - */ -#ifdef ZB_CONFIG_HIGH_TRAFFIC - -#if defined ZB_CONFIG_MODERATE_TRAFFIC || defined ZB_CONFIG_LIGHT_TRAFFIC -#error Only one ZB_CONFIG_xxx_TRAFFIC can be defined! -#endif - -/* More NWK traffic we route or send/recv from our app - more packet buffers required. */ -#define ZB_CONFIG_IOBUF_POOL_SIZE 48U -#define ZB_CONFIG_NWK_ROUTING_TABLE_SIZE ZB_CONFIG_NEIGHBOR_TABLE_SIZE -#define ZB_CONFIG_MAC_PENDING_QUEUE_SIZE (ZB_CONFIG_IOBUF_POOL_SIZE / 4U) -#define ZB_CONFIG_APS_BIND_TRANS_TABLE_SIZE ((ZB_CONFIG_IOBUF_POOL_SIZE + 15U)/16U * 4U) /* 1/4, at least 4 */ -#define ZB_CONFIG_SINGLE_TRANS_INDEX_SIZE ((ZB_CONFIG_APS_BIND_TRANS_TABLE_SIZE + 7U) / 8U) -#define ZB_CONFIG_APS_SRC_BINDING_TABLE_SIZE 32U -#define ZB_CONFIG_APS_DST_BINDING_TABLE_SIZE 32U - -#elif defined ZB_CONFIG_MODERATE_TRAFFIC - -#if defined ZB_CONFIG_HIGH_TRAFFIC || defined ZB_CONFIG_LIGHT_TRAFFIC -#error Only one ZB_CONFIG_xxx_TRAFFIC can be defined! -#endif - -#define ZB_CONFIG_IOBUF_POOL_SIZE 32U -#define ZB_CONFIG_NWK_ROUTING_TABLE_SIZE ZB_CONFIG_NEIGHBOR_TABLE_SIZE -#define ZB_CONFIG_MAC_PENDING_QUEUE_SIZE (ZB_CONFIG_IOBUF_POOL_SIZE / 4U) -#define ZB_CONFIG_APS_BIND_TRANS_TABLE_SIZE ((ZB_CONFIG_IOBUF_POOL_SIZE + 15U)/16U * 4U) /* 1/4, at least 4 */ -#define ZB_CONFIG_SINGLE_TRANS_INDEX_SIZE ((ZB_CONFIG_APS_BIND_TRANS_TABLE_SIZE + 7U) / 8U) -#define ZB_CONFIG_APS_SRC_BINDING_TABLE_SIZE 24U -#define ZB_CONFIG_APS_DST_BINDING_TABLE_SIZE 24U - -#elif defined ZB_CONFIG_LIGHT_TRAFFIC - -#if defined ZB_CONFIG_HIGH_TRAFFIC || defined ZB_CONFIG_MODERATE_TRAFFIC -#error Only one ZB_CONFIG_xxx_TRAFFIC can be defined! -#endif - -#define ZB_CONFIG_IOBUF_POOL_SIZE 26U -#define ZB_CONFIG_NWK_ROUTING_TABLE_SIZE 8U -#define ZB_CONFIG_MAC_PENDING_QUEUE_SIZE (ZB_CONFIG_IOBUF_POOL_SIZE / 4U) -#define ZB_CONFIG_APS_BIND_TRANS_TABLE_SIZE ((ZB_CONFIG_IOBUF_POOL_SIZE + 15U)/16U * 4U) /* 1/4, at least 4 */ -#define ZB_CONFIG_SINGLE_TRANS_INDEX_SIZE ((ZB_CONFIG_APS_BIND_TRANS_TABLE_SIZE + 7U) / 8U) -#define ZB_CONFIG_APS_SRC_BINDING_TABLE_SIZE 16U -#define ZB_CONFIG_APS_DST_BINDING_TABLE_SIZE 16U - -#else - -#error Define exactly one ZB_CONFIG_xxx_TRAFFIC! - -#endif /* ZB_CONFIG_HIGH_TRAFFIC */ - -/* check that 5 bits of src_table_index is enough */ -ZB_ASSERT_COMPILE_DECL(ZB_CONFIG_APS_SRC_BINDING_TABLE_SIZE <= (1U<<5U)); - -/* - Complexity of the application interconnection to other Zigbee devices. - */ -#ifdef ZB_CONFIG_APPLICATION_COMPLEX - -#if defined ZB_CONFIG_APPLICATION_MODERATE || defined ZB_CONFIG_APPLICATION_SIMPLE -#error Only one ZB_CONFIG_APPLICATION_xxx can be defined! -#endif - -#define ZB_CONFIG_SCHEDULER_Q_SIZE 48U - -/* Increase pool and neighbor table sizes of complex application is supposed. */ - -#if ZB_CONFIG_IOBUF_POOL_SIZE < 32U -#undef ZB_CONFIG_IOBUF_POOL_SIZE -#define ZB_CONFIG_IOBUF_POOL_SIZE 32U -#endif - -#if ZB_CONFIG_NEIGHBOR_TABLE_SIZE < 16U -#undef ZB_CONFIG_NEIGHBOR_TABLE_SIZE -#define ZB_CONFIG_NEIGHBOR_TABLE_SIZE 16U -#endif - -#define ZB_CONFIG_APS_DUPS_TABLE_SIZE 32U -#define ZB_CONFIG_N_APS_RETRANS_ENTRIES ((ZB_CONFIG_IOBUF_POOL_SIZE + 8U)/9U * 3U) /* 1/3, at least 3 */ - -#elif defined ZB_CONFIG_APPLICATION_MODERATE - -#if defined ZB_CONFIG_APPLICATION_COMPLEX || defined ZB_CONFIG_APPLICATION_SIMPLE -#error Only one ZB_CONFIG_APPLICATION_xxx can be defined! -#endif - -#ifdef ZB_CONFIG_HIGH_TRAFFIC -#define ZB_CONFIG_SCHEDULER_Q_SIZE 48U -#else -#define ZB_CONFIG_SCHEDULER_Q_SIZE 32U -#endif - -#if ZB_CONFIG_IOBUF_POOL_SIZE < 24U -#undef ZB_CONFIG_IOBUF_POOL_SIZE -#define ZB_CONFIG_IOBUF_POOL_SIZE 24U -#endif - -#define ZB_CONFIG_APS_DUPS_TABLE_SIZE 16U -#define ZB_CONFIG_N_APS_RETRANS_ENTRIES ((ZB_CONFIG_IOBUF_POOL_SIZE + 8U)/9U * 3U) /* 1/3, at least 3 */ - -#elif defined ZB_CONFIG_APPLICATION_SIMPLE - -#if defined ZB_CONFIG_APPLICATION_MODERATE || defined ZB_CONFIG_APPLICATION_COMPLEX -#error Only one ZB_CONFIG_APPLICATION_xxx can be defined! -#endif - -#define ZB_CONFIG_SCHEDULER_Q_SIZE 20U - -#define ZB_CONFIG_APS_DUPS_TABLE_SIZE 8U -#define ZB_CONFIG_N_APS_RETRANS_ENTRIES 6U - -#else - -#error Define exactly one ZB_CONFIG_APPLICATION_xxx! - -#endif /* ZB_CONFIG_APPLICATION_COMPLEX */ - -#ifdef ZB_CONFIG_SCHEDULER_Q_SIZE -/** - The purpose of the define. Ret code handling implementation on the application side - (via ZB_SCHEDULE_USER_APP_ALARM and ZB_SCHEDULE_USER_APP_CALLBACK) implies that we have some part - of the callback and alarm queues which can not be used from the user app and always should be reserved - for stack schedule purposes. So, let's define this part as 12 (for both immediate callbacks and alarms) - for all configurations. - */ -#define ZB_CONFIG_SCHEDULER_Q_SIZE_PROTECTED_STACK_POOL 12U -#if (ZB_CONFIG_SCHEDULER_Q_SIZE - ZB_CONFIG_SCHEDULER_Q_SIZE_PROTECTED_STACK_POOL) < 6U -#error The size of application scheduler queue is very small! Please, change ZB_CONFIG_SCHEDULER_Q_SIZE_PROTECTED_STACK_POOL, ZB_CONFIG_SCHEDULER_Q_SIZE to set it at least 6 -#endif -#endif - -#ifdef ZB_CONFIG_ROLE_ZED -/* That parameters will not be used in ZED, but just in case - let - * compiler fail if routing parameter used by mistake. */ -#undef ZB_CONFIG_NWK_ROUTING_TABLE_SIZE -#undef ZB_CONFIG_MAC_PENDING_QUEUE_SIZE -#define ZB_CONFIG_NWK_ROUTING_TABLE_SIZE 0U -#define ZB_CONFIG_MAC_PENDING_QUEUE_SIZE 0U -#endif - -#ifdef ZB_MAC_SOFTWARE_PB_MATCHING -/* Child heighbor hash table size equals to size of addr table + 33% aligned to 32 */ -#define ZB_CONFIG_CHILD_HASH_TABLE_SIZE (((ZB_CONFIG_IEEE_ADDR_TABLE_SIZE + ZB_CONFIG_IEEE_ADDR_TABLE_SIZE / 3U) + 31U) / 32U * 32U) - -/* Pending bitmap size. Each bit corresponds to "child_hash_table" */ -#define ZB_CONFIG_PENDING_BITMAP_SIZE ((ZB_CONFIG_CHILD_HASH_TABLE_SIZE + 31U) / 32U) -#endif - -/* This value must not be changed. Initialization is based on the ZB_CONFIG_IOBUF_POOL_SIZE value. */ -#define ZB_CONFIG_BUF_POOL_BITMAP_SIZE ((ZB_CONFIG_IOBUF_POOL_SIZE + 7U) / 8U) - -#endif /* ZB_CONFIGURABLE_MEM */ - -#endif /* ZB_MEM_CONFIG_COMMON_H */ diff --git a/zboss/development/include/zb_mem_config_context.h b/zboss/development/include/zb_mem_config_context.h deleted file mode 100644 index 0694e8ed87..0000000000 --- a/zboss/development/include/zb_mem_config_context.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Contexts for ZBOSS configurable memory -*/ -#ifndef ZB_MEM_CONFIG_CONTEXT_H -#define ZB_MEM_CONFIG_CONTEXT_H 1 - - -/*! @internal */ -/*! @{ */ - -/** - @defgroup configurable_mem_internals - @{ - @details - Design of configurable ZBOSS internal memory provides an ability to - configure some storage parameters at application link time without - recompiling ZBOSS libraries. - If application does not configure storage parameters, default values will be used. - - ZBOSS uses static memory allocation technique. - - Initially (before introducing configurable memory) ZBOSS used static arrays inside data structures and defines for array's sizes. - Defines are fixed at ZBOSS compile time. @see zb_buf_pool_t.pool as an example. - - To be able to configure memory at compile time, ZBOSS changes static buffers to pointers (@see zb_buf_pool_t.pool again). - Size constants are redefined to variables (@see gc_pool_size). - So ZBOSS code mostly not changed and can be compiled with or without configurable memory feature. - - This header file defines variables for buffers and variables for buffer sizes. - That file can be included strictly once from the kernel (zb_init.c) or - from the user's application (indirectly, from file zb_mem_config_xxx.h). - When included form the kernel, ZB_CONFIG_DEFAULT_KERNEL_DEFINITION is defined, so all symbols are defined as weak. - As a result, if application does not included any memory configuration includes, - default buffers and its sizes (weak) are used. - If application includes one of zb_mem_config_xxx.h, it overwrites weak symbols for buffers and its sizes. - - Pointers assignment (like @ref zb_buf_pool_t.pool) and arrays syzes - initialization are done at ZBOSS start time from @ref zb_init_configurable_mem(). - - Default storage settings are defined in zb_vendor.h file. - @note Changing zb_vendor.h is meaningful only if you re-compile ZBOSS library. - Do not change it when you compile the application. - - See also @ref configurable_mem. - @} -*/ - -#if defined ZB_CONFIGURABLE_MEM || defined DOXYGEN - -/* - some data structures use 7 bits to address a buffer, so can have up to 127 buffers. - Actually it is big enough because more than 48 are rarely used.. - */ -#if ZB_CONFIG_IOBUF_POOL_SIZE > 127U -#error ZB_CONFIG_IOBUF_POOL_SIZE must be <= 127 -#endif - -/**@brief Maximum buffer index. - * This macro is just an abbreviation for a corresponding macro in ZBOSS sources and its value must not be changed. - */ -#define ZB_CONFIG_N_BUF_IDS (ZB_CONFIG_IOBUF_POOL_SIZE + 1U) - -/** - @par - Define default configuration in the kernel lib as a weak symbol - */ -#if defined ZB_CONFIG_DEFAULT_KERNEL_DEFINITION || defined DOXYGEN - -/** - Kernel's default buffers. Define weak global variables. -*/ -#define ZB_CONFIG_POST ZB_WEAK -#define ZB_CONFIG_PRE ZB_WEAK_PRE ZB_ALIGNED_PRE -#define ZB_CONFIG_USE_DEFAULTS 1U - -#else - -/* User's app. Just define global variables. */ -#define ZB_CONFIG_POST -#define ZB_CONFIG_PRE ZB_ALIGNED_PRE -#define ZB_CONFIG_USE_DEFAULTS 0U - -#endif - - -/** - If user did not overwrite default memory configuration, that variable value is 1, else 0. - - Currently used in trace only, but, maybe, implement user API for it if customer require it? - */ -ZB_CONFIG_PRE zb_uint_t gc_use_defaults ZB_CONFIG_POST = ZB_CONFIG_USE_DEFAULTS; - -/* Can't put all that variables into the struct because its sizes will - * be different for in-kernel default case and in the application - * which overwritten some sizes. So declare variables one by one. */ - -/* If we are here from the user's app, here are buffers - definition. Application must be here only once. - - If we are here from the kernel, it can be either default buffers - definition or variables declaration (including variables storing - sizes). - */ - - -/** -Buffer pool: -ZB_IOBUF_POOL_SIZE and derivatives. - -Arrays directly defined by ZB_IOBUF_POOL_SIZE: - -zb_zdo_globals.h -nwk_addr_req_pending_tsns -nwk_addr_req_pending_mask - -zb_bufpool_globals.h - -zb_buf_pool_t.pool -zb_buf_pool_t.bufs_busy_bitmap -zb_buf_pool_t.buf_in_use - */ -ZB_CONFIG_PRE zb_buf_ent_t gc_iobuf_pool[ZB_CONFIG_IOBUF_POOL_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint8_t gc_bufs_busy_bitmap[ZB_CONFIG_BUF_POOL_BITMAP_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint8_t gc_buf_pool_bitmap_size ZB_CONFIG_POST = ZB_CONFIG_BUF_POOL_BITMAP_SIZE; -#ifdef ZB_BUF_SHIELD -ZB_CONFIG_PRE zb_uint8_t gc_iobuf_buf_in_use[(ZB_CONFIG_IOBUF_POOL_SIZE + 7)/8] ZB_CONFIG_POST = { 0 }; -#endif - -/** -Input packets queue - -zb_nwk_globals.h - -zb_nwk_handle_t.input_q -*/ -ZB_RING_BUFFER_DECLARE(zb_nwk_in_q_buf, zb_uint8_t, (ZB_CONFIG_IOBUF_POOL_SIZE/2)); -ZB_CONFIG_PRE zb_nwk_in_q_buf_t gc_nwk_in_q ZB_CONFIG_POST = { 0 }; - -/** -TSNs pending for address request complete. - -zb_zdo_globals.h -nwk_addr_req_pending_tsns -nwk_addr_req_pending_mask -*/ -ZB_CONFIG_PRE zb_uint8_t gc_nwk_addr_req_pending_tsns[ZB_CONFIG_N_BUF_IDS] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint8_t gc_nwk_addr_req_pending_mask[(ZB_CONFIG_N_BUF_IDS + 7) / 8] ZB_CONFIG_POST = { 0 }; - -/** -Node Desc feature: mask of pending pkt for every buffer - -zb_zdo_globals.h -node_desc_req_pending_mask -*/ -ZB_CONFIG_PRE zb_uint8_t gc_node_desc_req_pending_mask[(ZB_CONFIG_N_BUF_IDS + 7) / 8] ZB_CONFIG_POST = { 0 }; - -/** -MAC pending TX queue (FFDs). - -zb_mac_globals.h -ZB_MAC_PENDING_QUEUE_SIZE (ZB_IOBUF_POOL_SIZE / 4) - - */ -#ifdef ZB_ROUTER_ROLE -ZB_CONFIG_PRE zb_mac_pending_data_t gc_mac_pending_data_queue[ZB_CONFIG_MAC_PENDING_QUEUE_SIZE] ZB_CONFIG_POST = { 0 }; -#endif - -#ifdef ZB_MAC_SOFTWARE_PB_MATCHING -ZB_CONFIG_PRE zb_uint_t gc_child_hash_table_size ZB_CONFIG_POST = ZB_CONFIG_CHILD_HASH_TABLE_SIZE; - -ZB_CONFIG_PRE zb_uint16_t gc_child_hash_table[ZB_CONFIG_CHILD_HASH_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint32_t gc_pending_bitmap[ZB_CONFIG_PENDING_BITMAP_SIZE] ZB_CONFIG_POST = { 0 }; - -#ifdef ZB_MAC_POLL_INDICATION_CALLS_REDUCED -ZB_CONFIG_PRE zb_time_t gc_poll_timestamp_table[ZB_CONFIG_CHILD_HASH_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint16_t gc_poll_timeout_table[ZB_CONFIG_CHILD_HASH_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; -#endif /* ZB_MAC_POLL_INDICATION_CALLS_REDUCED */ - -#endif /* ZB_MAC_SOFTWARE_PB_MATCHING */ - -/** - APS bound transmission buffers - - zb_aps_globals.h - - zb_aps_bind_dst_table_t.trans_index - */ - -ZB_CONFIG_PRE zb_uint8_t gc_trans_table_size ZB_CONFIG_POST = ZB_CONFIG_APS_BIND_TRANS_TABLE_SIZE; -ZB_CONFIG_PRE zb_uint8_t gc_single_trans_index_size ZB_CONFIG_POST = ZB_CONFIG_SINGLE_TRANS_INDEX_SIZE; -ZB_CONFIG_PRE zb_uint8_t gc_trans_index_buf[ZB_CONFIG_APS_DST_BINDING_TABLE_SIZE][ZB_CONFIG_SINGLE_TRANS_INDEX_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint8_t gc_trans_table[ZB_CONFIG_APS_BIND_TRANS_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; - -/** - APS bind tables - - zb_aps_globals.h - - ZG->aps.binding.zb_aps_bind_src_table_t - ZG->aps.binding.zb_aps_bind_dst_table_t - */ -ZB_CONFIG_PRE zb_uint8_t gc_aps_bind_src_table_size ZB_CONFIG_POST = ZB_CONFIG_APS_SRC_BINDING_TABLE_SIZE; -ZB_CONFIG_PRE zb_uint8_t gc_aps_bind_dst_table_size ZB_CONFIG_POST = ZB_CONFIG_APS_DST_BINDING_TABLE_SIZE; -ZB_CONFIG_PRE zb_aps_bind_src_table_t gc_aps_bind_src_table[ZB_CONFIG_APS_SRC_BINDING_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_aps_bind_dst_table_t gc_aps_bind_dst_table[ZB_CONFIG_APS_DST_BINDING_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; - -/** - APS retransmission buffer - - zb_aps_globals.h - zb_aps_retrans_t.hash - */ - -ZB_CONFIG_PRE zb_aps_retrans_ent_t gc_aps_retrans[ZB_CONFIG_N_APS_RETRANS_ENTRIES] ZB_CONFIG_POST = { 0 }; - -/* - Declarations of variables defining parameters sizes. - */ - -ZB_CONFIG_PRE zb_uint_t gc_pool_size ZB_CONFIG_POST = ZB_CONFIG_IOBUF_POOL_SIZE; -ZB_CONFIG_PRE zb_uint_t gc_mac_pending_queue_size ZB_CONFIG_POST = ZB_CONFIG_MAC_PENDING_QUEUE_SIZE; -ZB_CONFIG_PRE zb_uint_t gc_n_aps_retrans_entries ZB_CONFIG_POST = ZB_CONFIG_N_APS_RETRANS_ENTRIES; - - -/* ZB_CONFIG_SCHEDULER_Q_SIZE */ -ZB_RING_BUFFER_DECLARE(zb_cb_q_buf, zb_cb_q_ent_t, ZB_CONFIG_SCHEDULER_Q_SIZE); -ZB_CONFIG_PRE zb_cb_q_buf_t gc_cb_q ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_tm_q_ent_t gc_tm_buf[ZB_CONFIG_SCHEDULER_Q_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint32_t gc_cb_flag_bm[(ZB_CONFIG_SCHEDULER_Q_SIZE + 31)/32] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint_t gc_sched_q_size ZB_CONFIG_POST = ZB_CONFIG_SCHEDULER_Q_SIZE; -ZB_CONFIG_PRE zb_uint_t gc_sched_stack_unprotected_q_size ZB_CONFIG_POST = ZB_CONFIG_SCHEDULER_Q_SIZE_PROTECTED_STACK_POOL; - - -/* ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE */ -#if defined ZB_COORDINATOR_ROLE && defined ZB_SECURITY_INSTALLCODES -ZB_CONFIG_PRE zb_aps_installcode_storage_t gc_installcodes_table[ZB_CONFIG_N_APS_KEY_PAIR_ARR_MAX_SIZE] ZB_CONFIG_POST = { 0 }; -#endif -ZB_CONFIG_PRE zb_aps_device_key_pair_array_t gc_key_pair_set[ZB_CONFIG_N_APS_KEY_PAIR_ARR_MAX_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint_t gc_n_aps_key_pair ZB_CONFIG_POST = ZB_CONFIG_N_APS_KEY_PAIR_ARR_MAX_SIZE; - - -/* ZB_IEEE_ADDR_TABLE_SIZE */ -ZB_CONFIG_PRE zb_address_map_t gc_addr_map[ZB_CONFIG_IEEE_ADDR_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint8_t gc_short_sorted[ZB_CONFIG_IEEE_ADDR_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint8_t gc_addr_to_neighbor[ZB_CONFIG_IEEE_ADDR_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint_t gc_addr_table_size ZB_CONFIG_POST = ZB_CONFIG_IEEE_ADDR_TABLE_SIZE; - -/* ZB_NEIGHBOR_TABLE_SIZE */ -#ifdef ZB_ROUTER_ROLE -ZB_CONFIG_PRE zb_uint8_t gc_passive_ack[ZB_NWK_BRR_TABLE_SIZE][((ZB_CONFIG_NEIGHBOR_TABLE_SIZE + 7) / 8)] ZB_CONFIG_POST = { 0 }; -#endif - - -ZB_CONFIG_PRE zb_neighbor_tbl_ent_t gc_neighbor[ZB_CONFIG_NEIGHBOR_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint_t gc_neighbor_table_size ZB_CONFIG_POST = ZB_CONFIG_NEIGHBOR_TABLE_SIZE; - -/* ZB_NWK_ROUTING_TABLE_SIZE */ -#ifdef ZB_ROUTER_ROLE -ZB_CONFIG_PRE zb_nwk_routing_t gc_routing_table[ZB_CONFIG_NWK_ROUTING_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint_t gc_routing_table_size ZB_CONFIG_POST = ZB_CONFIG_NWK_ROUTING_TABLE_SIZE; -/* ZB_NWK_SOURCE_ROUTING_TABLE_SIZE */ -#if defined ZB_PRO_STACK && !defined ZB_LITE_NO_SOURCE_ROUTING -/* 10/21/2019 EE CR:MAJOR ZC only! Not ZB_ROUTER_ROLE but ZB_COORDINATOR_ROLE */ -ZB_CONFIG_PRE zb_nwk_rrec_t gc_src_routing_table[ZB_CONFIG_NWK_MAX_SOURCE_ROUTES] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint8_t gc_nwk_max_source_routes ZB_CONFIG_POST = ZB_CONFIG_NWK_MAX_SOURCE_ROUTES; -#endif -#endif - -/* ZB_APS_DUPS_TABLE_SIZE */ -ZB_CONFIG_PRE zb_aps_dup_tbl_ent_t gc_dups_table[ZB_CONFIG_APS_DUPS_TABLE_SIZE] ZB_CONFIG_POST = { 0 }; -ZB_CONFIG_PRE zb_uint_t gc_aps_dups_table_size ZB_CONFIG_POST = ZB_CONFIG_APS_DUPS_TABLE_SIZE; - -#if defined NCP_MODE && !defined NCP_MODE_HOST -ZB_CONFIG_PRE zb_ncp_pending_calls_t gc_ncp_pending_calls[ZB_CONFIG_N_BUF_IDS] ZB_CONFIG_POST = { 0 }; -#endif - -#endif /* ZB_CONFIGURABLE_MEM */ - -/*! @} */ -/*! @} */ - -#endif /* ZB_MEM_CONFIG_CONTEXT_H */ diff --git a/zboss/development/include/zb_mem_config_max.h b/zboss/development/include/zb_mem_config_max.h deleted file mode 100644 index c4f402b358..0000000000 --- a/zboss/development/include/zb_mem_config_max.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: The biggest possible configuration: ZC, big net, high load, high complexity -*/ -#ifndef ZB_MEM_CONFIG_MAXIMUM_H -#define ZB_MEM_CONFIG_MAXIMUM_H 1 - -/** - @addtogroup configurable_mem - @{ -*/ -/** - Configure memory sizes for ZC device role - */ -#define ZB_CONFIG_ROLE_ZC - -#ifdef DOXYGEN -/** - Configure memory sizes for ZED device role - */ -#define ZB_CONFIG_ROLE_ZED -/** - Configure memory sizes for ZR device role - */ -#define ZB_CONFIG_ROLE_ZR -#endif - -/*#define ZB_CONFIG_ROLE_ZR*/ -/*#define ZB_CONFIG_ROLE_ZED*/ -/** - Max total number of devices in Zigbee network. - - From 2 to 200. - */ -#define ZB_CONFIG_OVERALL_NETWORK_SIZE 200U -/*#define ZB_CONFIG_OVERALL_NETWORK_SIZE 16*/ -/*#define ZB_CONFIG_OVERALL_NETWORK_SIZE 32*/ - -/** - High routing and application traffic from/to that device. - */ -#define ZB_CONFIG_HIGH_TRAFFIC -/*#define ZB_CONFIG_MODERATE_TRAFFIC*/ -/*#define ZB_CONFIG_LIGHT_TRAFFIC*/ - -/** - Complex user's application at that device: complex relations to other devices. - */ -#define ZB_CONFIG_APPLICATION_COMPLEX -/*#define ZB_CONFIG_APPLICATION_MODERATE*/ -/*#define ZB_CONFIG_APPLICATION_SIMPLE*/ - -/** - @} -*/ - -/* Now common logic derives numerical parameters from the defined configuration. */ -#include "zb_mem_config_common.h" - -/* Now if you REALLY know what you do, you can study zb_mem_config_common.h and redefine some configuration parameters, like: -#undef ZB_CONFIG_SCHEDULER_Q_SIZE -#define ZB_CONFIG_SCHEDULER_Q_SIZE 56 -*/ - -/* Memory context definitions */ -#include "zb_mem_config_context.h" - -#endif /* ZB_MEM_CONFIG_MAXIMUM_H */ diff --git a/zboss/development/include/zb_mem_config_med.h b/zboss/development/include/zb_mem_config_med.h deleted file mode 100644 index c63d738991..0000000000 --- a/zboss/development/include/zb_mem_config_med.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: The medium configuration: ZC, medium network size, moderate load, medium complexity -*/ -#ifndef ZB_MEM_CONFIG_MAXIMUM_H -#define ZB_MEM_CONFIG_MAXIMUM_H 1 - -/** - @addtogroup configurable_mem - @{ - @cond skip_this - @{ -*/ -#define ZB_CONFIG_ROLE_ZC -/*#define ZB_CONFIG_ROLE_ZR*/ -/*#define ZB_CONFIG_ROLE_ZED*/ - -/*#define ZB_CONFIG_OVERALL_NETWORK_SIZE 128*/ -#define ZB_CONFIG_OVERALL_NETWORK_SIZE 32U -/*#define ZB_CONFIG_OVERALL_NETWORK_SIZE 16*/ - -/** - @} - @endcond -*/ - -/*#define ZB_CONFIG_HIGH_TRAFFIC*/ -/** - Medium routing and application traffic from/to that device. - */ -#define ZB_CONFIG_MODERATE_TRAFFIC -/*#define ZB_CONFIG_LIGHT_TRAFFIC*/ - -/*#define ZB_CONFIG_APPLICATION_COMPLEX*/ -/** - Medium user's application complexity at that device: medium relations to other devices. - */ -#define ZB_CONFIG_APPLICATION_MODERATE -/*#define ZB_CONFIG_APPLICATION_SIMPLE*/ - -/** - @} -*/ - -/* Now common logic derives numerical parameters from the defined configuration. */ -#include "zb_mem_config_common.h" - -/* Now if you REALLY know what you do, you can study zb_mem_config_common.h and redefine some configuration parameters, like: -#undef ZB_CONFIG_SCHEDULER_Q_SIZE -#define ZB_CONFIG_SCHEDULER_Q_SIZE 56 -*/ - -/* Memory context definitions */ -#include "zb_mem_config_context.h" - -#endif /* ZB_MEM_CONFIG_MAXIMUM_H */ diff --git a/zboss/development/include/zb_mem_config_min.h b/zboss/development/include/zb_mem_config_min.h deleted file mode 100644 index 55d44c885c..0000000000 --- a/zboss/development/include/zb_mem_config_min.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: The smallest possible configuration: ZC, small net, small load, low complexity -*/ -#ifndef ZB_MEM_CONFIG_MAXIMUM_H -#define ZB_MEM_CONFIG_MAXIMUM_H 1 - -/** - @addtogroup configurable_mem - @{ - @cond skip_this - @{ -*/ - - -#define ZB_CONFIG_ROLE_ZC -/*#define ZB_CONFIG_ROLE_ZR*/ -/*#define ZB_CONFIG_ROLE_ZED*/ - -/*#define ZB_CONFIG_OVERALL_NETWORK_SIZE 128*/ -/*#define ZB_CONFIG_OVERALL_NETWORK_SIZE 32*/ -#define ZB_CONFIG_OVERALL_NETWORK_SIZE 16U - - -/** - @} - @endcond -*/ - -/*#define ZB_CONFIG_HIGH_TRAFFIC*/ -/*#define ZB_CONFIG_MODERATE_TRAFFIC*/ -/** - Light routing and application traffic from/to that device. - */ -#define ZB_CONFIG_LIGHT_TRAFFIC - -/*#define ZB_CONFIG_APPLICATION_COMPLEX*/ -/*#define ZB_CONFIG_APPLICATION_MODERATE*/ -/** - Simple user's application at that device: not too many relations to other devices. - */ -#define ZB_CONFIG_APPLICATION_SIMPLE - -/** - @} -*/ - - -/* Now common logic derives numerical parameters from the defined configuration. */ -#include "zb_mem_config_common.h" - -/* Now if you REALLY know what you do, you can study zb_mem_config_common.h and redefine some configuration parameters, like: -#undef ZB_CONFIG_SCHEDULER_Q_SIZE -#define ZB_CONFIG_SCHEDULER_Q_SIZE 56 -*/ - -/* Memory context definitions */ -#include "zb_mem_config_context.h" - -#endif /* ZB_MEM_CONFIG_MAXIMUM_H */ diff --git a/zboss/development/include/zb_ncp.h b/zboss/development/include/zb_ncp.h deleted file mode 100644 index 59e60565cb..0000000000 --- a/zboss/development/include/zb_ncp.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Internal header for stack - NCP protocol interaction -*/ -#ifndef ZB_NCP_INTERNAL_H -#define ZB_NCP_INTERNAL_H 1 - -/** - * @name NCP Signals - * @anchor ncp_signal - * - * Note: These values were members of `enum ncp_signal_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define NCP_SIGNAL_NWK_FORMATION_OK 0U -#define NCP_SIGNAL_NWK_FORMATION_FAILED 1U -#define NCP_SIGNAL_NWK_PERMIT_JOINING_COMPLETED 2U -#define NCP_SIGNAL_NWK_JOIN_FAILED 3U -#define NCP_SIGNAL_NWK_JOIN_AUTH_FAILED 4U -#define NCP_SIGNAL_NWK_JOIN_DONE 5U -#define NCP_SIGNAL_NWK_REJOIN_FAILED 6U -#define NCP_SIGNAL_NWK_REJOIN_DONE 7U -#define NCP_SIGNAL_SECUR_TCLK_EXCHANGE_COMPLETED 8U -#define NCP_SIGNAL_SECUR_TCLK_EXCHANGE_FAILED 9U -#define NCP_SIGNAL_NLME_PARENT_LOST 10U -/** @} */ - -/** - * @brief Type for NCP signals. - * - * Holds one of @ref ncp_signal. Kept only for backward compatibility as - * @ref ncp_signal were declared previously as enum. Can be removed in future - * releases. - */ -typedef zb_uint8_t ncp_signal_t; - -#if defined NCP_MODE && !defined NCP_MODE_HOST -void ncp_signal(ncp_signal_t signal, zb_uint8_t param); -void ncp_signal_exec(ncp_signal_t signal, zb_uint8_t param); -#define NCP_CALL_COMPLETED(sig, param) ncp_signal(sig, param) - -zb_bool_t ncp_catch_zcl_packet(zb_uint8_t param, zb_zcl_parsed_hdr_t *cmd_info, zb_uint8_t zcl_parse_status); -#define NCP_CATCH_ZCL_PACKET(param, cmd_info, status) ncp_catch_zcl_packet(param, cmd_info, status) - -zb_bool_t ncp_catch_aps_data_conf(zb_uint8_t param); -#define NCP_CATCH_APS_DATA_CONF(param) ncp_catch_aps_data_conf(param) - -zb_bool_t ncp_catch_nwk_disc_conf(zb_uint8_t param); -#define NCP_CATCH_NWK_DISC_CFM(param) ncp_catch_nwk_disc_conf(param) - -#ifdef ZB_ENABLE_SE_MIN_CONFIG -void ncp_se_signal(zse_commissioning_signal_t signal, zb_uint8_t param); -void ncp_se_signal_exec(zse_commissioning_signal_t signal, zb_uint8_t param); - -zb_bool_t ncp_partner_lk_failed(zb_uint8_t param); -#define NCP_CATCH_PARTNER_LK_FAILED(param) ncp_partner_lk_failed(param) - -#endif /* ZB_ENABLE_SE_MIN_CONFIG */ - -void ncp_address_update_ind(zb_uint16_t short_address); -void ncp_apsme_remote_bind_unbind_ind(zb_uint8_t param, zb_bool_t bind); - -#ifdef ZB_APSDE_REQ_ROUTING_FEATURES -void ncp_nwk_route_req_send_ind(zb_nwk_cmd_rreq_t *rreq); -void ncp_nwk_route_send_rrec_ind(zb_nwk_cmd_rrec_t *rrec); -void ncp_route_reply_ind(zb_nwk_cmd_rrep_t *rrep); -#endif /* ZB_APSDE_REQ_ROUTING_FEATURES*/ - -#else - -#define NCP_CALL_COMPLETED(sig, param) if (param) { zb_buf_free(param); } -#define NCP_CATCH_ZCL_PACKET(param, cmd_info, status) ZB_FALSE -#define NCP_CATCH_APS_DATA_CONF(param) ZB_FALSE -#define NCP_CATCH_NWK_DISC_CFM(param) ZB_FALSE -#define NCP_CATCH_PARTNER_LK_FAILED(param) ZB_FALSE - -#endif - -#ifdef SNCP_MODE -void sncp_auto_turbo_poll_ed_timeout(zb_bool_t is_on); -void sncp_auto_turbo_poll_aps_rx(zb_bool_t is_on); -void sncp_auto_turbo_poll_aps_tx(zb_bool_t is_on); -void sncp_auto_turbo_poll_stop(void); -#endif - -#endif /* ZB_NCP_INTERNAL_H */ diff --git a/zboss/development/include/zb_osif.h b/zboss/development/include/zb_osif.h deleted file mode 100644 index c3817f0823..0000000000 --- a/zboss/development/include/zb_osif.h +++ /dev/null @@ -1,922 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Main header for OS and platform dependent stuff -*/ - -#ifndef ZB_OSIF_H -#define ZB_OSIF_H 1 - - -/** - @internal - - \addtogroup ZB_OSIF */ -/*! @{ */ - -/** -@par OS/HW abstraction -OS/HW platform abstraction is necessary to achieve high portability. -C language tool to separate abstraction layer is C preprocessor. - -Main idea is to avoid number of ifdefs related to portability in the code, and -decrease number of ifdefs in the header files not related to the OS abstraction -layer. - -Platform abstraction is implemented as C functions placed into OS abstraction -layers and platform-dependent global typedefs and definitions placed into header -files. All platform-related stuff is in osif/ directory. Global definitions -and typedefs can be used anywhere - that is why on the architecture picture OS -abstraction layer depicted as global. - -Following things are platform-dependent: -* typedefs for base types (8-bit controller vs 32-bit Linux device) -* definitions for different 8051 compilers (SDCC and Keil) -* transceiver i/o (interrupts handling for 8051 vs file i/o in Linux); -* wait for i/o (device sleep for 8051, wait in select() in Linux) -* trace i/o (UART for 8051, file in Linux); -* MAC traffic dump (UART for 8051, file in Linux); -* Timer (8051 timer at device, select() timeout in Linux) - - */ - - - -#include "zb_config.h" - - /** -OSIF platform selection. One of pre-defined platform should be selected in -zb_config.h configurations. -zb_osif_platform.h is different in different platforms repo. -*/ -/** - * OSIF timer expiration callback type - * @param user_data - any user specified data which will be sent to this callback - * Might be used to determine particular timer which cause callback - * -*/ -typedef void (*zb_osif_timer_exp_cb_t)(void *user_data); - -#include "zb_osif_platform.h" - -#include "zb_ringbuffer.h" - -#ifndef ZB_PLATFORM_INIT -#error Define ZB_PLATFORM_INIT in you platform file -//#define ZB_PLATFORM_INIT() -#endif - -#ifndef ZB_OSIF_IS_EXIT -#define ZB_OSIF_IS_EXIT() ZB_FALSE -#endif - -/* Default (C standard) definition of MAIN() if not redefined in zb_osif_platform.h */ -#ifndef MAIN -#define MAIN() int main(int argc, char *argv[]) -#define FAKE_ARGV -#define ARGV_UNUSED ZVUNUSED(argc) ; ZVUNUSED(argv) -#define MAIN_RETURN(v) return (v) -#endif - -#ifndef ZB_SET_TRACE_TRANSPORT -/* - * If platform supports choosing transport at runtime - * (i.e. Telink can choose between UART and USB debug interface) - * define this macro. - * Note that this is intended to be called before ZB_TRACE_INIT is called as - * only one interface will be configured and the rest of them will be left as is - * so that it would be usable from non-Zigbee purposes (application) if needed. - */ -#define ZB_SET_TRACE_TRANSPORT(transport) -#endif - -/* - * If platform supports NCP architecture and the ability to put the SoC to - * sleep state, this function should be implemented. - * - * This function is meant to be called from zboss_signal_handler(), after - * receiving ZB_COMMON_SIGNAL_CAN_SLEEP signal. - * It should configure the NCP transport in a way that is can wake up the MCU - * through external interrupt and call the zb_sleep_now(). - * Afterwards, it should recover the NCP transport, so it is able to continue - * its normal operation. - */ -#ifndef ZB_OSIF_NCP_TRANSPORT_PREPARE_TO_SLEEP -#define ZB_OSIF_NCP_TRANSPORT_PREPARE_TO_SLEEP() -#endif - -#if !defined ZB_KICK_HW_WATCHDOG -#define ZB_KICK_HW_WATCHDOG() -#endif - -/*! @} */ - - -/* common osif API */ -zb_uint32_t zb_random_seed(void); -zb_uint32_t zb_get_utc_time(void); - -zb_uint32_t osif_get_time_ms(void); - -/* note: that api is only for some platforms */ -zb_ret_t osif_set_transmit_power(zb_uint8_t channel, zb_int8_t power); -void osif_set_default_trasnmit_powers(zb_int8_t *tx_powers); - -#if defined ZB_MACSPLIT_TRANSPORT_SERIAL || defined ZB_NCP_TRANSPORT_TYPE_SERIAL -void zb_osif_serial_transport_init(); -void zb_osif_serial_transport_put_bytes(zb_uint8_t *buf, zb_short_t len); -#endif - -#ifndef ZB_SERIAL_INT_DISABLE -#define ZB_SERIAL_INT_DISABLE() ZB_OSIF_GLOBAL_LOCK() -#endif /* ZB_SERIAL_INT_DISABLE */ - -#ifndef ZB_SERIAL_INT_ENABLE -#define ZB_SERIAL_INT_ENABLE() ZB_OSIF_GLOBAL_UNLOCK() -#endif /* ZB_SERIAL_INT_ENABLE */ - -#if defined ZB_HAVE_SERIAL || defined DOXYGEN - -/* Serial interface (trace, traffic dump, serial transport) */ - -/** @cond DOXYGEN_UART_SECTION */ -/*! \addtogroup uart */ -/*! @{ */ - -/** - Initialize UART low level. - - If ZBOSS uses UART for trace or traffic dump, it calls zb_osif_serial_init() - itself. - If UART is used by application, application must call zb_osif_serial_init(). - */ -void zb_osif_serial_init(void); - -/** - Deinitialize UART low level. - */ -void zb_osif_serial_deinit(void); - -/** - Setup callback to be called when single byte received over UART - - @param hnd user's rx callback - */ -void zb_osif_set_uart_byte_received_cb(zb_callback_t hnd); - - -/* errors generated by serial transport */ - -#define ZB_ERROR_SERIAL_INIT_FAILED 1U -#define ZB_ERROR_SERIAL_READ_FAILED 2U - -/** - Set user's buffer to be used by UART TX logic. - - ZBOSS normally uses its internal UART buffer. The buffer is not too big - - about 200 bytes which is enough for its usage by ZBOSS (trace). - Some applications needs large io buffers. So declare there type placeholder for use ringbuffer zb_byte_array_t; - by default application will set user tx buffer to stack tx buffer and access it through pointer; - User can override this pointer to use it's own serial buffer. - - @param buf_ptr user's buffer - @param capacity buffer capacity - */ -void zb_osif_set_user_io_buffer(zb_byte_array_t *buf_ptr, zb_ushort_t capacity); - -/** - Set user callback that will be called from uart IRQ handler. - Replaces zboss uart irq handler. - - Note: that call is to be used when application initializes and uses UART - itself. - Do not use this call if use ZBOSS serial port API. - Call to that functions disables ZBOSS debug trace and traffic dump. -*/ -void zb_osif_set_uart_user_irq_handler(void (*irq_hnd)()); - -/** - Prepare UART to a sleep. Shall be invoked before putting ZBOSS to a sleep. - Perform OS-dependent actions. -*/ -void zb_osif_uart_sleep(void); - -/** - Restore UART from a sleep. Shall be invoked after wake up. - Perform OS-dependent actions. -*/ -void zb_osif_uart_wake_up(void); - -#if defined(ZB_HAVE_ASYNC_SERIAL) || defined(DOXYGEN) -/* Asynchronous API extension for serial interface. */ - -#define SERIAL_SEND_SUCCESS 0U /**< Serial interface has sent the data. */ -#define SERIAL_SEND_BUSY 1U /**< Serial interface is busy. */ -#define SERIAL_SEND_TIMEOUT_EXPIRED 2U /**< Transmission operation timed out. */ -#define SERIAL_SEND_ERROR 255U /**< Serial interface internal error. */ - - -/** - Type of callback called by serial interface when it received requested buffer. - - @param buf - pointer to data received - @param len - length of received data - */ -typedef void (*serial_recv_data_cb_t)(zb_uint8_t *buf, zb_ushort_t len); - -/** - Type of callback called by serial interface when it completed transmission of data. - - @param status - status of the transmission - */ -typedef void (*serial_send_data_cb_t)(zb_uint8_t status); - - -/** - Receive data from serial interface. - - @param buf - pointer to the buffer for received data - @param len - length of the buffer - */ -void zb_osif_serial_recv_data(zb_uint8_t *buf, zb_ushort_t len); - -/** - Set serial interface callback for receiving completion. - - @param cb - receiving completion callback - */ -void zb_osif_serial_set_cb_recv_data(serial_recv_data_cb_t cb); - -/** - Send data over serial interface. - - @param buf - pointer to the buffer with data to send - @param len - length of the buffer - */ -void zb_osif_serial_send_data(zb_uint8_t *buf, zb_ushort_t len); - -/** - Set serial interface callback for transmission completion. - - @param cb - transmission completion callback - */ -void zb_osif_serial_set_cb_send_data(serial_send_data_cb_t cb); - -#endif /* ZB_HAVE_ASYNC_SERIAL */ -#endif /* ZB_HAVE_SERIAL || DOXYGEN */ - -#if defined ZB_BINARY_TRACE || defined ZB_HAVE_SERIAL || defined ZB_TRACE_OVER_USART || defined DOXYGEN || defined ZB_NSNG - -/** - TX data over UART - - Put data to internal buffer to be transmitted over UART. - It is guaranteed that all data will be sent. - Block is no space in the buffer waiting for previous TX complete. - - Note: this is low level routine. Its direct usage may conflict with ZBOSS - debug trace and traffic dump (if enabled). - - @param buf data buffer - @param len data length. - */ -void zb_osif_serial_put_bytes(const zb_uint8_t *buf, zb_short_t len); -#endif - -#ifdef ZB_OSIF_SERIAL_GET_FD -/** - * @brief Get the file descriptor used for the serial port. - * - * @return file descriptor used for the serial port, or -1 if the serial port is not in use now. - */ -zb_int_t zb_osif_serial_get_fd(void); -#endif - -#if defined ZB_SERIAL_FOR_TRACE && !defined ZB_OSIF_SERIAL_FLUSH -#define ZB_OSIF_SERIAL_FLUSH() -#endif /* ZB_SERIAL_FOR_TRACE && !ZB_OSIF_SERIAL_FLUSH */ - -#ifdef ZB_TRACE_OVER_JTAG -void zb_osif_jtag_put_bytes(const zb_uint8_t *buf, zb_short_t len); -void zb_osif_jtag_flush(void); -#endif - -/*! @} */ -/** @endcond */ /* DOXYGEN_UART_SECTION */ - - - -#ifdef ZB_TRACE_OVER_SIF -void zb_osif_sif_put_bytes(const zb_uint8_t *buf, zb_short_t len); -void zb_osif_sif_init(void); -void zb_osif_sif_debug_trace(zb_uint8_t param); -#endif - -#ifdef ZB_HAVE_FILE -/* File */ -zb_uint32_t zb_osif_get_file_size(zb_char_t *name); -zb_bool_t zb_osif_check_dir_exist(const zb_char_t *name); -int zb_osif_create_dir(const zb_char_t *name); -zb_bool_t zb_osif_check_file_exist(const zb_char_t *name, const zb_uint8_t mode); -void zb_osif_file_copy(const zb_char_t *name_src, const zb_char_t *name_dst); -zb_osif_file_t *zb_osif_file_open(const zb_char_t *name, const zb_char_t *mode); -zb_osif_file_t *zb_osif_init_trace(zb_char_t *name); -zb_osif_file_t *zb_osif_file_stdout(void); -zb_osif_file_t *zb_osif_file_stdin(void); -void zb_osif_file_close(zb_osif_file_t *f); -int zb_osif_file_remove(const zb_char_t *name); -void zb_osif_trace_printf(zb_osif_file_t *f, const zb_char_t *format, ...); -void zb_osif_trace_vprintf(zb_osif_file_t *f, const zb_char_t *format, va_list arglist); -void zb_osif_trace_lock(void); -void zb_osif_trace_unlock(void); -zb_osif_file_t *zb_osif_init_dump(zb_char_t *name); -int zb_osif_file_read(zb_osif_file_t *f, zb_uint8_t *buf, zb_uint_t len); -int zb_osif_file_write(zb_osif_file_t *f, const zb_uint8_t *buf, zb_uint_t len); -int zb_osif_file_is_eof(zb_osif_file_t *f); -int zb_osif_file_is_err(zb_osif_file_t *f); -int zb_osif_file_flush(zb_osif_file_t *f); -int zb_osif_file_seek(zb_osif_file_t *f, zb_uint32_t off, zb_uint8_t mode); -int zb_osif_file_get_size(zb_osif_file_t *f); -int zb_osif_file_truncate(zb_osif_file_t *f, zb_uint32_t off); -int zb_osif_file_sync(zb_osif_file_t *f); -void zb_osif_trace_get_time(zb_uint_t *sec, zb_uint_t *msec); -zb_osif_file_t *zb_osif_popen(zb_char_t *arg); - -int zb_osif_stream_read(zb_osif_file_t *stream, zb_uint8_t *buf, zb_uint_t len); -int zb_osif_stream_write(zb_osif_file_t *stream, zb_uint8_t *buf, zb_uint_t len); - -enum zb_file_path_base_type_e -{ - ZB_FILE_PATH_BASE_NOT_SPECIFIED, /* not specified base type - allows to use default base path */ - ZB_FILE_PATH_BASE_ROMFS_BINARIES, /* ROM FS */ /* elf binaries, etc */ - ZB_FILE_PATH_BASE_MNTFS_BINARIES, /* RW FS */ /* prod config, etc */ - ZB_FILE_PATH_BASE_MNTFS_USER_DATA, /* RW FS */ /* nvram. etc */ - ZB_FILE_PATH_BASE_MNTFS_TRACE_LOGS, /* RW FS */ - ZB_FILE_PATH_BASE_RAMFS_UNIX_SOCKET, /* RAM FS */ - ZB_FILE_PATH_BASE_RAMFS_TRACE_LOGS, /* RAM FS */ - ZB_FILE_PATH_BASE_RAMFS_TMP_DATA, /* RAM FS */ - - ZB_FILE_PATH_BASE_MAX_TYPE -}; - -#ifndef ZB_TRACE_LOG_FILE_EXTENSION -#define ZB_TRACE_LOG_FILE_EXTENSION "" -#endif /* ZB_TRACE_LOG_FILE_EXTENSION */ - -#define ZB_MAX_FILE_PATH_SIZE 256 - -#ifdef ZB_FILE_PATH_MGMNT -#ifndef ZB_FILE_PATH_MAX_TYPES -#define ZB_FILE_PATH_MAX_TYPES ZB_FILE_PATH_BASE_MAX_TYPE -#endif - -typedef struct zb_file_path_base_type_s -{ - zb_bool_t declared; - char base[ZB_MAX_FILE_PATH_SIZE]; -} zb_file_path_base_type_t; - -void zb_file_path_init(void); -zb_ret_t zb_file_path_declare(zb_uint8_t base_type, const char *base); -const char* zb_file_path_get(zb_uint8_t base_type, const char *default_base); -void zb_file_path_get_with_postfix(zb_uint8_t base_type, const char *default_base, const char *postfix, char *file_path); -#define ZB_FILE_PATH_GET(base_type, default_base) \ - zb_file_path_get(base_type, default_base) -#define ZB_FILE_PATH_GET_WITH_POSTFIX(base_type, default_base, postfix, file_path) \ - zb_file_path_get_with_postfix(base_type, default_base, postfix, file_path) -#else -#define ZB_FILE_PATH_GET(base_type, default_base) default_base -#define ZB_FILE_PATH_GET_WITH_POSTFIX(base_type, default_base, postfix, file_path) \ - { \ - zb_uint_t sn_ret; \ - sn_ret = snprintf(file_path, ZB_MAX_FILE_PATH_SIZE, "%s", (default_base postfix)); \ - ZB_ASSERT(sn_ret > 0); \ - ZB_ASSERT(sn_ret < ZB_MAX_FILE_PATH_SIZE); \ - } -#endif /* ZB_FILE_PATH_MGMNT */ - -#ifdef ZB_USE_LOGFILE_ROTATE -zb_uint32_t zb_osif_get_max_logfile_size(void); -zb_ret_t zb_osif_set_max_logfile_size(zb_uint32_t val); - -zb_uint32_t zb_osif_get_max_logfiles_count(void); -zb_ret_t zb_osif_set_max_logfiles_count(zb_uint32_t val); - -zb_ret_t zb_osif_file_rotate(const zb_char_t *file_path, const zb_char_t *file_name); -#endif /* ZB_USE_LOGFILE_ROTATE */ -#endif /* ZB_HAVE_FILE */ - -/*! \addtogroup zb_platform */ -/*! @{ */ - -/** - Platform dependent soft reset -*/ -void zb_reset(zb_uint8_t param); - -/** - * @name Possible reset sources - * @anchor reset_source - * - * Note: These values were members of `enum zb_reset_source_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_RESET_SRC_POWER_ON 0U -#define ZB_RESET_SRC_SW_RESET 1U -#define ZB_RESET_SRC_RESET_PIN 2U -#define ZB_RESET_SRC_BROWN_OUT 3U -#define ZB_RESET_SRC_CLOCK_LOSS 4U -#define ZB_RESET_SRC_OTHER 5U -/** @} */ - -/** - * @brief Get the reason that triggered the last reset - * - * @return @ref reset_source - * */ -zb_uint8_t zb_get_reset_source(void); - -/*! @} */ - -#if defined ZB_USE_NVRAM || defined DOXYGEN -/** - * @brief osif NVRAM initializer - */ -void zb_osif_nvram_init(const zb_char_t *name); - - -/** - * @brief Deinitialize osif-layer NVRAM support - */ -void zb_osif_nvram_deinit(void); - -/** - * @brief Get NVRAM page length - * - * @return NVRAM page length - */ -zb_uint32_t zb_get_nvram_page_length(void); - -/** - * @brief Get NVRAM page count - * - * @return NVRAM page count - */ -zb_uint8_t zb_get_nvram_page_count(void); - -/** - * @brief Read from NVRAM directly, by address - * Read some bytes from NVRAM use address - * - * @param address - NVRAM address - * @param len - count bytes from read data - * @param buf - (in) buffer for contains read data - * - * @return RET_OK if success or code error - */ -zb_ret_t zb_osif_nvram_read_memory(zb_uint32_t address, zb_uint32_t len, zb_uint8_t *buf); - -/** - * @brief Read from NVRAM page - * Read some bytes from NVRAM - * - * @param page - NVRAM page - * @param pos - Start position - * @param buf - (in) buffer for contains read data - * @param len - count bytes from read data - * - * @return RET_OK if success or code error - */ -zb_ret_t zb_osif_nvram_read(zb_uint8_t page, zb_uint32_t pos, zb_uint8_t *buf, zb_uint16_t len ); - -/** - * @brief Read from NVRAM page with test - * Read some bytes from NVRAM with test contents. - * If all byte equal 0xFF then return RET_ERROR - * Exists not for all platforms. - * - * @param page - NVRAM page - * @param pos - Start position - * @param buf - (in) buffer for contains read data - * @param len - count bytes from read data - * - * @return RET_OK if success or code error - */ -zb_ret_t zb_osif_nvram_read_test(zb_uint8_t page, zb_uint32_t pos, zb_uint8_t *buf, zb_uint16_t len ); - -/** - * @brief Write from NVRAM page - * Write some bytes to NVRAM - * - * @param page - NVRAM page - * @param pos - Start position - * @param buf - buffer contains data for write - * @param len - count bytes for write data - * - * @return RET_OK if success or code error - */ -zb_ret_t zb_osif_nvram_write(zb_uint8_t page, zb_uint32_t pos, void *buf, zb_uint16_t len ); - -/** - * @brief Write to NVRAM directly, by address - * Write bytes into NVRAM use address - * - * @param address - NVRAM address - * @param len - count bytes for write data - * @param buf - (in) buffer contains data to write - * - * @return RET_OK if success or code error - */ -zb_ret_t zb_osif_nvram_write_memory(zb_uint32_t address, zb_uint32_t len, zb_uint8_t *buf); - -/** - * @brief Erase NVRAM directly, by address - * - * @param address - NVRAM address - * @param len - count bytes for erase, aligned - * - * @return RET_OK if success or code error - */ -zb_ret_t zb_osif_nvram_erase_memory(zb_uint32_t address, zb_uint32_t len); - - -/** - * @brief Erase NVRAM page - * Fill NVRAM page by 0xFF. - * - * @param page - page index - * - * @return RET_OK if success or code error - */ -zb_ret_t zb_osif_nvram_erase_async(zb_uint8_t page); - -void zb_osif_nvram_wait_for_last_op(void); - -/** - * @brief Flush NVRAM page - * Flash NVRAM page to file or NVRAM. - * Different to hardware device - * - */ -void zb_osif_nvram_flush(void); - -#endif - -#ifdef ZB_USE_OSIF_OTA_ROUTINES -/** - * @addtogroup ll - * @{ - */ - -/** - * @defgroup ota Low level API for OTA - */ -/*! @{ */ - -/** - * Size of sub-element includes OTA header. - * - * @see Zigbee Cluster Library specification revision 7 subsection 11.4.3 Sub-element Format - */ -#define OTA_UPGRADE_HEADING_DATA \ - (sizeof(zb_zcl_ota_upgrade_file_header_t) + 2 /* fw tag Id */ + 4 /* fw length */) - -/** - * Size of the OTA image hash. - * - * @see Zigbee Cluster Library specification revision 7 subsection 11.7.2.1 Hash Value Calculation - */ -#define OTA_UPGRADE_HASH_SIZE 16 - -/** - * Size of sub-element includes a hash value. - * - * @see Zigbee Cluster Library specification revision 7 subsection 11.4.8 Image Integrity Code Sub-element - */ -#define OTA_UPGRADE_TRAILING_DATA \ - (2 /* hash tag Id */ + 4 /* hash length */ + OTA_UPGRADE_HASH_SIZE /* Hash */) - - -/** - Open device to be used for OTA image write or read. - - Take into account which flash (A or B) current FW is running at. - @see zb_osif_ota_close_storage - - @return handle - */ -void *zb_osif_ota_open_storage(void); - -/** - Close device used for OTA image write - - @param dev flash device handle used to write OTA image @see zb_osif_ota_open_storage -*/ -void zb_osif_ota_close_storage(void *dev); - -/** - Erase flash to be used for OTA image store. - - @note: offset and size must be aligned to minimal eraseable page boundary - - see zb_osif_ota_get_erase_portion(). - - @param dev flash device handle @see zb_osif_ota_open_storage - @param offset file offset in flash memory - @param size OTA file image size - */ -void zb_osif_ota_erase_fw(void *dev, zb_uint_t offset, zb_uint_t size); - -/** - Get portion of OTA storage which can be erased at once. - - @return erase block size in bytes - */ -zb_uint32_t zb_osif_ota_get_erase_portion(void); - -/** - Write OTA image data to flash. - - Deal with alignment. - - @param dev flash device handle @see zb_osif_ota_open_storage - @param data pointer to the data to write - @param off offset in OTA file - @param block_size amount of data to write - @param image_size total image size - */ -void zb_osif_ota_write(void *dev, zb_uint8_t *data, zb_uint32_t off, zb_uint32_t block_size, zb_uint32_t image_size); - -/** - Mark FW as downloaded and ready to use by bootloader. - - To be called when finishing OTA, after FW loaded and verified. - - @param ota_dev flash device handle used to write OTA image @see zb_osif_ota_open_storage - @param size OTA image size, without CRC - @param revision OTA image revision - */ -void zb_osif_ota_mark_fw_ready(void *ota_dev, zb_uint32_t size, zb_uint32_t revision); - - -/** - Mark new FW as absent so bootloader does not attempt to re-flash it. - - To be called when starting OTA. - */ -void zb_osif_ota_mark_fw_absent(void); - - -/** - Mark FW upgrade finished, so bootloader just loads current FW. - - To be called from newly started application FW. - Usually not need to be called by the application. ZBOSS kernel cares about it. - */ -void zb_osif_ota_mark_fw_updated(void); - -/** - Verify OTA file image written to device @p dev. - - @param dev flash device handle used to write OTA image @see zb_osif_ota_open_storage - @param raw_len - OTA image file length - @return ZB_TRUE if ok, ZB_FALSE if error - */ -zb_bool_t zb_osif_ota_verify_integrity(void *dev, zb_uint32_t raw_len); - -/** - Verify OTA file image written to device @p dev asynchronously. - - @param dev flash device handle used to write OTA image @see zb_osif_ota_open_storage - @param raw_len - OTA image file length - @return ZB_TRUE if ok, ZB_FALSE if error - */ -zb_bool_t zb_osif_ota_verify_integrity_async(void *dev, zb_uint32_t raw_len); - -/** - * Check whether OTA image recording was successful and finalize OTA. - * - * @param integrity_is_ok - is verification of OTA image recording successful - */ -void zb_osif_ota_verify_integrity_done(zb_uint8_t integrity_is_ok); - -/** - * Read OTA image data from flash. - * - * @param dev flash device handle @see zb_osif_ota_open_storage - * @param data pointer to the read data - * @param addr - * @param size amount of data to read - */ -void zb_osif_ota_read(void *dev, zb_uint8_t *data, zb_uint32_t addr, zb_uint32_t size); - -/** - Check whether the current device flash memory has enough space for the OTA file image. - - @param image_size OTA file image size - @return ZB_TRUE if ok, ZB_FALSE if error - */ -zb_bool_t zb_osif_ota_fw_size_ok(zb_uint32_t image_size); - -/** - Get OTA image data at OTA server - - @param dev flash device handle used to write OTA image @see zb_osif_ota_open_storage - @param offset offset in the OTA image - @param len - length of image block to get - @return pointer to image block - */ -zb_uint8_t *zb_osif_ota_srv_get_image(void *dev, zb_uint32_t offset, zb_uint32_t len); - -/** - Get OTA header at OTA server - - @param dev flash device handle used to write OTA image @see zb_osif_ota_open_storage - @return pointer to header block - */ -zb_uint8_t *zb_osif_ota_srv_get_image_header(void *dev); - -/** @} */ /* ota */ -/** @} */ /* ll */ - -#endif /* ZB_USE_OSIF_OTA_ROUTINES */ - -/** - * Run the bootloader after next reset - * - * @return RET_OK is success, RET_ERROR otherwise - */ -zb_ret_t zb_osif_bootloader_run_after_reboot(void); - -/** - * Inform that image was successfully loaded - */ -void zb_osif_bootloader_report_successful_loading(void); - - -#if defined ZB_PROFILE_STACK_USAGE -/* Both functions are platform-specific */ - -/** - * @brief Prepare stack profiler. - * Fill stack area with a predefined pattern. - * - */ -void zb_stack_profiler_pre(void); - -/** - * @brief Get stack usage by previously called function. - * - * @return Count of bytes in stack area used - */ -zb_uint16_t zb_stack_profiler_usage(void); - -#endif /* ZB_PROFILE_STACK_USAGE */ - - -#ifdef ZB_USE_SLEEP -zb_uint32_t zb_osif_sleep(zb_uint32_t sleep_tmo); -void zb_osif_wake_up(void); -#endif - -#ifdef ZB_PRODUCTION_CONFIG - -/* Check whether production configuration block is present in memory */ -zb_bool_t zb_osif_prod_cfg_check_presence(void); - -/* Read data from production configuration header - * - * @param prod_cfg_hdr - pointer to production configuration header - * @param hdr_len - size of production configuration header - * - * @return RET_OK is success, RET_ERROR otherwise - */ -zb_ret_t zb_osif_prod_cfg_read_header(zb_uint8_t *prod_cfg_hdr, zb_uint16_t hdr_len); - -/* Read data from production configuration block - * - * @param buffer - buffer to read into - * @param len - length of block to read - * @param offset - offset to read from - * - * @return - */ -zb_ret_t zb_osif_prod_cfg_read(zb_uint8_t *buffer, zb_uint16_t len, zb_uint16_t offset); - -#ifdef ZB_OSIF_CONFIGURABLE_TX_POWER -/* Set transmit power of radio on selected channel - * - * @param channel - channel on which radio applies new transmit power - * @param power - transmit power in dBm - * - * return RET_OK if power was set successfully, RET_ERROR otherwise - */ -zb_ret_t zb_osif_set_transmit_power(zb_uint8_t channel, zb_int8_t power); -#endif /* ZB_OSIF_CONFIGURABLE_TX_POWER */ - -#endif - -/* Wait for a given number of empty cycle iterations. Timeout of 1 iteration is platform-specific - * - * @param count - number of empty wait cycles - */ -void zb_osif_busy_loop_delay(zb_uint32_t count); - - -/* Get OSIF timer counter value in microseconds - * - * @return Timer counter value in microseconds - */ -zb_uint32_t zb_osif_get_timer_reminder(void); - -#ifndef ZB_USE_INTERNAL_HEADERS -/* Init leds and buttons - * - */ -void zb_osif_led_button_init(void); - -/* Set a LED on - * It must be initialized first. - * - * @param led_no - id of the LED in board (check platform specific headers to identify LED) - */ -void zb_osif_led_on(zb_uint8_t led_no); - -/* Set a LED off - * It must be initialized first. - * - * @param led_no - id of the LED in board (check platform specific headers to identify LED) - */ -void zb_osif_led_off(zb_uint8_t led_no); - -/* Get the current button tate - * It must be initialized first. - * - * @param arg - id of the LED in board (check platform specific headers to identify LED) - * - * @return ZB_FALSE is button is pressed, ZB_TRUE if button is not being pressed - */ -zb_bool_t zb_osif_button_state(zb_uint8_t arg); - -/* Inform osif layer that button callback is being set - * @return ZB_TRUE if leds and buttons are not initialized yet - * with zb_osif_led_button_init(). In this case stack logic - * should call it explicitly. - */ -zb_bool_t zb_setup_buttons_cb(zb_callback_t cb); - -void zb_osif_button_cb(zb_uint8_t arg); - -#endif /* ZB_USE_INTERNAL_HEADERS */ - -/* Configure one LED to be dimmable - * - * @param led_no - Led id to be dimmable - */ -zb_bool_t zb_osif_led_level_init(zb_uint8_t led_no); - -/* Set level of a dimmable LED (only one led is supported) - * It must be initialized first with zb_osif_led_level_init(zb_uint8_t led_no) - * - * @param level - brightness level to set from (0 to 255) to the dimmable led - */ -void zb_osif_led_on_set_level(zb_uint8_t level); - -#endif /* ZB_OSIF_H */ diff --git a/zboss/development/include/zb_pooled_list.h b/zboss/development/include/zb_pooled_list.h deleted file mode 100644 index e8515f2e84..0000000000 --- a/zboss/development/include/zb_pooled_list.h +++ /dev/null @@ -1,612 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: simple lists operations (macroses). Use 1- or 2-bytes instead -instead of pointer. -*/ -#ifndef POOLED_LIST_H -#define POOLED_LIST_H 1 - -/*! @cond internals_doc */ -/** - @addtogroup ZB_BASE - @{ -*/ - - -#ifndef ZB_POOLED_LIST_INCLUDED -#define ZB_POOLED_LIST_INCLUDED - -#define ZP_POOLED_LIST_NULL -1 - -#define ZP_TYPE8( x ) ( ( zb_uint8_t ) ( x ) ) -#define ZP_RIND8( x ) ( ( x ) - ZP_TYPE8( 1U ) ) - -#define ZP_TYPE16( x ) ( ( zb_uint16_t ) ( x ) ) -#define ZP_RIND16( x ) ( ( x ) - ZP_TYPE16( 1U ) ) - -#define ZP_NULL8 ( ZP_TYPE8 ( ZP_POOLED_LIST_NULL ) ) -#define ZP_NULL16 ( ZP_TYPE16 ( ZP_POOLED_LIST_NULL ) ) - -#define ZB_POOLED_LIST8_FIELD( link_field ) zb_uint8_t link_field ## _next; zb_uint8_t link_field ## _prev -#define ZB_POOLED_LIST16_FIELD( link_field ) zb_uint16_t link_field ## _next; zb_uint16_t link_field ## _prev - -#define ZB_POOLED_LIST8_DEF( list ) zb_uint8_t list = ZP_NULL8 -#define ZB_POOLED_LIST16_DEF( list ) zb_uint16_t list = ZP_NULL16 - -#define ZB_POOLED_LIST8_DEFINE( list ) zb_uint8_t list -#define ZB_POOLED_LIST16_DEFINE( list ) zb_uint16_t list - - -#define ZB_POOLED_LIST8_INIT( list ) (list) = ZP_NULL8 -#define ZB_POOLED_LIST16_INIT( list ) (list) = ZP_NULL16 - - -#define ZB_POOLED_LIST8_IS_EMPTY( list ) ( ( list ) == ZP_NULL8 ) -#define ZB_POOLED_LIST8_IS_NOT_EMPTY( list ) ( ( list ) != ZP_NULL8 ) - -#define ZB_POOLED_LIST16_IS_EMPTY( list ) ( ( list ) == ZP_NULL16 ) -#define ZB_POOLED_LIST16_IS_NOT_EMPTY( list ) ( ( list ) != ZP_NULL16 ) - -#define ZB_POOLED_LIST8_NEXT( base, index, link_field ) ( ( ZP_NULL8 == ( index ) ) ? ZP_NULL8 : ( base )[ ( index ) ].link_field##_next) -#define ZB_POOLED_LIST8_PREV( base, index, link_field ) ( ( ZP_NULL8 == ( index ) ) ? ZP_NULL8 : ( base )[ ( index ) ].link_field##_prev) - -#define ZB_POOLED_LIST8_GET_HEAD( base, list, link_field ) ( list ) -#define ZB_POOLED_LIST8_GET_TAIL( base, list, link_field ) ( ( ZP_NULL8 != list ) ? base[ list ].link_field##_prev : ZP_NULL8 ) - -#define ZB_POOLED_LIST16_GET_HEAD( base, list, link_field ) ( list ) -#define ZB_POOLED_LIST16_GET_TAIL( base, list, link_field ) ( ( ZP_NULL16 != list ) ? base[ list ].link_field##_prev : ZP_NULL16 ) - -#define ZB_POOLED_LIST16_NEXT( base, index, link_field ) ( ( ZP_NULL16 == index ) ) ? ZP_NULL16 : base[ index ].link_field##_next ) ) -#define ZB_POOLED_LIST16_PREV( base, index, link_field ) ( ( ZP_NULL16 == index ) ) ? ZP_NULL16 : base[ index ].link_field##_prev ) ) - -/** - Remove element from the list head, and store it in removed_entry - */ - -#define ZB_POOLED_LIST8_CUT_HEAD( base,list, link_field, removed_elem_index ) do \ -{ \ - removed_elem_index = list; \ - if( ( list ) != ZP_NULL8 ) \ - { \ - if( ( base )[ list ].link_field##_next != ZP_NULL8 ) \ - { \ - ( base )[ ( base )[ list ].link_field##_next ].link_field##_prev = \ - ( base )[ list ].link_field##_prev; \ - } \ - ( base )[ list ].link_field##_prev = ZP_NULL8; \ - ( list ) = ( base )[ list ].link_field##_next ; \ - } \ -} while (0) \ - - -/** - Insert to the list head - */ - -#define ZB_POOLED_LIST8_INSERT_HEAD( base, list, link_field, elem_index ) do \ -{ \ - ZB_ASSERT( ( elem_index ) != ZP_NULL8 ); \ - ( base )[ elem_index ].link_field##_next = ( list ); \ - if( ( list ) != ZP_NULL8 ) \ - { \ - ( base )[ ( elem_index ) ].link_field##_prev = ( base )[ list ].link_field##_prev; \ - ( base )[ ( list ) ].link_field##_prev = ( elem_index ) ; \ - } \ - else \ - { \ - ( base )[ elem_index ].link_field##_prev = ( elem_index ); \ - } \ - ( list ) = ( elem_index ); \ -} while( 0 ) - - -/** - Insert to the list tail - */ - -#define ZB_POOLED_LIST8_INSERT_TAIL( base, list, link_field, elem_index ) do \ -{ \ - ZB_ASSERT( ( elem_index ) != ZP_NULL8 ); \ - ( base )[ ( elem_index ) ].link_field##_next = ZP_NULL8; \ - if( ( list ) != ZP_NULL8 ) \ - { \ - ( base )[ ( elem_index ) ].link_field##_prev = ( base )[ ( list ) ].link_field##_prev; \ - ( base )[ ( base )[ ( list ) ].link_field##_prev ].link_field##_next = ( elem_index ); \ - ( base )[ ( list ) ].link_field##_prev = ( elem_index ); \ - } \ - else \ - { \ - ( base )[ ( elem_index ) ].link_field##_prev = ( elem_index ); \ - ( list ) = ( elem_index ); \ - } \ -} while (0) - - -/** - Insert after existed elem_indexry - */ - -#define ZB_POOLED_LIST8_INSERT_AFTER( base, list, link_field, elem_index, new_elem_index ) do \ -{ \ - ZB_ASSERT( ( new_elem_index ) != ZP_NULL8 ); \ - if( ( elem_index ) != ZP_NULL8 ) \ - { \ - if( ( ( elem_index ) ) == ZB_POOLED_LIST8_GET_TAIL( ( base ), ( list ), link_field ) ) \ - { \ - ZB_POOLED_LIST8_INSERT_TAIL( ( base ), ( list ), link_field, ( new_elem_index ) ); \ - } \ - else \ - { \ - ( base )[ new_elem_index ].link_field##_next = ( base )[ ( elem_index ) ].link_field##_next ; \ - ( base )[ new_elem_index ].link_field##_prev = ( elem_index ); \ - ( base )[ ( base )[ ( elem_index ) ].link_field##_next ].link_field##_prev = ( new_elem_index ); \ - ( base )[ ( elem_index ) ].link_field##_next = ( new_elem_index ); \ - } \ - } \ -} while(0) - - -/** - Remove from the list head - */ - -#define ZB_POOLED_LIST8_REMOVE_HEAD( base, list, link_field ) do \ -{ \ - if( list != ZP_NULL8 ) \ - { \ - if( base[ list ].link_field##_next != ZP_NULL8 ) \ - { \ - base[ base[ list ].link_field##_next ].link_field##_prev = base[ list ].link_field##_prev; \ - } \ - base[ list ].link_field##_prev = ZP_NULL8; \ - list = base[ list ].link_field##_next; \ - } \ -} while (0) - -/** - Remove from the list tail - */ - -#define ZB_POOLED_LIST8_REMOVE_TAIL( base, list, link_field ) do \ -{ \ - if( list != ZP_NULL8 ) \ - { \ - if( base[ list ].link_field ## _prev == ( list ) ) /* made an empty list */ \ - { \ - base[ list ].link_field ## _prev = ZP_NULL8; \ - ( list ) = ZP_NULL8; \ - } \ - else \ - { \ - base[ base[ base[ list ].link_field##_prev ].link_field##_prev ].link_field##_next = ZP_NULL8; \ - \ - /* This is a bit tricky: we need to assign list->prev and set \ - * tail->prev to 0, but we can't use temporary variable because \ - * we have no type here. Use _next as temporary variable. */ \ - \ - base[ base[ list ].link_field##_prev ].link_field##_next = \ - base[ base[ list ].link_field##_prev ].link_field##_prev; \ - \ - base[ base[ list ].link_field##_prev ].link_field##_prev = ZP_NULL8; \ - \ - base[ list ].link_field##_prev = base[ base[ list ].link_field##_prev ].link_field##_next; \ - } \ - } \ -} while (0) - -#define ZB_POOLED_LIST8_ITERATE( base, list, link_field, elem_index ) \ - for( ( elem_index ) = ( list ) ; ( elem_index != ZP_NULL8 ) ; ( elem_index ) = base[ elem_index ].link_field##_next ) - - -#define ZB_POOLED_LIST8_ITERATE_BACK( base, list, link_field, elem_index) \ - for( ( elem_index ) = ( list ) ? base[ list ].link_field##_prev : ZP_NULL8; \ - ( elem_index != ZP_NULL8 ); \ - ( elem_index ) = ( ( base[ base[ elem_index ].link_field##_prev ].link_field##_next != ZP_NULL8 ) ? \ - base[ elem_index ].link_field##_prev : ZP_NULL8 ) ) - -/* NOTE! elem_index is just some index from base array, but not - ordinary number of the list. So, if you remove elem_index == 2, - it doesn't mean that you remove third element from the list. It means - just that you remove some element placed in base[ 2 ] from the list which can - be actually any ordinary number of the list. -*/ - -#define ZB_POOLED_LIST8_REMOVE( base, list, link_field, elem_index ) \ -do \ -{ \ - ZB_ASSERT( ( elem_index ) != ZP_NULL8 ); \ - if( base[ ( elem_index ) ].link_field##_prev != ZP_NULL8 ) \ - { \ - if( ( base )[ ( elem_index ) ].link_field##_next != ZP_NULL8 ) /* this is not a tail */ \ - { \ - ( base )[ ( base )[ ( elem_index ) ].link_field##_next ].link_field##_prev = ( base )[ ( elem_index ) ].link_field##_prev; \ - } \ - else /* this is a tail */ \ - { \ - ( base )[ ( list ) ].link_field##_prev = ( base )[ ( elem_index ) ].link_field##_prev; \ - } \ - if( ( elem_index ) == ( list ) ) /* this is a head */ \ - { \ - ( list ) = ( base )[ ( elem_index ) ].link_field##_next; \ - } \ - else /* this is not a head */ \ - { \ - ( base )[ ( base )[ ( elem_index ) ].link_field##_prev ].link_field##_next = ( base )[ ( elem_index ) ].link_field##_next; \ - } \ - ( base )[ ( elem_index ) ].link_field##_prev = ZP_NULL8; \ - } \ -} \ -while( 0 ) \ - - -/** - Remove element from the list head, and store it in removed_entry - */ -#define ZB_POOLED_LIST16_CUT_HEAD( base,list, link_field, removed_elem_index ) do \ -{ \ - ZB_ASSERT( removed_elem_index != ZP_NULL16 ); \ - removed_elem_index = list; \ - if( ( list ) != ZP_NULL16 ) \ - { \ - if( base[ list ].link_field##_next != ZP_NULL16 ) \ - { \ - base[ base[ list ].link_field##_next ].link_field##_prev = \ - base[ list ].link_field##_prev; \ - } \ - base[ list ].link_field##_prev = ZP_NULL16; \ - ( list ) = base[ list ].link_field##_next ; \ - } \ -} while (0) - - -/** - Insert to the list head - */ - -#define ZB_POOLED_LIST16_INSERT_HEAD( base, list, link_field, elem_index ) do \ -{ \ - ZB_ASSERT( ( elem_index ) != ZP_NULL16 ); \ - base[ elem_index ].link_field##_next = ( list ); \ - if( ( list ) != ZP_NULL16 ) \ - { \ - base[ elem_index ].link_field##_prev = base[ list ].link_field##_prev; \ - base[ list ].link_field##_prev = elem_index ; \ - } \ - else \ - { \ - base[ elem_index ].link_field##_prev = elem_index; \ - } \ - ( list ) = ( elem_index ); \ -} while( 0 ) - - -/** - Insert to the list tail - */ - -#define ZB_POOLED_LIST16_INSERT_TAIL( base, list, link_field, elem_index ) do \ -{ \ - ZB_ASSERT( ( elem_index ) != ZP_NULL16 ); \ - base[ elem_index ].link_field##_next = ZP_NULL16; \ - if( ( list ) != ZP_NULL16 ) \ - { \ - base[ elem_index ].link_field##_prev = base[ list ].link_field##_prev; \ - base[ base[ list ].link_field##_prev ].link_field##_next = elem_index; \ - base[ list ].link_field##_prev = elem_index; \ - } \ - else \ - { \ - base[ elem_index ].link_field##_prev = elem_index; \ - ( list ) = ( elem_index ); \ - } \ -} while (0) - - -/** - Insert after existed elem_indexry - */ - -#define ZB_POOLED_LIST16_INSERT_AFTER( base, list, link_field, elem_index, new_elem_index ) do \ -{ \ - ZB_ASSERT( new_elem_index != ZP_NULL16 ); \ - if( elem_index != ZP_NULL16 ) \ - { \ - if( elem_index == ZB_POOLED_LIST16_GET_TAIL( base, list, link_field ) ) \ - { \ - ZB_POOLED_LIST16_INSERT_TAIL( base, list, link_field, new_elem_index ); \ - } \ - else \ - { \ - base[ new_elem_index ].link_field##_next = base[ elem_index ].link_field##_next ; \ - base[ new_elem_index ].link_field##_prev = elem_index; \ - base[ base[ elem_index ].link_field##_next ].link_field##_prev = new_elem_index; \ - base[ elem_index ].link_field##_next = ( new_elem_index ); \ - } \ - } \ -} while(0) - - -/** - Remove from the list head - */ - -#define ZB_POOLED_LIST16_REMOVE_HEAD( base, list, link_field ) do \ -{ \ - if( list != ZP_NULL16 ) \ - { \ - if( base[ list ].link_field##_next != ZP_NULL16 ) \ - { \ - base[ base[ list ].link_field##_next ].link_field##_prev = base[ list ].link_field##_prev; \ - } \ - base[ list ].link_field##_prev = ZP_NULL16; \ - list = base[ list ].link_field##_next; \ - } \ -} while (0) - -/** - Remove from the list tail - */ - -#define ZB_POOLED_LIST16_REMOVE_TAIL( base, list, link_field ) do \ -{ \ - if( list != ZP_NULL16 ) \ - { \ - if( base[ list ].link_field ## _prev == ( list ) ) /* made an empty list */ \ - { \ - base[ list ].link_field ## _prev = ZP_NULL16; \ - ( list ) = ZP_NULL16; \ - } \ - else \ - { \ - base[ base[ base[ list ].link_field##_prev ].link_field##_prev ].link_field##_next = ZP_NULL16; \ - \ - /* This is a bit tricky: we need to assign list->prev and set \ - * tail->prev to 0, but we can't use temporary variable because \ - * we have no type here. Use _next as temporary variable. */ \ - \ - base[ base[ list ].link_field##_prev ].link_field##_next = \ - base[ base[ list ].link_field##_prev ].link_field##_prev; \ - \ - base[ base[ list ].link_field##_prev ].link_field##_prev = ZP_NULL16; \ - \ - base[ list ].link_field##_prev = base[ base[ list ].link_field##_prev ].link_field##_next; \ - } \ - } \ -} while (0) - -#define ZB_POOLED_LIST16_ITERATE( base, list, link_field, elem_index ) \ - for( ( elem_index ) = ( list ) ; ( elem_index != ZP_NULL16 ) ; ( elem_index ) = base[ elem_index ].link_field##_next ) - - -#define ZB_POOLED_LIST16_ITERATE_BACK( base, list, link_field, elem_index) \ - for( ( elem_index ) = ( list ) ? base[ list ].link_field##_prev : ZP_NULL16; \ - ( elem_index != ZP_NULL16 ); \ - ( elem_index ) = ( ( base[ base[ elem_index ].link_field##_prev ].link_field##_next != ZP_NULL16 ) ? \ - base[ elem_index ].link_field##_prev : ZP_NULL16 ) ) - -/* NOTE! elem_index is just some index from base array, but not - ordinary number of the list. So, if you remove elem_index == 2, - it doesn't mean that you remove third element from the list. It means - just that you remove some element placed in base[ 2 ] from the list which can - be actually any ordinary number of the list. -*/ - -#define ZB_POOLED_LIST16_REMOVE( base, list, link_field, elem_index ) \ -do \ -{ \ - ZB_ASSERT( elem_index != ZP_NULL16 ); \ - if( base[ elem_index ].link_field##_prev != ZP_NULL16 ) \ - { \ - if( base[ elem_index ].link_field##_next != ZP_NULL16 ) /* this is not a tail */ \ - { \ - base[ base[ elem_index ].link_field##_next ].link_field##_prev = base[ elem_index ].link_field##_prev; \ - } \ - else /* this is a tail */ \ - { \ - base[ list ].link_field##_prev = base[ elem_index ].link_field##_prev; \ - } \ - if( ( elem_index ) == ( list ) ) /* this is a head */ \ - { \ - ( list ) = base[ elem_index ].link_field##_next; \ - } \ - else /* this is not a head */ \ - { \ - base[ base[ elem_index ].link_field##_prev ].link_field##_next = base[ elem_index ].link_field##_next; \ - } \ - base[ elem_index ].link_field##_prev = ZP_NULL16; \ - } \ -} \ -while( 0 ) - - -/* Single liked lists */ -#define ZP_POOLED_SL_LIST8_NULL 255U - - -#define ZB_POOLED_SL_LIST8_DEFINE(type, list) type list ## _head; type list ## _tail - -#define ZB_POOLED_SL_LIST8_INIT(list) list ## _head = ZP_POOLED_SL_LIST8_NULL; list ## _tail = ZP_POOLED_SL_LIST8_NULL - - -#define ZB_POOLED_SL_LIST8_FIELD(type, name) type name ## _next - - -#define ZB_POOLED_SL_LIST8_NEXT(base, index, name) ( ( (index) == ZP_POOLED_SL_LIST8_NULL ) ? ZP_POOLED_SL_LIST8_NULL : (base)[index].name ## _next ) - -#define ZB_POOLED_SL_LIST8_HEAD(list) list ## _head - -#define ZB_POOLED_SL_LIST8_TAIL(list) list ## _tail - -#define ZB_POOLED_SL_LIST8_IS_EMPTY(list) ( list ## _head == ZP_POOLED_SL_LIST8_NULL ) -#define ZB_POOLED_SL_LIST8_IS_NOT_EMPTY(list) ( list ## _head != ZP_POOLED_SL_LIST8_NULL ) - - -/** - Insert to the list head - */ -#define ZB_POOLED_SL_LIST8_INSERT_HEAD(base, list, name, index) \ -do \ -{ \ - (base)[index].name ## _next = list ## _head; \ - if ( (list ## _head) + 1 == ZP_POOLED_SL_LIST8_NULL ) \ - { \ - (list ## _tail) = (index); \ - } \ - list ## _head = (index); \ -} while( 0 ) - - -/** - Insert to the list tail - */ -#define ZB_POOLED_SL_LIST8_INSERT_TAIL(base, list, name, index) \ -do \ -{ \ - (base)[index].name##_next = ZP_POOLED_SL_LIST8_NULL; \ - if ( (list ## _tail) != ZP_POOLED_SL_LIST8_NULL) \ - { \ - (base)[list ## _tail].name##_next = index; \ - list ## _tail = (index); \ - } \ - else \ - { \ - (list ## _head) = (index); \ - (list ## _tail) = (index); \ - } \ -} while (0) - - -/** - Remove from the list head - */ -#define ZB_POOLED_SL_LIST8_REMOVE_HEAD(base, list, name) \ -do \ -{ \ - if ( (list ## _head) != ZP_POOLED_SL_LIST8_NULL ) \ - { \ - list ## _head = (base)[list ## _head].name ## _next; \ - if ( (list ## _head) == ZP_POOLED_SL_LIST8_NULL) \ - { \ - (list ## _tail) = ZP_POOLED_SL_LIST8_NULL; \ - } \ - } \ -} while (0) - - -/** - Remove element from the list head, and store it in index - */ -#define ZB_POOLED_SL_LIST8_CUT_HEAD(base, list, name, index) \ -do \ -{ \ - if ( (list ## _head) != ZP_POOLED_SL_LIST8_NULL ) \ - { \ - (index) = (list ## _head); \ - (list ## _head) = (base)[list ## _head].name ## _next; \ - if ( (list ## _head) == ZP_POOLED_SL_LIST8_NULL) \ - { \ - (list ## _tail) = ZP_POOLED_SL_LIST8_NULL; \ - } \ - } \ - else \ - { \ - (index) = ZP_POOLED_SL_LIST8_NULL; \ - } \ -} while (0) - - -/** - Remove element from the list tail - */ -#define ZB_POOLED_SL_LIST8_CUT_TAIL(base, list, name, index) \ -do \ -{ \ - (index) = (list ## _tail); \ - ZB_POOLED_SL_LIST8_REMOVE(base, list, name, index); \ -} while (0) - - -/** - Remove index from list - */ -#define ZB_POOLED_SL_LIST8_REMOVE(base, list, name, index) \ -do \ -{ \ - zb_uint8_t p; \ - zb_uint8_t prev = ZP_POOLED_SL_LIST8_NULL; \ - for (p = (list ## _head); \ - p != ZP_POOLED_SL_LIST8_NULL; \ - prev = p, p = (base)[p].name ## _next ) \ - { \ - if ( p == (index) ) \ - { \ - if ( prev != ZP_POOLED_SL_LIST8_NULL ) \ - { \ - (base)[prev].name ## _next = (base)[p].name ## _next; \ - if ((list ## _tail) == index) \ - { \ - (list ## _tail) = prev; \ - } \ - } \ - else \ - { \ - (list ## _head) = (base)[p].name ## _next; \ - } \ - if ( (list ## _head) == ZP_POOLED_SL_LIST8_NULL ) \ - { \ - (list ## _tail) = ZP_POOLED_SL_LIST8_NULL; \ - } \ - break; \ - } \ - } \ -} \ -while( 0 ) - - -#define ZB_POOLED_SL_LIST8_ITERATE(base, list, name, index) \ - for( (index) = (list); (index != ZP_POOLED_SL_LIST8_NULL); (index) = base[index].name##_next ) - -#endif - -/*! @} */ -/*! @endcond */ - -#endif diff --git a/zboss/development/include/zb_ringbuffer.h b/zboss/development/include/zb_ringbuffer.h deleted file mode 100644 index f27cc68600..0000000000 --- a/zboss/development/include/zb_ringbuffer.h +++ /dev/null @@ -1,551 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Declare ring buffer internals -*/ - -#ifndef ZB_RINGBUFFER_H -#define ZB_RINGBUFFER_H 1 - -/*! @cond internals_doc */ -/** - @addtogroup ZB_BASE - @{ -*/ - - -/** - \par Generic ring buffer macros - */ - -/** - Declare ring buffer for entries of given type and capacity. - This is typedef, not variable declaration. - - @param type_name_prefix - prefix for names (like xxx_s, xxx_t) - @param ent_type - type of the ring buffer entry - @param capacity - ring buffer capacity - */ -#define ZB_RING_BUFFER_DECLARE(type_name_prefix, ent_type, capacity) \ -typedef struct type_name_prefix ## _s \ -{ \ - zb_ushort_t read_i; \ - zb_ushort_t write_i; \ - zb_ushort_t written; \ - ent_type ring_buf[capacity]; \ -} type_name_prefix ## _t - - -/** - * Initialize ring buffer internals - */ -#define ZB_RING_BUFFER_INIT(rb) ( (rb)->read_i = (rb)->write_i = (rb)->written = 0U) - -/** - * Return ring buffer capacity - * - * @param rb - ring buffer pointer. - */ -#define ZB_RING_BUFFER_CAPACITY(rb) ((sizeof((rb)->ring_buf) / sizeof((rb)->ring_buf[0]))) - -/** - * Return 1 if ring buffer is full - * - * @param rb - ring buffer pointer. - */ -#define ZB_RING_BUFFER_IS_FULL(rb) ((zb_uint_t)(rb)->written >= ZB_RING_BUFFER_CAPACITY(rb)) - -/** - * Return 1 if ring buffer is empty - * - * @param rb - ring buffer pointer. - */ -#define ZB_RING_BUFFER_IS_EMPTY(rb) ((rb)->written == 0U) - - -/** - * Return free space available in the ring buffer - * - * @param rb - ring buffer pointer. - */ -#define ZB_RING_BUFFER_FREE_SPACE(rb) (ZB_RING_BUFFER_CAPACITY(rb) - (zb_uint_t)(rb)->written) - -/** - * Reserve slot in the ring buffer but do not update pointers - * - * @param rb - ring buffer pointer. - * @return Pointer to the ring buffer entry or NULL if ring buffer is full - */ -#define ZB_RING_BUFFER_PUT_RESERVE(rb) \ -( \ - ZB_RING_BUFFER_IS_FULL(rb) ? NULL \ - : (rb)->ring_buf + (rb)->write_i \ - ) - -#define ZB_RING_BUFFER_PUT_HEAD_RESERVE_IDX(rb) \ -( \ - ((rb)->read_i > 0U) ? \ - ((rb)->read_i - 1U) : (ZB_RING_BUFFER_CAPACITY(rb) - 1U) \ - ) - -#define ZB_RING_BUFFER_PUT_HEAD_RESERVE(rb) \ -( \ - ZB_RING_BUFFER_IS_FULL(rb) ? NULL \ - : ((rb)->ring_buf + ZB_RING_BUFFER_PUT_HEAD_RESERVE_IDX(rb)) \ - ) - -/** - * Put to the ring buffer. - * Get free slot from the ring buffer, return pointer to it. - * - * @param rb - ring buffer pointer. - * @return nothing - */ -#define ZB_RING_BUFFER_FLUSH_PUT(rb) \ -( \ - (rb)->written++, \ - (rb)->write_i = ((rb)->write_i + 1U) % ZB_RING_BUFFER_CAPACITY(rb) \ - ) - -#define ZB_RING_BUFFER_FLUSH_PUT_HEAD(rb) \ -do \ -{ \ - (rb)->written++; \ - if ((rb)->read_i > 0U) \ - { \ - --((rb)->read_i); \ - } \ - else \ - { \ - (rb)->read_i = ZB_RING_BUFFER_CAPACITY(rb) - 1U; \ - } \ -} while(ZB_FALSE) - - - -/** - Return amount of data which can be put into ring buffer tail starting from write_i - - @param rb - ring buffer pointer - @param size - requested data size - */ -#define ZB_RING_BUFFER_LINEAR_PORTION(rb, size) \ -( \ - ZB_RING_BUFFER_CAPACITY(rb) - (rb)->write_i < size ? \ - ZB_RING_BUFFER_CAPACITY(rb) - (rb)->write_i : size \ -) - -/** - Return amount of data which can be put into ring buffer tail starting from write_i using external rb capacity - - @param rb - ring buffer pointer - @param size - requested data size - */ -#define ZB_RING_BUFFER_LINEAR_PORTION_BY_CAP(rb, size, rb_cap) \ -( \ - (rb_cap) - (rb)->write_i < (size) ? \ - (rb_cap) - (rb)->write_i : (size) \ - ) - -/** - * Get the size of available for writing continuous portion in ring buffer. - * - * That portion is from write_i index to the end of the buffer or - * from write_i index to the beginning of previously written but still not read data - * - * @param buf - ring buffer pointer - * @return size of available continuous portion - */ -#define ZB_RING_BUFFER_AVAILABLE_CONTINUOUS_PORTION(rb) \ - ZB_RING_BUFFER_LINEAR_PORTION((rb), ZB_RING_BUFFER_FREE_SPACE(rb)) - -/** - Batch put data into ringbuffer - - To be used to copy from external buffer to ring buffer - - @param rb - ring buffer pointer - @param data - data ptr - @param size - requested data size - @param entries_written - (out) amount of data put - */ -#define ZB_RING_BUFFER_BATCH_PUT(rb, data, size, entries_written) \ -do \ -{ \ - (entries_written) = ZB_RING_BUFFER_LINEAR_PORTION((rb), (size)); \ - ZB_MEMCPY((rb)->ring_buf + (rb)->write_i, (data), (entries_written)); \ - (rb)->written += (entries_written); \ - (rb)->write_i = (((rb)->write_i + (entries_written)) % ZB_RING_BUFFER_CAPACITY(rb)); \ -} while(ZB_FALSE) - -/** - Batch put data into ringbuffer using external rb capacity - - To be used to copy from external buffer to ring buffer - - @param rb - ring buffer pointer - @param data - data ptr - @param size - requested data size - @param entries_written - (out) amount of data put - @param rb_cap - cap of the ring buffer - */ -#define ZB_RING_BUFFER_BATCH_PUT_BY_CAP(rb, data, size, entries_written, rb_cap) \ -do \ -{ \ - (entries_written) = ZB_RING_BUFFER_LINEAR_PORTION_BY_CAP((rb), (size), (rb_cap)); \ - ZB_MEMCPY((rb)->ring_buf + (rb)->write_i, (data), (entries_written)); \ - (rb)->written += (entries_written); \ - (rb)->write_i = (((rb)->write_i + (entries_written)) % (rb_cap)); \ -} while(ZB_FALSE) - - -/** - * Flush after put more then 1 element to the ring buffer - * - * Do not check for write_i overflow! - * - * @param rb - ring buffer pointer. - * @param size - number of items put - * @return nothing - */ -#define ZB_RING_BUFFER_FLUSH_BATCH_PUT(rb, size) \ -( \ - (rb)->written += size, \ - (rb)->write_i = (((rb)->write_i) + size) % ZB_RING_BUFFER_CAPACITY(rb) \ - ) - - -/** - * Put value to the ring buffer. - * - * @param rb - ring buffer pointer. - * @param value - value to put to ring buffer - * @return nothing - */ -#define ZB_RING_BUFFER_PUT(rb, value) \ -( \ - (rb)->ring_buf[(rb)->write_i] = (value), \ - (rb)->written++, \ - (rb)->write_i = ((rb)->write_i + 1U) % ZB_RING_BUFFER_CAPACITY(rb) \ - ) - - -/** - * Put value to the ring buffer using memcpy. - * - * @param rb - ring buffer pointer. - * @param value_ptr - pointer to value to put to ring buffer - * @return nothing - */ -#define ZB_RING_BUFFER_PUT_PTR(rb, value_ptr) \ -( \ - memcpy(&((rb)->ring_buf[(rb)->write_i]), (value_ptr), sizeof((rb)->ring_buf[0])), \ - (rb)->written++, \ - (rb)->write_i = ((rb)->write_i + 1U) % ZB_RING_BUFFER_CAPACITY(rb) \ - ) - - -/** - * Reinsert last value into the ring buffer using memcpy. - * - * @param rb - ring buffer pointer. - * @param value_ptr - pointer to value to put to ring buffer - * @return nothing - */ -#define ZB_RING_BUFFER_PUT_REUSE_LAST(rb, value_ptr) \ -( \ - memcpy(&((rb)->ring_buf[((rb)->write_i ? (rb)->write_i - 1U : (rb)->write_i + ZB_RING_BUFFER_CAPACITY(rb) - 1U)]), \ - (value_ptr), \ - sizeof((rb)->ring_buf[0])) \ - ) - - -/** - * Get entry from the ring buffer read pointer position - * - * @param rb - ring buffer pointer. - * - * @return pointer to the ring buffer entry or NULL if it is empty - */ -#define ZB_RING_BUFFER_PEEK(rb) \ -( \ - ZB_RING_BUFFER_IS_EMPTY(rb) ? NULL \ - : (rb)->ring_buf + (rb)->read_i \ - ) - -/** - * Get entry from the ring buffer read pointer position - * - * @param rb - ring buffer pointer. - * - * @return pointer to the ring buffer entry - */ -#define ZB_RING_BUFFER_GET(rb) \ -( \ - (rb)->ring_buf + (rb)->read_i \ - ) - -/** - * Get entry from the ring buffer write pointer position - * - * @param rb - ring buffer pointer. - * - * @return pointer to the ring buffer entry - */ -#define ZB_RING_BUFFER_GETW(rb) \ -( (rb)->ring_buf + (rb)->write_i ) - -/** - * Move ring buffer read pointer. - * - * To be used after ZB_RING_BUFFER_PEEK(). - * @note This macro does not check for an empty ring buffer. - * - * @param rb - ring buffer pointer. - * @return nothing - */ -#define ZB_RING_BUFFER_FLUSH_GET(rb) \ -( \ - (rb)->written--, \ - ((rb)->read_i = ((rb)->read_i + 1U) % ZB_RING_BUFFER_CAPACITY(rb)) \ - ) - - -/** - * Get entries from the ring buffer read pointer position which can be get at once - * - * @param rb - ring buffer pointer. - * @param size - (out) number of entries which can be got - * - * @return pointer to the ring buffer entry - */ -#define ZB_RING_BUFFER_GET_BATCH(rb, size) \ - ( \ - (size) = ((rb)->written <= (ZB_RING_BUFFER_CAPACITY(rb) - (rb)->read_i) \ - ? \ - (rb)->written \ - : \ - (ZB_RING_BUFFER_CAPACITY(rb) - (rb)->read_i)), \ - (rb)->ring_buf + (rb)->read_i \ - ) \ - - - -/** - * Move ring buffer read pointer for more than 1 element - * - * @note This macro does not check for empty ring buffer. - * - * @param rb - ring buffer pointer. - * @param size - number of elements to mark as read - * @return nothing - */ -#define ZB_RING_BUFFER_FLUSH_GET_BATCH(rb, size) \ -( \ - (rb)->written -= (size), \ - ((rb)->read_i = ((rb)->read_i + (size)) % ZB_RING_BUFFER_CAPACITY((rb))) \ - ) - -/** - * Move ring buffer's read and write pointers to the specified pos - * - * @param rb - ring buffer pointer. - * @param b - new position of read_i buffer's pointer - * @param e - new position of write_i buffer's pointer - * @return nothing - */ -#define ZB_RING_BUFFER_LOCATE(rb, b, e) \ - ( (rb)->read_i = b, \ - (rb)->write_i = e, \ - (rb)->written = e - b \ - ) - -/** - * Returns number of used entries - * - * @param rb - ring buffer pointer. - */ - -#define ZB_RING_BUFFER_USED_SPACE(rb) \ -( \ - (rb)->written \ - ) - -#define ZB_RING_BUFFER_SEARCH_GET(_rb, _i) \ -( \ - ZB_RING_BUFFER_IS_EMPTY(_rb) ? NULL \ - : (_rb)->ring_buf + ((_rb)->read_i +(_i)) % ZB_RING_BUFFER_CAPACITY(_rb) \ - ) - - -/** - * This is a fake type used for type casting. - * Represents array of bytes, used for serial trace e.t.c. - * - * @Example: - * @code - * ZB_RING_BUFFER_DECLARE(sniffer_io_buffer, zb_uint8_t, 4096); - * ... - * zb_osif_set_user_io_buffer((zb_byte_array_t*)&gs_sniffer_io_buf, 4096); - * @endcode - */ -ZB_RING_BUFFER_DECLARE(zb_byte_array, zb_uint8_t, 1); - -/** - * @see ZB_RING_BUFFER_IS_EMPTY - */ -#define ZB_BYTE_ARRAY_IS_EMPTY(rb) ZB_RING_BUFFER_IS_EMPTY(rb) - -/** - * @see ZB_RING_BUFFER_PEEK - */ -#define ZB_BYTE_ARRAY_PEEK(rb) ZB_RING_BUFFER_PEEK(rb) - -/** - * Return 1 if ring buffer is full - * - * @param rb - ring buffer pointer. - * @param cap - ring buffer capacity (number of bytes) - */ -#define ZB_BYTE_ARRAY_IS_FULL(rb, cap) ((zb_uint_t)(rb)->written >= cap) - -/** - * Move ring buffer read pointer. - * - * To be used after ZB_BYTE_ARRAY_PEEK(). - * @note This macro does not check for empty ring buffer. - * - * @param rb - ring buffer pointer. - * @param cap - ring buffer capacity (number of bytes) - * @return nothing - */ -#define ZB_BYTE_ARRAY_FLUSH_GET(rb, cap) \ -( \ - (rb)->written--, \ - ((rb)->read_i = ((rb)->read_i + 1U) % (cap)) \ - ) - -/* 10/04/17 CR Ustimenko start */ -/** - * Get entries from the ring buffer read pointer position which can be get at once - * - * @param rb - ring buffer pointer. - * @param size - (out) number of entries which can be got - * @param cap - ring buffer capacity (number of bytes) - * - * @return pointer to the ring buffer entry - */ -#define ZB_BYTE_ARRAY_GET_BATCH(rb, size, cap) \ - ( \ - size = ((rb)->written <= (cap - (rb)->read_i) \ - ? \ - (rb)->written \ - : \ - (cap - (rb)->read_i)), \ - (rb)->ring_buf + (rb)->read_i \ - ) - -/** - * Move ring buffer read pointer for more than 1 element - * - * This macro does not check for an empty ring buffer. - * - * @param rb - ring buffer pointer. - * @param size - number of elements to mark as read - * @param cap - ring buffer capacity (number of bytes) - * @return nothing - */ -#define ZB_BYTE_ARRAY_FLUSH_GET_BATCH(rb, size, cap) \ -( \ - (rb)->written -= size, \ - ((rb)->read_i = ((rb)->read_i + size) % cap) \ - ) -/* 10/04/17 CR Ustimenko end */ - -/** - * Put value to the ring buffer. - * - * @param rb - ring buffer pointer. - * @param value - value to put to ring buffer - * @param cap - ring buffer capacity (number of bytes) - * @return nothing - */ -#define ZB_BYTE_ARRAY_PUT(rb, value, cap) \ -( \ - (rb)->ring_buf[(rb)->write_i] = (value), \ - (rb)->written++, \ - (rb)->write_i = ((rb)->write_i + 1U) % cap \ - ) - -#define ZB_BYTE_ARRAY_PUT_HEAD_RESERVE_IDX(rb, cap) \ -( \ - ((rb)->read_i > 0U) ? \ - ((rb)->read_i - 1U) : ((cap) - 1U) \ - ) - -#define ZB_BYTE_ARRAY_PUT_HEAD_RESERVE(rb, cap) \ -( \ - ((rb)->ring_buf + ZB_BYTE_ARRAY_PUT_HEAD_RESERVE_IDX(rb, (cap))) \ - ) - -#define ZB_BYTE_ARRAY_FLUSH_PUT_HEAD(rb, cap) \ -do \ -{ \ - (rb)->written++; \ - if ((rb)->read_i > 0U) \ - { \ - --((rb)->read_i); \ - } \ - else \ - { \ - (rb)->read_i = (cap) - 1U; \ - } \ -} while(ZB_FALSE) - -#define ZB_BYTE_ARRAY_FLUSH_PUT(rb, cap) \ -( \ - (rb)->written++, \ - (rb)->write_i = ((rb)->write_i + 1U) % (cap) \ - ) - -/*! @} */ -/*! @endcond */ - -#endif /* ZB_RINGBUFFER_H */ diff --git a/zboss/development/include/zb_trace.h b/zboss/development/include/zb_trace.h deleted file mode 100644 index aaaf808c76..0000000000 --- a/zboss/development/include/zb_trace.h +++ /dev/null @@ -1,1246 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZigBee trace. Application should include it. -*/ -#ifndef ZB_LOGGER_H -#define ZB_LOGGER_H 1 - -#ifdef ZB_TRACE_USE_VA_LIST -#include -#endif - -/** @cond DOXYGEN_DEBUG_SECTION */ -/** - * @addtogroup ZB_TRACE Debug trace - * @{ - */ -/** @cond DSR_TRACE */ -/** - * @addtogroup ZB_TRACE_CONFIG Trace configuration - * @{ - */ -/** @endcond */ /* DSR_TRACE */ - -#if defined(ZB_TRACE_LEVEL) -/** @cond DOXYGEN_INTERNAL_DOC */ -extern zb_uint8_t g_trace_level, g_o_trace_level; -extern zb_uint32_t g_trace_mask; -extern zb_uint_t g_trace_inside_intr; -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -/** - Set trace level at runtime - - That macro can switch trace level on and off. Trace level must be included - into build at compile time by setting ZB_TRACE_LEVEL compiler time define. - - @param l - new trace level. - - @par Example - @snippet thermostat/thermostat_zr/thermostat_zr.c set_trace - @par - */ -#define ZB_SET_TRACE_LEVEL(l) g_trace_level = (l) - -/** - Switch off all trace at runtime - */ -#define ZB_SET_TRACE_OFF() g_o_trace_level = g_trace_level, g_trace_level = 0U - -/** - Switch on trace at runtime - - That macro enables trace which was active before call to ZB_SET_TRACE_OFF(). - - @snippet light_sample/dimmable_light/bulb.c switch_trace_on - */ -#define ZB_SET_TRACE_ON() g_trace_level = g_o_trace_level - -/** - Set trace mask at runtime - - That macro can switch trace mask on and off. Trace mask must be included - into build at compile time by setting ZB_TRACE_MASK compiler time define. - - @param m - new trace mask. - - @par Example - @snippet thermostat/thermostat_zr/thermostat_zr.c set_trace - @par - */ -#define ZB_SET_TRACE_MASK(m) g_trace_mask = (m) - -#else - -#define ZB_SET_TRACE_OFF() -#define ZB_SET_TRACE_LEVEL(l) -#define ZB_SET_TRACE_ON() -#define ZB_SET_TRACE_MASK(m) - -#endif /* defined(ZB_TRACE_LEVEL) */ - -/** @cond DSR_TRACE */ -/** @} */ /* ZB_TRACE_CONFIG */ -/** @endcond */ /* DSR_TRACE */ - -/** @cond DSR_TRACE */ -/** - * @addtogroup TRACE_SUBSYSTEMS - * @{ - */ -#define TRACE_SUBSYSTEM_COMMON 0x0001U /**< Common subsystem. */ -#define TRACE_SUBSYSTEM_MEM 0x0002U /**< MEM subsystem (buffers pool). */ -#define TRACE_SUBSYSTEM_MAC 0x0004U /**< MAC subsystem. */ -#define TRACE_SUBSYSTEM_NWK 0x0008U /**< NWK subsystem. */ - -#define TRACE_SUBSYSTEM_APS 0x0010U /**< APS subsystem. */ -#define TRACE_SUBSYSTEM_ZSE 0x0020U /**< ZSE subsystem. */ -#define TRACE_SUBSYSTEM_ZDO 0x0040U /**< ZDO subsystem. */ -#define TRACE_SUBSYSTEM_SECUR 0x0080U /**< Security subsystem. */ - -#define TRACE_SUBSYSTEM_ZCL 0x0100U /**< ZCL subsystem. */ -/** @cond DOXYGEN_TOUCHLINK_FEATURE */ -#define TRACE_SUBSYSTEM_ZLL 0x0200U /**< ZLL/Touchlink subsystem. */ -/** @endcond */ /* DOXYGEN_TOUCHLINK_FEATURE */ -/** @cond DOXYGEN_INTERNAL_DOC */ -#define TRACE_SUBSYSTEM_SSL 0x0400U /**< SSL subsystem */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -/** @endcond */ /* DSR_TRACE */ -#define TRACE_SUBSYSTEM_APP 0x0800U /**< User Application */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -#define TRACE_SUBSYSTEM_LWIP 0x1000U /* LWIP is used, else free */ -#define TRACE_SUBSYSTEM_ALIEN 0x2000U /* Some special debug */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -#define TRACE_SUBSYSTEM_ZGP 0x4000U /**< ZGP subsystem */ -/** @cond DOXYGEN_INTERNAL_DOC */ -#define TRACE_SUBSYSTEM_MAC_API 0x8000U /**< MAC API subsystem */ -#define TRACE_SUBSYSTEM_MACLL 0x10000U /**< MAC LL subsystem */ -#define TRACE_SUBSYSTEM_SPECIAL1 0x20000U /**< Special subsystem */ -#define TRACE_SUBSYSTEM_BATTERY 0x40000U /**< Battery subsystem */ -#define TRACE_SUBSYSTEM_OTA 0x80000U /**< OTA subsystem */ -#define TRACE_SUBSYSTEM_TRANSPORT 0x100000U /**< Transport subsystem */ -#define TRACE_SUBSYSTEM_USB 0x200000U /**< USB subsystem */ -#define TRACE_SUBSYSTEM_SPI 0x400000U /**< SPI subsystem */ -#define TRACE_SUBSYSTEM_UART 0x800000U /**< UART subsystem */ -#define TRACE_SUBSYSTEM_JSON 0x1000000U /**< JSON subsystem */ -#define TRACE_SUBSYSTEM_HTTP 0x2000000U /**< HTTP subsystem */ -#define TRACE_SUBSYSTEM_CLOUD 0x4000000U /**< Interface to the Cloud */ -#define TRACE_SUBSYSTEM_ZBDIRECT 0x8000000U /**< Zigbee Direct subsystem */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -#define TRACE_SUBSYSTEM_INFO ((zb_uint_t)-1) /**< Common subsystem */ - -/* to be continued... */ - -/** @cond DSR_TRACE */ -/** @} */ /* TRACE_SUBSYSTEMS */ -/** @endcond */ /* DSR_TRACE */ -/** @} */ /* ZB_TRACE */ - -/** - * @addtogroup ZB_TRACE Debug trace - * @{ - */ -#if defined ZB_TRACE_LEVEL || defined DOXYGEN -/** - * @addtogroup ZB_TRACE_CONFIG Trace configuration - * @{ - */ - -#ifndef DOXYGEN -#define TRACE_ENABLED_(mask,lev) ((lev) <= ZB_TRACE_LEVEL && ((mask) & ZB_TRACE_MASK)) -#endif /* DOXYGEN */ - -/** - * @brief Check that trace is enabled for provided level. - * To be used in constructions like: - * @code - * if (TRACE_ENABLED(TRACE_APS3)) - * { - * call_some_complex_trace(); - * } - * @endcode - * @param m - trace level macro. - * @return 1 if enabled, 0 if disabled. - */ -#define TRACE_ENABLED(m) TRACE_ENABLED_(m) - -#ifndef DOXYGEN -zb_uint32_t zb_trace_get_counter(void); -#endif /* DOXYGEN */ - -#ifdef DOXYGEN -/** - Trace file ID used by win_com_dump to identify source file. - - Must be first define in the .c file, just before first include directive. - @par Example - @snippet light_sample/dimmable_light/bulb.c trace_file_id - @par -*/ -#define ZB_TRACE_FILE_ID 12345U -#endif -/** @} */ /* ZB_TRACE_CONFIG */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -#ifdef ZB_INTERRUPT_SAFE_CALLBACKS -/* If HW can detect that we are inside ISR, let's use it and do not trace from ISR. */ -zb_bool_t zb_osif_is_inside_isr(void); -#define ZB_HW_IS_INSIDE_ISR() zb_osif_is_inside_isr() -#else -#define ZB_HW_IS_INSIDE_ISR() 0 -#endif - -#define TRACE_ENTER_INT() g_trace_inside_intr = 1U -#define TRACE_LEAVE_INT() g_trace_inside_intr = 0U -#define ZB_TRACE_INSIDE_INTR() (g_trace_inside_intr || ZB_HW_IS_INSIDE_ISR()) - -#ifndef ZB_TRACE_FROM_INTR -#define ZB_TRACE_INSIDE_INTR_BLOCK() ZB_TRACE_INSIDE_INTR() -#else -#define ZB_TRACE_INSIDE_INTR_BLOCK() 0 -#endif -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** - * @brief A universal way to print raw string as trace message. - */ -void zb_trace_str(const zb_char_t *str); - -#if defined ZB_TRACE_TO_FILE || defined ZB_TRACE_TO_SYSLOG || defined DOXYGEN -/** @cond DOXYGEN_INTERNAL_DOC */ -/** - \par Trace to file means trace to disk file using printf() or its analog. - Tricks to decrease code size by excluding format strings are not used. - */ -void zb_trace_init_file(zb_char_t *name); -void zb_trace_deinit_file(void); -void zb_file_trace_commit(void); -void zb_trace_disable_deinit(void); - -/** - - Initialize trace subsystem - - @param name - trace file name component -*/ -#define TRACE_INIT(name) zb_trace_init_file(name) -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** - Deinitialize trace subsystem -*/ -#define TRACE_DEINIT zb_trace_deinit_file - -/** @cond DOXYGEN_INTERNAL_DOC */ -#define ZB_T0_TRACE(...) __VA_ARGS__ - -#if defined ZB_TRACE_USE_VA_LIST && (defined ZB_BINARY_AND_TEXT_TRACE_MODE || defined ZB_TRACE_TO_SYSLOG || !defined ZB_BINARY_TRACE) -/** - * @brief Print trace message. Option with va_list - */ -void zb_trace_msg_txt_file_vl( - zb_uint_t mask, - zb_uint_t level, - const zb_char_t *format, - const zb_char_t *file_name, - zb_int_t line_number, - zb_int_t args_size, - va_list arglist); -#endif - -#if defined ZB_BINARY_TRACE && !defined ZB_TRACE_TO_SYSLOG - -/** - * @brief Print binary trace message. - */ -void zb_trace_msg_bin_file( - zb_uint_t mask, - zb_uint_t level, -#if defined ZB_BINARY_AND_TEXT_TRACE_MODE - zb_char_t *file_name, -#endif - zb_uint16_t file_id, - zb_int_t line_number, - zb_int_t args_size, ...); - -#ifdef ZB_TRACE_USE_VA_LIST -/** - * @brief Print binary trace message. Option with va_list - */ -void zb_trace_msg_bin_file_vl( - zb_uint_t mask, - zb_uint_t level, - zb_uint16_t file_id, - zb_int_t line_number, - zb_int_t args_size, - va_list arglist); -#endif - -#if defined ZB_BINARY_AND_TEXT_TRACE_MODE -#define ZB_TRACE_MODE_BINARY 0U -#define ZB_TRACE_MODE_TEXT 1U -extern zb_uint8_t g_trace_text_mode; -void zb_trace_set_mode(zb_uint8_t mode); - -/** - * @brief Print trace message. - */ -void zb_trace_msg_txt_file( - zb_uint_t mask, - zb_uint_t level, - const zb_char_t *format, - const zb_char_t *file_name, - zb_uint16_t file_id, - zb_int_t line_number, - zb_int_t args_size, ...); - -#define ZB_T1_TRACE(s, l, fmts, args) \ - if ((zb_int_t)ZB_TRACE_LEVEL>=(zb_int_t)l && \ - ((s) & ZB_TRACE_MASK)) \ - { \ - if (g_trace_text_mode == 0U) \ - { \ - zb_trace_msg_bin_file(s, l, ZB_T0_TRACE args); \ - } \ - else \ - { \ - zb_trace_msg_txt_file(s, l, fmts, ZB_T0_TRACE args); \ - } \ - } -#else -#define ZB_T1_TRACE(s, l, fmts, args) if ((zb_int_t)ZB_TRACE_LEVEL>=(zb_int_t)l && ((s) & ZB_TRACE_MASK)) zb_trace_msg_bin_file(s, l, ZB_T0_TRACE args) -#endif -#else -/** - * @brief Print trace message. - */ -void zb_trace_msg_txt_file( - zb_uint_t mask, - zb_uint_t level, - const zb_char_t *format, - const zb_char_t *file_name, - zb_int_t line_number, - zb_int_t args_size, ...); - -#define ZB_T1_TRACE(s, l, fmts, args) if ((zb_int_t)ZB_TRACE_LEVEL>=(zb_int_t)l && ((s) & ZB_TRACE_MASK)) zb_trace_msg_txt_file(s, l, fmts, ZB_T0_TRACE args) -#endif -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** - * @brief Put trace output. - * @param lm - trace subsystem and level marker. - * @param fmts - printf()-like format string. - * @param args - format string substitution parameters with a size marker. - * - * @par Example - * @snippet light_sample/dimmable_light/bulb.c trace_msg - * @par - */ -#define TRACE_MSG(lm, fmts, args) \ - do { \ - ZB_T1_TRACE(lm, fmts, args); \ - } while (0) - -/** @cond DOXYGEN_INTERNAL_DOC */ -#elif (defined ZB_TRACE_TO_PORT || defined ZB_TRACE_OVER_SIF) -/* - 8051 trace does not use format string in the code to save code space. - -- will modify trace at device only, Linux will work as before -- trace implementation will hex dump all arguments as set of bytes -- external utility will parse dump, divide trace arguments dump into separate arguments and -convert hex-int, unsigned etc. -- utility will get argument strings from the source files (trace macros) and find it -by file:line -- Add one more parameter to the trace macro: sum of the trace argument sizes. -Define readable constants like -#define FMT_D_HD_X 5 -- create script/program to modify existing trace calls -- combine dump parse utility functionality with win_com_dump, so it will produce human-readable trace - - */ - -#if defined ZB_TRACE_OVER_SIF -#define TRACE_INIT(name) zb_osif_sif_init() -#elif ! defined ZB_SERIAL_FOR_TRACE || defined ZB_TRACE_OVER_JTAG -#define TRACE_INIT(name) -#else -#define TRACE_INIT(name) zb_osif_serial_init() -#endif /* defined ZB_TRACE_OVER_SIF */ - -/* No trace deinit */ -#define TRACE_DEINIT() - -#ifndef ZB_BINARY_TRACE -void zb_trace_msg_port( - const zb_char_t ZB_IAR_CODE *file_name, - zb_int_t line_number, - zb_uint8_t args_size, ...); - -#else - -#ifndef ZB_TRACE_FILE_ID -#ifndef ZB_DONT_NEED_TRACE_FILE_ID -#warning ZB_TRACE_FILE_ID undefined! Insert #define ZB_TRACE_FILE_ID NNN before 1-st #include -#endif -#define ZB_TRACE_FILE_ID 0 -#else -ZB_ASSERT_COMPILE_DECL(ZB_TRACE_FILE_ID < ZB_UINT16_MAX); -#endif - -void zb_trace_msg_port( - zb_uint_t mask, - zb_uint_t level, - zb_uint16_t file_id, - zb_uint16_t line_number, - zb_uint_t args_size, ...); - -#ifdef ZB_TRACE_USE_VA_LIST -/* Option with va_list */ -void zb_trace_msg_port_vl( - zb_uint_t mask, - zb_uint_t level, - zb_uint16_t file_id, - zb_uint16_t line_number, - zb_uint_t args_size, - va_list arglist); -#endif - -#endif - -#ifdef ZB_BINARY_TRACE -#define ZB_T0_TRACE(...) __VA_ARGS__ -#define ZB_T1_TRACE(s, l, args) if ((zb_int_t)ZB_TRACE_LEVEL>=(zb_int_t)l && ((s) == (zb_uint_t)-1 || (s) & ZB_TRACE_MASK) && !ZB_TRACE_INSIDE_INTR_BLOCK()) zb_trace_msg_port(s, l, ZB_T0_TRACE args) - -#else -#define ZB_T1_TRACE(s, l, args) \ - if ((zb_int_t)ZB_TRACE_LEVEL>=(zb_int_t)l && ((s) == -1 || ((s) & ZB_TRACE_MASK)) && !ZB_TRACE_INSIDE_INTR_BLOCK()) zb_trace_msg_port args -#endif - - -#define TRACE_MSG(lm, fmt, args) \ - do { \ - ZB_T1_TRACE(lm, args); \ - } while (0) - -#else - -#error Must define either ZB_TRACE_TO_FILE or ZB_TRACE_TO_PORT || ZB_TRACE_OVER_SIF - -#endif /* trace type */ - - -#else /* if trace off */ - -#ifndef KEIL -#define TRACE_MSG(...) ((void)0) -#else -/* Keil does not support vararg macros */ -#define TRACE_MSG(a,b,c) ((void)0) -#endif - -#define TRACE_INIT(name) -#define TRACE_DEINIT(c) - -#define TRACE_ENABLED(m) ZB_FALSE - -#define TRACE_ENTER_INT() -#define TRACE_LEAVE_INT() - -#endif /* trace on/off */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** @cond DSR_TRACE */ -/** - * @addtogroup TRACE_DATA_FORMAT_ADDITIONAL Trace data format for keys - * @{ - */ -#if defined ZB_TRACE_TO_FILE || defined ZB_TRACE_TO_SYSLOG || defined DOXYGEN -/** - Trace format for 64-bit address. - - @snippet light_sample/dimmable_light/bulb.c trace_64_example_variable - @snippet light_sample/dimmable_light/bulb.c trace_64_example -*/ -#define TRACE_FORMAT_64 "%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx" - -/** - Trace format for 128-bit number (key etc). - - @snippet se/energy_service_interface/se_esi_zc.c TRACE_128 -*/ -#define TRACE_FORMAT_128 "%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx" - -/** - Trace format arguments for 64-bit address. - - @snippet light_sample/dimmable_light/bulb.c trace_64_example_variable - @snippet light_sample/dimmable_light/bulb.c trace_64_example -*/ -#define TRACE_ARG_64(a) (zb_uint8_t)((a)[7]),(zb_uint8_t)((a)[6]),(zb_uint8_t)((a)[5]),(zb_uint8_t)((a)[4]),(zb_uint8_t)((a)[3]),(zb_uint8_t)((a)[2]),(zb_uint8_t)((a)[1]),(zb_uint8_t)((a)[0]) - -/** - Trace format arguments for 128-bit number. - - @snippet se/energy_service_interface/se_esi_zc.c TRACE_128 -*/ -#define TRACE_ARG_128(a) (zb_uint8_t)((a)[0]),(zb_uint8_t)((a)[1]),(zb_uint8_t)((a)[2]),(zb_uint8_t)((a)[3]),(zb_uint8_t)((a)[4]),(zb_uint8_t)((a)[5]),(zb_uint8_t)((a)[6]),(zb_uint8_t)((a)[7]),(zb_uint8_t)((a)[8]),(zb_uint8_t)((a)[9]),(zb_uint8_t)((a)[10]),(zb_uint8_t)((a)[11]),(zb_uint8_t)((a)[12]),(zb_uint8_t)((a)[13]),(zb_uint8_t)((a)[14]),(zb_uint8_t)((a)[15]) - - -#else - -/** @brief Trace format for 64-bit address - single argument for 8051. */ -#define TRACE_FORMAT_64 "%A" -#define TRACE_FORMAT_128 "%A:%A" - -/** @endcond */ /* DSR_TRACE */ -/** @cond internals_doc */ -typedef struct zb_addr64_struct_s -{ - zb_64bit_addr_t addr; -} ZB_PACKED_STRUCT zb_addr64_struct_t; - -typedef struct zb_byte128_struct_s -{ - zb_uint8_t d[16]; -} ZB_PACKED_STRUCT zb_byte128_struct_t; - -/* Pass 8-bytes address as structure by value */ -#define TRACE_ARG_64(a) *((zb_addr64_struct_t *)a) -/* Pass 16-bytes key as structure by value */ -#define TRACE_ARG_128(a) *((zb_byte128_struct_t *)a) -/** @endcond */ /* internals_doc */ -/** @cond DSR_TRACE */ - -#endif /* ti file / !to file */ -/** @} */ /* TRACE_DATA_FORMAT_ADDITIONAL */ -/** @endcond */ /* DSR_TRACE */ - - -/** @cond DSR_TRACE */ -/** - * @addtogroup TRACE_GENERAL_MESSAGES - * @{ - */ -/** @brief Error message. */ -#define TRACE_ERROR TRACE_SUBSYSTEM_INFO, 0U -/** @brief Information message level 1. */ -#define TRACE_INFO1 TRACE_SUBSYSTEM_INFO, 1U -/** @brief Information message level 2. */ -#define TRACE_INFO2 TRACE_SUBSYSTEM_INFO, 2U -/** @brief Information message level 3. */ -#define TRACE_INFO3 TRACE_SUBSYSTEM_INFO, 3U - -/** @} */ /* TRACE_GENERAL_MESSAGES */ - -#ifdef ZB_TRACE_LEVEL -#ifndef ZB_TRACE_MASK -#define ZB_TRACE_MASK ((zb_uint_t)-1) -#endif /* if not defined trace_mask */ -#endif /* if defined trace level */ - -/** - * @addtogroup TRACE_DATA_FORMAT - * @{ - */ - -/* - Trace format constants for serial trace -*/ - -/* Keil and sdcc put byte values to the stack as is, but IAR/8051 casts it to 16-bit - * integers, so constant lengths differs */ - -/** - * @brief Calculates trace argument size. - * @param n_h - number of Hs/Cs. - * @param n_d - number of Ds. - * @param n_l - number of Ls. - * @param n_p - number of Ps. - * @param n_a - number of As. - * @hideinitializer - */ -#ifdef KEIL - -/* Keil pass 1-byte to varargs as is, pointer is 3-bytes, short is 2-bytes */ - -#ifndef ZB_BINARY_TRACE -#define TRACE_ARG_SIZE(n_h, n_d, n_l, n_p, n_a) __FILE__,__LINE__, (n_h + n_d*2 + n_l*4 + n_p*3 + n_a*8) -#else -#define TRACE_ARG_SIZE(n_h, n_d, n_l, n_p, n_a) ZB_TRACE_FILE_ID,__LINE__, (n_h + n_d*2 + n_l*4 + n_p*3 + n_a*8) -#endif - -#else /* IAR & GCC - 32-bit */ -/* IAR for Cortex passes 1-byte abd 2-bytes arguments as 4-bytes to vararg functions. - * Pointers are 4-bytes. */ - -#if defined ZB_BINARY_TRACE && !defined ZB_TRACE_TO_SYSLOG -#if defined ZB_BINARY_AND_TEXT_TRACE_MODE - #define TRACE_ARG_SIZE(n_h, n_d, n_l, n_p, n_a) __FILE__,ZB_TRACE_FILE_ID,__LINE__, (n_h*4 + n_d*4 + n_l*4 + n_p*4 + n_a*8) -#else -#define TRACE_ARG_SIZE(n_h, n_d, n_l, n_p, n_a) ZB_TRACE_FILE_ID,__LINE__, (n_h*4 + n_d*4 + n_l*4 + n_p*4 + n_a*8) -#endif -#else -#define TRACE_ARG_SIZE(n_h, n_d, n_l, n_p, n_a) __FILE__,__LINE__, (n_h*4 + n_d*4 + n_l*4 + n_p*4 + n_a*8) -#endif - -#endif - -#define FMT__0 TRACE_ARG_SIZE(0,0,0,0,0) -#define FMT__A TRACE_ARG_SIZE(0,0,0,0,1) -#define FMT__A_A TRACE_ARG_SIZE(0,0,0,0,2) -#define FMT__A_A_A_A TRACE_ARG_SIZE(0,0,0,0,4) -#define FMT__A_D_A_P TRACE_ARG_SIZE(0,1,0,1,2) -#define FMT__A_D_D TRACE_ARG_SIZE(0,2,0,0,1) -#define FMT__A_D_D_P_H TRACE_ARG_SIZE(1,2,0,1,1) -#define FMT__A_D_H TRACE_ARG_SIZE(1,1,0,0,1) -#define FMT__A_D_H_H TRACE_ARG_SIZE(2,1,0,0,1) -#define FMT__A_D_P_H_H_H TRACE_ARG_SIZE(3,1,0,1,1) -#define FMT__A_H TRACE_ARG_SIZE(1,0,0,0,1) -#define FMT__A_H_H TRACE_ARG_SIZE(2,0,0,0,1) -#define FMT__A_H_H_H TRACE_ARG_SIZE(3,0,0,0,1) -#define FMT__A_D_H_H_H TRACE_ARG_SIZE(3,1,0,0,1) -#define FMT__A_P TRACE_ARG_SIZE(0,0,0,1,1) -#define FMT__AA TRACE_ARG_SIZE(0,0,0,0,2) -#define FMT__C TRACE_ARG_SIZE(1,0,0,0,0) -#define FMT__C_C TRACE_ARG_SIZE(2,0,0,0,0) -#define FMT__C_C_C TRACE_ARG_SIZE(3,0,0,0,0) -#define FMT__C_C_C_C TRACE_ARG_SIZE(4,0,0,0,0) -#define FMT__C_C_C_C_C TRACE_ARG_SIZE(5,0,0,0,0) -#define FMT__C_C_H_H TRACE_ARG_SIZE(4,0,0,0,0) -#define FMT__C_H TRACE_ARG_SIZE(2,0,0,0,0) -#define FMT__D TRACE_ARG_SIZE(0,1,0,0,0) -#define FMT__D_A TRACE_ARG_SIZE(0,1,0,0,1) -#define FMT__D_A_A_H TRACE_ARG_SIZE(1,1,0,0,2) -#define FMT__D_A_D_D_D_D_D_D_D_D TRACE_ARG_SIZE(0,9,0,0,1) -#define FMT__D_A_D_P_H_H_H TRACE_ARG_SIZE(3,2,0,1,1) -#define FMT__D_A_H_H TRACE_ARG_SIZE(2,1,0,0,1) -#define FMT__D_A_P TRACE_ARG_SIZE(0,1,0,1,1) -#define FMT__D_C TRACE_ARG_SIZE(1,1,0,0,0) -#define FMT__D_D TRACE_ARG_SIZE(0,2,0,0,0) -#define FMT__D_D_A TRACE_ARG_SIZE(0,2,0,0,1) -#define FMT__D_D_A_A TRACE_ARG_SIZE(0,2,0,0,2) -#define FMT__D_D_A_D TRACE_ARG_SIZE(0,3,0,0,1) -#define FMT__D_D_A_D_D_D_D TRACE_ARG_SIZE(0,6,0,0,1) -#define FMT__D_D_D TRACE_ARG_SIZE(0,3,0,0,0) -#define FMT__D_D_D_C TRACE_ARG_SIZE(1,3,0,0,0) -#define FMT__D_D_D_D TRACE_ARG_SIZE(0,4,0,0,0) -#define FMT__D_D_D_D_D TRACE_ARG_SIZE(0,5,0,0,0) -#define FMT__D_D_D_D_D_D TRACE_ARG_SIZE(0,6,0,0,0) -#define FMT__D_D_D_D_D_D_D TRACE_ARG_SIZE(0,7,0,0,0) -#define FMT__D_D_D_D_D_D_D_D TRACE_ARG_SIZE(0,8,0,0,0) -#define FMT__D_D_D_D_D_D_D_D_D_D_D TRACE_ARG_SIZE(0,11,0,0,0) -#define FMT__D_D_D_D_D_D_D_D_D_D_D_D_D_D TRACE_ARG_SIZE(0,14,0,0,0) -#define FMT__D_D_D_D_D_D_D_D_D_D_D_D_D_D_D_D_D TRACE_ARG_SIZE(0,17,0,0,0) -#define FMT__D_D_D_D_D_D_P TRACE_ARG_SIZE(0,6,0,1,0) -#define FMT__D_D_D_D_H TRACE_ARG_SIZE(1,4,0,0,0) -#define FMT__D_D_D_H TRACE_ARG_SIZE(1,3,0,0,0) -#define FMT__D_D_D_H_H TRACE_ARG_SIZE(2,3,0,0,0) -#define FMT__D_D_D_L TRACE_ARG_SIZE(0,3,1,0,0) -#define FMT__D_D_D_L_L TRACE_ARG_SIZE(0,3,2,0,0) -#define FMT__D_D_D_P TRACE_ARG_SIZE(0,3,0,1,0) -#define FMT__D_D_H TRACE_ARG_SIZE(1,2,0,0,0) -#define FMT__D_D_H_D_H TRACE_ARG_SIZE(2,3,0,0,0) -#define FMT__D_D_H_H TRACE_ARG_SIZE(2,2,0,0,0) -#define FMT__D_D_H_P_D TRACE_ARG_SIZE(1,3,0,1,0) -#define FMT__D_D_L TRACE_ARG_SIZE(0,2,1,0,0) -#define FMT__D_D_L_P TRACE_ARG_SIZE(0,2,1,1,0) -#define FMT__D_D_P TRACE_ARG_SIZE(0,2,0,1,0) -#define FMT__D_D_P_D TRACE_ARG_SIZE(0,3,0,1,0) -#define FMT__D_P_P_D TRACE_ARG_SIZE(0,2,0,2,0) -#define FMT__D_P_P_P TRACE_ARG_SIZE(0,1,0,3,0) -#define FMT__D_D_P_D_D TRACE_ARG_SIZE(0,4,0,1,0) -#define FMT__D_D_P_D_L TRACE_ARG_SIZE(0,3,1,1,0) -#define FMT__D_D_P_H TRACE_ARG_SIZE(1,2,0,1,0) -#define FMT__D_D_P_H_H_H TRACE_ARG_SIZE(3,2,0,1,0) -#define FMT__D_D_P_P_P TRACE_ARG_SIZE(0,2,0,3,0) -#define FMT__D_H TRACE_ARG_SIZE(1,1,0,0,0) -#define FMT__D_H_D TRACE_ARG_SIZE(1,2,0,0,0) -#define FMT__D_H_D_D TRACE_ARG_SIZE(1,3,0,0,0) -#define FMT__D_H_D_D_H TRACE_ARG_SIZE(2,3,0,0,0) -#define FMT__D_H_D_D_H_D TRACE_ARG_SIZE(2,4,0,0,0) -#define FMT__D_H_D_H TRACE_ARG_SIZE(2,2,0,0,0) -#define FMT__D_H_D_H_H TRACE_ARG_SIZE(3,2,0,0,0) -#define FMT__D_H_D_P TRACE_ARG_SIZE(1,2,0,1,0) -#define FMT__D_H_D_P_D TRACE_ARG_SIZE(1,3,0,1,0) -#define FMT__D_H_H TRACE_ARG_SIZE(2,1,0,0,0) -#define FMT__D_H_H_D TRACE_ARG_SIZE(2,2,0,0,0) -#define FMT__D_H_H_D_D_D_D TRACE_ARG_SIZE(2,5,0,0,0) -#define FMT__D_H_H_H TRACE_ARG_SIZE(3,1,0,0,0) -#define FMT__D_H_H_H_H TRACE_ARG_SIZE(4,1,0,0,0) -#define FMT__D_H_H_H_H_H TRACE_ARG_SIZE(5,1,0,0,0) -#define FMT__D_H_H_H_H_H_H_D_D_D_D TRACE_ARG_SIZE(6,5,0,0,0) -#define FMT__D_H_L TRACE_ARG_SIZE(1,1,1,0,0) -#define FMT__D_H_P TRACE_ARG_SIZE(1,1,0,1,0) -#define FMT__D_L TRACE_ARG_SIZE(0,1,1,0,0) -#define FMT__D_L_L TRACE_ARG_SIZE(0,1,2,0,0) -#define FMT__D_L_L_D TRACE_ARG_SIZE(0,2,2,0,0) -#define FMT__D_L_L_H TRACE_ARG_SIZE(1,1,2,0,0) -#define FMT__D_L_L_L TRACE_ARG_SIZE(0,1,3,0,0) -#define FMT__D_P TRACE_ARG_SIZE(0,1,0,1,0) -#define FMT__D_P_D TRACE_ARG_SIZE(0,2,0,1,0) -#define FMT__D_P_D_D TRACE_ARG_SIZE(0,3,0,1,0) -#define FMT__D_P_H_H_D_D TRACE_ARG_SIZE(2,3,0,1,0) -#define FMT__D_P_H_H_D_H_H TRACE_ARG_SIZE(4,2,0,1,0) -#define FMT__D_P_H_H_H_H TRACE_ARG_SIZE(4,1,0,1,0) -#define FMT__D_P_H_H_H_H_H TRACE_ARG_SIZE(5,1,0,1,0) -#define FMT__D_P_H_H_H_H_H_H TRACE_ARG_SIZE(6,1,0,1,0) -#define FMT__D_P_H_P TRACE_ARG_SIZE(1,1,0,1,0) -#define FMT__D_P_P TRACE_ARG_SIZE(0,1,0,2,0) -#define FMT__D_P_P_D_D TRACE_ARG_SIZE(0,3,0,2,0) -#define FMT__D_P_P_D_D_P TRACE_ARG_SIZE(0,3,0,3,0) -#define FMT__D_P_P_D_D_H_H TRACE_ARG_SIZE(2,3,0,2,0) -#define FMT__D_P_P_H TRACE_ARG_SIZE(1,1,0,2,0) -#define FMT__H TRACE_ARG_SIZE(1,0,0,0,0) -#define FMT__H_A TRACE_ARG_SIZE(1,0,0,0,1) -#define FMT__H_A_A TRACE_ARG_SIZE(1,0,0,0,2) -#define FMT__H_A_A_H_H TRACE_ARG_SIZE(3,0,0,0,2) -#define FMT__H_A_H TRACE_ARG_SIZE(2,0,0,0,1) -#define FMT__H_A_H_H_H TRACE_ARG_SIZE(4,0,0,0,1) -#define FMT__H_A_H_H_H_H_H_H_H_H TRACE_ARG_SIZE(9,0,0,0,1) -#define FMT__H_C_D_C TRACE_ARG_SIZE(3,1,0,0,0) -#define FMT__H_C_H_C TRACE_ARG_SIZE(4,0,0,0,0) -#define FMT__H_D TRACE_ARG_SIZE(1,1,0,0,0) -#define FMT__H_D_L TRACE_ARG_SIZE(1,1,1,0,0) -#define FMT__H_D_A TRACE_ARG_SIZE(1,1,0,0,1) -#define FMT__H_D_A_H_D TRACE_ARG_SIZE(2,2,0,0,1) -#define FMT__H_D_A_H_H TRACE_ARG_SIZE(3,1,0,0,1) -#define FMT__H_D_A_H_H_H_H TRACE_ARG_SIZE(5,1,0,0,1) -#define FMT__H_D_D TRACE_ARG_SIZE(1,2,0,0,0) -#define FMT__H_D_D_D TRACE_ARG_SIZE(1,3,0,0,0) -#define FMT__H_D_D_D_D TRACE_ARG_SIZE(1,4,0,0,0) -#define FMT__H_D_D_D_D_H TRACE_ARG_SIZE(2,4,0,0,0) -#define FMT__H_D_D_D_H_H_D TRACE_ARG_SIZE(3,4,0,0,0) -#define FMT__H_D_D_H TRACE_ARG_SIZE(2,2,0,0,0) -#define FMT__H_D_D_H_D TRACE_ARG_SIZE(2,3,0,0,0) -#define FMT__H_D_D_H_D_H TRACE_ARG_SIZE(3,3,0,0,0) -#define FMT__H_D_D_H_H TRACE_ARG_SIZE(3,2,0,0,0) -#define FMT__H_D_D_H_H_H TRACE_ARG_SIZE(4,2,0,0,0) -#define FMT__H_D_D_H_H_H_H TRACE_ARG_SIZE(5,2,0,0,0) -#define FMT__H_D_D_H_P TRACE_ARG_SIZE(2,2,0,1,0) -#define FMT__H_D_D_P TRACE_ARG_SIZE(1,2,0,1,0) -#define FMT__H_D_H TRACE_ARG_SIZE(2,1,0,0,0) -#define FMT__H_D_H_D TRACE_ARG_SIZE(2,2,0,0,0) -#define FMT__H_D_H_D_D TRACE_ARG_SIZE(2,3,0,0,0) -#define FMT__H_D_H_D_H TRACE_ARG_SIZE(3,2,0,0,0) -#define FMT__H_D_H_D_H_H TRACE_ARG_SIZE(4,2,0,0,0) -#define FMT__H_D_H_A TRACE_ARG_SIZE(2,1,0,0,1) -#define FMT__H_D_H_H TRACE_ARG_SIZE(3,1,0,0,0) -#define FMT__H_D_H_P_D TRACE_ARG_SIZE(2,2,0,1,0) -#define FMT__H_D_H_H_H TRACE_ARG_SIZE(4,1,0,0,0) -#define FMT__H_D_H_H_H_H TRACE_ARG_SIZE(5,1,0,0,0) -#define FMT__H_D_H_H_H_H_H_H TRACE_ARG_SIZE(7,1,0,0,0) -#define FMT__H_D_P_H_H_H_H_H TRACE_ARG_SIZE(6,1,0,1,0) -#define FMT__H_D_P_H_H_H_H_H_H_H TRACE_ARG_SIZE(8,1,0,1,0) -#define FMT__H_D_P_P_P TRACE_ARG_SIZE(1,1,0,3,0) -#define FMT__H_H TRACE_ARG_SIZE(2,0,0,0,0) -#define FMT__H_H_A TRACE_ARG_SIZE(2,0,0,0,1) -#define FMT__H_H_A_A TRACE_ARG_SIZE(2,0,0,0,2) -#define FMT__H_H_D TRACE_ARG_SIZE(2,1,0,0,0) -#define FMT__H_H_D_D TRACE_ARG_SIZE(2,2,0,0,0) -#define FMT__H_H_D_D_D TRACE_ARG_SIZE(2,3,0,0,0) -#define FMT__H_H_D_H TRACE_ARG_SIZE(3,1,0,0,0) -#define FMT__H_H_D_H_H_H_H_H_H_H_H TRACE_ARG_SIZE(10,1,0,0,0) -#define FMT__D_H_H_H_H_H_H_H_H TRACE_ARG_SIZE(8,1,0,0,0) -#define FMT__H_H_D_H_P TRACE_ARG_SIZE(3,1,0,1,0) -#define FMT__H_D_P TRACE_ARG_SIZE(1,1,0,1,0) -#define FMT__H_H_D_P TRACE_ARG_SIZE(2,1,0,1,0) -#define FMT__H_H_H TRACE_ARG_SIZE(3,0,0,0,0) -#define FMT__H_H_H_D TRACE_ARG_SIZE(3,1,0,0,0) -#define FMT__H_H_H_D_D TRACE_ARG_SIZE(3,2,0,0,0) -#define FMT__H_H_H_D_D_H_A_H_A TRACE_ARG_SIZE(5,2,0,0,2) -#define FMT__H_D_H_H_H_D_D_H_A_H_A TRACE_ARG_SIZE(6,3,0,0,2) -#define FMT__D_H_H_H_D_D_H_A_H_A TRACE_ARG_SIZE(5,3,0,0,2) -#define FMT__H_H_H_D_D_D TRACE_ARG_SIZE(3,3,0,0,0) -#define FMT__H_H_H_D_H TRACE_ARG_SIZE(4,1,0,0,0) -#define FMT__H_H_H_D_H_P TRACE_ARG_SIZE(4,1,0,1,0) -#define FMT__H_H_H_H TRACE_ARG_SIZE(4,0,0,0,0) -#define FMT__H_H_H_H_D TRACE_ARG_SIZE(4,1,0,0,0) -#define FMT__H_H_H_H_D_H TRACE_ARG_SIZE(5,1,0,0,0) -#define FMT__H_H_H_H_H TRACE_ARG_SIZE(5,0,0,0,0) -#define FMT__H_H_H_H_H_H TRACE_ARG_SIZE(6,0,0,0,0) -#define FMT__H_H_H_H_H_H_H TRACE_ARG_SIZE(7,0,0,0,0) -#define FMT__H_H_H_H_H_H_H_H TRACE_ARG_SIZE(8,0,0,0,0) -#define FMT__H_H_H_H_H_H_H_H_H TRACE_ARG_SIZE(9,0,0,0,0) -#define FMT__H_H_H_H_H_H_H_H_P_P TRACE_ARG_SIZE(8,0,0,2,0) -#define FMT__H_H_H_H_H_H_P_P TRACE_ARG_SIZE(6,0,0,2,0) -#define FMT__H_H_H_H_H_H_P_P_P_P TRACE_ARG_SIZE(6,2,0,4,0) -#define FMT__H_H_H_H_P_P_P TRACE_ARG_SIZE(4,0,0,3,0) -#define FMT__H_H_H_P TRACE_ARG_SIZE(3,0,0,1,0) -#define FMT__H_D_H_P TRACE_ARG_SIZE(2,1,0,1,0) -#define FMT__H_H_L TRACE_ARG_SIZE(2,0,1,0,0) -#define FMT__H_H_L_H TRACE_ARG_SIZE(3,0,1,0,0) -#define FMT__H_H_H_L TRACE_ARG_SIZE(3,0,1,0,0) -#define FMT__H_H_H_H_L TRACE_ARG_SIZE(4,0,1,0,0) -#define FMT__H_H_L_H_P TRACE_ARG_SIZE(3,0,1,4,0) -#define FMT__H_H_P TRACE_ARG_SIZE(2,0,0,1,0) -#define FMT__H_H_P_D TRACE_ARG_SIZE(2,1,0,1,0) -#define FMT__H_H_P_P_P TRACE_ARG_SIZE(2,0,0,3,0) -#define FMT__H_L TRACE_ARG_SIZE(1,0,1,0,0) -#define FMT__H_L_A TRACE_ARG_SIZE(1,0,1,0,1) -#define FMT__H_L_D TRACE_ARG_SIZE(1,1,1,0,0) -#define FMT__H_L_L TRACE_ARG_SIZE(1,0,2,0,0) -#define FMT__H_L_H TRACE_ARG_SIZE(2,0,1,0,0) -#define FMT__H_L_D_D TRACE_ARG_SIZE(1,2,1,0,0) -#define FMT__H_L_D_D_D TRACE_ARG_SIZE(1,3,1,0,0) -#define FMT__H_L_D_P TRACE_ARG_SIZE(1,1,1,1,0) -#define FMT__H_L_H_D TRACE_ARG_SIZE(2,1,1,0,0) -#define FMT__H_L_H_D_D TRACE_ARG_SIZE(2,2,1,0,0) -#define FMT__H_L_H_H_H_H_H_H_H_H_H_H_H_H TRACE_ARG_SIZE(13,0,1,0,0) -#define FMT__H_D_H_H_H_H_H_H_H_H_H_H_H_H TRACE_ARG_SIZE(13,1,0,0,0) -#define FMT__H_L_H_H_P TRACE_ARG_SIZE(3,0,1,4,0) -#define FMT__H_L_L_H_A TRACE_ARG_SIZE(2,0,2,0,1) -#define FMT__H_L_D_D_H TRACE_ARG_SIZE(2,2,1,0,0) -#define FMT__H_P_D_P TRACE_ARG_SIZE(1,1,0,2,0) -#define FMT__H_P_P_D_P TRACE_ARG_SIZE(1,1,0,3,0) -#define FMT__H_P_D_D_H TRACE_ARG_SIZE(2,2,0,1,0) -#define FMT__H_P TRACE_ARG_SIZE(1,0,0,1,0) -#define FMT__H_P_D TRACE_ARG_SIZE(1,1,0,1,0) -#define FMT__H_P_D_D_H_P TRACE_ARG_SIZE(2,2,0,2,0) -#define FMT__H_P_D_D_P TRACE_ARG_SIZE(1,2,0,2,0) -#define FMT__H_P_H TRACE_ARG_SIZE(2,0,0,1,0) -#define FMT__H_P_H_D TRACE_ARG_SIZE(2,1,0,1,0) -#define FMT__H_P_H_D_H TRACE_ARG_SIZE(3,1,0,1,0) -#define FMT__H_P_H_H TRACE_ARG_SIZE(3,0,0,1,0) -#define FMT__H_P_H_H_H TRACE_ARG_SIZE(4,0,0,1,0) -#define FMT__H_P_H_H_D TRACE_ARG_SIZE(3,1,0,1,0) -#define FMT__H_P_H_H_H_H TRACE_ARG_SIZE(5,0,0,1,0) -#define FMT__H_P_H_P TRACE_ARG_SIZE(2,0,0,2,0) -#define FMT__H_P_H_P_H TRACE_ARG_SIZE(3,0,0,2,0) -#define FMT__H_P_H_P_H_H TRACE_ARG_SIZE(4,0,0,2,0) -#define FMT__H_P_H_P_H_H_P TRACE_ARG_SIZE(4,0,0,3,0) -#define FMT__H_P_L_H TRACE_ARG_SIZE(2,0,1,1,0) -#define FMT__H_P_P_P TRACE_ARG_SIZE(1,0,0,3,0) -#define FMT__H_P_P_P_D_P_P TRACE_ARG_SIZE(1,1,0,5,0) -#define FMT__H_P_P_P_P TRACE_ARG_SIZE(1,0,0,4,0) -#define FMT__H_P_P_P_P_P TRACE_ARG_SIZE(1,0,0,5,0) -#define FMT__L TRACE_ARG_SIZE(0,0,1,0,0) -#define FMT__L_A TRACE_ARG_SIZE(0,0,1,0,1) -#define FMT__L_D TRACE_ARG_SIZE(0,1,1,0,0) -#define FMT__L_D_D TRACE_ARG_SIZE(0,2,1,0,0) -#define FMT__L_D_D_D TRACE_ARG_SIZE(0,3,1,0,0) -#define FMT__L_H TRACE_ARG_SIZE(1,0,1,0,0) -#define FMT__L_H_H TRACE_ARG_SIZE(2,0,1,0,0) -#define FMT__L_H_H_H TRACE_ARG_SIZE(3,0,1,0,0) -#define FMT__L_L TRACE_ARG_SIZE(0,0,2,0,0) -#define FMT__L_L_L TRACE_ARG_SIZE(0,0,3,0,0) -#define FMT__L_L_L_H TRACE_ARG_SIZE(1,0,3,0,0) -#define FMT__L_L_A_A TRACE_ARG_SIZE(0,0,2,0,2) -#define FMT__L_D_A TRACE_ARG_SIZE(0,1,1,0,1) -#define FMT__L_D_A_A TRACE_ARG_SIZE(0,1,1,0,2) -#define FMT__L_L_A_A_H_L_H_H_H_H_H_H_H_H_H_H_H_H TRACE_ARG_SIZE(13,0,3,0,2) -#define FMT__L_L_D_D TRACE_ARG_SIZE(0,2,2,0,0) -#define FMT__L_L_H_L_H_H_H_H_H_H_H_H_H_H_H_H TRACE_ARG_SIZE(13,0,3,0,0) -#define FMT__L_L_L_D TRACE_ARG_SIZE(0,1,3,0,0) -#define FMT__L_L_L_D_L_D TRACE_ARG_SIZE(0,2,4,0,0) -#define FMT__L_L_L_L TRACE_ARG_SIZE(0,0,4,0,0) -#define FMT__L_L_L_L_L TRACE_ARG_SIZE(0,0,5,0,0) -#define FMT__L_L_L_L_L_L TRACE_ARG_SIZE(0,0,6,0,0) -#define FMT__L_L_L_L_L_L_L TRACE_ARG_SIZE(0,0,7,0,0) -#define FMT__L_P TRACE_ARG_SIZE(0,0,1,1,0) -#define FMT__L_P_L TRACE_ARG_SIZE(0,0,2,1,0) -#define FMT__P TRACE_ARG_SIZE(0,0,0,1,0) -#define FMT__P_A TRACE_ARG_SIZE(0,0,0,1,1) -#define FMT__P_D TRACE_ARG_SIZE(0,1,0,1,0) -#define FMT__P_D_D TRACE_ARG_SIZE(0,2,0,1,0) -#define FMT__P_D_D_D TRACE_ARG_SIZE(0,3,0,1,0) -#define FMT__P_D_D_D_D TRACE_ARG_SIZE(0,4,0,1,0) -#define FMT__P_D_D_H_D TRACE_ARG_SIZE(1,3,0,1,0) -#define FMT__P_D_D_D_D_D TRACE_ARG_SIZE(0,5,0,1,0) -#define FMT__P_D_D_D_D_D_D TRACE_ARG_SIZE(0,6,0,1,0) -#define FMT__P_D_D_D_D_D_D_D TRACE_ARG_SIZE(0,7,0,1,0) -#define FMT__P_D_D_D_H_D TRACE_ARG_SIZE(1,4,0,1,0) -#define FMT__P_D_D_H TRACE_ARG_SIZE(1,2,0,1,0) -#define FMT__P_D_D_L_L_P TRACE_ARG_SIZE(0,2,2,2,0) -#define FMT__P_D_H TRACE_ARG_SIZE(1,1,0,1,0) -#define FMT__P_D_P TRACE_ARG_SIZE(0,1,0,2,0) -#define FMT__P_D_L TRACE_ARG_SIZE(0,1,1,1,0) -#define FMT__P_D_P_D TRACE_ARG_SIZE(0,2,0,2,0) -#define FMT__P_H TRACE_ARG_SIZE(1,0,0,1,0) -#define FMT__P_H_D TRACE_ARG_SIZE(1,1,0,1,0) -#define FMT__P_H_D_D TRACE_ARG_SIZE(1,2,0,1,0) -#define FMT__P_H_D_D_H TRACE_ARG_SIZE(2,2,0,1,0) -#define FMT__P_H_D_P TRACE_ARG_SIZE(1,1,0,2,0) -#define FMT__P_H_D_H TRACE_ARG_SIZE(2,1,0,1,0) -#define FMT__P_H_D_L TRACE_ARG_SIZE(1,1,1,1,0) -#define FMT__P_H_H TRACE_ARG_SIZE(2,0,0,1,0) -#define FMT__P_H_H_D_D TRACE_ARG_SIZE(2,2,0,1,0) -#define FMT__P_H_H_H TRACE_ARG_SIZE(3,0,0,1,0) -#define FMT__P_H_H_H_A TRACE_ARG_SIZE(3,0,0,1,1) -#define FMT__P_H_H_H_D TRACE_ARG_SIZE(3,1,0,1,0) -#define FMT__P_H_H_H_H TRACE_ARG_SIZE(4,0,0,1,0) -#define FMT__P_H_H_H_H_D TRACE_ARG_SIZE(4,1,0,1,0) -#define FMT__P_H_H_H_H_H_H TRACE_ARG_SIZE(6,0,0,1,0) -#define FMT__P_H_H_H_H_H_H_H TRACE_ARG_SIZE(7,0,0,1,0) -#define FMT__P_H_H_H_L TRACE_ARG_SIZE(3,0,1,1,0) -#define FMT__P_H_H_L TRACE_ARG_SIZE(2,0,1,1,0) -#define FMT__P_H_L TRACE_ARG_SIZE(1,0,1,1,0) -#define FMT__P_H_L_H_L TRACE_ARG_SIZE(2,0,2,1,0) -#define FMT__P_H_P TRACE_ARG_SIZE(1,0,0,2,0) -#define FMT__P_H_P_D TRACE_ARG_SIZE(1,1,0,2,0) -#define FMT__P_H_P_D_D TRACE_ARG_SIZE(1,2,0,2,0) -#define FMT__P_H_P_D_D_D TRACE_ARG_SIZE(1,3,0,2,0) -#define FMT__P_H_P_H TRACE_ARG_SIZE(2,0,0,2,0) -#define FMT__P_H_P_H_L TRACE_ARG_SIZE(2,0,1,2,0) -#define FMT__P_H_P_P TRACE_ARG_SIZE(1,0,0,3,0) -#define FMT__P_H_P_L TRACE_ARG_SIZE(1,0,1,2,0) -#define FMT__P_H_P_P_H TRACE_ARG_SIZE(2,0,0,3,0) -#define FMT__P_H_P_P_P TRACE_ARG_SIZE(1,0,0,4,0) -#define FMT__P_L TRACE_ARG_SIZE(0,0,1,1,0) -#define FMT__P_L_D TRACE_ARG_SIZE(0,1,1,1,0) -#define FMT__P_L_H TRACE_ARG_SIZE(1,0,1,1,0) -#define FMT__P_L_P TRACE_ARG_SIZE(0,0,1,2,0) -#define FMT__P_L_L_D TRACE_ARG_SIZE(0,1,2,1,0) -#define FMT__P_L_L_L TRACE_ARG_SIZE(0,0,3,1,0) -#define FMT__P_L_P_L TRACE_ARG_SIZE(0,0,2,2,0) -#define FMT__P_L_P_P_P TRACE_ARG_SIZE(0,0,1,4,0) -#define FMT__P_P TRACE_ARG_SIZE(0,0,0,2,0) -#define FMT__P_P_L TRACE_ARG_SIZE(0,0,1,2,0) -#define FMT__P_P_D TRACE_ARG_SIZE(0,1,0,2,0) -#define FMT__P_P_D_D TRACE_ARG_SIZE(0,2,0,2,0) -#define FMT__P_P_D_D_H TRACE_ARG_SIZE(1,2,0,2,0) -#define FMT__P_P_D_D_P TRACE_ARG_SIZE(0,2,0,3,0) -#define FMT__P_P_D_H_H TRACE_ARG_SIZE(2,1,0,2,0) -#define FMT__P_P_D_H_P TRACE_ARG_SIZE(1,1,0,3,0) -#define FMT__P_P_D_P TRACE_ARG_SIZE(0,1,0,3,0) -#define FMT__P_P_D_P_D TRACE_ARG_SIZE(0,2,0,3,0) -#define FMT__P_P_D_P_H TRACE_ARG_SIZE(1,1,0,3,0) -#define FMT__P_P_H TRACE_ARG_SIZE(1,0,0,2,0) -#define FMT__P_P_H_D TRACE_ARG_SIZE(1,1,0,2,0) -#define FMT__P_P_H_H TRACE_ARG_SIZE(2,0,0,2,0) -#define FMT__P_P_H_H_P TRACE_ARG_SIZE(2,0,0,3,0) -#define FMT__P_P_H_H_H TRACE_ARG_SIZE(3,0,0,2,0) -#define FMT__P_P_H_P TRACE_ARG_SIZE(1,0,0,3,0) -#define FMT__P_P_H_P_D_P TRACE_ARG_SIZE(1,2,0,4,0) -#define FMT__P_P_H_P_H TRACE_ARG_SIZE(2,0,0,3,0) -#define FMT__P_P_L_D TRACE_ARG_SIZE(0,1,1,2,0) -#define FMT__P_P_L_L_H TRACE_ARG_SIZE(1,0,2,2,0) -#define FMT__P_P_P TRACE_ARG_SIZE(0,0,0,3,0) -#define FMT__P_P_P_H TRACE_ARG_SIZE(1,0,0,3,0) -#define FMT__P_P_P_D TRACE_ARG_SIZE(0,1,0,3,0) -#define FMT__P_P_P_D_P TRACE_ARG_SIZE(0,1,0,4,0) -#define FMT__P_P_P_H_H TRACE_ARG_SIZE(2,0,0,3,0) -#define FMT__P_P_P_P TRACE_ARG_SIZE(0,0,0,4,0) -#define FMT__P_P_P_P_P TRACE_ARG_SIZE(0,0,0,5,0) -#define FMT__D_D_L_D TRACE_ARG_SIZE(0,3,1,0,0) -#define FMT__D_D_L_L TRACE_ARG_SIZE(0,2,2,0,0) -#define FMT__D_D_D_D_L_L TRACE_ARG_SIZE(0,4,2,0,0) -#define FMT__L_D_D_D_D_L_L TRACE_ARG_SIZE(0,4,3,0,0) -#define FMT__L_L_L_D_D TRACE_ARG_SIZE(0,2,3,0,0) -#define FMT__D_H_P_H TRACE_ARG_SIZE(2,1,0,1,0) -#define FMT__H_D_H_H_D TRACE_ARG_SIZE(3,2,0,0,0) -#define FMT__D_A_B_H_H TRACE_ARG_SIZE(2,1,0,0,3) -#define FMT__A_A_P TRACE_ARG_SIZE(0,0,0,1,2) -#define FMT__B TRACE_ARG_SIZE(0,0,0,0,2) -#define FMT__B_H_B TRACE_ARG_SIZE(1,0,0,0,4) -#define FMT__A_D TRACE_ARG_SIZE(0,1,0,0,1) -#define FMT__L_D_P_H TRACE_ARG_SIZE(1,1,1,1,0) -#define FMT__D_D_H_H_H TRACE_ARG_SIZE(3,2,0,0,0) -#define FMT__P_B_D_D TRACE_ARG_SIZE(0,2,0,1,2) -#define FMT__H_B_H_B TRACE_ARG_SIZE(2,0,0,0,4) -#define FMT__B_A TRACE_ARG_SIZE(0,0,0,0,3) -#define FMT__D_H_A TRACE_ARG_SIZE(1,1,0,0,1) -#define FMT__D_H_A_H TRACE_ARG_SIZE(2,1,0,0,1) -#define FMT__D_A_H TRACE_ARG_SIZE(1,1,0,0,1) -#define FMT__D_D_D_A_B TRACE_ARG_SIZE(0,3,0,0,3) -#define FMT__D_B_A TRACE_ARG_SIZE(0,1,0,0,3) -#define FMT__H_B_A TRACE_ARG_SIZE(1,0,0,0,3) -#define FMT__D_D_H_H_D_D_D_D TRACE_ARG_SIZE(2,6,0,0,0) -#define FMT__P_D_H_H_H_A TRACE_ARG_SIZE(3,1,0,1,1) -#define FMT__H_A_H_H_H_H_H TRACE_ARG_SIZE(6,0,0,0,1) -#define FMT__H_D_A_H TRACE_ARG_SIZE(2,1,0,0,1) -#define FMT__D_A_H_D TRACE_ARG_SIZE(1,2,0,0,1) -#define FMT__P_H_H_H_H_H_H_H_H TRACE_ARG_SIZE(8,0,0,1,0) -#define FMT__D_D_H_L_H_H TRACE_ARG_SIZE(3,2,1,0,0) -#define FMT__D_H_L_H_H TRACE_ARG_SIZE(3,1,1,0,0) -#define FMT__D_H_L_L_D_D_D TRACE_ARG_SIZE(1,4,2,0,0) -#define FMT__H_D_H_L_H_H TRACE_ARG_SIZE(4,1,1,0,0) -#define FMT__D_H_D_H_L_H_H TRACE_ARG_SIZE(4,2,1,0,0) -#define FMT__D_D_H_H_H_D_D_D_D TRACE_ARG_SIZE(3,6,0,0,0) -#define FMT__H_D_H_L TRACE_ARG_SIZE(2,1,1,0,0) -#define FMT__H_H_L_L TRACE_ARG_SIZE(2,0,2,0,0) -#define FMT__D_D_H_H_D_H_D_D_D_D TRACE_ARG_SIZE(3,7,0,0,0) -#define FMT__D_A_D_A TRACE_ARG_SIZE(0,2,0,0,2) -#define FMT__H_H_H_L_H_H_H TRACE_ARG_SIZE(6,0,1,0,0) -#define FMT__H_D_D_D_D_D TRACE_ARG_SIZE(1,5,0,0,0) -#define FMT__P_P_D_D_L TRACE_ARG_SIZE(0,2,1,2,0) -#define FMT__P_L_L TRACE_ARG_SIZE(0,0,2,1,0) -#define FMT__P_P_L_L TRACE_ARG_SIZE(0,0,2,2,0) -#define FMT__D_D_H_D_D_H TRACE_ARG_SIZE(2,4,0,0,0) -#define FMT__NC(N) TRACE_ARG_SIZE(N,0,0,0,0) -#define FMT__H_L_H_H TRACE_ARG_SIZE(3,0,1,0,0) -#define FMT__A_B TRACE_ARG_SIZE(0,0,0,1,1) -#define FMT__D_H_H_L_D_D_D TRACE_ARG_SIZE(2,4,1,0,0) -#define FMT__H_H_D_D_H TRACE_ARG_SIZE(3,3,0,0,0) -#define FMT__L_D_H_H_H_H TRACE_ARG_SIZE(4,1,1,0,0) -#define FMT__P_A_A TRACE_ARG_SIZE(0,0,0,1,2) -#define FMT__D_D_P_H_H_H_H TRACE_ARG_SIZE(4,2,1,0,0) -#define FMT__P_P_D_D_D TRACE_ARG_SIZE(0,4,2,0,0) -#define FMT__D_D_H_H_H_H TRACE_ARG_SIZE(2,4,0,0,0) -#define FMT__P_D_P_D_P_P TRACE_ARG_SIZE(4,2,0,0,0) -#define FMT__D_A_D TRACE_ARG_SIZE(0,2,0,0,1) -#define FMT__D_H_D_D_D_D TRACE_ARG_SIZE(1,5,0,0,0) -#define FMT__H_D_D_D_H_H TRACE_ARG_SIZE(3,3,0,0,0) -#define FMT__P_H_D_D_D_H_H TRACE_ARG_SIZE(3,3,1,0,0) -#define FMT__H_H_H_D_H_L_H_H TRACE_ARG_SIZE(6,1,1,0,0) -#define FMT__D_D_P_P TRACE_ARG_SIZE(0,2,0,2,0) -#define FMT__D_D_P_P_D_D TRACE_ARG_SIZE(0,4,0,2,0) -#define FMT__H_P_P_H_H TRACE_ARG_SIZE(3,0,0,2,0) -#define FMT__H_P_H_H_P TRACE_ARG_SIZE(3,0,0,2,0) -#define FMT__H_P_P TRACE_ARG_SIZE(1,0,0,2,0) -#define FMT__H_P_P_H TRACE_ARG_SIZE(2,0,0,2,0) -#define FMT__D_P_D_D_P TRACE_ARG_SIZE(0,3,0,2,0) -#define FMT__D_D_D_A_A TRACE_ARG_SIZE(0,3,0,0,2) -#define FMT__H_D_A_D_D_D TRACE_ARG_SIZE(1,4,0,0,1) -#define FMT__H_D_A_P TRACE_ARG_SIZE(1,1,0,1,1) - -/** @} */ /* TRACE_DATA_FORMAT */ - -/** - * @addtogroup TRACE_FIRST_ARG - * @{ - */ -#define TRACE_COMMON1 TRACE_SUBSYSTEM_COMMON, 1U -#define TRACE_COMMON2 TRACE_SUBSYSTEM_COMMON, 2U -#define TRACE_COMMON3 TRACE_SUBSYSTEM_COMMON, 3U -#define TRACE_COMMON4 TRACE_SUBSYSTEM_COMMON, 4U - -/* osif subsystem is nearly not used. Place it to the same with common and free - * 1 bit for buffers. */ -#define TRACE_OSIF1 TRACE_SUBSYSTEM_COMMON, 1U -#define TRACE_OSIF2 TRACE_SUBSYSTEM_COMMON, 2U -#define TRACE_OSIF3 TRACE_SUBSYSTEM_COMMON, 3U -#define TRACE_OSIF4 TRACE_SUBSYSTEM_COMMON, 4U - -#define TRACE_MAC1 TRACE_SUBSYSTEM_MAC, 1U -#define TRACE_MAC2 TRACE_SUBSYSTEM_MAC, 2U -#define TRACE_MAC3 TRACE_SUBSYSTEM_MAC, 3U -#define TRACE_MAC4 TRACE_SUBSYSTEM_MAC, 4U - -#define TRACE_MACLL1 TRACE_SUBSYSTEM_MACLL, 1U -#define TRACE_MACLL2 TRACE_SUBSYSTEM_MACLL, 2U -#define TRACE_MACLL3 TRACE_SUBSYSTEM_MACLL, 3U -#define TRACE_MACLL4 TRACE_SUBSYSTEM_MACLL, 4U - -#define TRACE_NWK1 TRACE_SUBSYSTEM_NWK, 1U -#define TRACE_NWK2 TRACE_SUBSYSTEM_NWK, 2U -#define TRACE_NWK3 TRACE_SUBSYSTEM_NWK, 3U -#define TRACE_NWK4 TRACE_SUBSYSTEM_NWK, 4U - -#define TRACE_APS1 TRACE_SUBSYSTEM_APS, 1U -#define TRACE_APS2 TRACE_SUBSYSTEM_APS, 2U -#define TRACE_APS3 TRACE_SUBSYSTEM_APS, 3U -#define TRACE_APS4 TRACE_SUBSYSTEM_APS, 4U - -#define TRACE_AF1 TRACE_SUBSYSTEM_AF, 1U -#define TRACE_AF2 TRACE_SUBSYSTEM_AF, 2U -#define TRACE_AF3 TRACE_SUBSYSTEM_AF, 3U -#define TRACE_AF4 TRACE_SUBSYSTEM_AF, 4U - -#define TRACE_ZDO1 TRACE_SUBSYSTEM_ZDO, 1U -#define TRACE_ZDO2 TRACE_SUBSYSTEM_ZDO, 2U -#define TRACE_ZDO3 TRACE_SUBSYSTEM_ZDO, 3U -#define TRACE_ZDO4 TRACE_SUBSYSTEM_ZDO, 4U - -#define TRACE_SECUR1 TRACE_SUBSYSTEM_SECUR, 1U -#define TRACE_SECUR2 TRACE_SUBSYSTEM_SECUR, 2U -#define TRACE_SECUR3 TRACE_SUBSYSTEM_SECUR, 3U -#define TRACE_SECUR4 TRACE_SUBSYSTEM_SECUR, 4U - -#define TRACE_ZCL1 TRACE_SUBSYSTEM_ZCL, 1U -#define TRACE_ZCL2 TRACE_SUBSYSTEM_ZCL, 2U -#define TRACE_ZCL3 TRACE_SUBSYSTEM_ZCL, 3U -#define TRACE_ZCL4 TRACE_SUBSYSTEM_ZCL, 4U - -#define TRACE_ZLL1 TRACE_SUBSYSTEM_ZLL, 1U -#define TRACE_ZLL2 TRACE_SUBSYSTEM_ZLL, 2U -#define TRACE_ZLL3 TRACE_SUBSYSTEM_ZLL, 3U -#define TRACE_ZLL4 TRACE_SUBSYSTEM_ZLL, 4U - -#define TRACE_ZGP1 TRACE_SUBSYSTEM_ZGP, 1U -#define TRACE_ZGP2 TRACE_SUBSYSTEM_ZGP, 2U -#define TRACE_ZGP3 TRACE_SUBSYSTEM_ZGP, 3U -#define TRACE_ZGP4 TRACE_SUBSYSTEM_ZGP, 4U - -#define TRACE_ZSE1 TRACE_SUBSYSTEM_ZSE, 1U -#define TRACE_ZSE2 TRACE_SUBSYSTEM_ZSE, 2U -#define TRACE_ZSE3 TRACE_SUBSYSTEM_ZSE, 3U -#define TRACE_ZSE4 TRACE_SUBSYSTEM_ZSE, 4U - -#ifndef DOXYGEN -#define TRACE_SPI1 TRACE_SUBSYSTEM_SPI, 1U -#define TRACE_SPI2 TRACE_SUBSYSTEM_SPI, 2U -#define TRACE_SPI3 TRACE_SUBSYSTEM_SPI, 3U -#define TRACE_SPI4 TRACE_SUBSYSTEM_SPI, 4U - -#define TRACE_SSL1 TRACE_SUBSYSTEM_SSL, 1U -#define TRACE_SSL2 TRACE_SUBSYSTEM_SSL, 2U -#define TRACE_SSL3 TRACE_SUBSYSTEM_SSL, 3U -#define TRACE_SSL4 TRACE_SUBSYSTEM_SSL, 4U -#endif /* DOXYGEN */ - -#define TRACE_APP1 TRACE_SUBSYSTEM_APP, 1U -#define TRACE_APP2 TRACE_SUBSYSTEM_APP, 2U -#define TRACE_APP3 TRACE_SUBSYSTEM_APP, 3U -#define TRACE_APP4 TRACE_SUBSYSTEM_APP, 4U - -#ifndef DOXYGEN -#define TRACE_SPECIAL1 TRACE_SUBSYSTEM_SPECIAL1, 1U -#define TRACE_SPECIAL2 TRACE_SUBSYSTEM_SPECIAL1, 2U -#define TRACE_SPECIAL3 TRACE_SUBSYSTEM_SPECIAL1, 3U -#define TRACE_SPECIAL4 TRACE_SUBSYSTEM_SPECIAL1, 4U - -#define TRACE_USB1 TRACE_SUBSYSTEM_USB, 1U -#define TRACE_USB2 TRACE_SUBSYSTEM_USB, 2U -#define TRACE_USB3 TRACE_SUBSYSTEM_USB, 3U -#define TRACE_USB4 TRACE_SUBSYSTEM_USB, 4U - -#define TRACE_MEMDBG1 TRACE_SUBSYSTEM_MEM, 1U -#define TRACE_MEMDBG2 TRACE_SUBSYSTEM_MEM, 2U -#define TRACE_MEMDBG3 TRACE_SUBSYSTEM_MEM, 3U -#define TRACE_MEMDBG4 TRACE_SUBSYSTEM_MEM, 4U - -#define TRACE_CLOUD1 TRACE_SUBSYSTEM_CLOUD, 1U -#define TRACE_CLOUD2 TRACE_SUBSYSTEM_CLOUD, 2U -#define TRACE_CLOUD3 TRACE_SUBSYSTEM_CLOUD, 3U -#define TRACE_CLOUD4 TRACE_SUBSYSTEM_CLOUD, 4U - -#define TRACE_HTTP1 TRACE_SUBSYSTEM_HTTP, 1U -#define TRACE_HTTP2 TRACE_SUBSYSTEM_HTTP, 2U -#define TRACE_HTTP3 TRACE_SUBSYSTEM_HTTP, 3U -#define TRACE_HTTP4 TRACE_SUBSYSTEM_HTTP, 4U - -#define TRACE_JSON1 TRACE_SUBSYSTEM_JSON, 1U -#define TRACE_JSON2 TRACE_SUBSYSTEM_JSON, 2U -#define TRACE_JSON3 TRACE_SUBSYSTEM_JSON, 3U -#define TRACE_JSON4 TRACE_SUBSYSTEM_JSON, 4U - -#define TRACE_LWIP1 TRACE_SUBSYSTEM_LWIP, 1U -#define TRACE_LWIP2 TRACE_SUBSYSTEM_LWIP, 2U -#define TRACE_LWIP3 TRACE_SUBSYSTEM_LWIP, 3U -#define TRACE_LWIP4 TRACE_SUBSYSTEM_LWIP, 4U - -#define TRACE_VENSTAR1 TRACE_SUBSYSTEM_VENSTAR, 1U -#define TRACE_VENSTAR2 TRACE_SUBSYSTEM_VENSTAR, 2U -#define TRACE_VENSTAR3 TRACE_SUBSYSTEM_VENSTAR, 3U -#define TRACE_VENSTAR4 TRACE_SUBSYSTEM_VENSTAR, 4U - -#define TRACE_TRANSPORT1 TRACE_SUBSYSTEM_TRANSPORT, 1U -#define TRACE_TRANSPORT2 TRACE_SUBSYSTEM_TRANSPORT, 2U -#define TRACE_TRANSPORT3 TRACE_SUBSYSTEM_TRANSPORT, 3U -#define TRACE_TRANSPORT4 TRACE_SUBSYSTEM_TRANSPORT, 4U - -#define TRACE_UART1 TRACE_SUBSYSTEM_UART, 1U -#define TRACE_UART2 TRACE_SUBSYSTEM_UART, 2U -#define TRACE_UART3 TRACE_SUBSYSTEM_UART, 3U -#define TRACE_UART4 TRACE_SUBSYSTEM_UART, 4U - -#define TRACE_BATTERY1 TRACE_SUBSYSTEM_BATTERY, 1U -#define TRACE_BATTERY2 TRACE_SUBSYSTEM_BATTERY, 2U -#define TRACE_BATTERY3 TRACE_SUBSYSTEM_BATTERY, 3U -#define TRACE_BATTERY4 TRACE_SUBSYSTEM_BATTERY, 4U - -#define TRACE_OTA1 TRACE_SUBSYSTEM_OTA, 1U -#define TRACE_OTA2 TRACE_SUBSYSTEM_OTA, 2U -#define TRACE_OTA3 TRACE_SUBSYSTEM_OTA, 3U -#define TRACE_OTA4 TRACE_SUBSYSTEM_OTA, 4U - -#define TRACE_MAC_API1 TRACE_SUBSYSTEM_MAC_API, 1U -#define TRACE_MAC_API2 TRACE_SUBSYSTEM_MAC_API, 2U -#define TRACE_MAC_API3 TRACE_SUBSYSTEM_MAC_API, 3U -#define TRACE_MAC_API4 TRACE_SUBSYSTEM_MAC_API, 4U - -#define TRACE_ZBDIRECT1 TRACE_SUBSYSTEM_ZBDIRECT, 1U -#define TRACE_ZBDIRECT2 TRACE_SUBSYSTEM_ZBDIRECT, 2U -#define TRACE_ZBDIRECT3 TRACE_SUBSYSTEM_ZBDIRECT, 3U -#define TRACE_ZBDIRECT4 TRACE_SUBSYSTEM_ZBDIRECT, 4U -#endif /* DOXYGEN */ - -#ifndef ZB_SET_TRACE_LEVEL - -/* empty definitions if not implemented */ -#define ZB_SET_TRACE_LEVEL(l) -#define ZB_SET_TRACE_MASK(m) -#define ZB_SET_TRACE_OFF() -#define ZB_SET_TRACE_ON() - -#endif - -/** @} */ /* TRACE_FIRST_ARG */ -/** @endcond */ /* DSR_TRACE */ -/** @} */ /* Debug trace */ - -#if defined ZB_TRAFFIC_DUMP_ON || defined DOXYGEN -/** - @addtogroup DUMP_ON_OFF - @{ -*/ -/** @cond DOXYGEN_INTERNAL_DOC */ -extern zb_uint8_t g_traf_dump; -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -static ZB_INLINE zb_uint8_t zb_get_traf_dump_state(void) -{ - return g_traf_dump; -} - -/** - * Switch Zigbee traffic dump OFF - */ -#define ZB_SET_TRAF_DUMP_OFF() g_traf_dump = 0U -/** - * Switch Zigbee traffic dump ON - * - * That function works only if traffic dump is enabled at compile time. - */ -#define ZB_SET_TRAF_DUMP_ON() g_traf_dump = 1U -#define ZB_GET_TRAF_DUMP_STATE() zb_get_traf_dump_state() -/** @} */ /* DUMP_ON_OFF */ -#else -#define ZB_SET_TRAF_DUMP_OFF() -#define ZB_SET_TRAF_DUMP_ON() -#define ZB_GET_TRAF_DUMP_STATE() 0U -#endif - -/** @endcond */ /* DOXYGEN_DEBUG_SECTION */ - -#endif /* ZB_LOGGER_H */ diff --git a/zboss/development/include/zb_types.h b/zboss/development/include/zb_types.h deleted file mode 100644 index 3560bce501..0000000000 --- a/zboss/development/include/zb_types.h +++ /dev/null @@ -1,1585 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: general-purpose typedefs -*/ - -#ifndef ZB_TYPES_H -#define ZB_TYPES_H 1 - -#ifndef ZB_CONFIG_H -#error zb_config.h must be included before zb_types.h. Dont do it directly. Include zb_common.h or zboss_api.h instead. -#endif - -/** - * @addtogroup base_types - * @{ - */ - -/* - * C standard being used during compilation. - * The preferred standard is C99 and it should be used whenever possible. - * However, C90 compatibility should be maintained. Macroses ZB_STDC_* can be - * used for conditional compilation based on C standard. Note: __STDC__ and - * __STDC_VERSION__ are expected to be supported by all compilers in use. - */ -#if defined __STDC__ -#if defined __STDC_VERSION__ && (__STDC_VERSION__ >= 199901L) -#define ZB_STDC_99 -#else -#define ZB_STDC_90 -#endif /* __STDC_VERSION__ && (__STDC_VERSION__ >= 199901L) */ -#else -#warning __STDC__ is not defined, assume C90 standard -#define ZB_STDC_90 -#endif /* __STDC__ */ - -#ifdef __IAR_SYSTEMS_ICC__ -#ifndef ZB_IAR -#define ZB_IAR -#endif -#endif - -#define ZB_32BIT_WORD - -/* Really need xdata declaration here, not in osif: don't want to include osif.h here */ -#ifdef ZB_IAR -#define ZB_XDATA -#define ZB_CODE -#define ZB_IAR_CODE -#elif defined __LINT__ -#define ZB_XDATA -#define ZB_CODE -#define ZB_IAR_CODE -#elif defined KEIL -#define ZB_XDATA xdata -#define ZB_CODE code -#define ZB_IAR_CODE code -#else -#define ZB_XDATA -#define ZB_CODE -#define ZB_IAR_CODE -#endif - -/* register modifier for variables. Can be defined to "register". Will it help to the compiler? */ -/* #define ZB_REGISTER */ -#define ZB_REGISTER register - -#define ZB_VOID_ARGLIST void - -/* Not sure all C compilers support 'const'. Let's add some conditional - * compilation when we will find such compiler */ -#define ZB_CONST const - -/* inline directive for functions placed into .h files in C */ -#if defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus -#define ZB_INLINE inline -#define ZB_INLINE_IN_C -#define ZB_BITFIELD_CAST(x) (x) -#elif defined _MSC_VER -#define ZB_INLINE __inline -#define ZB_BITFIELD_CAST(x) (zb_uint_t)(x) -#else -/* which other C compiler knows about inline? */ -#define ZB_INLINE -#define ZB_BITFIELD_CAST(x) (x) -#endif - - -#define ZB_CPP_STR2(x) #x -/** - Create a string at compile time, like 0 - "0" - */ -#define ZB_CPP_STR(x) ZB_CPP_STR2(x) - - -/** @brief General purpose parameter type. */ -enum zb_param_e -{ - ZB_UNUSED_PARAM = 0 -}; - -#if defined WIN32 && !defined ZB_WINDOWS -#define ZB_WINDOWS -#endif - -#if !defined ZB_USE_STDINT && defined UNIX && !defined ZB_WINDOWS -#define ZB_USE_STDINT -#endif - -#ifndef ZB_USE_STDINT - -/* base types */ - -typedef char zb_char_t; - -typedef unsigned char zb_uchar_t; - -typedef unsigned char zb_uint8_t; - -typedef signed char zb_int8_t; - -typedef unsigned short zb_uint16_t; - -typedef signed short zb_int16_t; -#if defined ZB_16BIT_WORD - -typedef unsigned long zb_uint32_t; - -typedef signed long zb_int32_t; - -typedef zb_uint16_t zb_bitfield_t; -typedef zb_uint32_t zb_lbitfield_t; - -typedef zb_int16_t zb_sbitfield_t; - -/* FIXME: 16 or 32? */ -typedef zb_uint32_t zb_size_t; - -typedef long long zb_int64_t; -typedef unsigned long long zb_uint64_t; - -#else /* defined ZB8051 */ -/* - project-local 4-byte unsigned int type -*/ -typedef unsigned int zb_uint32_t; -/* - project-local 4-byte signed int type -*/ -typedef signed int zb_int32_t; - - -/* - type to be used for unsigned bit fields inside structure -*/ -#if defined ZB_TI_ARM_CODE_COMPOSER -typedef zb_uint8_t zb_bitfield_t; -#elif defined ZB_IAR -typedef zb_uint8_t zb_bitfield_t; -#else -typedef zb_uint32_t zb_bitfield_t; -#endif - -typedef zb_uint32_t zb_lbitfield_t; -/* - type to be used for signed bit fields inside structure -*/ -typedef zb_int32_t zb_sbitfield_t; - -typedef zb_uint32_t zb_size_t; - -typedef long long zb_int64_t; -typedef unsigned long long zb_uint64_t; - -#endif /* defined ZB8051 */ - - -#else /* ! defined UNIX || ZB_WINDOWS */ -/* Unix */ - -#include - -#ifdef __GNUC__ -#include "stddef.h" -#endif - -typedef uint8_t zb_uint8_t; -typedef int8_t zb_int8_t; -typedef uint16_t zb_uint16_t; -typedef int16_t zb_int16_t; -typedef uint32_t zb_uint32_t; -typedef int32_t zb_int32_t; - -typedef int64_t zb_int64_t; -typedef uint64_t zb_uint64_t; - -typedef char zb_char_t; -typedef unsigned char zb_uchar_t; - -typedef unsigned zb_bitfield_t; -typedef unsigned zb_lbitfield_t; -typedef signed zb_sbitfield_t; - -/* Integer with size equal to the pointer size. */ -typedef size_t zb_size_t; -typedef zb_size_t zb_ptrsize_uint_t; - - -#endif /* ! defined UNIX */ - -/* - Our short and int definition. - Short size == 8051 register size, int size is 2 bytes. - */ -#ifdef ZB_8BIT_WORD -/* - Short int (can fit into single CPU register) - */ -typedef zb_int8_t zb_short_t; -/* - short unsigned int (can fit into single CPU register) - */ -typedef zb_uint8_t zb_ushort_t; -/* - short unsigned int (can fit into single CPU register) used as a loop index - */ -typedef zb_ushort_t zb_uindex_t; -/* - int (at least 2 bytes) - */ -typedef zb_int16_t zb_int_t; -/* - unsigned int (at least 2 bytes) - */ -typedef zb_uint16_t zb_uint_t; -/* - long int (at least 4 bytes) - */ -typedef zb_int32_t zb_long_t; -/* - unsigned long int (at least 4 bytes) - */ -typedef zb_uint32_t zb_ulong_t; - -#elif defined ZB_16BIT_WORD -/* - short int (can fit into single CPU register) - */ -typedef int zb_short_t; -/* - unsigned short int (can fit into single CPU register) - */ -typedef unsigned int zb_ushort_t; -/* - short unsigned int (can fit into single CPU register) used as a loop index - */ -typedef zb_ushort_t zb_uindex_t; -/* - int (at least 2 bytes) - */ -typedef int zb_int_t; -/* - unsigned int (at least 2 bytes) - */ -typedef unsigned int zb_uint_t; -/* - long int (at least 4 bytes) - */ -typedef zb_int32_t zb_long_t; -/* - unsigned long int (at least 4 bytes) - */ -typedef zb_uint32_t zb_ulong_t; - -#else /* 32-bit word */ -/* - short int (can fit into single CPU register) - */ -typedef int zb_short_t; -/* - unsigned short int (can fit into single CPU register) - */ -typedef unsigned int zb_ushort_t; -/* - short unsigned int (can fit into single CPU register) used as a loop index - */ -typedef zb_ushort_t zb_uindex_t; -/* - int (at least 2 bytes) - */ -typedef int zb_int_t; -/* - unsigned int (at least 2 bytes) - */ -typedef unsigned int zb_uint_t; -/* - long int (at least 4 bytes) - */ -typedef zb_int_t zb_long_t; -/* - unsigned long int (at least 4 bytes) - */ -typedef zb_uint_t zb_ulong_t; -#endif - -/** @brief General purpose boolean type. - * For C90, 'zb_bool_t' is an alias of 'zb_uint8_t'. - * For C99, the availability of the 'stdbool.h' standard header is expected and 'zb_bool_t' is an - * alias of 'bool'. - * ZB_FALSE and ZB_TRUE are defined as macros for both standards. - * - * To ensure that zb_bool_t always has the same size of one byte, static - * compile time assertions were added. See 'zb_common.h'. - */ -#ifdef ZB_STDC_90 -typedef zb_uint8_t zb_bool_t; -typedef zb_bitfield_t zb_bitbool_t; - -#define ZB_FALSE 0U /**< False value literal. */ -#define ZB_TRUE 1U /**< True value literal. */ - -#define ZB_FALSE_U ZB_FALSE -#define ZB_TRUE_U ZB_TRUE - -#define ZB_B2U(b) (((b) != ZB_FALSE) ? (1U) : (0U)) -#define ZB_U2B(u) (((u) != 0U) ? (ZB_TRUE) : (ZB_FALSE)) - -#else /* ZB_STDC_90 */ -#include - -typedef bool zb_bool_t; -typedef bool zb_bitbool_t; - -#define ZB_FALSE false /**< False value literal. */ -#define ZB_TRUE true /**< True value literal. */ - -#define ZB_FALSE_U 0U -#define ZB_TRUE_U 1U - -#define ZB_B2U(b) ((b) ? (1U) : (0U)) -#define ZB_U2B(u) ((u) != 0U) - -#endif /* ZB_STDC_90 */ - -#define ZB_INT8_MIN (-127 - 1) -#define ZB_INT8_MAX 127 -#define ZB_UINT8_MIN 0U -#define ZB_UINT8_MAX 255U - -#define ZB_INT16_MIN (-32767 - 1) -#define ZB_INT16_MAX 32767 -#define ZB_UINT16_MIN 0U -#define ZB_UINT16_MAX 65535U - -/* 2147483648 is unsigned indeed - can't change its sign. prevent warning from - * msvc 8 */ -#define ZB_INT32_MIN (-2147483647L - 1) -#define ZB_INT32_MAX 2147483647L -#define ZB_UINT32_MIN 0UL -#define ZB_UINT32_MAX 4294967295UL - -#define ZB_UINT_MIN 0UL - -/* - Short defined as register size, int as large enough int on this platform. - 32 bit on PC, 8 and 16 bit on 8051 - */ - - -/* - Max value constants per type - */ -#ifdef ZB_32BIT_WORD - -#define ZB_SHORT_MIN ZB_INT32_MIN -#define ZB_SHORT_MAX ZB_INT32_MAX -#define ZB_USHORT_MAX ZB_UINT32_MAX - -#define ZB_INT_MIN ZB_INT32_MIN -#define ZB_INT_MAX ZB_INT32_MAX -#define ZB_UINT_MAX ZB_UINT32_MAX - -#define ZB_INT_MASK 0x7fffffffU - -#elif defined ZB_16BIT_WORD - -#define ZB_SHORT_MIN ZB_INT8_MIN -#define ZB_SHORT_MAX ZB_INT8_MAX -#define ZB_USHORT_MAX ZB_UINT8_MAX - -#define ZB_INT_MIN ZB_INT16_MIN -#define ZB_INT_MAX ZB_INT16_MAX -#define ZB_UINT_MAX ZB_UINT16_MAX - -#define ZB_INT_MASK 0x7fffU - -#elif defined ZB_8BIT_WORD - -#define ZB_SHORT_MIN ZB_INT8_MIN -#define ZB_SHORT_MAX ZB_INT8_MAX -#define ZB_USHORT_MAX ZB_UINT8_MAX - -#define ZB_INT_MIN ZB_INT16_MIN -#define ZB_INT_MAX ZB_INT16_MAX -#define ZB_UINT_MAX ZB_UINT16_MAX - -#define ZB_INT_MASK 0x7fff - -#else -#error Portme -#endif - -#if defined __GNUC__ || defined __TI_COMPILER_VERSION__ - #define ZB_PACKED_STRUCT __attribute__ ((packed)) - #define ZB_WEAK __attribute__ ((weak)) -#else - #define ZB_PACKED_STRUCT -#endif - -/* IAR or Keil ARM CPU */ -#if (defined __IAR_SYSTEMS_ICC__ || defined __ARMCC_VERSION) && !defined ZB8051 -#define ZB_PACKED_PRE __packed -#define ZB_WEAK_PRE __weak -#else -#define ZB_PACKED_PRE -#endif - -#ifndef ZB_WEAK_PRE -#define ZB_WEAK_PRE -#endif -#ifndef ZB_WEAK -#define ZB_WEAK -#endif - -#if (defined __ARMCC_VERSION) && !defined ZB8051 -#define ZB_ALIGNED_PRE __attribute__((aligned)) -#endif - -#ifndef ZB_ALIGNED_PRE -#define ZB_ALIGNED_PRE -#endif - -#if defined __GNUC__ - #define ZB_DEPRECATED __attribute__((deprecated)) -#else - #define ZB_DEPRECATED -#endif /* __GNUC__ */ - -#if defined __GNUC__ - #define ZB_NORETURN __attribute__((noreturn)) -#else - #define ZB_NORETURN -#endif /* __GNUC__ */ - -/* - 8-bytes address (xpanid or long device address) base type - */ -typedef zb_uint8_t zb_64bit_addr_t[8]; - -/* - 8-bytes data base type - */ -typedef zb_uint8_t zb_64bit_data_t[8]; - - -extern ZB_CODE ZB_CONST zb_64bit_addr_t g_zero_addr; -extern ZB_CODE ZB_CONST zb_64bit_addr_t g_unknown_ieee_addr; - -/* - Return true if long address is zero - */ - /* g_zero_addr is declared as ZB_CONST which allows IAR to place it in CODE memory. - Compiled this by IAR 7.60 for 8051. - This placement changes pointer type making it unusable - Is this cast needed here? - */ -#define ZB_IS_64BIT_ADDR_ZERO(addr) (ZB_MEMCMP((addr), (void const*)g_zero_addr, 8) == 0) -#define ZB_IS_64BIT_ADDR_UNKNOWN(addr) (ZB_MEMCMP((addr), (void const*)g_unknown_ieee_addr, 8) == 0) - -/* - Clear long address - */ -#define ZB_64BIT_ADDR_ZERO(addr) \ - ZB_MEMSET((addr), 0, 8) - -/* - Make long address unknown - */ -#define ZB_64BIT_ADDR_UNKNOWN(addr) \ - ZB_MEMSET((addr), -1, 8) - -/* - Copy long address - */ -#define ZB_64BIT_ADDR_COPY(dst, src) ZB_MEMCPY(dst, src, sizeof(zb_64bit_addr_t)) - -/* - Return 1 if long addresses are equal - */ -#define ZB_64BIT_ADDR_CMP(one, two) (ZB_MEMCMP((one), (two), 8) == 0) - -/* - Long (64-bit) device address - */ -typedef zb_64bit_addr_t zb_ieee_addr_t; -/* - Long (64-bit) Extended Pan ID - */ -typedef zb_64bit_addr_t zb_ext_pan_id_t; - -#define ZB_EXTPANID_IS_ZERO ZB_IS_64BIT_ADDR_ZERO -#define ZB_EXTPANID_ZERO ZB_64BIT_ADDR_ZERO -#define ZB_EXTPANID_COPY ZB_64BIT_ADDR_COPY -#define ZB_EXTPANID_CMP ZB_64BIT_ADDR_CMP - -#define ZB_IEEE_ADDR_IS_ZERO ZB_IS_64BIT_ADDR_ZERO -#define ZB_IEEE_ADDR_IS_UNKNOWN ZB_IS_64BIT_ADDR_UNKNOWN -#define ZB_IEEE_ADDR_ZERO ZB_64BIT_ADDR_ZERO -#define ZB_IEEE_ADDR_UNKNOWN ZB_64BIT_ADDR_UNKNOWN -#define ZB_IEEE_ADDR_COPY ZB_64BIT_ADDR_COPY -#define ZB_IEEE_ADDR_CMP ZB_64BIT_ADDR_CMP - -#define ZB_CCM_KEY_IS_ZERO(k) (ZB_IS_64BIT_ADDR_ZERO((zb_uint8_t*)(k)) && ZB_IS_64BIT_ADDR_ZERO(((zb_uint8_t*)(k)) + 8U)) -#define ZB_IEEE_ADDR_IS_VALID(addr) !(ZB_IEEE_ADDR_IS_ZERO(addr)||ZB_IEEE_ADDR_IS_UNKNOWN(addr)) - -#define ZB_ADDR_CMP(addr_mode, addr1, addr2) \ - ((addr_mode == ZB_ADDR_16BIT_DEV_OR_BROADCAST) ? \ - (addr1.addr_short == addr2.addr_short) : ZB_64BIT_ADDR_CMP(addr1.addr_long, addr2.addr_long)) - -typedef ZB_PACKED_PRE union zb_addr_u_t -{ - zb_uint16_t addr_short; - zb_ieee_addr_t addr_long; -} ZB_PACKED_STRUCT -zb_addr_u; - -#define ZB_ADDR_U_CAST(addr) ((const zb_addr_u *)(const void *)(&(addr))) - -/* - definitions for constants of given type -*/ -#define ZB_INT8_C(c) c -#define ZB_UINT8_C(c) c ## U - -#define ZB_INT16_C(c) c -#define ZB_UINT16_C(c) c ## U - -#define ZB_INT32_C(c) c ## L -#define ZB_UINT32_C(c) c ## UL - -#if (defined __GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -#define ZB_OFFSETOF(t, f) __builtin_offsetof(t,f) -#else -#define ZB_OFFSETOF(t, f) ((zb_size_t)(&((t *)NULL)->f)) -#endif - -#define ZB_OFFSETOF_VAR(s, f) (zb_size_t)(((zb_int8_t *)(&(s)->f)) - ((zb_int8_t *)(s))) - -#define ZB_SIZEOF_FIELD(type, field) (sizeof(((type*)0)->field)) - -#define ZB_ARRAY_SIZE(arr) (sizeof((arr))/sizeof((arr)[0])) - - -#define ZB_SIGNED_SHIFT(v, s) ((zb_int_t)(v) >> (s)) - -#define ZB_ASSERT_IF_NOT_ALIGNED(data_type,length) \ - ZB_ASSERT_COMPILE_DECL(((sizeof(data_type) % (length)) == 0U)) - -#define ZB_ASSERT_IF_NOT_ALIGNED_TO_4(data_type) ZB_ASSERT_IF_NOT_ALIGNED(data_type,4U) - -#define ZB_ASSERT_VALUE_ALIGNED(const_expr, length) \ - ZB_ASSERT_COMPILE_DECL((((const_expr) % (length)) == 0U)) - -#define ZB_ASSERT_VALUE_ALIGNED_TO_4(const_expr) ZB_ASSERT_VALUE_ALIGNED(const_expr, 4U) - -/** - * @name Endian change API. - * Macros to change words endian and access words at potentially - * non-aligned pointers. - * - * Zigbee uses little endian, see ZB spec, subclause 1.2.1.3. - * @{ - */ - -/** - */ - -#define ZB_8BIT_SIZE 1U -#define ZB_16BIT_SIZE 2U -#define ZB_24BIT_SIZE 3U -#define ZB_32BIT_SIZE 4U -#define ZB_48BIT_SIZE 6U -#define ZB_64BIT_SIZE 8U - -#ifdef ZB_LITTLE_ENDIAN - -#ifdef ZB_NEED_ALIGN -/** - Convert 16-bits integer from the host endian to the little endian - - @param ptr - destination pointer. It is ok if it not aligned to 2. - @param val - source pointer. It is ok if it not aligned to 2. -*/ - -#define ZB_HTOLE16(ptr, val) ZB_MEMCPY((ptr), (val), ZB_16BIT_SIZE) -#define ZB_HTOLE32(ptr, val) ZB_MEMCPY((ptr), (val), ZB_32BIT_SIZE) -#define ZB_HTOLE64(ptr, val) ZB_MEMCPY((ptr), (val), ZB_64BIT_SIZE) -#else - -#define ZB_HTOLE16(ptr, val) (((zb_uint16_t *)(ptr))[0] = *((zb_uint16_t *)(val))) -#define ZB_HTOLE32(ptr, val) (((zb_uint32_t *)(ptr))[0] = *((zb_uint32_t *)(val))) -/* -#define ZB_HTOLE64(ptr, val) \ - (((zb_uint32_t *)(ptr))[0] = ((zb_uint32_t *)(val))[0], \ - ((zb_uint32_t *)(ptr))[1] = ((zb_uint32_t *)(val))[1]) -*/ -#define ZB_HTOLE64(ptr, val) zb_memcpy8(ptr, val) -#endif /* need_align */ - - -#define ZB_HTOLE16_ONPLACE(v) ZVUNUSED(v) - -#define ZB_HTOLE32_ONPLACE(v) ZVUNUSED(v) - -#define ZB_HTOLE64_ONPLACE(v) ZVUNUSED(v) - -#define ZB_HTOBE16(ptr, val) \ - (((zb_uint8_t *)(ptr))[0] = ((zb_uint8_t *)(val))[1], \ - ((zb_uint8_t *)(ptr))[1] = ((zb_uint8_t *)(val))[0] \ - ) - -void zb_htobe32(zb_uint8_t ZB_XDATA *ptr, zb_uint8_t ZB_XDATA *val); -#define ZB_HTOBE32(ptr, val) zb_htobe32((zb_uint8_t*)(ptr), (zb_uint8_t*)(val)) - -#define ZB_HTOBE16_VAL(ptr, val) \ -{ \ - zb_uint16_t _v = (val); \ - ZB_HTOBE16((ptr), &_v); \ -} - -#else /* !little endian */ - -void zb_htole16(zb_uint8_t ZB_XDATA *ptr, zb_uint8_t ZB_XDATA *val); -#define ZB_HTOLE16(ptr, val) zb_htole16((zb_uint8_t*)(ptr), (zb_uint8_t*)(val)) - -#define ZB_HTOLE16_ONPLACE(val) \ -{ \ - zb_uint8_t *pval = (zb_uint8_t*)(&(val)); \ - zb_uint8_t a = pval[0]; \ - pval[0] = pval[1]; \ - pval[1] = a; \ -} - -#define ZB_HTOLE32_ONPLACE(val) { zb_uint32_t _v = (val); ZB_HTOLE32(&(val), &_v); } - -void zb_htole32(zb_uint8_t ZB_XDATA *ptr, zb_uint8_t ZB_XDATA *val); -#define ZB_HTOLE32(ptr, val) zb_htole32((zb_uint8_t*)(ptr), (zb_uint8_t*)(val)) - -#define ZB_HTOBE32(ptr, val) ZB_MEMCPY(ptr, val, 4U) - -#define ZB_HTOBE16(ptr, val) (*(zb_uint16_t *)(ptr)) = *((zb_uint16_t *)(val)) - -#ifdef ZB_NEED_ALIGN - -#define ZB_HTOBE16_VAL(ptr, val) \ -{ \ - zb_uint16_t _v = (val); \ - ZB_MEMCPY((ptr), &_v, 2U) \ -} - -#else /* ZB_NEED_ALIGN */ - -#define ZB_HTOBE16_VAL(ptr, val) ((zb_uint16_t *)(ptr))[0] = (val) - -#endif /* ZB_NEED_ALIGN */ - -/* Let's not rotate 64-bit address: store it as - * 8-byte array in the order it transmitted. */ -#define ZB_HTOLE64(ptr, val) zb_memcpy8(ptr, val) - -#endif /* ZB_LITTLE_ENDIAN */ - -#define ZB_HTOLE32_VAL(ptr, val) \ -{ \ - zb_uint32_t tmp_val = (val); \ - ZB_HTOLE32((ptr), &tmp_val); \ -} - -#define ZB_HTOLE16_VAL(ptr, val) \ -{ \ - zb_uint16_t tmp_val = (val); \ - ZB_HTOLE16((ptr), &tmp_val); \ -} - -/** - Put next 2-bite value into buffer, move pointer - - To be used for headers compose. - - @param dst - (in/out) address of the buffer pointer - As a side effect it will be incremented by 2. - @param val - value - */ -//void zb_put_next_htole16(zb_uint8_t **dst, zb_uint16_t val); -void* zb_put_next_htole16(zb_uint8_t *dst, zb_uint16_t val); - -#ifdef ZB_LITTLE_ENDIAN -#define ZB_PUT_NEXT_HTOLE16(ptr, val) \ -{ \ - *((ptr)++) = (zb_uint8_t)((val) & 0xffU); \ - *((ptr)++) = (zb_uint8_t)(((val) >> 8U) & 0xffU); \ -} - -#else -#define ZB_PUT_NEXT_HTOLE16(ptr, val) \ -{ \ - *((ptr)++) = (zb_uint8_t)(((val) >> 8U) & 0xffU); \ - *((ptr)++) = (zb_uint8_t)((val) & 0xffU); \ -} -#endif /* ZB_LITTLE_ENDIAN */ - -void* zb_put_next_htole32(zb_uint8_t *dst, zb_uint32_t val1); - -#define ZB_PUT_NEXT_HTOLE32(ptr, val) (ptr) = zb_put_next_htole32((ptr), (val)) - -#ifndef ZB_IAR -void zb_get_next_letoh16(zb_uint16_t *dst, zb_uint8_t **src); -#else -/* for IAR define as macro due to problems with packet structs */ -#define zb_get_next_letoh16(dst, src) \ -{ \ - ZB_LETOH16((dst), *(src)); \ - (*(src)) = (void *)(((char *)(*(src))) + 2U); \ -} -#endif - -void* zb_put_next_2_htole16(zb_uint8_t *dst, zb_uint16_t val1, zb_uint16_t val2); -void* zb_put_next_2_htole32(zb_uint8_t *dst, zb_uint32_t val1, zb_uint32_t val2); -#define ZB_LETOH64(dst, src) zb_memcpy8((zb_uint8_t*)dst, (zb_uint8_t*)src) - -/** - Convert 16-bits integer from the little endian to the host endian - - @param ptr - destination pointer. It is ok if it not aligned to 2. - @param val - source pointer. It is ok if it not aligned to 2. -*/ -#define ZB_LETOH16 ZB_HTOLE16 -#define ZB_LETOH24 ZB_HTOLE24 -#define ZB_LETOH48 ZB_HTOLE48 -#define ZB_LETOH32 ZB_HTOLE32 -#define ZB_BETOH16 ZB_HTOBE16 -#define ZB_BETOH32 ZB_HTOBE32 - -#define ZB_LETOH16_ONPLACE ZB_HTOLE16_ONPLACE -#define ZB_LETOH32_ONPLACE ZB_HTOLE32_ONPLACE - -/** @} */ /* Endian change API. */ - -#define ZB_GET_LOW_BYTE(val) (zb_uint8_t)((val) & 0xFFU) -#define ZB_GET_HI_BYTE(val) (zb_uint8_t)(((val) >> 8U) & 0xFFU) - -#define ZB_SET_LOW_BYTE(res, val) (res) = ((((zb_uint16_t)(res)) & 0xFF00U) | (((zb_uint16_t)(val)) & 0xFFU)) -#define ZB_SET_HI_BYTE(res, val) (res) = (((((zb_uint16_t)(val)) << 8U) & 0xFF00U) | (((zb_uint16_t)(res)) & 0xFFU)) - -#define ZB_PKT_16B_ZERO_BYTE 0U -#define ZB_PKT_16B_FIRST_BYTE 1U - -#ifdef ZB_NEED_ALIGN - -#define ZB_ASSIGN_UINT16(ptr, vp) ZB_MEMCPY((ptr), (vp), 2U) -#define ZB_ASSIGN_INT16(ptr, vp) ZB_MEMCPY((ptr), (vp), 2U) -#define ZB_COPY_UINT24(ptr, vp) ZB_MEMCPY((ptr), (vp), 3U) -#define ZB_COPY_INT24(ptr, vp) ZB_MEMCPY((ptr), (vp), 3U) -#define ZB_ASSIGN_UINT32(ptr, vp) ZB_MEMCPY((ptr), (vp), 4U) -#define ZB_ASSIGN_INT32(ptr, vp) ZB_MEMCPY((ptr), (vp), 4U) - -#else - -#define ZB_ASSIGN_UINT16(ptr, vp) *((zb_uint16_t*)(ptr)) = *(zb_uint16_t*)(vp) -#define ZB_ASSIGN_INT16(ptr, vp) *((zb_int16_t*)(ptr)) = *(zb_int16_t*)(vp) -#define ZB_COPY_UINT24(ptr, vp) *((zb_uint24_t*)(ptr)) = *(zb_uint24_t*)(vp) -#define ZB_COPY_INT24(ptr, vp) *((zb_int24_t*)(ptr)) = *(zb_int24_t*)(vp) -#define ZB_ASSIGN_UINT32(ptr, vp) *((zb_uint32_t*)(ptr)) = *(zb_uint32_t*)(vp) -#define ZB_ASSIGN_INT32(ptr, vp) *((zb_int32_t*)(ptr)) = *(zb_int32_t*)(vp) - - -#endif /* ZB_NEED_ALIGN */ - -#define ZB_REVERSE16(ptr, val) \ - (((zb_uint8_t *)(ptr))[0] = ((zb_uint8_t *)(val))[1], \ - ((zb_uint8_t *)(ptr))[1] = ((zb_uint8_t *)(val))[0]) - -#define ZB_REVERSE64(ptr, val) \ - *((zb_uint8_t*)(ptr)+7) = *((zb_uint8_t*)(val) ), \ - *((zb_uint8_t*)(ptr)+6) = *((zb_uint8_t*)(val)+1), \ - *((zb_uint8_t*)(ptr)+5) = *((zb_uint8_t*)(val)+2), \ - *((zb_uint8_t*)(ptr)+4) = *((zb_uint8_t*)(val)+3), \ - *((zb_uint8_t*)(ptr)+3) = *((zb_uint8_t*)(val)+4), \ - *((zb_uint8_t*)(ptr)+2) = *((zb_uint8_t*)(val)+5), \ - *((zb_uint8_t*)(ptr)+1) = *((zb_uint8_t*)(val)+6), \ - *((zb_uint8_t*)(ptr) ) = *((zb_uint8_t*)(val)+7) - -#define ZB_ARRAY_IDX_BY_ELEM(ar, el) ((el) - (ar)) - -#define ZB_ARRAY_IDX_BY_STRUCT_ELEM(ar, el, el_size) ( ((zb_size_t)(el) - (zb_size_t)(ar)) / (el_size) ) - -/** - * @name Base types. - * @{ - * @typedef zb_char_t - * @brief Project-local char type. - * - * @typedef zb_uchar_t - * @brief Project-local unsigned char type. - * - * @typedef zb_uint8_t - * @brief Project-local 1-byte unsigned int type. - * - * @typedef zb_int8_t - * @brief Project-local 1-byte signed int type. - * - * @typedef zb_uint16_t - * @brief Project-local 2-byte unsigned int type. - * - * - * @typedef zb_int16_t - * @brief Project-local 2-byte signed int type. - * - * @typedef zb_int32_t - * @brief Project-local 4-byte signed int type. - * - * @typedef zb_uint32_t - * @brief Project-local 4-byte unsigned int type. - * - * @typedef zb_bitfield_t - * @brief Type to be used for unsigned bit fields inside structure. - * - * @typedef zb_sbitfield_t - * @brief Type to be used for signed bit fields inside structure. - * - * @typedef zb_size_t - * @brief Project-local size_t type. - * - * @typedef zb_short_t - * @brief Short int (can fit into single CPU register). - * - * @typedef zb_ushort_t - * @brief Short unsigned int (can fit into single CPU register). - * - * @typedef zb_int_t - * @brief Int (at least 2 bytes). - * - * @typedef zb_uint_t - * @brief Unsigned int (at least 2 bytes). - * - * @typedef zb_long_t - * @brief Long int (at least 4 bytes). - * - * @typedef zb_ulong_t - * @brief Unsigned long int (at least 4 bytes). - * - * @typedef zb_bool_t - * @brief Boolean type can be ZB_TRUE or ZB_FALSE - * - * @typedef zb_bitbool_t - * @brief Type to be used for boolean bit fields inside structure. - * @} - */ - -/** - * @name Address types and API. - * @{ - * @typedef zb_64bit_addr_t - * @brief 8-bytes address (xpanid or long device address) base type. - * - * @typedef zb_ieee_addr_t - * @brief Long (64-bit) device address. - * - * @typedef zb_ext_pan_id_t - * @brief Long (64-bit) extended Pan ID. - * - * @union zb_addr_u - * @brief Union to address either long or short address. - * - * @def ZB_IS_64BIT_ADDR_ZERO - * @brief Checks that long address is a zero one. - * @param addr address to check. - * @returns ZB_TRUE if address is zero, ZB_FALSE otherwise. - * - * @def ZB_64BIT_ADDR_ZERO - * @brief Clears long address. - * @param addr address to clear. - * - * @def ZB_64BIT_ADDR_COPY - * @brief Copy long address. - * @param dst where to copy the address. - * @param src address to copy. - * - * @def ZB_64BIT_ADDR_CMP - * @brief Check two long addresses are equal. - * @param one address to compare. - * @param two address to compare to. - * @returns ZB_TRUE if addresses are equal, ZB_FALSE otherwise. - * @} - */ - -/* FIXME: which value to prefer? Because 0x800000 is reserved in ZCL */ -/* IAR C-STAT generates falsepositive for hexadecimal value */ -#define MIN_SIGNED_24BIT_VAL (-8388607LL) /* (0xFF800001LL) */ -#define MAX_SIGNED_24BIT_VAL (0x7FFFFF) -#define MAX_UNSIGNED_24BIT_VAL (0xFFFFFFU) - -/* IAR C-STAT generates falsepositive for hexadecimal value */ -#define MIN_SIGNED_48BIT_VAL (-140737488355327LL) /* (0xFFFF800000000001LL) */ -#define MAX_SIGNED_48BIT_VAL (0x7FFFFFFFFFFF) -#define MAX_UNSIGNED_48BIT_VAL (0xFFFFFFFFFFFFU) - -#define ZB_S64_FROM_S48(x) ((x & 0xFFFFFFFFFFFF) | ((x & 0x800000000000) ? 0xFFFF000000000000 : 0x0)) - -#define ZB_S64_TO_S48(x) ((zb_int64_t)(x & 0xFFFFFFFFFFFF)) - -#define ZB_S32_FROM_S24(x) ((x & 0xFFFFFF) | ((x & 0x800000) ? 0xFF000000 : 0x0)) - -#define ZB_S32_TO_S24(x) ((zb_int32_t)(x & 0xFFFFFF)) - -#ifdef ZB_UINT24_48_SUPPORT - -#define ZB_INT32_MINUS_ONE (0xFFFFFFFF) -#define ZB_INT24_MAX_POSITIVE (0x7FFFFF) - -#define ZB_INT24_IS_NEGATIVE(int24_val) \ - ((int24_val).high & 0x80U) - - -#if defined ZB_LITTLE_ENDIAN - -typedef ZB_PACKED_PRE struct zb_int24_s -{ - zb_uint16_t low; - zb_int8_t high; -} ZB_PACKED_STRUCT zb_int24_t; - -typedef ZB_PACKED_PRE struct zb_uint24_s -{ - zb_uint16_t low; - zb_uint8_t high; -} ZB_PACKED_STRUCT zb_uint24_t; - -typedef ZB_PACKED_PRE struct zb_uint48_s -{ - zb_uint32_t low; - zb_uint16_t high; -} ZB_PACKED_STRUCT zb_uint48_t; - - -typedef ZB_PACKED_PRE struct zb_int48_s -{ - zb_uint32_t low; - zb_int16_t high; -} ZB_PACKED_STRUCT zb_int48_t; - -#else /* defined ZB_BIG_ENDIAN */ - -typedef ZB_PACKED_PRE struct zb_int24_s -{ - zb_int8_t high; - zb_uint16_t low; -} ZB_PACKED_STRUCT zb_int24_t; - -typedef ZB_PACKED_PRE struct zb_uint24_s -{ - zb_uint8_t high; - zb_uint16_t low; -} ZB_PACKED_STRUCT zb_uint24_t; - -typedef ZB_PACKED_PRE struct zb_uint48_s -{ - zb_uint16_t high; - zb_uint32_t low; -} ZB_PACKED_STRUCT zb_uint48_t; - -typedef ZB_PACKED_PRE struct zb_int48_s -{ - zb_int16_t high; - zb_uint32_t low; -} ZB_PACKED_STRUCT zb_int48_t; - -#endif /* ZB_LITTLE_ENDIAN/ZB_BIG_ENDIAN */ - -#define ZB_INIT_INT24(high_val, low_val) \ -{ \ - .low = (low_val), \ - .high = (high_val) \ -} - -#define ZB_ASSIGN_INT24(var, high_val, low_val) \ -{ \ - var.low = (low_val); \ - var.high = (high_val); \ -} - -#define ZB_GET_INT32_FROM_INT24(int24_val) \ - (zb_int32_t) \ - ( \ - ((ZB_INT24_IS_NEGATIVE(int24_val))? ((zb_uint32_t)0xFFU << 24U): 0U) | \ - ((zb_uint32_t)(int24_val).high << 16U) | \ - (int24_val).low \ - ) - -#define ZB_ASSIGN_UINT24_FROM_UINT32(uint32_val) \ -{ \ - .low = (zb_uint16_t)((uint32_val) & 0xFFFFU), \ - .high = (zb_uint8_t)((uint32_val) >> 16U) \ -} - -#define ZB_GET_UINT32_FROM_UINT24(uint24_val) \ -((((zb_uint32_t) (uint24_val).high) << 16) + (uint24_val).low) - -#define ZB_INIT_UINT48(high_val, low_val) \ -{ \ - .low = (low_val), \ - .high = (high_val) \ -} - -#define ZB_INIT_UINT24(high_val, low_val) \ -{ \ - .low = (low_val), \ - .high = (high_val) \ -} - -#define ZB_ASSIGN_UINT48(var, high_val, low_val) \ -{ \ - var.low = (low_val); \ - var.high = (high_val); \ -} - -#define ZB_ASSIGN_UINT24(var, high_val, low_val) \ -{ \ - var.low = (low_val); \ - var.high = (high_val); \ -} - -/* TODO: test for negative int24 */ -#define ZB_UINT48_ADD_INT24(uint48_val, int24_val) \ - if (ZB_INT24_IS_NEGATIVE(int24_val)) \ - { \ - if ((uint48_val).low < (zb_uint32_t)((int24_val).low + (int24_val).high)) \ - { \ - (uint48_val).high -= 1U; \ - } \ - (uint48_val).low -= (int24_val).low + (int24_val).high; \ - } \ - else \ - { \ - if (((zb_uint64_t) (uint48_val).low) + ZB_GET_UINT32_FROM_UINT24(int24_val) > ZB_UINT32_MAX) \ - { \ - (uint48_val).high += 1U; \ - } \ - (uint48_val).low += ZB_GET_UINT32_FROM_UINT24(int24_val); \ - } - -#define ZB_UINT48_IS_EQUAL(val1, val2) \ - (((val1).high == (val2).high) && ((val1).low == (val2).low)) - -#define ZB_UINT48_IS_GREAT(val1, val2) \ - ((val1).high > (val2).high || \ - ((val1).high == (val2).high && (val1).low > (val2).low)) - -#define ZB_UINT48_IS_LESS(val1, val2) \ - (!ZB_UINT48_IS_EQUAL(val1, val2) && !ZB_UINT48_IS_GREAT(val1, val2)) - -#define ZB_UINT48_IS_GREAT_OR_EQUAL(val1, val2) \ - (!ZB_UINT48_IS_LESS(val1, val2)) - -#define ZB_UINT48_IS_LESS_OR_EQUAL(val1, val2) \ - (!ZB_UINT48_IS_GREAT(val1, val2)) - -#if defined ZB_LITTLE_ENDIAN - -#define ZB_HTOLE24(ptr, val) ZB_MEMCPY((ptr), (val), ZB_24BIT_SIZE) -#define ZB_HTOLE48(ptr, val) ZB_MEMCPY((ptr), (val), ZB_48BIT_SIZE) - -#else /* ZB_BIG_ENDIAN */ - -void zb_reverse_bytes(zb_uint8_t *ptr, zb_uint8_t *val, zb_uint8_t size); - -#define ZB_HTOLE24(ptr, val) zb_reverse_bytes((zb_uint8_t*)(ptr), (val), ZB_24BIT_SIZE) -#define ZB_HTOLE48(ptr, val) zb_reverse_bytes((zb_uint8_t*)(ptr), (val), ZB_48BIT_SIZE) - -#endif /* ZB_BIG_ENDIAN */ - -#if defined ZB_UINT24_48_SUPPORT || defined DOXYGEN -/** - * @name 24-bit and 48-bit arithmetic API - * @{ - */ - -/** - * @name Return statuses of mathematical operations - * @anchor math_status - * - * Note: These values were members of `enum zb_math_status_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_MATH_OK 0U -#define ZB_MATH_OVERFLOW 1U -#define ZB_MATH_ERROR 2U -/** @} */ - - -/** - * Convert unsigned 32-bit value to unsigned 24-bit value - * @param[in] var - unsigned 32-bit value - * @param[out] res - pointer to unsigned 24-bit value - */ -void zb_uint32_to_uint24(zb_uint32_t var, zb_uint24_t *res); - - -/** - * Convert signed 24-bit value to signed 32-bit value - * @param[in] var - pointer to signed 24-bit value - * @return signed 32-bit representation of 24-bit value - */ -zb_int32_t zb_int24_to_int32(const zb_int24_t *var); - - -/** - * Convert signed 32-bit value to signed 24-bit value - * @param[in] var - signed 32-bit value - * @param[out] res - pointer to signed 24-bit value (Returns #MAX_SIGNED_24BIT_VAL or #MIN_SIGNED_24BIT_VAL when out of bounds) - */ -void zb_int32_to_int24(zb_int32_t var, zb_int24_t *res); - - -/** - * Convert signed 32-bit value to unsigned 24-bit value - * @param[in] var - signed 32-bit value - * @param[out] res - pointer to unsigned 24-bit value (Returns #MAX_UNSIGNED_24BIT_VAL or 0U when out of bounds) - */ -void zb_int32_to_uint24(zb_int32_t var, zb_uint24_t *res); - - -/** - * Convert unsigned 24-bit value to signed 32-bit value - * @param[in] var - pointer to unsigned 24-bit value - * @return signed 32-bit representation of unsigned 24-bit value - */ -zb_int32_t zb_uint24_to_int32(const zb_uint24_t *var); - - -/** - * Addition of two unsigned 24-bit values - * @param[in] f - pointer to first unsigned 24-bit operand - * @param[in] s - pointer to second unsigned 24-bit operand - * @param[out] r - pointer to unsigned 24-bit variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_uint24_add(const zb_uint24_t *f, const zb_uint24_t *s, zb_uint24_t *r); - - -/** - * Addition of two signed 24-bit values - * @param[in] f - pointer to first signed 24-bit operand - * @param[in] s - pointer to second signed 24-bit operand - * @param[out] r - pointer to 24-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int24_add(const zb_int24_t *f, const zb_int24_t *s, zb_int24_t *r); - - -/** - * Subtraction of two signed 24-bit values - * @param[in] f - pointer to first signed 24-bit operand - * @param[in] s - pointer to second signed 24-bit operand - * @param[out] r - pointer to 24-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int24_sub(const zb_int24_t *f, const zb_int24_t *s, zb_int24_t *r); - - -/** - * Subtraction of two unsigned 24-bit values - * @param[in] f - pointer to first unsigned 24-bit operand - * @param[in] s - pointer to second unsigned 24-bit operand - * @param[out] r - pointer to 24-bit unsigned variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_uint24_sub(const zb_uint24_t *f, const zb_uint24_t *s, zb_uint24_t *r); - - -/** - * Negation of signed 24-bit values - * @param[in] f - pointer to signed 24-bit operand - * @param[out] r - pointer to 24-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int24_neg(const zb_int24_t *f, zb_int24_t *r); - - -/** - * Multiplication of two unsigned 24-bit values - * @param[in] f - pointer to first unsigned 24-bit operand - * @param[in] s - pointer to second unsigned 24-bit operand - * @param[out] r - pointer to 24-bit unsigned variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_uint24_mul(const zb_uint24_t *f, const zb_uint24_t *s, zb_uint24_t *r); - - -/** - * Multiplication of two signed 24-bit values - * @param[in] f - pointer to first signed 24-bit operand - * @param[in] s - pointer to second signed 24-bit operand - * @param[out] r - pointer to 24-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int24_mul(const zb_int24_t *f, const zb_int24_t *s, zb_int24_t *r); - - -/** - * Integer division of two unsigned 24-bit values - * @param[in] f - pointer to first unsigned 24-bit operand - * @param[in] s - pointer to second unsigned 24-bit operand - * @param[out] r - pointer to unsigned 24-bit variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_uint24_div(const zb_uint24_t *f, const zb_uint24_t *s, zb_uint24_t *r); - - -/** - * Integer division of two signed 24-bit values - * @param[in] f - pointer to first signed 24-bit operand - * @param[in] s - pointer to second signed 24-bit operand - * @param[out] r - pointer to 24-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int24_div(const zb_int24_t *f, const zb_int24_t *s, zb_int24_t *r); - - -/** - * Modular division of two unsigned 24-bit values - * @param[in] f - pointer to first unsigned 24-bit operand - * @param[in] s - pointer to second unsigned 24-bit operand - * @param[out] r - pointer to unsigned 24-bit variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_uint24_mod(const zb_uint24_t *f, const zb_uint24_t *s, zb_uint24_t *r); - - -/** - * Modular division of two signed 24-bit values - * @param[in] f - pointer to first signed 24-bit operand - * @param[in] s - pointer to second signed 24-bit operand - * @param[out] r - pointer to 24-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int24_mod(const zb_int24_t *f, const zb_int24_t *s, zb_int24_t *r); - - -/** - * Convert 64-bit value to 48-bit representation - * @param[in] var - 64-bit value - * @param[out] res - pointer to 48-bit variable - */ -void zb_uint64_to_uint48(zb_uint64_t var, zb_uint48_t *res); - - -/** - * Convert signed 48-bit value to signed 64-bit value - * @param[in] var - pointer to signed 48-bit value - * @return signed 64-bit representation of signed 48-bit value - */ -zb_int64_t zb_int48_to_int64(const zb_int48_t *var); - - -/** - * Convert signed 64-bit value to signed 48-bit value - * @param[in] var - signed 64-bit value - * @param[out] res - pointer to signed 48-bit value (Returns #MAX_SIGNED_48BIT_VAL or #MIN_SIGNED_48BIT_VAL when out of the bounds) - */ -void zb_int64_to_int48(zb_int64_t var, zb_int48_t *res); - - -/** - * Convert signed 64-bit value to unsigned 48-bit value - * @param[in] var - signed 64-bit value - * @param[out] res - unsigned 48-bit value (Returns #MAX_UNSIGNED_48BIT_VAL or 0U when out of the bounds) - */ -void zb_int64_to_uint48(zb_int64_t var, zb_uint48_t *res); - - -/** - * Convert unsigned 48-bit value to signed 64-bit value - * @param[in] var - pointer to unsigned 64-bit value - * @return signed 64-bit representation of unsigned 48-bit value - */ -zb_int64_t zb_uint48_to_int64(const zb_uint48_t *var); - - -/** - * Addition of two unsigned 48-bit values - * @param[in] f - pointer to first insigne4824-bit operand - * @param[in] s - pointer to second insigne4824-bit operand - * @param[out] r - pointer to 48signed 24-bit variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_uint48_add(const zb_uint48_t *f, const zb_uint48_t *s, zb_uint48_t *r); - - -/** - * Addition of two signed 48-bit values - * @param[in] f - pointer to first signed 48-bit operand - * @param[in] s - pointer to second signed 48-bit operand - * @param[out] r - pointer to 48-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int48_add(const zb_int48_t *f, const zb_int48_t *s, zb_int48_t *r); - - -/** - * Subtraction of two signed 48-bit values - * @param[in] f - pointer to first signed 48-bit operand - * @param[in] s - pointer to second signed 48-bit operand - * @param[out] r - pointer to 48-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int48_sub(const zb_int48_t *f, const zb_int48_t *s, zb_int48_t *r); - - -/** - * Subtraction of two unsigned 48-bit values - * @param[in] f - pointer to first unsigne4824-bit operand - * @param[in] s - pointer to second unsigne4824-bit operand - * @param[out] r - pointer to 48-bit unsigned variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_uint48_sub(const zb_uint48_t *f, const zb_uint48_t *s, zb_uint48_t *r); - - -/** - * Negation of signed 24-bit values - * @param[in] f - pointer to signed 24-bit operand - * @param[out] r - pointer to 24-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int48_neg(const zb_int48_t *f, zb_int48_t *r); - - -/** - * Multiplication of two unsigned 48-bit values - * @param[in] f - pointer to first unsigned 48-bit operand - * @param[in] s - pointer to second unsigned 48-bit operand - * @param[out] r - pointer to 48-bit unsigned variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_uint48_mul(const zb_uint48_t *f, const zb_uint48_t *s, zb_uint48_t *r); - - -/** - * Multiplication of two signed 48-bit values - * @param[in] f - pointer to first signed 48-bit operand - * @param[in] s - pointer to second signed 48-bit operand - * @param[out] r - pointer to 48-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int48_mul(const zb_int48_t *f, const zb_int48_t *s, zb_int48_t *r); - - -/** - * Integer division of two unsigned 48-bit values - * @param[in] f - pointer to first unsigned 48-bit operand - * @param[in] s - pointer to second unsigned 48-bit operand - * @param[out] r - pointer to unsigned 48-bit variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_uint48_div(const zb_uint48_t *f, const zb_uint48_t *s, zb_uint48_t *r); - - -/** - * Integer division of two signed 48-bit values - * @param[in] f - pointer to first signed 48-bit operand - * @param[in] s - pointer to second signed 48-bit operand - * @param[out] r - pointer to 48-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int48_div(const zb_int48_t *f, const zb_int48_t *s, zb_int48_t *r); - - -/** - * Modular division of two unsigned 48-bit values - * @param[in] f - pointer to first unsigned 48-bit operand - * @param[in] s - pointer to second unsigned 48-bit operand - * @param[out] r - pointer to unsigned 48-bit variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_uint48_mod(const zb_uint48_t *f, const zb_uint48_t *s, zb_uint48_t *r); - - -/** - * Modular division of two signed 48-bit values - * @param[in] f - pointer to first signed 48-bit operand - * @param[in] s - pointer to second signed 48-bit operand - * @param[out] r - pointer to 48-bit signed variable to store result of operation - * @return @e ZB_MATH_OK on success, @e ZB_MATH_OVERFLOW on arithmetic overflow - * and @e ZB_MATH_ERROR on failure (see @ref math_status). - */ -zb_uint8_t zb_int48_mod(const zb_int48_t *f, const zb_int48_t *s, zb_int48_t *r); - -/** @} */ /* 24_and_48_bit_arithm */ - -#define ZB_UINT48_ADD(val1, val2) zb_uint48_add(&val1, &val2, &val1) - -#define ZB_UINT48_SUB(val1, val2) zb_uint48_sub(&val1, &val2, &val1) - -#define ZB_INT24_FROM_INT32(var, int32_val) \ -{ \ - if (int32_val >= 0) \ - { \ - if (int32_val > (zb_int32_t)ZB_INT24_MAX_POSITIVE) \ - { \ - int32_val = (zb_int32_t)ZB_INT24_MAX_POSITIVE; \ - } \ - } \ - else \ - { \ - if (int32_val < (zb_int32_t)ZB_INT32_MINUS_ONE - (zb_int32_t)ZB_INT24_MAX_POSITIVE) \ - { \ - int32_val = (zb_int32_t)ZB_INT32_MINUS_ONE - (zb_int32_t)ZB_INT24_MAX_POSITIVE; \ - } \ - } \ - zb_int32_to_int24(int32_val, &var); \ -} - -#else /* ZB_UINT24_48_SUPPORT */ - -/* Now U48 type implemented as U32 */ -/* Now S24 type implemented as S32 */ - -typedef zb_uint64_t zb_uint48_t; -typedef zb_int64_t zb_int48_t; -typedef zb_int32_t zb_int24_t; -typedef zb_uint32_t zb_uint24_t; - - -#define ZB_INIT_UINT48(high_val, low_val) \ - (high_val) - -#define ZB_ASSIGN_UINT48(high_val, low_val) \ - (high_val) - -/* Stubs for operations with this types */ -#define ZB_UINT48_ADD(val1, val2) ((val1) + (val2)) -#define ZB_UINT48_SUB(val1, val2) ((val1) - (val2)) -#define ZB_UINT48_ADD_INT24(uint48_val, int24_val) ((zb_uint48_t)((uint48_val) + (int24_val))) - -#define ZB_ASSIGN_INT24_FROM_INT32(int32_val) \ - (int32_val) - -#define ZB_GET_INT32_FROM_INT24(int24_val) \ - (int24_val) - -#define ZB_ASSIGN_UINT24_FROM_UINT32(uint32_val) \ - (uint32_val) - -#define ZB_GET_UINT32_FROM_UINT24(uint24_val) \ - (uint24_val) - -#ifdef ZB_LITTLE_ENDIAN - -#define ZB_HTOLE24(ptr, val) ZB_MEMCPY((ptr), (val), ZB_24BIT_SIZE) -#define ZB_HTOLE48(ptr, val) ZB_MEMCPY((ptr), (val), ZB_48BIT_SIZE) - -#else - -#define ZB_HTOLE24(ptr, val) ZB_HTOLE32((ptr), (val)) -#define ZB_HTOLE48(ptr, val) ZB_HTOLE32((ptr), (val)) - -#endif - -#define ZB_UINT48_IS_EQUAL(val1, val2) \ - ((val1) == (val2)) - -#define ZB_UINT48_IS_GREAT(val1, val2) \ - ((val1) > (val2)) - -#define ZB_UINT48_IS_LESS(val1, val2) \ - ((val1) < (val2)) - -#define ZB_UINT48_IS_GREAT_OR_EQUAL(val1, val2) \ - (!ZB_UINT48_IS_LESS(val1, val2)) - -#define ZB_UINT48_IS_LESS_OR_EQUAL(val1, val2) \ - (!ZB_UINT48_IS_GREAT(val1, val2)) - -#endif /* ZB_UINT24_48_SUPPORT */ - -#define PUT_DATA24(ptr, val) (ZB_HTOLE24(ptr, val), (ptr) += ZB_24BIT_SIZE) -#define PUT_DATA24_VAL(ptr, val) \ -{ \ - zb_int24_t tmp_val = (val); \ - ZB_HTOLE24((ptr), &tmp_val); \ - (ptr) += ZB_24BIT_SIZE; \ -} - -#define PUT_DATA48(ptr, val) (ZB_HTOLE48(ptr, val), (ptr) += ZB_48BIT_SIZE) -#define PUT_DATA48_VAL(ptr, val) \ -{ \ - zb_uint48_t tmp_val = (val); \ - ZB_HTOLE48((ptr), &tmp_val); \ - (ptr) += ZB_48BIT_SIZE; \ -} - -/* take MSB nibble from uint8_t */ -#define ZB_UINT8_MSB_NIBBLE(X) (((X) >> 4U) & 0x0FU) - -/* take LSB nibble from uint8_t */ -#define ZB_UINT8_LSB_NIBBLE(X) ((X) & 0x0FU) - -/* convert pair of nibbles into uint8_t */ -#define ZB_UINT4x2_TO_UINT8(MSB_N, LSB_N) \ - ((MSB_N << 4) | ZB_UINT8_LSB_NIBBLE(LSB_N)) - - -#endif /* ZB_UINT24_48_SUPPORT */ - -/** @} */ - -#endif /* ZB_TYPES_H */ diff --git a/zboss/development/include/zb_version.h b/zboss/development/include/zb_version.h deleted file mode 100644 index fbe9dcaf45..0000000000 --- a/zboss/development/include/zb_version.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZBOSS version declare -*/ - -#ifndef ZB_VERSION_H -#define ZB_VERSION_H 1 - -/* - ZBOSS Core version: A.B.C - - ZBOSS_MAJOR (defines ZBOSS core version) - - ZBOSS_MINOR (defines ZBOSS core version) - - ZBOSS SDK revision -*/ - -#ifndef ZBOSS_MAJOR -#define ZBOSS_MAJOR 3U -#endif - -#ifndef ZBOSS_MINOR -#define ZBOSS_MINOR 12U -#endif - -#endif /* ZB_VERSION_H */ diff --git a/zboss/development/include/zb_zgp_default_match_info.h b/zboss/development/include/zb_zgp_default_match_info.h deleted file mode 100644 index 46ac57e9fc..0000000000 --- a/zboss/development/include/zb_zgp_default_match_info.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Provides example of matching table declaration for ZGPS sink -*/ - -#ifndef ZB_ZGP_DEFAULT_MATCH_INFO_H -#define ZB_ZGP_DEFAULT_MATCH_INFO_H 1 - -#include "zb_common.h" - -#ifdef ZB_ENABLE_ZGP_SINK -#include "zboss_api_zgp.h" - -#ifdef ZB_ZGP_SINK_SUPPORT_LEGACY_MATCH_INFO - -/** - * @ingroup zgp_sink - * @file zb_zgp_default_match_info.h - * Provides example of matching table declaration for ZGPS sink - * @include zb_zgp_default_match_info.h - */ - -/** - * Default matching table. - */ -zgps_dev_match_rec_t g_zgps_match_tbl[] = -{ -#ifdef ZGPS_MATCH_TBL_TEMPERATURE_SENSOR_ENTRY - { - ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - {ZB_GPDF_CMD_ATTR_REPORT, ZB_GPDF_CMD_MULTI_CLUSTER_ATTR_REPORT, 0}, - ZB_ZGP_TEMPERATURE_SENSOR_DEV_ID, - }, -#endif - -}; - - -/** - * Mapping of ZGPD commands IDs to Zigbee ZCL commands IDs - */ -zgp_to_zb_cmd_mapping_t g_cmd_mapping[] = -{ -#if defined ZGPS_MATCH_TBL_TEMPERATURE_SENSOR_ENTRY - {ZB_GPDF_CMD_ATTR_REPORT, ZB_ZCL_CMD_REPORT_ATTRIB}, -#endif -}; - - -/** - * Default matching info - */ -zb_zgps_match_info_t g_default_zgps_match_info = -{ - ZB_ARRAY_SIZE(g_zgps_match_tbl), - g_zgps_match_tbl, - ZB_ARRAY_SIZE(g_cmd_mapping), - g_cmd_mapping, - 0, - NULL -}; -#endif /* ZB_ZGP_SINK_SUPPORT_LEGACY_MATCH_INFO */ -#endif /* ZB_ENABLE_ZGP_SINK */ -#endif //ZB_ZGP_DEFAULT_MATCH_INFO_H diff --git a/zboss/development/include/zboss_api.h b/zboss/development/include/zboss_api.h deleted file mode 100644 index 7355b717b8..0000000000 --- a/zboss/development/include/zboss_api.h +++ /dev/null @@ -1,1828 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZBOSS API header -*/ -#ifndef ZBOSS_API_H -#define ZBOSS_API_H 1 - -#include "zb_version.h" -#include "zb_channel_page.h" -#include "zboss_api_core.h" -#include "zboss_api_buf.h" -#include "zboss_api_internal.h" -#include "zboss_api_nwk.h" -#include "zboss_api_af.h" -#include "zboss_api_zdo.h" -#include "zboss_api_aps.h" -#ifdef ZB_ENABLE_HA -#include "zb_ha.h" -#endif -#include "zb_address.h" -#ifdef ZB_ENABLE_SE_MIN_CONFIG -#include "zboss_api_se.h" -#endif -#ifdef ZB_ENABLE_ZCL -#include "zboss_api_zcl.h" -#endif /* ZB_ENABLE_ZCL */ -#ifdef ZB_ENABLE_ZGP -#include "zboss_api_zgp.h" -#endif - -/** @cond (!DOXYGEN_ERL_SECTION) */ -/*! @cond DOXYGEN_SECUR_SECTION */ -/*! @addtogroup secur_api */ -/*! @{ */ - -/** @addtogroup secur_nwk_key NWK keys settings - * @{ - */ -/** @fn void zb_secur_setup_nwk_key(zb_uint8_t *key, zb_uint8_t i) - * @brief Setup NWK key from the application level manually. - * @param key - key to be used - * @param i - key number (0-3) - * @details Call this routine at TC to change random nwk key generated from zb_ib_set_defaults - * to well-known key. To be used in certification tests mainly. - * @snippet simple_gw/simple_gw.c zb_secur_setup_preconfigured_key_value - * @snippet simple_gw/simple_gw.c zb_secur_setup_preconfigured_key - */ -void zb_secur_setup_nwk_key(zb_uint8_t *key, zb_uint8_t i); - -#ifdef ZB_COORDINATOR_ROLE -/** - * Initiate procedure of NWK key switching. - * - * Generate next NWK key if it not exists, broadcast new NWK key, after delay broadcast NWK key switch command. - * Can run at TC only. - * - * @param param - work buffer ID or 0 (is zero, function allocates buffer itself) - */ -void zb_secur_nwk_key_switch_procedure(zb_uint8_t param); -#endif /* ZB_COORDINATOR_ROLE */ -/** @} */ /* secur_nwk_key */ - -/** @addtogroup secur_tc_rejoin TC rejoin settings - * @{ - */ -/** - * Specifies whether unsecure Trust Center Rejoin is allowed. - * - * If set to ZB_FALSE, devices that attempted unsecure rejoin will not be authorized. - * - * @param enable - whether to enable or disable TC Rejoin. - */ -void zb_secur_set_tc_rejoin_enabled(zb_bool_t enable); -/** - * Specifies whether Trust Center Rejoin is ignored. - * - * If set to ZB_TRUE, devices that attempted unsecure rejoin will be ignored. - * - * @param enable - whether to enable or disable TC Rejoin ignore. - */ -void zb_secur_set_ignore_tc_rejoin(zb_bool_t enable); - -/** - * Specifies whether Trust Center Rejoin is allowed, when there is no unique TCLK. - * On joiner device it could be used to perform TC rejoin with legacy ZC. - * - * If set to ZB_TRUE on joiner device, it can make TC rejoin without unique TCLK. - * - * @param enable - whether to enable or disable unsecured TC Rejoin. - */ -void zb_secur_set_unsecure_tc_rejoin_enabled(zb_bool_t enable); - -/** @} */ /* secur_tc_rejoin */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -#ifdef ZB_COORDINATOR_ROLE -#ifndef ZB_LITE_NO_TRUST_CENTER_REQUIRE_KEY_EXCHANGE -/** - * Initiate procedure of NWK key switching. - * - * Generate link key with device, update link key. - * Can run at TC only. - * - * @param addr_of_interest - network address of ZC to ask ZC for KEC. - */ -void se_tc_update_link_key(zb_uint16_t addr_of_interest); -#endif -#endif -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** @addtogroup secur_ic_usage Install code usage - * @{ - */ - -/** - * @name IC types - * @anchor ic_types - */ -/** @{ */ -#define ZB_IC_TYPE_48 0U -#define ZB_IC_TYPE_64 1U -#define ZB_IC_TYPE_96 2U -#define ZB_IC_TYPE_128 3U -#define ZB_IC_TYPE_MAX 4U -/** @} */ - -/** - * @brief Type for IC types. - * - * Holds one of @ref ic_types. Kept only for backward compatibility as - * @ref ic_types were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_ic_types_t; - -/** - * Declares application callback that is called after installcode addition. - * - * @param status - status of installcode addition - */ -typedef void (*zb_secur_ic_add_cb_t)(zb_ret_t status); - -#if (defined ZB_COORDINATOR_ROLE && defined ZB_SECURITY_INSTALLCODES) || (defined DOXYGEN) -/** @fn void zb_secur_ic_add(zb_ieee_addr_t address, zb_uint8_t ic_type, zb_uint8_t *ic, zb_secur_ic_add_cb_t cb) - * @brief Add install code for the device with specified long address - * @param[in] address - long address of the device to add the install code - * @param[in] ic_type - install code type as enumerated in - * @param[in] cb - callback that will be called after installcode addition - * @if ZB_SECUR - * @ref ic_types - * @else - * ic_types - * @endif - * @param[in] ic - pointer to the install code buffer - * @details This call allows to add install codes for several devices into NVRAM. It makes - * sense for Trust Center/Coordinator devices only as usual device doesn't need to have - * someone's else install codes. - * @note This call is valid only for the TC (ZC)! - * @par Example - * @snippet ic_sample/ic_zc.c zb_secur_ic_add_usage_1 - * @snippet ic_sample/ic_zc.c zb_secur_ic_add_usage_2 - */ -void zb_secur_ic_add(zb_ieee_addr_t address, zb_uint8_t ic_type, zb_uint8_t *ic, zb_secur_ic_add_cb_t cb); -#endif /* ZB_COORDINATOR_ROLE && ZB_SECURITY_INSTALLCODES */ - - -/** @fn zb_ret_t zb_secur_ic_set(zb_uint8_t ic_type, zb_uint8_t *ic) - * @brief Set install code for the device - * @param[in] ic_type - install code type as enumerated in - * @if ZB_SECUR - * @ref ic_types - * @else - * ic_types - * @endif - * @param[in] ic - pointer to the install code buffer - * @details This call allows to set the install code for the current device. It is assumed - * that device can have only one install code. - * @note This function is to be run at client side (not at TC). - * @return RET_OK on success or RET_CONVERSION_ERROR on error in install code - * @snippet ic_sample/ic_zr1.c zb_secur_ic_set_usage - */ -zb_ret_t zb_secur_ic_set(zb_uint8_t ic_type, zb_uint8_t *ic); - -/** @brief Request for zb_secur_ic_get_list_req. -*/ -typedef ZB_PACKED_PRE struct zb_secur_ic_get_list_req_s -{ - zb_uint8_t start_index; /*!< Starting Index for the requested elements - * of the IC table */ - zb_callback_t response_cb; /*!< Callback that will be called on response receiving */ -} -ZB_PACKED_STRUCT -zb_secur_ic_get_list_req_t; - -/** @brief Response for zb_secur_ic_get_list_req. -*/ -typedef ZB_PACKED_PRE struct zb_secur_ic_get_list_resp_s -{ - zb_uint8_t status; /*!< The status of the command.*/ - zb_uint8_t ic_table_entries; /*!< Total number of IC table entries within the device */ - zb_uint8_t start_index; /*!< Starting index within the IC table */ - zb_uint8_t ic_table_list_count; /*!< Number of received IC table entries */ -} -ZB_PACKED_STRUCT -zb_secur_ic_get_list_resp_t; - -/** @brief IC entry type zb_secur_ic_get_list_req -*/ -typedef ZB_PACKED_PRE struct zb_secur_ic_entry_s -{ - zb_ieee_addr_t device_address; /*!< Partner address */ - zb_uint8_t options; /* lowest 2 bits [0-1]: 00-48, 01-64, 10-96, 11-128 bits ic type */ - zb_uint8_t align; - zb_uint8_t installcode[ZB_CCM_KEY_SIZE+ZB_CCM_KEY_CRC_SIZE]; /*!< 16b installcode +2b crc */ -} ZB_PACKED_STRUCT zb_secur_ic_entry_t; - -/** @brief Request for zb_secur_ic_get_by_idx_req. - */ -typedef ZB_PACKED_PRE struct zb_secur_ic_get_by_idx_req_s -{ - zb_uint8_t ic_index; /*!< Starting Index for the requested elements - * of the IC table */ - zb_callback_t response_cb; /*!< Callback that will be called on response receiving */ -} -ZB_PACKED_STRUCT -zb_secur_ic_get_by_idx_req_t; - -/** @brief Response for zb_secur_ic_get_by_idx_req. - */ -typedef ZB_PACKED_PRE struct zb_secur_ic_get_by_idx_resp_s -{ - zb_uint8_t status; /*!< The status of the command.*/ - zb_ieee_addr_t device_address; /*!< Partner address */ - zb_ic_types_t ic_type; /*!< Installcode type.*/ - zb_uint8_t installcode[ZB_CCM_KEY_SIZE+ZB_CCM_KEY_CRC_SIZE]; /*!< 16b installcode +2b crc */ - zb_uint8_t ic_index; /*!< Starting Index for the requested elements */ -} -ZB_PACKED_STRUCT -zb_secur_ic_get_by_idx_resp_t; - -/** @brief Request for zb_secur_ic_remove_req. - */ -typedef ZB_PACKED_PRE struct zb_secur_ic_remove_req_s -{ - zb_ieee_addr_t device_address; /*!< Address of the device to remove installcode */ - zb_callback_t response_cb; /*!< Callback that will be called on response receiving */ -} -ZB_PACKED_STRUCT -zb_secur_ic_remove_req_t; - -/** @brief Response for zb_secur_ic_remove_req. - */ -typedef ZB_PACKED_PRE struct zb_secur_ic_remove_resp_s -{ - zb_uint8_t status; /*!< The status of the command.*/ -} -ZB_PACKED_STRUCT -zb_secur_ic_remove_resp_t; - -/** @brief Request for zb_secur_ic_remove_all_req. - */ -typedef ZB_PACKED_PRE struct zb_secur_ic_remove_all_req_s -{ - zb_callback_t response_cb; /*!< Callback that will be called on response receiving */ -} -ZB_PACKED_STRUCT -zb_secur_ic_remove_all_req_t; - -/** @brief Response for zb_secur_ic_remove_all_req. - */ -typedef ZB_PACKED_PRE struct zb_secur_ic_remove_all_resp_s -{ - zb_uint8_t status; /*!< The status of the command.*/ -} -ZB_PACKED_STRUCT -zb_secur_ic_remove_all_resp_t; - -#if defined ZB_COORDINATOR_ROLE && defined ZB_SECURITY_INSTALLCODES -/** - * @brief Get list of the install codes. - * It is valid only for the TC (ZC). - * - * @param param buffer with request parameters, will be also used to store response. - * - * @snippet ic_sample/ic_zc.c zb_secur_ic_get_list_req_usage -*/ -void zb_secur_ic_get_list_req(zb_uint8_t param); - -/** - * @brief Get the install code by index. - * It is valid only for the TC (ZC). - * - * @param param buffer with request parameters, will be also used to store response. - * @snippet ic_sample/ic_zc.c zb_secur_ic_get_by_idx_req_usage -*/ -void zb_secur_ic_get_by_idx_req(zb_uint8_t param); - -/** - * @brief Remove the install code for the device with specified long - * address. - * It is valid only for the TC (ZC). - * - * @param param buffer with request parameters, will be also used to store response. - * @snippet ic_sample/ic_zc.c zb_secur_ic_remove_req_usage -*/ -void zb_secur_ic_remove_req(zb_uint8_t param); - -/** - * Remove the install code for all devices. - * It is valid only for the TC (ZC). - * - * @param param buffer with request parameters, will be also used to store response. - * @snippet ic_sample/ic_zc.c zb_secur_ic_remove_all_req_usage -*/ -void zb_secur_ic_remove_all_req(zb_uint8_t param); -#endif /* ZB_COORDINATOR_ROLE && ZB_SECURITY_INSTALLCODES */ - -/** @fn zb_ret_t zb_secur_ic_str_set(char *ic_str) - * @brief Set install code for the device from character string - * @param[in] ic_str - install code text string - * @details This call allows to set the install code for the current device. It is assumed - * that device can have only one install code. - * @note This function is to be run at client side (not at TC). - * @returns RET_OK on success. - * @snippet ic_sample/ic_zr2.c zb_secur_ic_str_set_usage_1 - * @snippet ic_sample/ic_zr2.c zb_secur_ic_str_set_usage_2 - */ -zb_ret_t zb_secur_ic_str_set(char *ic_str); - -#ifndef ZB_USE_INTERNAL_HEADERS - -/** @fn void zb_secur_ic_str_add(zb_ieee_addr_t address, char *ic_str, zb_secur_ic_add_cb_t cb) - * @brief Add install code for the device from character string - * @param[in] address - long address of the device to add the install code for - * @param[in] ic_str - install code text string - * @param[in] cb - callback that will be called after installcode addition - * @details This call allows to add install codes for several devices into NVRAM. It makes - * sense for Trust Center/Coordinator devices only as usual device doesn't need to have - * someone's else install codes. - * @note This call is valid only for the TC (ZC)! - * @snippet ic_sample/ic_zc.c zb_secur_ic_str_add_usage - */ -void zb_secur_ic_str_add(zb_ieee_addr_t address, char *ic_str, zb_secur_ic_add_cb_t cb); - -#endif /* ZB_USE_INTERNAL_HEADERS */ - -/** - Set installcode policy flag. - - @param allow_ic_only - use ZB_TRUE value to check installcodes - @snippet ic_sample/ic_zc.c zb_set_installcode_policy_usage -*/ -void zb_set_installcode_policy(zb_bool_t allow_ic_only); -/** @} */ /* secur_ic_usage */ - -#ifdef ZB_ROUTER_ROLE -/** @cond DOXYGEN_INTERNAL_DOC */ -/** - Disable APS-encryption of Transport Key from the ZC. - - This valid is only for the TC (ZC). -*/ -void zb_disable_transport_key_aps_encryption(void); -/** - Enable APS-encryption of Transport Key from the ZC. - - This valid is only for the TC (ZC). -*/ -void zb_enable_transport_key_aps_encryption(void); -/** - Get the status of the APS-encryption of Transport Key from the ZC. - - This valid is only for the TC (ZC). - - @return ZB_TRUE when APS-encryption of Transport Key is enabled, ZB_FALSE otherwise -*/ -zb_bool_t zb_is_transport_key_aps_encryption_enabled(void); -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -#endif /* ZB_ROUTER_ROLE */ - -/*! @} */ /* se_secur */ -/*! @endcond */ /* DOXYGEN_SECUR_SECTION */ -/*! @endcond */ /* (!DOXYGEN_ERL_SECTION) */ - -/*! @cond DOXYGEN_GENERAL_SECTION */ -/*! @addtogroup zboss_general_api */ -/*! @{ */ - -#ifdef DOXYGEN -/** - ZBOSS application entry point. - - Application program using ZBOSS must use MAIN() as an entry point and do not implement function main(). - At some, but not at all platforms MAIN() is an alias for main(). - */ -#define MAIN() main(a,v) - - -/** - Return statement of ZBOSS application entry point. - Corresponds to exit() call from main(). - Platform-dependent. - */ -#define MAIN_RETURN(retc) return (retc) - -#endif /* DOXYGEN */ - -/*! @} */ /* zboss_general_api */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -/** - Check whether the right library is selected at application compilation time - - To be called from ZB_INIT() at start. - */ -#ifdef ZB_ED_ROLE -#define ZB_CHECK_LIBRARY() since_you_got_that_symbol_unresolved_you_probably_use_ZB_ED_ROLE_preprocessor_define_while_linking_with_zc_library(); -void since_you_got_that_symbol_unresolved_you_probably_use_ZB_ED_ROLE_preprocessor_define_while_linking_with_zc_library(void); -#else -#define ZB_CHECK_LIBRARY() since_you_got_that_symbol_unresolved_you_probably_forget_use_ZB_ED_ROLE_preprocessor_define_while_linking_with_zed_library(); -void since_you_got_that_symbol_unresolved_you_probably_forget_use_ZB_ED_ROLE_preprocessor_define_while_linking_with_zed_library(void); -#endif /* ZB_ED_ROLE */ - - -/** @endcond*/ /* DOXYGEN_INTERNAL_DOC */ - -/*! @addtogroup zb_general_start */ -/*! @{ */ -#if defined ZB_INIT_HAS_ARGS || defined DOXYGEN -/** - Global stack initialization. - - To be called from MAIN() at start. - - Usual initialization sequence: ZB_INIT(), then assign some IB values, then zboss_start(). - - @param trace_comment - trace file name component (valid for Unix, ignored at MCU) - - @b Example: -@code - ZB_INIT("zdo_zc"); -@endcode - */ -#define ZB_INIT(trace_comment) \ -{ \ - ZB_CHECK_LIBRARY(); \ - zb_init((zb_char_t *)trace_comment); \ -} -/** @cond DOXYGEN_INTERNAL_DOC */ -/** @brief Global stack initialization. - - Don't call directly, use ZB_INIT() instead -*/ -void zb_init(zb_char_t *trace_comment); -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -#else -/** - Global stack initialization. - - To be called from MAIN() at start. - - Usual initialization sequence: ZB_INIT(), then assign some IB values, then zboss_start(). - - @param trace_comment - trace file name component (valid for Unix, ignored at MCU) - - @b Example: -@code - ZB_INIT("zdo_zc"); -@endcode - */ -#define ZB_INIT(trace_comment) \ -{ \ - ZB_CHECK_LIBRARY(); \ - zb_init(); \ -} -void zb_init(void); -#endif /* ZB_INIT_HAS_ARGS || defined DOXYGEN */ -/*! @} */ /* zb_general_start */ - -/*! @addtogroup zb_general_set */ -/*! @{ */ -/** - Set channel mask on device. - @param channel_mask - Zigbee channel mask - - @b Example: -@code - zb_set_channel((1l<<13) | (1l<<14)); -@endcode -*/ -void zb_set_channel_mask(zb_uint32_t channel_mask); - -/** @cond DOXYGEN_BDB_SECTION */ - -#ifdef ZB_OSIF_CONFIGURABLE_TX_POWER -/** - Set transmit power. - @param tx_power - Transmit power [dBm]. - - @b Example: -@code - zb_set_tx_power(0x32); -@endcode -*/ -zb_ret_t zb_set_tx_power(zb_uint8_t tx_power); -#endif - -#ifdef ZB_MAC_CONFIGURABLE_TX_POWER - -/** - * @brief A struct with params for zb_get_tx_power_async and zb_set_tx_power_async - */ -typedef struct zb_tx_power_params_s -{ - zb_ret_t status; /*!< Status of the operation. Can be RET_OK, RET_UNINITIALIZED or one of - RET_INVALID_PARAMETET_1, RET_INVALID_PARAMETET_2 or RET_INVALID_PARAMETET_3 - for the following three fields respectively. */ - zb_uint8_t page; /*!< Page number. Should be provided by the application. */ - zb_uint8_t channel; /*!< Channel number on a given page. Should be provided by the application. */ - zb_int8_t tx_power; /*!< Transceiver power for a given page and channel. - Should be provided by the application in case of setting the power */ - zb_callback_t cb; /*!< Callback function to be called after the function finishes. Should be provided by the application. */ -} zb_tx_power_params_t; - - -/** - * @brief Get transceiver power for given page and channel asynchronously. - * - * This function requires param to contain @ref zb_tx_power_params_t. - * Will return status RET_UNINITIALIZED if the channel/page storage hasn't been initialized yet. - * - * @param param - buffer, containing @ref zb_tx_power_params_t. -*/ -void zb_get_tx_power_async(zb_bufid_t param); - -/** - * @brief Set transceiver power to a given value on a given page and channel asynchronously. - * - * This function requires param to contain @ref zb_tx_power_params_t. - * If the power change is for the current channel, the function will attempt to change power immediately, - * otherwise it will save the change until channel switch. - * - * @param param - buffer, containing @ref zb_tx_power_params_t. -*/ -void zb_set_tx_power_async(zb_bufid_t param); -#endif - -/** @endcond */ /* DOXYGEN_BDB_SECTION */ - -/** - Set RxOnWhenIdle attribute - @param rx_on - attribute value - - @b Example: -@snippet ias_zone_sensor/src/izs_device.c set_rx_on_when_idle_attribute -*/ -void zb_set_rx_on_when_idle(zb_bool_t rx_on); - -/*! @} */ /* zb_general_set */ - -/*! @addtogroup zb_general_get */ -/*! @{ */ - -/** - Returns current state of RX-ON-When-Idle of Zigbee ZED - - @return ZB_TRUE if ZED is not sleepy ZED, ZB_FALSE if ZED is a sleepy ZED - */ -zb_bool_t zb_get_rx_on_when_idle(void); - -/*! @} */ /* zb_general_get */ - -/*! @addtogroup zb_general_start */ -/*! @{ */ - -/** @brief ZBOSS start function. - * - * Typical device start: init, load some parameters from NVRAM and proceed with startup. - * - * Startup means either Formation (for ZC), rejoin or discovery/association join. After startup - * complete @ref zboss_signal_handler callback is called, so application will know when to do - * some useful things. - * - * Precondition: stack must be inited by @ref ZB_INIT() call. @ref ZB_INIT() sets default IB - * parameters, so caller has a chance to change some of them. Note that NVRAM will be loaded after - * zboss_start() call. - * @note ZB is not looped in this routine. Instead, it schedules callback and returns. Caller - * must run @ref zboss_main_loop() after this routine. - * - * @return RET_OK on success. - */ -zb_ret_t zboss_start(void); - - -/*! @} */ /* zb_general_start */ - -/*! @addtogroup zb_general_get */ -/*! @{ */ -/** - * @brief Get ZBOSS version. - * @returns Pointer to zero-terminated version string. - */ -const zb_char_t ZB_IAR_CODE *zb_get_version(void); -/*! @} */ /* zb_general_get */ - -/*! @addtogroup zb_general_start */ -/*! @{ */ - -/** - Start ZBOSS with only minimal initialization, without starting commissioning. - - This function initializes scheduler and buffers pool, but not MAC and upper layers. - Typically zboss_start_no_autostart() is used when application wants to do something before - starting joining the network. - - For example, you can use this function if it is needed to enable leds, timers - or any other devices on periphery to work with them before starting working in a network. It's - also useful if you want to run something locally during joining. - - Application should later call ZBOSS commissioning initiation - for - instance, - @if zb_bdb_mode - @ref bdb_start_top_level_commissioning(). - @else - bdb_start_top_level_commissioning() - @endif - - - To finish node initialization without triggering commissioning call @ref - bdb_start_top_level_commissioning() with commissioning mask 0 (no steering, no formation, - initialization only). - - @return RET_OK on success. - */ -zb_ret_t zboss_start_no_autostart(void); - -void zboss_start_continue(void); - - -#ifdef ZB_ZBOSS_DEINIT - -/** - Initiate ZBOSS shut procedure. - - ZBOSS shutdown is meaningful for Linux platform where it is necessary to stop - or restart ZBOSS without stopping the current process. - - When ZBOSS is ready to be shut, application receives @ref ZB_SIGNAL_READY_TO_SHUT signal. - It then must call @ref zboss_complete_shut() and must not use ZBOSS afterwords. - */ -void zboss_start_shut(zb_bufid_t param); - -/** - Complete ZBOSS shut procedure. - - ZBOSS shutdown is meaningful for Linux platform where it is necessary to stop - or restart ZBOSS without stopping the current process. - - That function must be called after application received @ref - ZB_SIGNAL_READY_TO_SHUT signal. - */ -void zboss_complete_shut(void); -#endif /* #ifdef ZB_ZBOSS_DEINIT */ - -#ifdef ZB_INTERPAN_PREINIT -/** - Start ZBOSS pre-init to be able to send inter-pan before Formation/Join - - That function is to be called after ZB_ZDO_SIGNAL_SKIP_STARTUP signal received, before commissioning start. - After pre-init complete ZBOSS issues ZB_SIGNAL_INTERPAN_PREINIT. - After that it is possible to use zb_intrp_data_request_with_chan_change() API. - - @param param - work buffer -*/ -void zboss_preinit_for_interpan(zb_bufid_t param); -#endif /* #ifdef ZB_INTERPAN_PREINIT */ - -#ifdef ZB_PROMISCUOUS_MODE - -/** - Start ZBOSS in the sniffer mode - - Initialize ZBOSS MAC layer to work as a sniffer. - Once ZBOSS is initialized in the sniffer mode, it can't be commissioned in the - normal mode until reboot. - */ -zb_ret_t zboss_start_in_sniffer_mode(void); - -/** - Start sniffing - - ZBOSS must be started in the sniffer mode. - - @param data_ind_cb - callback to be called to pass data to the sniffer application - */ -void zboss_sniffer_start(zb_callback_t data_ind_cb); - -/** - Stop sniffing or do nothing if not sniffing now. - - ZBOSS must be started in the sniffer mode. - */ -void zboss_sniffer_stop(void); -#endif /* ZB_PROMISCUOUS_MODE */ - -/*! @} */ /* zb_general_start */ - -/*! @addtogroup zb_general_get */ -/*! @{ */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -zb_bool_t zb_zdo_joined(void); -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** - Checks that device is joined to the network. - @return true if device is joined; false - otherwise -*/ -#define ZB_JOINED() zb_zdo_joined() - -/*! @} */ /* zb_general_get */ - -/*! @addtogroup zb_general_main_loop */ -/*! @{ */ - -/** - ZBOSS main loop. - Must be called after ZB_INIT() and zboss_start(). - Loops infinitely. - - @snippet light_sample/dimmable_light/bulb.c zboss_main_loop_init - @snippet light_sample/dimmable_light/bulb.c zboss_main_loop -*/ -void zboss_main_loop(void); - -/** - ZBOSS main loop iteration. - - This function is useful if application wants to do something special in the - main loop without involving ZBOSS scheduler. - - Must be called after ZB_INIT() and zboss_start() / zboss_start_no_autostart() - inside the application's main cycle. - @snippet onoff_server/on_off_switch_zed.c zboss_main_loop_iteration_declaring - @snippet onoff_server/on_off_switch_zed.c zboss_main_loop_iteration_usage -*/ - -void zboss_main_loop_iteration(void); - -/*! @} */ /* zb_general_main_loop */ - -/*! @addtogroup zb_general_set */ -/*! @{ */ - -/** - Set 64-bit long address - @param addr - long address structure -*/ -void zb_set_long_address(const zb_ieee_addr_t addr); - -/** @fn void zb_set_pan_id(zb_uint16_t pan_id) - * @brief Set 16-bit PAN ID - * @param[in] pan_id - PAN ID - */ -void zb_set_pan_id(zb_uint16_t pan_id); - - -/** - * Declares callback that is called after setting manufacturer code - * - * @param status - status of manufacturer code setting - */ -typedef void (*zb_set_manufacturer_code_cb_t)(zb_ret_t status); - -/** - * Set Manufacturer code of Node Descriptor Request - * - * @param manuf_code - manufacturer code to set - * @param cb - callback that is called after manufacturer code setting -*/ -void zb_set_node_descriptor_manufacturer_code_req(zb_uint16_t manuf_code, zb_set_manufacturer_code_cb_t cb); - -/** - Set Extended Pan ID (apsUseExtendedPANID attribute) - @param ext_pan_id - Long (64-bit) Extended Pan ID -*/ -void zb_set_extended_pan_id(const zb_ext_pan_id_t ext_pan_id); - -/*! @} */ /* zb_general_set */ - -/*! @addtogroup zb_general_get */ -/*! @{ */ - -/** - Get 64-bit long address - @param addr - pointer to memory where result will be stored - */ -void zb_get_long_address(zb_ieee_addr_t addr); - -/** - Get 16-bit PAN ID -*/ -zb_uint16_t zb_get_pan_id(void); - -/** Get current short address of the device - */ -zb_uint16_t zb_get_short_address(void); - -/** - Get Extended Pan ID (nwkExtendedPANId attribute) - @param ext_pan_id - pointer to memory where result will be stored - */ -void zb_get_extended_pan_id(zb_ext_pan_id_t ext_pan_id); - -/** - Get the currently used channel page. -*/ -zb_uint8_t zb_get_current_page(void); - -/** - Get the currently used channel. -*/ -zb_uint8_t zb_get_current_channel(void); - -/*! @} */ /* zb_general_get */ - -/*! @addtogroup zb_general_set */ -/*! @{ */ - -#ifdef ZB_COORDINATOR_ROLE -/** - Initiate device as a Zigbee 3.0 (not SE!) coordinator - @param channel_mask - Zigbee channel mask - - @note BDB channel sets that are set using @ref zb_set_bdb_primary_channel_set() and @ref - zb_set_bdb_secondary_channel_set(), are always reset to zero after changing network role of the device. -*/ -void zb_set_network_coordinator_role(zb_uint32_t channel_mask); -#endif /* ZB_COORDINATOR_ROLE */ - -#if defined ZB_ROUTER_ROLE && defined ZB_BDB_MODE && !defined BDB_OLD -/** - Initiate device as a Zigbee Zigbee 3.0 (not SE!) router - @param channel_mask - Zigbee channel mask - - @note BDB channel sets that are set using @ref zb_set_bdb_primary_channel_set() and @ref - zb_set_bdb_secondary_channel_set(), are always reset to zero after changing network role of the device. -*/ -void zb_set_network_router_role(zb_uint32_t channel_mask); -#endif /* ZB_ROUTER_ROLE && ZB_BDB_MODE && !BDB_OLD */ - -#if defined ZB_ED_FUNC && defined ZB_BDB_MODE && !defined BDB_OLD -/** - Initiate device as a Zigbee Zigbee 3.0 (not SE!) End Device - @param channel_mask - Zigbee channel mask - - @note BDB channel sets that are set using @ref zb_set_bdb_primary_channel_set() and @ref - zb_set_bdb_secondary_channel_set(), are always reset to zero after changing network role of the device. -*/ -void zb_set_network_ed_role(zb_uint32_t channel_mask); -#endif /* ZB_ED_FUNC && ZB_BDB_MODE && !BDB_OLD */ - -#ifndef ZB_USE_INTERNAL_HEADERS - -#ifdef ZB_COORDINATOR_ROLE -/** - Initiate device as a legacy (pre-r21) Zigbee coordinator - @param channel_mask - Zigbee channel mask -*/ -void zb_set_network_coordinator_role_legacy(zb_uint32_t channel_mask); -#endif /* ZB_COORDINATOR_ROLE */ - -#ifdef ZB_ROUTER_ROLE -/** - Initiate device as a legacy (pre-r21) Zigbee router - @param channel_mask - Zigbee channel mask -*/ -void zb_set_network_router_role_legacy(zb_uint32_t channel_mask); -#endif /* ZB_ROUTER_ROLE */ - -#ifdef ZB_ED_FUNC -/** - Initiate device as a legacy (pre-r21) Zigbee End Device - @param channel_mask - Zigbee channel mask -*/ -void zb_set_network_ed_role_legacy(zb_uint32_t channel_mask); -#endif /* ZB_ED_FUNC */ - -#endif /* ZB_USE_INTERNAL_HEADERS */ - -/** @cond DOXYGEN_SUBGHZ_FEATURE */ -#ifdef ZB_COORDINATOR_ROLE -/** - Initiate device as a Zigbee 3.0 BDB coordinator with channel list. - Provides functionality to set mask for Sub-GHz and 2.4GHz page. - @param channel_list - Zigbee channels list -*/ -void zb_set_network_coordinator_role_ext(zb_channel_list_t channel_list); -#endif /* ZB_COORDINATOR_ROLE */ - -#if defined ZB_ROUTER_ROLE && defined ZB_BDB_MODE && !defined BDB_OLD -/** - Initiate device as a Zigbee 3.0 BDB router with channel list. - Provides functionality to set mask for Sub-GHz and 2.4GHz page. - @param channel_list - Zigbee channels list -*/ -void zb_set_network_router_role_ext(zb_channel_list_t channel_list); -#endif /* ZB_ROUTER_ROLE && ZB_BDB_MODE && !BDB_OLD */ - -#if defined ZB_ED_FUNC && defined ZB_BDB_MODE && !defined BDB_OLD -/** - Initiate device as a Zigbee 3.0 BDB End Device with channel list. - Provides functionality to set mask for Sub-GHz and 2.4GHz page. - @param channel_list - Zigbee channels list -*/ -void zb_set_network_ed_role_ext(zb_channel_list_t channel_list); -#endif /* ZB_ED_FUNC && ZB_BDB_MODE && !BDB_OLD */ -/** @endcond */ /* DOXYGEN_SUBGHZ_FEATURE */ - -/** @} */ - -/*! @addtogroup zb_general_get */ -/*! @{ */ - -/** - * Returns the device role ID - * - * @return - zb_nwk_device_type_t device_role_id - */ -zb_nwk_device_type_t zb_get_network_role(void); - -/** - * Returns the maximum number of children allowed - */ -zb_uint8_t zb_get_max_children(void); - -/*! @} */ /* zb_general_get */ - -/** @addtogroup zb_general_set -@{ -*/ - -/** @cond DOXYGEN_SE_SECTION */ -#if defined ZB_SE_COMMISSIONING && defined ZB_SE_BDB_MIXED -void zb_se_set_bdb_mode_enabled(zb_bool_t enabled); -#endif /* ZB_SE_COMMISSIONING && ZB_SE_BDB_MIXED */ -/** @endcond */ /* DOXYGEN_SE_SECTION */ - -/** - * @name Channel pages' numbers - * @anchor channel_pages_numbers - * - * Note: These values were members of `enum zb_channel_page_num_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_CHANNEL_PAGE0_2_4_GHZ 0U -#define ZB_CHANNEL_PAGE23_SUB_GHZ 23U -#define ZB_CHANNEL_PAGE24_SUB_GHZ 24U -#define ZB_CHANNEL_PAGE25_SUB_GHZ 25U -#define ZB_CHANNEL_PAGE26_SUB_GHZ 26U -#define ZB_CHANNEL_PAGE27_SUB_GHZ 27U -#define ZB_CHANNEL_PAGE28_SUB_GHZ 28U -#define ZB_CHANNEL_PAGE29_SUB_GHZ 29U -#define ZB_CHANNEL_PAGE30_SUB_GHZ 30U -#define ZB_CHANNEL_PAGE31_SUB_GHZ 31U -/** @} */ - -/** - Initialize a channel list - @param channel_list - pointer to a channel list - */ -void zb_channel_list_init(zb_channel_list_t channel_list); - - -/** - Add channel mask for a specified channel page in a channel list - @param channel_list - pointer to a channel list - @param page_num - channel page number - @ref channel_pages_numbers - @param channel_mask - Zigbee channel mask - - @return RET_OK if ok, else error code - */ -zb_ret_t zb_channel_list_add(zb_channel_list_t channel_list, zb_uint8_t page_num, zb_uint32_t channel_mask); - -/** - Set the maximum number of connected devices. Used for coordinators - and routers - @param max_children - maximum number of connected devices. -*/ -void zb_set_max_children(zb_uint8_t max_children); - -/** - * @name End Device (ED) timeout request - * @anchor nwk_requested_timeout - */ -/** @{ */ -#define ED_AGING_TIMEOUT_10SEC 0U /*!< 10 second timeout */ -#define ED_AGING_TIMEOUT_2MIN 1U /*!< 2 minutes */ -#define ED_AGING_TIMEOUT_4MIN 2U /*!< 4 minutes */ -#define ED_AGING_TIMEOUT_8MIN 3U /*!< 8 minutes */ -#define ED_AGING_TIMEOUT_16MIN 4U /*!< 16 minutes */ -#define ED_AGING_TIMEOUT_32MIN 5U /*!< 32 minutes */ -#define ED_AGING_TIMEOUT_64MIN 6U /*!< 64 minutes */ -#define ED_AGING_TIMEOUT_128MIN 7U /*!< 128 minutes */ -#define ED_AGING_TIMEOUT_256MIN 8U /*!< 256 minutes */ -#define ED_AGING_TIMEOUT_512MIN 9U /*!< 512 minutes */ -#define ED_AGING_TIMEOUT_1024MIN 10U /*!< 1024 minutes */ -#define ED_AGING_TIMEOUT_2048MIN 11U /*!< 2048 minutes */ -#define ED_AGING_TIMEOUT_4096MIN 12U /*!< 4096 minutes */ -#define ED_AGING_TIMEOUT_8192MIN 13U /*!< 8192 minutes */ -#define ED_AGING_TIMEOUT_16384MIN 14U /*!< 16384 minutes */ -/** @} */ - -/** - * @brief Type for End Device (ED) timeout request - * - * @deprecated holds one of @ref nwk_requested_timeout. Kept only for backward compatibility as - * @ref nwk_requested_timeout were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t nwk_requested_timeout_t; - -/** - Set end device timeout. - - Use it on End Device to specify End Device timeout period used in ED Timeout request. - @param to - index in @ref nwk_requested_timeout -*/ -void zb_set_ed_timeout(zb_uint_t to); - -/** - Set keep alive timeout. - - Use it on End Device to specify how often device should poll its parent. - @param to - timeout, in beacon intervals -*/ -void zb_set_keepalive_timeout(zb_uint_t to); - -/** - * @name ZC/ZR supported keepalive methods - * @anchor keepalive_supported_method - */ -/** @{ */ -#define ED_KEEPALIVE_DISABLED 0U /*!< ZC/ZR doesn't support Keepalive feature */ -#define MAC_DATA_POLL_KEEPALIVE 1U /*!< ZC/ZR supports Keepalive feature by means of MAC Data Poll */ -#define ED_TIMEOUT_REQUEST_KEEPALIVE 2U /*!< ZC/ZR supports Keepalive feature by means of ED Timeout Request */ -#define BOTH_KEEPALIVE_METHODS 3U /*!< ZC/ZR supports both MAC Data Poll and ED Timeout Request as Keepalive methods */ -/** @} */ - -/** - * @brief Type for ZC/ZR supported keepalive methods. - * - * Holds one of @ref keepalive_supported_method. Kept only for backward compatibility as - * @ref keepalive_supported_method were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t nwk_keepalive_supported_method_t; - - -/** - Set keep alive mode. - - Use it to set which method a device should use in poll context. - @param mode - the keepalive mode a device wants to set -*/ -void zb_set_keepalive_mode(nwk_keepalive_supported_method_t mode); - -/** @} */ /* zb_general_set */ - - -/** - * @addtogroup zb_comm_signals - * @{ - */ - - -#ifndef ZB_USE_INTERNAL_HEADERS - -/** - ZBOSS application signal handler. - - Mandatory for all applications implemented on the top of ZBOSS stack. - See @ref zdo_app_signal_type. - - @param param - reference to the buffer which contains signal. See @ref zb_get_app_signal. -*/ -void zboss_signal_handler(zb_uint8_t param); - -#endif /* ZB_USE_INTERNAL_HEADERS */ - -/** @} */ /* zb_comm_signals */ - -/*! @endcond */ /* DOXYGEN_GENERAL_SECTION */ - -/*! @cond DOXYGEN_LL_SECTION */ -/*! @addtogroup zboss_nvram */ -/** @{ */ - -/** - * Enum All NVRAM dataset types - * - * ZB_NVRAM_DATASET_NUMBER - count of dataset types. Not a real dataset type! - */ -typedef enum zb_nvram_dataset_types_e -{ - /* Do not use 0 as dataset type: it can be used internally */ - ZB_NVRAM_RESERVED = 0, /**< Reserved value */ - ZB_NVRAM_COMMON_DATA = 1, /**< Dataset, contains common Zigbee data */ - ZB_NVRAM_HA_DATA = 2, /**< Dataset, contains HA profile Zigbee data */ - ZB_NVRAM_ZCL_REPORTING_DATA = 3, /**< Dataset, contains ZCL reporting data */ - ZB_NVRAM_APS_SECURE_DATA_GAP = 4, /**< Reserved value */ - ZB_NVRAM_APS_BINDING_DATA_GAP = 5, /**< Reserved value */ - ZB_NVRAM_HA_POLL_CONTROL_DATA = 6, /**< Dataset, contains HA POLL CONTROL data */ - ZB_IB_COUNTERS = 7, /**< Dataset, contains NIB outgoing frame counter */ - ZB_NVRAM_DATASET_GRPW_DATA = 8, /**< Green Power dataset */ - ZB_NVRAM_APP_DATA1 = 9, /**< Application-specific data #1 */ - ZB_NVRAM_APP_DATA2 = 10, /**< Application-specific data #2 */ - ZB_NVRAM_ADDR_MAP = 11, /**< Dataset stores address map info */ - ZB_NVRAM_NEIGHBOUR_TBL = 12, /**< Dataset stores Neighbor table info */ - ZB_NVRAM_INSTALLCODES = 13, /**< Dataset contains APS installcodes data */ - ZB_NVRAM_APS_SECURE_DATA = 14, /**< Dataset, contains APS secure keys data */ - ZB_NVRAM_APS_BINDING_DATA = 15, /**< Dataset, contains APS binding data */ - ZB_NVRAM_DATASET_GP_PRPOXYT = 16, /**< Green Power Proxy table */ - ZB_NVRAM_DATASET_GP_SINKT = 17, /**< Green Power Sink table */ - ZB_NVRAM_DATASET_GP_CLUSTER = 18, /**< Green Power Cluster data */ - ZB_NVRAM_APS_GROUPS_DATA = 19, /**< Dataset, contains APS groups data */ - ZB_NVRAM_DATASET_SE_CERTDB = 20, /**< Smart Energy Dataset - Certificates DataBase */ - ZB_NVRAM_ZCL_WWAH_DATA = 21, /**< Dataset, contains ZCL WWAH data */ - ZB_NVRAM_DATASET_GP_APP_TBL = 22, /**< Dataset, contains ZCL WWAH data */ - /* Note: added new app_data datasets down and created a hole for new system datasets. - */ - ZB_NVRAM_APP_DATA3 = 27, /**< Application-specific data #3 */ - ZB_NVRAM_APP_DATA4 = 28, /**< Application-specific data #4 */ - ZB_NVRAM_KE_WHITELIST = 29, - ZB_NVRAM_ZDO_DIAGNOSTICS_DATA = 31, /**< Dataset of the Diagnostics cluster */ - ZB_NVRAM_DATASET_NUMBER = 32, /**< Count of Dataset */ - ZB_NVRAM_DATA_SET_TYPE_PAGE_HDR = 30, /**< Special internal dataset type */ -} zb_nvram_dataset_types_t; - -#define ZB_NVRAM_APP_DATASET_NUMBER 4U - -/** - * Declares application callback used for reading application datasets from NVRAM. - * - * @param page - page in NVRAM from data will be read - * @param pos - offset in page - * @param payload_length - number of bytes to read - */ -typedef void (*zb_nvram_read_app_data_t)(zb_uint8_t page, zb_uint32_t pos, zb_uint16_t payload_length); - -/** - * Declares application callback used for writing application datasets into NVRAM. - * - * @param page - page in NVRAM where data will be stored - * @param pos - offset in page - * - * @return - RET_OK on successful write - */ -typedef zb_ret_t (*zb_nvram_write_app_data_t)(zb_uint8_t page, zb_uint32_t pos); - -/** - * Returns size of application datasets - * - * @return - size of application dataset in bytes - */ -typedef zb_uint16_t (*zb_nvram_get_app_data_size_t)(void); - -/** - * Register application callback for reading @ref ZB_NVRAM_APP_DATA1 from NVRAM - * - * @param cb - callback that will be called upon reading dataset - */ -void zb_nvram_register_app1_read_cb(zb_nvram_read_app_data_t cb); - -/** - * Register application callback for reading @ref ZB_NVRAM_APP_DATA2 from NVRAM - * - * @param cb - callback that will be called upon reading dataset - */ -void zb_nvram_register_app2_read_cb(zb_nvram_read_app_data_t cb); - -/** - * Register application callback for reading @ref ZB_NVRAM_APP_DATA3 from NVRAM - * - * @param cb - callback that will be called upon reading dataset - */ -void zb_nvram_register_app3_read_cb(zb_nvram_read_app_data_t cb); - -/** - * Register application callback for reading @ref ZB_NVRAM_APP_DATA4 from NVRAM - * - * @param cb - callback that will be called upon reading dataset - */ -void zb_nvram_register_app4_read_cb(zb_nvram_read_app_data_t cb); - -/** - * Register application callback for writing @ref ZB_NVRAM_APP_DATA1 to NVRAM - * - * @param wcb - callback that will be called upon writing - * @param gcb - this callback will be called upon writing to determine dataset size - */ -void zb_nvram_register_app1_write_cb( - zb_nvram_write_app_data_t wcb, - zb_nvram_get_app_data_size_t gcb); - -/** - * Register application callback for writing @ref ZB_NVRAM_APP_DATA2 to NVRAM - * - * @param wcb - callback that will be called upon writing - * @param gcb - this callback will be called upon writing to determine dataset size - */ -void zb_nvram_register_app2_write_cb( - zb_nvram_write_app_data_t wcb, - zb_nvram_get_app_data_size_t gcb); - -/** - * Register application callback for writing @ref ZB_NVRAM_APP_DATA3 to NVRAM - * - * @param wcb - callback that will be called upon writing - * @param gcb - this callback will be called upon writing to determine dataset size - */ -void zb_nvram_register_app3_write_cb( - zb_nvram_write_app_data_t wcb, - zb_nvram_get_app_data_size_t gcb); - -/** - * Register application callback for writing @ref ZB_NVRAM_APP_DATA4 to NVRAM - * - * @param wcb - callback that will be called upon writing - * @param gcb - this callback will be called upon writing to determine dataset size - */ -void zb_nvram_register_app4_write_cb( - zb_nvram_write_app_data_t wcb, - zb_nvram_get_app_data_size_t gcb); - -/** - * Write specified dataset into NVRAM - * - * @param t - dataset index, see @ref zb_nvram_dataset_types_e - * @return Status of operation - * - * @b Example - * @snippet light_sample/dimmable_light/bulb.c nvram_usage_example - */ -zb_ret_t zb_nvram_write_dataset(zb_nvram_dataset_types_t t); - -/** @cond DOXYGEN_INTERNAL_DOC */ -/** - * Clears all datasets except @ref ZB_IB_COUNTERS and application datasets. - */ -void zb_nvram_clear(void); - -/** - Disable using NVRAM till ZBOSS restart - */ -void zb_nvram_disable(void); -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -#ifndef ZB_USE_INTERNAL_HEADERS -/** - Erase Informational Bases to NVRAM or other persistent storage - */ -void zb_nvram_erase(void); -#endif /* ZB_USE_INTERNAL_HEADERS */ - -/** - Enable or disable NVRAM erasing on every application startup. - @param erase - 1 to enable erasing; 0 - disable. - Erasing is disabled by default. -*/ -void zb_set_nvram_erase_at_start(zb_bool_t erase); - -/** - Start NVRAM transaction. - - Start writing multiple datasets at once. - A transaction must finished by calling zb_nvram_transaction_commit(). - */ -void zb_nvram_transaction_start(void); - -/** - Commit NVRAM transaction. - - Finish writing multiple datasets at once. - A transaction must started by calling zb_nvram_transaction_start(). - */ -void zb_nvram_transaction_commit(void); - -/** - * Reads a portion of some dataset. - * - * @param page - an NVRAM page to read from - * @param pos - a position on the NVRAM page - * @param buf - a buffer where read data will be saved - * @param len - a data length to read - * - * @return Status of operation - */ -zb_ret_t zb_nvram_read_data(zb_uint8_t page, zb_uint32_t pos, zb_uint8_t *buf, zb_uint16_t len); - - -/** - * Writes a portion of some dataset. - * - * @param page - an NVRAM page to write - * @param pos - a position on the NVRAM page - * @param buf - a buffer with data to be written - * @param len - a buffer size - * - * @return Status of operation - */ -zb_ret_t zb_nvram_write_data(zb_uint8_t page, zb_uint32_t pos, zb_uint8_t *buf, zb_uint16_t len); - -/** @} */ /* zboss_nvram */ -/*! @endcond */ /* DOXYGEN_LL_SECTION */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -#define ZB_INVALID_TX_POWER_VALUE 0x7F -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -#ifdef ZB_PRODUCTION_CONFIG - -/** @cond DOXYGEN_INTERNAL_DOC */ -/** Maximum size of production configuration */ -#define ZB_PRODUCTION_CONFIG_APP_MAX_SIZE 128U - -typedef ZB_PACKED_PRE struct zb_production_config_hdr_s -{ - zb_uint32_t crc; /*!< crc for the whole production configuration (including application specific part) */ - zb_uint16_t len; /*!< length of production configuration (including application specific part) */ - zb_uint16_t version; /*!< Version of production configuration (reserved for future changes) */ -} -ZB_PACKED_STRUCT zb_production_config_hdr_t; - -typedef ZB_PACKED_PRE struct zb_production_config_ver_1_s -{ - zb_production_config_hdr_t hdr; /*!< Header */ - zb_uint32_t aps_channel_mask; /*!< APS Channel Mask */ - zb_64bit_addr_t extended_address; /*!< IEEE address */ - zb_int8_t mac_tx_power[16]; /*!< Tx power specified for every possible channel */ - zb_uint8_t install_code[ZB_CCM_KEY_SIZE+ZB_CCM_KEY_CRC_SIZE]; /*!< Installation code + its own crc */ -} -ZB_PACKED_STRUCT zb_production_config_ver_1_t; - -/* NOTE: ZB_PROD_CFG_V2_APS_CHANNEL_LIST_SIZE support only 4 subghz pages 28-31 and 2.4. */ -#define ZB_PROD_CFG_V2_APS_CHANNEL_LIST_SIZE 5U -/* NOTE: ZB_PROD_CFG_V3_APS_CHANNEL_LIST_SIZE for prod config with support 9 subghz pages 23-31 and 2.4. */ -#define ZB_PROD_CFG_V3_APS_CHANNEL_LIST_SIZE (ZB_PROD_CFG_V2_APS_CHANNEL_LIST_SIZE + 5U) -#define ZB_PROD_CFG_MAC_TX_POWER_CHANNEL_N 27U - -#define ZB_PROD_CFG_OPTIONS_IC_TYPE_MASK 0x03U -#define ZB_PROD_CFG_OPTIONS_CERT_PRESENT_MASK 0x80U - -typedef ZB_PACKED_PRE struct zb_production_config_ver_2_s -{ - zb_production_config_hdr_t hdr; /*!< Header */ - zb_channel_page_t aps_channel_mask_list[ZB_PROD_CFG_V2_APS_CHANNEL_LIST_SIZE]; /*!< Channel mask for device to operate on */ - zb_64bit_addr_t extended_address; /*!< IEEE address */ - zb_int8_t mac_tx_power[ZB_PROD_CFG_V2_APS_CHANNEL_LIST_SIZE][ZB_PROD_CFG_MAC_TX_POWER_CHANNEL_N]; /*! < Tx power specified for every possible channel */ - zb_uint8_t options;/*low 2 bits - ic_type field *//*7th bit - certificates block presents*/ - zb_uint8_t install_code[ZB_CCM_KEY_SIZE+ZB_CCM_KEY_CRC_SIZE]; /*!< Installation code + its own crc */ -} -ZB_PACKED_STRUCT zb_production_config_ver_2_t; - -typedef ZB_PACKED_PRE struct zb_production_config_ver_3_s -{ - zb_production_config_hdr_t hdr; /*!< Header */ - zb_channel_page_t aps_channel_mask_list[ZB_PROD_CFG_V3_APS_CHANNEL_LIST_SIZE]; /*!< Channel mask for device to operate on */ - zb_64bit_addr_t extended_address; /*!< IEEE address */ - zb_int8_t mac_tx_power[ZB_PROD_CFG_V3_APS_CHANNEL_LIST_SIZE][ZB_PROD_CFG_MAC_TX_POWER_CHANNEL_N]; /*! < Tx power specified for every possible channel */ - zb_uint8_t options;/*low 2 bits - ic_type field *//*7th bit - certificates block presents*/ - zb_uint8_t install_code[ZB_CCM_KEY_SIZE+ZB_CCM_KEY_CRC_SIZE]; /*!< Installation code + its own crc */ -} -ZB_PACKED_STRUCT zb_production_config_ver_3_t; - -typedef union zb_production_config_e -{ - zb_production_config_ver_2_t v2; - zb_production_config_ver_3_t v3; -} zb_production_config_t; - -#define ZB_CS1_PUBLISHER_PUBLIC_KEY_SIZE 22 -#define ZB_CS1_CERTIFICATE_SIZE 48 -#define ZB_CS1_PRIVATE_KEY_SIZE 21 - -#define ZB_CS2_PUBLISHER_PUBLIC_KEY_SIZE 37 -#define ZB_CS2_CERTIFICATE_SIZE 74 -#define ZB_CS2_PRIVATE_KEY_SIZE 36 - -typedef ZB_PACKED_PRE struct zb_cs1_key_material_s -{ - zb_uint8_t publisher_public_key[ZB_CS1_PUBLISHER_PUBLIC_KEY_SIZE]; - zb_uint8_t certificate[ZB_CS1_CERTIFICATE_SIZE]; - zb_uint8_t private_key[ZB_CS1_PRIVATE_KEY_SIZE]; -} ZB_PACKED_STRUCT zb_cs1_key_material_t; - -typedef ZB_PACKED_PRE struct zb_cs2_key_material_s -{ - zb_uint8_t publisher_public_key[ZB_CS2_PUBLISHER_PUBLIC_KEY_SIZE]; - zb_uint8_t certificate[ZB_CS2_CERTIFICATE_SIZE]; - zb_uint8_t private_key[ZB_CS2_PRIVATE_KEY_SIZE]; -} ZB_PACKED_STRUCT zb_cs2_key_material_t; - -typedef ZB_PACKED_PRE struct zb_cs_key_material_header_s -{ - zb_uint16_t certificate_mask; -} ZB_PACKED_STRUCT zb_cs_key_material_header_t; - -#define ZB_PROD_CFG_IS_PRESENT_CERT_ANY(v) ((v->options) & 0x80U) -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** - * Disable usage of production configuration at runtime. - * - * @param val - ZB_TRUE means production configuration is disabled, ZB_FALSE - enabled. - */ -void zb_production_config_disable(zb_bool_t val); - -/** - * Get state of production configuration disabling. - * - * @return ZB_TRUE if production configuration is disabled, ZB_FALSE - enabled. - */ -zb_bool_t zb_is_production_config_disabled(void); - -zb_ret_t zb_production_config_check(zb_production_config_hdr_t *prod_cfg_hdr); - -#endif /* ZB_PRODUCTION_CONFIG */ - - - - -#ifdef ZB_USE_SLEEP -/*! @cond DOXYGEN_LL_SECTION */ -/*! @addtogroup sleep_api */ -/*! @{ */ - -/** Default sleep threshold. Do not sleep when it is less then 1 Beacon Interval to wake up. */ -#define ZB_SCHED_SLEEP_THRESHOLD_MS 20U - -/** Maximum sleep threshold. */ -#define ZB_MAXIMUM_SLEEP_THRESHOLD_MS 86400000U - -/** - Set sleep threshold on device; when scheduler detects that device can be put in sleep mode - it will notify application with signal @see ZB_COMMON_SIGNAL_CAN_SLEEP. - Device can not be put into sleep mode when sleep interval less than this threshold. - - @param threshold_ms - sleep threshold in milliseconds - If threshold is 0, means zero threshold, application will be notified each time when stack is ready to sleep - (no immediate callbacks in queue). - @return RET_OK if new threshold is valid and applied - @return RET_ERROR if user wants to set threshold greater that @ref ZB_MAXIMUM_SLEEP_THRESHOLD_MS or lesser than ZB_SCHED_SLEEP_THRESHOLD_MS. -*/ -zb_ret_t zb_sleep_set_threshold(zb_uint32_t threshold_ms); - -/** - Get sleep threshold value from stack. - @return threshold value in milliseconds -*/ -zb_uint32_t zb_get_sleep_threshold(void); - -/** - Blocking function responsible for putting device into sleep mode. - -*/ -void zb_sleep_now(void); - -/*! @} */ /* sleep_api */ -/*! @endcond */ /* DOXYGEN_LL_SECTION */ -#endif /* ZB_USE_SLEEP */ - -#if defined ZB_JOINING_LIST_SUPPORT - -/** - * \addtogroup zdo_joining_lists - * @{ - * @details - * The API executes only one operation at a time. - * It is necessary to account for that, issuing another operation - * only on completion of the previous one. See examples. - */ - - - -/** Parameters for @ref zb_ieee_joining_list_add. */ -typedef ZB_PACKED_PRE struct zb_ieee_joining_list_add_params_s -{ - zb_callback_t callback; /**< Callback to be scheduled on completion of adding. */ - - zb_ieee_addr_t address; /**< 64-bit address to add. */ - -} ZB_PACKED_STRUCT zb_ieee_joining_list_add_params_t; - - -/** Parameters for @ref zb_ieee_joining_list_delete. */ -typedef ZB_PACKED_PRE struct zb_ieee_joining_list_delete_params_s -{ - zb_callback_t callback; /**< Callback to be scheduled on completion of deleting. */ - - zb_ieee_addr_t address; /**< 64-bit address to delete. */ - -} ZB_PACKED_STRUCT zb_ieee_joining_list_delete_params_t; - - -/** - * @name MAC joining policy - * @anchor mac_joining_policy - * @brief MAC joining policy, see Table D-4 of Zigbee r22 spec. - */ -/** @{ */ -#define ZB_MAC_JOINING_POLICY_ALL_JOIN 0x0U /*!< Any device is allowed to join. */ -#define ZB_MAC_JOINING_POLICY_IEEELIST_JOIN 0x1U /*!< Only devices on the mibJoiningIeeeList are allowed to join.*/ -#define ZB_MAC_JOINING_POLICY_NO_JOIN 0x2U /*!< No device is allowed to join. */ -/** @} */ - -/** - * @brief Type for MAC joining policy. - * - * Holds one of @ref mac_joining_policy. Kept for backward compatibility as - * @ref mac_joining_policy were declared previously as enum. - */ -typedef zb_uint8_t zb_mac_joining_policy_t; - -/** Parameters for @ref zb_ieee_joining_list_clear. */ -typedef ZB_PACKED_PRE struct zb_ieee_joining_list_clear_params_s -{ - zb_callback_t callback; /**< Callback to be scheduled on completion - of clearing IEEE joining list. */ - - zb_mac_joining_policy_t new_joining_policy; /**< Joining list policy to set on the emptied list. - See @ref mac_joining_policy for possible - values.*/ - -} ZB_PACKED_STRUCT zb_ieee_joining_list_clear_params_t; - - -/** Parameters for @ref zb_ieee_joining_list_set_policy. */ -typedef ZB_PACKED_PRE struct zb_ieee_joining_list_set_policy_s -{ - zb_callback_t callback; /**< Callback to be scheduled on completion - of updating IEEE joining list policy. */ - - zb_mac_joining_policy_t new_joining_policy; /**< Joining list policy to set on the emptied list. - See @ref mac_joining_policy for possible - values.*/ - -} ZB_PACKED_STRUCT zb_ieee_joining_list_set_policy_t; - - -/** Parameters for @ref zb_ieee_joining_list_announce. */ -typedef ZB_PACKED_PRE struct zb_ieee_joining_list_announce_s -{ - zb_callback_t callback; /**< Callback to be scheduled on completion - of clearing IEEE joining list. */ - - zb_bool_t silent; /**< If set to ZB_TRUE, no broadcast happens. */ -} ZB_PACKED_STRUCT zb_ieee_joining_list_announce_t; - - -/** Parameters for @ref zb_ieee_joining_list_request. */ -typedef ZB_PACKED_PRE struct zb_ieee_joining_list_request_s -{ - zb_callback_t callback; /**< Callback to be scheduled on completion of the operation. */ -} ZB_PACKED_STRUCT zb_ieee_joining_list_request_t; - - -/** - * @name IEEE joining list result status - * @anchor ieee_joining_list_result_status - */ -/** @{ */ - -/** Operation completed successfully. */ -#define ZB_IEEE_JOINING_LIST_RESULT_OK 0U -/** Operation failed due to problems within ZBOSS. */ -#define ZB_IEEE_JOINING_LIST_RESULT_INTERNAL_ERROR 1U -/** Operation failed due to incorrect behavior of the opposite side. */ -#define ZB_IEEE_JOINING_LIST_RESULT_BAD_RESPONSE 2U -/** Basic conditions for execution of the operation are not satisfied (for example, it must be used - * by routers only, etc). */ -#define ZB_IEEE_JOINING_LIST_RESULT_PERMISSION_DENIED 3U -/** The situation forces the command to be restarted.*/ -#define ZB_IEEE_JOINING_LIST_RESULT_RESTART_LATER 4U -/** The device does not have storage space to support the requested operation. */ -#define ZB_IEEE_JOINING_LIST_RESULT_INSUFFICIENT_SPACE 5U - -/** @} */ - -/** - * @brief Type for IEEE joining list result status. - * - * Holds one of @ref ieee_joining_list_result_status. Kept for backward - * compatibility as @ref ieee_joining_list_result_status were declared previously as enum. - */ -typedef zb_uint8_t zb_ieee_joining_list_result_status_t; - - -/** Structure passed as a parameter to operation completion callbacks. */ -typedef ZB_PACKED_PRE struct zb_ieee_joining_list_result_s -{ - zb_ieee_joining_list_result_status_t status; -} ZB_PACKED_STRUCT zb_ieee_joining_list_result_t; - -/** - * Add an address to IEEE joining list. - * - * For coordinators only. - * - * @param param - Reference to buffer containing @ref zb_ieee_joining_list_add_params_t structure as a parameter. - * - * @b Example: - @code - -void function_add_cb(zb_uint8_t param) -{ - zb_ieee_joining_list_result_t *res; - zb_bufid_t buf = ZB_GET_BUF_FROM_REF(param); - - res = ZB_BUF_GET_PARAM(buf, zb_ieee_joining_list_result_t); - if (res->status == ZB_IEEE_JOINING_LIST_RESULT_OK) - { - TRACE_MSG(TRACE_APP1, "Address has been added", (FMT__0)); - } - - zb_free_buf(buf); -} - -/∗ 00:00:00:00:00:00:0E:01 ∗/ -static zb_ieee_addr_t new_addr = {0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -void function_add(zb_uint8_t param) -{ - zb_ieee_joining_list_add_params_t *add_params; - zb_bufid_t buf = ZB_GET_BUF_FROM_REF(param); - - add_params = ZB_BUF_GET_PARAM(buf, zb_ieee_joining_list_set_policy_t); - ZB_MEMCPY(add_params->address, &new_addr, sizeof(new_addr)); - add_params->callback = &function_add_cb; - - zb_ieee_joining_list_add(param); -} - @endcode - */ -void zb_ieee_joining_list_add(zb_uint8_t param); - - -/** - * Remove an address from IEEE joining list. - * - * For coordinators only. - * - * @param param - Reference to buffer containing @ref zb_ieee_joining_list_delete_params_t structure as a parameter. - */ -void zb_ieee_joining_list_delete(zb_uint8_t param); - - -/** - * Clear IEEE joining list. - * - * For coordinators only. - * - * @param param - Reference to buffer containing @ref zb_ieee_joining_list_clear_params_t structure as a parameter. - * - * @b Example: - @code - -void function_clear_cb(zb_uint8_t param) -{ - zb_ieee_joining_list_result_t *res; - zb_bufid_t buf = ZB_GET_BUF_FROM_REF(param); - - res = ZB_BUF_GET_PARAM(buf, zb_ieee_joining_list_result_t); - if (res->status == ZB_IEEE_JOINING_LIST_RESULT_OK) - { - TRACE_MSG(TRACE_APP1, "IEEE joining list is empty now", (FMT__0)); - } - - zb_free_buf(buf); -} - -void function_clear(zb_uint8_t param) -{ - zb_ieee_joining_list_clear_params_t *clear_params; - zb_bufid_t buf = ZB_GET_BUF_FROM_REF(param); - - clear_params = ZB_BUF_GET_PARAM(buf, zb_ieee_joining_list_clear_params_t); - clear_params->new_joining_policy = ZB_MAC_JOINING_POLICY_NO_JOIN; - clear_params->callback = &function_clear_cb; - - zb_ieee_joining_list_clear(param); -} - @endcode - */ -void zb_ieee_joining_list_clear(zb_uint8_t param); - - -/** - * Set joining policy for IEEE joining list. - * - * For coordinators only. - * - * @param param - Reference to buffer containing @ref zb_ieee_joining_list_set_policy_t structure as a parameter. - * - * @b Example: - @code - -void function_policy_cb(zb_uint8_t param) -{ - zb_ieee_joining_list_result_t *res; - zb_bufid_t buf = ZB_GET_BUF_FROM_REF(param); - - res = ZB_BUF_GET_PARAM(buf, zb_ieee_joining_list_result_t); - if (res->status == ZB_IEEE_JOINING_LIST_RESULT_OK) - { - TRACE_MSG(TRACE_APP1, "New policy has been set", (FMT__0)); - } - - zb_free_buf(buf); -} - -void function_policy(zb_uint8_t param) -{ - zb_ieee_joining_list_set_policy_t *policy_params; - zb_bufid_t buf = ZB_GET_BUF_FROM_REF(param); - - policy_params = ZB_BUF_GET_PARAM(buf, zb_ieee_joining_list_set_policy_t); - policy_params->new_joining_policy = ZB_MAC_JOINING_POLICY_NO_JOIN; - policy_params->callback = &function_policy_cb; - - zb_ieee_joining_list_set_policy(param); -} - @endcode - */ -void zb_ieee_joining_list_set_policy(zb_uint8_t param); - - -/** - * Increases update_id, marks IEEE joining list as consistent and broadcasts changes. - * - * For coordinators only. - * - * @param param - Reference to buffer containing @ref zb_ieee_joining_list_announce_t structure as a parameter. - */ -void zb_ieee_joining_list_announce(zb_uint8_t param); - - -/** - * Request IEEE joining list from the Trust Center. - * - * For routers only. - * - * If the Trust Center updates its list during zb_ieee_joining_list_request execution, - * zb_ieee_joining_list_request fails with ZB_IEEE_JOINING_LIST_RESULT_RESTART_LATER status. - * - * @param param - Reference to buffer containing @ref zb_ieee_joining_list_request_t structure as a parameter. - */ -void zb_ieee_joining_list_request(zb_uint8_t param); -/*!@} */ /* zdo_joining_lists */ - -#endif /* defined ZB_JOINING_LIST_SUPPORT */ - -#ifdef ZB_SECURITY_INSTALLCODES -/** - Set using of install codes by TC - - @param use_ic - enable/disable install code usage -*/ -void zb_tc_set_use_installcode(zb_uint8_t use_ic); -#endif /* ZB_SECURITY_INSTALLCODES */ - -#if defined ZB_ED_FUNC && defined ZB_CONTROL4_NETWORK_SUPPORT -/** - Permit joining Control4 Network -*/ -void zb_permit_control4_network(void); - -/** - Return if joining Control4 Network is allowed -*/ -zb_bool_t zb_control4_network_permitted(void); - -#endif /* defined ZB_ED_FUNC && defined ZB_CONTROL4_NETWORK_SUPPORT */ - -/** - * @brief Set the 'macTransactionPersistenceTime' attribute in the MAC PIB - * - * @param ms - value in milliseconds - */ -void zb_set_mac_transaction_persistence_time(zb_uint16_t ms); - -#endif /*ZBOSS_API_H*/ diff --git a/zboss/development/include/zboss_api_af.h b/zboss/development/include/zboss_api_af.h deleted file mode 100644 index bff605452a..0000000000 --- a/zboss/development/include/zboss_api_af.h +++ /dev/null @@ -1,687 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZBOSS AF API -*/ - -#ifndef ZBOSS_API_AF_H -#define ZBOSS_API_AF_H 1 - -/** - * @addtogroup af_api - * @{ - */ - -/** - * @addtogroup af_data_service AF data service - * @{ - */ - -/** - Node descriptor - */ -typedef ZB_PACKED_PRE struct zb_af_node_desc_s -{ - zb_uint16_t node_desc_flags; /*!< node description */ - zb_uint8_t mac_capability_flags; /*!< mac capability */ - zb_uint16_t manufacturer_code; /*!< Manufacturer code */ - zb_uint8_t max_buf_size; /*!< Maximum buffer size */ - zb_uint16_t max_incoming_transfer_size; /*!< Maximum incoming transfer size */ - zb_uint16_t server_mask; /*!< Server mask */ - zb_uint16_t max_outgoing_transfer_size; /*!< Maximum outgoing transfer size */ - zb_uint8_t desc_capability_field; /*!< Descriptor capability field */ -} -ZB_PACKED_STRUCT -zb_af_node_desc_t; - -typedef zb_nwk_device_type_t zb_logical_type_t; - -/** @} */ /* af_data_service */ - -/** - * @addtogroup af_node_desc_dev_types AF device types - * @{ - */ -/** Device type - Coordinator */ -#define ZB_COORDINATOR ZB_NWK_DEVICE_TYPE_COORDINATOR -/** Device type - Router */ -#define ZB_ROUTER ZB_NWK_DEVICE_TYPE_ROUTER -/** Device type - End Device */ -#define ZB_END_DEVICE ZB_NWK_DEVICE_TYPE_ED -/*! @} */ /* af_node_desc_dev_types */ - -/** - * @addtogroup af_common_constants AF common constants - * @{ - */ -/** - * @name Node descriptor - frequency value - * @anchor freq_band - * - * Note: These values were members of `enum zb_freq_band_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_FREQ_BAND_868 1U /*!< 868-868.6 MHz BPSK */ -#define ZB_FREQ_BAND_SUB_GHZ_NA_FSK (1U << 2) /*!< 902-928 MHz BPSK */ -#define ZB_FREQ_BAND_2400 (1U << 3) /*!< 2400-2483.5 MHz */ -/** Zigbee R22: European FSK sub-GHz bands (863-876MHz, 915-921MHz) */ -#define ZB_FREQ_BAND_SUB_GHZ_EU_FSK (1U << 4) -/** @} */ - -/** - * @name Node descriptor - server mask - * @anchor server_mask_bit - * - * Note: These values were members of `enum zb_server_mask_bit_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_PRIMARY_TRUST_CENTER 1U /*!< Primary Trust Center */ -#define ZB_BACKUP_TRUST_CENTER (1U << 1) /*!< Backup Trust Center */ -#define ZB_PRIMARY_BINDING_TABLE_CENTER (1U << 2) /*!< Primary Binding Table Center */ -#define ZB_BACKUP_BINDING_TABLE_CENTER (1U << 3) /*!< Backup Binding Table Center */ -#define ZB_PRIMARY_DISCOVERY_CACHE (1U << 4) /*!< Primary Discovery Cache */ -#define ZB_BACKUP_DISCOVERY_CACHE (1U << 5) /*!< Backup Discovery Cache */ -#define ZB_NETWORK_MANAGER (1U << 6) /*!< Network Manager */ -/** @} */ - -/** - * @name Node descriptor - capability mask - * @anchor desc_capability - * - * Note: These values were members of `enum zb_desc_capability_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_EXT_ACTIVE_EP_LIST 1U /*!< Extended Active Endpoint List Available */ -#define ZB_EXT_SIMPLE_DESC_LIST (1U << 1) /*!< Extended Simple Descriptor List Available */ -/** @} */ - -/** - * @name Power descriptor types - * @anchor current_power_mode - */ -/** @{ */ -/*!< Receiver synchronized with the receiver on when idle subfield of the node descriptor. */ -#define ZB_POWER_MODE_SYNC_ON_WHEN_IDLE 0U -/*!< Receiver comes on periodically as defined by the node power descriptor. */ -#define ZB_POWER_MODE_COME_ON_PERIODICALLY 1U -/*!< Receiver comes on when stimulated, for example, by a user pressing a button. */ -#define ZB_POWER_MODE_COME_ON_WHEN_STIMULATED 2U -/** @} */ - -/** - * @brief Type for power descriptor types. - * - * Holds one of @ref current_power_mode. Kept only for backward compatibility as - * @ref current_power_mode were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_current_power_mode_t; - -/** - * @name Power source types - * @anchor power_src - */ -/** @{ */ -#define ZB_POWER_SRC_CONSTANT 1U /*!< Constant (mains) power */ -#define ZB_POWER_SRC_RECHARGEABLE_BATTERY (1U << 1) /*!< Rechargeable battery */ -#define ZB_POWER_SRC_DISPOSABLE_BATTERY (1U << 2) /*!< Disposable battery */ -/** @} */ - -/** - * @brief Type for power source types. - * - * @deprecated holds one of @ref power_src. Kept only for backward compatibility as - * @ref power_src were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_power_src_t; - -/** - * @name Power source level values - * @anchor power_source_level - */ -/** @{ */ -#define ZB_POWER_LEVEL_CRITICAL 0U /*!< Critical */ -#define ZB_POWER_LEVEL_33 4U /*!< 33% */ -#define ZB_POWER_LEVEL_66 8U /*!< 66% */ -#define ZB_POWER_LEVEL_100 12U /*!< 100% */ -/** @} */ - -/** - * @brief Type for power source level values. - * - * Holds one of @ref power_source_level. Kept only for backward compatibility as - * @ref power_source_level were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_power_source_level_t; - -/** @} */ /* af_common_constants */ - -/** - * @addtogroup af_data_service AF data service - * @{ - */ - -/** - Node power descriptor - */ -typedef ZB_PACKED_PRE struct zb_af_node_power_desc_s -{ -/** Field name Bits - * Current power mode: 4@n - * Available power sources: 4@n - * Current power source: 4@n - * Current power source level: 4 - */ - zb_uint16_t power_desc_flags; -} ZB_PACKED_STRUCT zb_af_node_power_desc_t; - - -/** @cond DOXYGEN_INTERNAL_DOC */ -#define CAT5(a, b, c, d, e) a##b##c##d##e -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** Generate simple descriptor type name */ -#define ZB_AF_SIMPLE_DESC_TYPE(in_num, out_num) CAT5(zb_af_simple_desc_,in_num,_,out_num,_t) - -/** - Declares Simple descriptor type - - @param in_clusters_count - number of input clusters in descriptor - @param out_clusters_count - number of output clusters in descriptor - - @b Example: - @code - ZB_DECLARE_SIMPLE_DESC(5, 5); - @endcode - */ - -#define ZB_DECLARE_SIMPLE_DESC(in_clusters_count, out_clusters_count) \ - typedef ZB_PACKED_PRE struct zb_af_simple_desc_ ## in_clusters_count ## _ ## out_clusters_count ## _s \ - { \ - zb_uint8_t endpoint; /* Endpoint */ \ - zb_uint16_t app_profile_id; /* Application profile identifier */ \ - zb_uint16_t app_device_id; /* Application device identifier */ \ - zb_bitfield_t app_device_version:4; /* Application device version */ \ - zb_bitfield_t reserved:4; /* Reserved */ \ - zb_uint8_t app_input_cluster_count; /* Application input cluster count */ \ - zb_uint8_t app_output_cluster_count; /* Application output cluster count */ \ - /* Application input and output cluster list */ \ - zb_uint16_t app_cluster_list[(in_clusters_count) + (out_clusters_count)]; \ - } ZB_PACKED_STRUCT \ - zb_af_simple_desc_ ## in_clusters_count ## _ ## out_clusters_count ## _t - -/** @} */ /* af_data_service */ - -/** - * @addtogroup af_management_service AF management service - * @{ - */ -/** General descriptor type */ -ZB_DECLARE_SIMPLE_DESC(1,1); -/** ZDO descriptor type */ -ZB_DECLARE_SIMPLE_DESC(8,9); -/** @} */ /* af_management_service */ - -/** - * @addtogroup af_common_constants AF common constants - * @{ - */ - -/** - * @name Profile identifiers - * @anchor af_profile_id - * - * Note: These values were members of `enum zb_af_profile_id_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -/** ZDO profile ID */ -#define ZB_AF_ZDO_PROFILE_ID 0x0000U -/** Legacy profile */ -#define ZB_AF_LEGACY_PROFILE1_ID 0x0101U -/** Legacy profile */ -#define ZB_AF_LEGACY_PROFILE2_ID 0x0102U -/** Legacy profile */ -#define ZB_AF_LEGACY_PROFILE3_ID 0x0103U -/** HA profile ID*/ -#define ZB_AF_HA_PROFILE_ID 0x0104U -/** Legacy profile */ -#define ZB_AF_LEGACY_PROFILE4_ID 0x0105U -/** Legacy profile */ -#define ZB_AF_LEGACY_PROFILE5_ID 0x0106U -/** Legacy profile */ -#define ZB_AF_LEGACY_PROFILE6_ID 0x0107U -/** Legacy profile */ -#define ZB_AF_LEGACY_PROFILE7_ID 0x0108U -/** SE profile ID */ -#define ZB_AF_SE_PROFILE_ID 0x0109U -/** ZLL profile identifier. */ -#define ZB_AF_ZLL_PROFILE_ID 0xC05EU -/** Wildcard profile identifier. */ -#define ZB_AF_WILDCARD_PROFILE_ID 0xFFFFU -/** GreenPower profile ID */ -#define ZB_AF_GP_PROFILE_ID 0xA1E0U -#ifdef ZB_CONTROL4_NETWORK_SUPPORT -/** Control4 profile identifier. */ -#define ZB_AF_CONTROL4_PROFILE_ID 0xC25DU -#endif -/** @} */ - -/** @} */ /* af_common_constants */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -#if !(defined ZB_ZCL_DISABLE_REPORTING) || defined(DOXYGEN) -struct zb_zcl_reporting_info_s; /* Forward declaration */ -#endif -struct zb_zcl_cluster_desc_s; /* Forward declaration */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** - * @addtogroup af_management_service AF management service - * @{ - */ -/** - * Device command handler - * - * @param param - index of buffer with ZCL command - * @return status (see @ref zb_bool_t) - */ -typedef zb_uint8_t (*zb_device_handler_t)(zb_uint8_t param); -/** @} */ /* af_management_service */ -/** - * @addtogroup af_data_service AF data service - * @{ - */ - -/** Endpoint description for user applications. */ - -/*! @brief Endpoint descriptor. */ -typedef ZB_PACKED_PRE struct zb_af_endpoint_desc_s -{ - zb_uint8_t ep_id; /*!< Endpoint ID */ - zb_uint16_t profile_id; /*!< Application profile, which implemented on endpoint */ - zb_device_handler_t device_handler; /*!< Device specific callback, handles all commands */ - /*! @brief Identify notification callback - - If set, will be called on identification start and stop indicating start - event with a non-zero argument - */ - zb_callback_t identify_handler; - zb_uint8_t reserved_size; /*!< Unused parameter (reserved for future use) */ - void* reserved_ptr; /*!< Unused parameter (reserved for future use) */ - zb_uint8_t cluster_count; /*!< Number of supported clusters */ - struct zb_zcl_cluster_desc_s *cluster_desc_list; /*!< Supported clusters list */ - zb_af_simple_desc_1_1_t *simple_desc; /*!< Simple descriptor */ -#if defined ZB_ENABLE_ZLL || defined DOXYGEN - zb_uint8_t group_id_count; -#endif /* defined ZB_ENABLE_ZLL || defined DOXYGEN */ - - /* Moved here from device descriptor */ - zb_uint8_t rep_info_count; /*!< Number of reporting info slots */ - /* Reporting info structure should be better stored in ZCL main, - * moved here to allow compile-time memory allocating for - * reporting_info array, see ZB_AF_DECLARE_DEVICE_CTX() */ - struct zb_zcl_reporting_info_s *reporting_info; /*!< Attributes reporting information */ - - zb_uint8_t cvc_alarm_count; /*!< Number of continuous value change alarm slots */ - struct zb_zcl_cvc_alarm_variables_s *cvc_alarm_info; -}ZB_PACKED_STRUCT -zb_af_endpoint_desc_t; -/** @} */ /* af_data_service */ - -/** - * @addtogroup af_management_service AF management service - * @{ - */ - -/** - * @brief Search for endpoint (device) descriptor by endpoint ID. - * @param ep_id - identifier of the endpoint. - * @returns NULL if no endpoint found, or pointer to the endpoint descriptor. - */ -zb_af_endpoint_desc_t* zb_af_get_endpoint_desc(zb_uint8_t ep_id); - -/** - * @brief Check endpoint registration in ZCL. - * @param _ep - identifier of the endpoint under consideration. - * @returns ZB_TRUE if endpoint is registered, ZB_FALSE otherwise. - */ -#define ZB_AF_IS_EP_REGISTERED( _ep ) ((zb_af_get_endpoint_desc( _ep ) != NULL)?(ZB_TRUE):(ZB_FALSE)) -/** @} */ /* af_management_service */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -/** - AF device context, contains a list of registered endpoints -*/ -typedef ZB_PACKED_PRE struct zb_af_device_ctx_s -{ - zb_uint8_t ep_count; /*!< Number of endpoints on device */ - zb_af_endpoint_desc_t **ep_desc_list; /*!< Endpoint list */ -}ZB_PACKED_STRUCT -zb_af_device_ctx_t; -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** - * @addtogroup af_management_service AF management service - * @{ - */ -/** - General macro to declare endpoint description list - @param ep_list_name - name of ep list structure -*/ -#define ZB_AF_START_DECLARE_ENDPOINT_LIST(ep_list_name) \ - zb_af_endpoint_desc_t *ep_list_name[] = { - -/** - @brief Initialize endpoint descriptor - - @param ep_name - endpoint name - @param ep_id - endpoint ID - @param profile_id - ID of profile deployed on this endpoint - @param reserved_length - unused parameter - @param reserved_ptr - unused parameter - @param cluster_number - number of clusters deployed on endpoint - @param cluster_list - pointer to cluster list - @param simple_desc - pointer to simple descriptor - @param rep_count - maximum number of attributes that are - being reported on a device - @param rep_ctx - reporting context variable name (NULL if no reporting context) - @param lev_ctrl_count - number of level control attributes - @param lev_ctrl_ctx - level control context variable name (NULL if no level control context) -*/ -#define ZB_AF_DECLARE_ENDPOINT_DESC( \ - ep_name, \ - ep_id, \ - profile_id, \ - reserved_length, \ - reserved_ptr, \ - cluster_number, \ - cluster_list, \ - simple_desc, \ - rep_count, \ - rep_ctx, \ - lev_ctrl_count, \ - lev_ctrl_ctx) \ - zb_af_endpoint_desc_t ep_name = \ - { \ - ep_id, \ - profile_id, \ - NULL, \ - NULL, \ - reserved_length, \ - (void*)reserved_ptr, \ - cluster_number, \ - cluster_list, \ - simple_desc, \ - rep_count, \ - rep_ctx, \ - lev_ctrl_count, \ - lev_ctrl_ctx \ - } - -/** Finishes endpoint list declaration */ -#define ZB_AF_FINISH_DECLARE_ENDPOINT_LIST } - -/** - * @brief Allows application to register cluster commands handler for a specific endpoint - * @param endpoint - Endpoint number - * @param handler - Pointer to a function, function type zb_device_handler_t - * @attention Endpoint should be registered. ZB_AF_SET_ENDPOINT_HANDLER() should be called after - * device context is registered, using call to ZB_AF_REGISTER_DEVICE_CTX() - * - * @cond DOXYGEN_INTERNAL_DOC - * TODO: add snippet - * @endcond - */ -#define ZB_AF_SET_ENDPOINT_HANDLER(endpoint, handler) \ - (zb_af_get_endpoint_desc((endpoint))->device_handler = (handler)) - -/*! @brief Sets identify notification handler for endpoint - - Utilized by ZCL Identify cluster - @param endpoint number - @param handler to set - @attention Assumes that endpoint already registered - * - * @cond DOXYGEN_INTERNAL_DOC - * TODO: add snippet - * @endcond -*/ -#define ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(endpoint, handler) \ - (zb_af_get_endpoint_desc((endpoint))->identify_handler = (handler)) - -#define ZB_ZCL_CLUSTER_DESC(cluster_id, attr_count, attr_desc_list, cluster_role_mask, manuf_code) \ -{ \ - (cluster_id), \ - (attr_count), \ - (attr_desc_list), \ - (cluster_role_mask), \ - (manuf_code), \ - (((cluster_role_mask) == ZB_ZCL_CLUSTER_SERVER_ROLE) ? cluster_id##_SERVER_ROLE_INIT : \ - (((cluster_role_mask) == ZB_ZCL_CLUSTER_CLIENT_ROLE) ? cluster_id##_CLIENT_ROLE_INIT : NULL)) \ -} - -/** WARNING: This API is deprecated, use ZBOSS_DECLARE_DEVICE_CTX instead. */ -#define ZB_AF_DECLARE_DEVICE_CTX(device_ctx_name, ep_list_name, ep_count, reporting_attr_count) \ - zb_zcl_reporting_info_t reporting_info## device_ctx_name[reporting_attr_count]; \ - zb_af_device_ctx_t device_ctx_name = \ - { \ - ep_count, \ - ep_list_name, \ - reporting_attr_count, \ - reporting_info## device_ctx_name, \ - 0, \ - NULL \ - } - -/** WARNING: This API is deprecated, use ZBOSS_DECLARE_DEVICE_CTX instead. */ -#define ZB_AF_DECLARE_DEVICE_CTX_NO_REP(device_ctx_name, ep_list_name, ep_count) \ - zb_af_device_ctx_t device_ctx_name = \ - { \ - ep_count, \ - ep_list_name, \ - 0, \ - NULL, \ - 0, \ - NULL \ - } - -/** - Declare device reporting context - @param rep_ctx - reporting context variable name - @param rep_count - number of reporting attributes -*/ -#define ZBOSS_DEVICE_DECLARE_REPORTING_CTX(rep_ctx, rep_count) \ - zb_zcl_reporting_info_t rep_ctx[rep_count] - -/** - Declare device level control context - @param lev_ctrl_ctx - level control context variable name - @param lev_ctrl_count - number of level control attributes -*/ -#define ZBOSS_DEVICE_DECLARE_LEVEL_CONTROL_CTX(lev_ctrl_ctx, lev_ctrl_count) \ - zb_zcl_cvc_alarm_variables_t lev_ctrl_ctx[lev_ctrl_count] - -/** - Declare application's device context - @param device_ctx_name - device context variable name - @param ep_list_name - name of endpoint list - @param ep_count - number of supported endpoints -*/ -#define ZBOSS_DECLARE_DEVICE_CTX(device_ctx_name, ep_list_name, ep_count) \ - zb_af_device_ctx_t device_ctx_name = \ - { \ - ep_count, \ - ep_list_name, \ - } - -/** - Declare application's device context for single-endpoint device - - @note Device has an additional Green Power endpoint if it is ZC or ZR - and GPPB feature is enabled (Mandatory for Zigbee 3.0 ZC/ZR). - - @param device_ctx_name - device context variable name - @param ep_name - variable holding endpoint context -*/ -#define ZBOSS_DECLARE_DEVICE_CTX_1_EP(device_ctx_name, ep_name) \ - ZB_AF_START_DECLARE_ENDPOINT_LIST(ep_list_##device_ctx_name) \ - &ep_name, \ - ZB_AF_FINISH_DECLARE_ENDPOINT_LIST; \ - ZBOSS_DECLARE_DEVICE_CTX(device_ctx_name, ep_list_##device_ctx_name, \ - (ZB_ZCL_ARRAY_SIZE(ep_list_##device_ctx_name, zb_af_endpoint_desc_t*))) - -/** - Declare application's device context for two-endpoint device - - @note Device has an additional Green Power endpoint if it is ZC or ZR - and GPPB feature (Mandatory for Zigbee 3.0 ZC/ZR) is enabled. - - @param device_ctx_name - device context variable name - @param ep1_name - variable holding context for endpoint 1 - @param ep2_name - variable holding context for endpoint 2 -*/ -#define ZBOSS_DECLARE_DEVICE_CTX_2_EP(device_ctx_name, ep1_name, ep2_name) \ - ZB_AF_START_DECLARE_ENDPOINT_LIST(ep_list_##device_ctx_name) \ - &ep1_name, \ - &ep2_name, \ - ZB_AF_FINISH_DECLARE_ENDPOINT_LIST; \ - ZBOSS_DECLARE_DEVICE_CTX(device_ctx_name, ep_list_##device_ctx_name, \ - (ZB_ZCL_ARRAY_SIZE(ep_list_##device_ctx_name, zb_af_endpoint_desc_t*))) - -/** - Declare application's device context for three-endpoint device - - @note Device has an additional Green Power endpoint if it is ZC or ZR - and GPPB feature (Mandatory for Zigbee 3.0 ZC/ZR) is enabled. - - @param device_ctx_name - device context variable name - @param ep1_name - variable holding context for endpoint 1 - @param ep2_name - variable holding context for endpoint 2 - @param ep3_name - variable holding context for endpoint 3 -*/ -#define ZBOSS_DECLARE_DEVICE_CTX_3_EP(device_ctx_name, ep1_name, ep2_name, ep3_name) \ - ZB_AF_START_DECLARE_ENDPOINT_LIST(ep_list_##device_ctx_name) \ - &ep1_name, \ - &ep2_name, \ - &ep3_name, \ - ZB_AF_FINISH_DECLARE_ENDPOINT_LIST; \ - ZBOSS_DECLARE_DEVICE_CTX(device_ctx_name, ep_list_##device_ctx_name, \ - (ZB_ZCL_ARRAY_SIZE(ep_list_##device_ctx_name, zb_af_endpoint_desc_t*))) - -/** - Declare application's device context for for-endpoint device - - @note Device has an additional Green Power endpoint if it is ZC or ZR - and GPPB feature (Mandatory for Zigbee 3.0 ZC/ZR) is enabled. - - @param device_ctx_name - device context variable name - @param ep1_name - variable holding context for endpoint 1 - @param ep2_name - variable holding context for endpoint 2 - @param ep3_name - variable holding context for endpoint 3 - @param ep4_name - variable holding context for endpoint 4 -*/ -#define ZBOSS_DECLARE_DEVICE_CTX_4_EP(device_ctx_name, ep1_name, ep2_name, ep3_name, ep4_name) \ - ZB_AF_START_DECLARE_ENDPOINT_LIST(ep_list_##device_ctx_name) \ - &ep1_name, \ - &ep2_name, \ - &ep3_name, \ - &ep4_name, \ - ZB_AF_FINISH_DECLARE_ENDPOINT_LIST; \ - ZBOSS_DECLARE_DEVICE_CTX(device_ctx_name, ep_list_##device_ctx_name, \ - (ZB_ZCL_ARRAY_SIZE(ep_list_##device_ctx_name, zb_af_endpoint_desc_t*))) - - -/** @cond DOXYGEN_INTERNAL_DOC */ -#if defined ZB_ENABLE_ZCL && !defined ZB_ZCL_DISABLE_REPORTING -void zb_zcl_init_reporting_ctx(void); -void zb_zcl_reset_reporting_ctx(void); -#endif /* ZB_ENABLE_ZCL && !ZB_ZCL_DISABLE_REPORTING */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/* TODO: extend this ifdef*/ -#if defined ZB_ENABLE_ZCL || DOXYGEN -/** @cond DOXYGEN_INTERNAL_DOC */ -/** - Register device context. - @param device_ctx - pointer to device context - */ -void zb_af_register_device_ctx(zb_af_device_ctx_t *device_ctx); -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -/** - Register device context. - @param _device_ctx - Pointer to the device context - - @b Example: - @snippet onoff_server/on_off_output_zc.c af_register_device_context -*/ -#define ZB_AF_REGISTER_DEVICE_CTX(_device_ctx) zb_af_register_device_ctx(_device_ctx) -#endif /* defined ZB_ENABLE_ZCL */ -/** - * @brief Set Device user application callback. - * The macro sets a callback being called upon to need inform User App about change device attribute or - * need to execute H/W command - * @param func_ptr - a callback to set (of type @ref zb_callback_t). - * @hideinitializer - * - * @b Example: - * @snippet onoff_server/on_off_output_zc.c zcl_register_device_cb_example_cb - * @par Register callback: - * @snippet onoff_server/on_off_output_zc.c zcl_register_device_cb -*/ -#define ZB_ZCL_REGISTER_DEVICE_CB(func_ptr) ZCL_CTX().device_cb = (func_ptr) - -/** - Callback for notifying user about status of ZCL/ZDO command transmission - */ -typedef void (*zb_af_transmission_res_cb_t) (zb_uint8_t status); - -/** - Continue inconimg packet proicessing after ZG->zdo.af_data_cb returned TRUE - - @param param - incoming packet. Be sure it was initially passed to ZG->zdo.af_data_cb. - */ -void zb_apsde_data_indication_cont(zb_uint8_t param); -/** @} */ /* af_management_service */ -/*! @} */ - -#endif /* ZBOSS_API_AF_H */ diff --git a/zboss/development/include/zboss_api_aps.h b/zboss/development/include/zboss_api_aps.h deleted file mode 100644 index 6a8ce7ccb1..0000000000 --- a/zboss/development/include/zboss_api_aps.h +++ /dev/null @@ -1,612 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Public APS layer API -*/ -#ifndef ZB_ZBOSS_API_APS_H -#define ZB_ZBOSS_API_APS_H 1 - -/*! \addtogroup aps_api */ -/*! @{ */ - -/** @addtogroup aps_common_constants APS common constants - * @{ - */ - -#include "zb_config.h" -#include "zb_address.h" -#include "zboss_api_aps_interpan.h" - -/** - * @name APS status constants - * @anchor aps_status - */ -/** @{ */ - -/** A request has been executed successfully. */ -#define ZB_APS_STATUS_SUCCESS 0x00U -/** A transmit request failed since the ASDU is too large and fragmentation is not supported.*/ -#define ZB_APS_ASDU_TOO_LONG 0xa0U -/** A received fragmented frame could not be defragmented at the current time. */ -#define ZB_APS_DEFRAG_DEFERRED 0xa1U -/** A received fragmented frame could not be defragmented since the device does not support - * fragmentation. */ -#define ZB_APS_DEFRAG_UNSUPPORTED 0xa2U -/** A parameter value was out of range. */ -#define ZB_APS_STATUS_ILLEGAL_REQUEST 0xa3U -/** An APSME-UNBIND.request failed due to the requested binding link not existing in the binding - * table. */ -#define ZB_APS_STATUS_INVALID_BINDING 0xa4U -/** An APSME-REMOVE-GROUP.request has been issued with a group identifier that does not appear in - * the group table. */ -#define ZB_APS_STATUS_INVALID_GROUP 0xa5U -/** A parameter value was invalid or out of range. */ -#define ZB_APS_STATUS_INVALID_PARAMETER 0xa6U -/** An APSDE-DATA.request requesting acknowledged transmission failed due to no acknowledgement - * being received. */ -#define ZB_APS_STATUS_NO_ACK 0xa7U -/** An APSDE-DATA.request with a destination addressing mode set to 0x00 failed due to there being - * no devices bound to this device. */ -#define ZB_APS_STATUS_NO_BOUND_DEVICE 0xa8U -/** An APSDE-DATA.request with a destination addressing mode set to 0x03 failed due to no - * corresponding short address found in the address map table. */ -#define ZB_APS_STATUS_NO_SHORT_ADDRESS 0xa9U -/** An APSDE-DATA.request with a destination addressing mode set to 0x00 failed due to a binding - * table not being supported on the device. */ -#define ZB_APS_STATUS_NOT_SUPPORTED 0xaaU -/** An ASDU was received that was secured using a link key. */ -#define ZB_APS_STATUS_SECURED_LINK_KEY 0xabU -/** An ASDU was received that was secured using a network key. */ -#define ZB_APS_STATUS_SECURED_NWK_KEY 0xacU -/** An APSDE-DATA.request requesting security has resulted in an error during the corresponding - * security processing. */ -#define ZB_APS_STATUS_SECURITY_FAIL 0xadU -/** An APSME-BIND.request or APSME.ADD-GROUP.request issued when the binding or group tables, - * respectively, were full. */ -#define ZB_APS_STATUS_TABLE_FULL 0xaeU -/** An ASDU was received without any security. */ -#define ZB_APS_STATUS_UNSECURED 0xafU -/** An APSME-GET.request or APSME-SET.request has been issued with an unknown attribute identifier. - */ -#define ZB_APS_STATUS_UNSUPPORTED_ATTRIBUTE 0xb0U -/** @} */ - -/** - * @brief Type for APS status constants - * - * @deprecated holds one of @ref aps_status. Kept only for backward compatibility as - * @ref aps_status were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_aps_status_t; - -/** - * @name APS addressing mode constants - * @anchor aps_addr_mode - */ -/** @{ */ -#define ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT 0x00U /*!< DstAddress and DstEndpoint not present */ -#define ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT 0x01U /*!< 16-bit group address for DstAddress; DstEndpoint not present */ -#define ZB_APS_ADDR_MODE_16_ENDP_PRESENT 0x02U /*!< 16-bit address for DstAddress and DstEndpoint present */ -#define ZB_APS_ADDR_MODE_64_ENDP_PRESENT 0x03U /*!< 64-bit extended address for DstAddress and DstEndpoint present */ -#define ZB_APS_ADDR_MODE_BIND_TBL_ID 0x04U /*!< "destination endpoint" is interpreted as an index in the binding table, - all other destination address information is ignored */ -/** @} */ - -/** - * @brief Type for APS addressing mode constants. - * - * Holds one of @ref aps_addr_mode. Kept only for backward compatibility as - * @ref aps_addr_mode were declared previously as enum. - */ -typedef zb_uint8_t zb_aps_addr_mode_t; - -/** @brief Minimum valid endpoint number. */ -#define ZB_MIN_ENDPOINT_NUMBER 1U - -/** @brief Maximum valid endpoint number. */ -#define ZB_MAX_ENDPOINT_NUMBER 240U - -/** @brief Broadcast endpoint number. */ -#define ZB_APS_BROADCAST_ENDPOINT_NUMBER 255U - -/** @} */ - -/** @} */ /* aps_api */ - -/** @cond internals_doc */ -/*! \addtogroup aps_ib */ -/*! @{ */ - -/** - * @name APS Information Base constants - * @anchor aps_aib_attr_id - */ -/** @{ */ -/** The current set of binding table entries in the device (@see subclause 2.2.8.2.1). */ -#define ZB_APS_AIB_BINDING 0xc1U -/** TRUE if the device should become the Zigbee Coordinator on startupU FALSE if otherwise. */ -#define ZB_APS_AIB_DESIGNATED_COORD 0xc2U -/** The list of masks of allowable channels for this device to use for network operations. */ -#define ZB_APS_AIB_CHANNEL_MASK_LIST 0xc3U -/** The 64-bit address of a network to form or to join. */ -#define ZB_APS_AIB_USE_EXT_PANID 0xc4U -/** The current set of group table entries (@see Table 2.25). */ -#define ZB_APS_AIB_GROUP_TABLE 0xc5U -/** The value to be used for the NonmemberRadius parameter when using NWK layer multicast. */ -#define ZB_APS_AIB_NONMEMBER_RADIUS 0xc6U -/** The current set of permission configuration items. */ -#define ZB_APS_AIB_PERMISSION_CONFIG 0xc7U -/** A flag controlling the use of insecure join at startup. */ -#define ZB_APS_AIB_USE_INSECURE_JOIN 0xc8U -/** Fragmentation parameter - the standard delayU in millisecondsU between sending two blocks of a - * fragmented transmission (@see subclause 2.2.8.4.5). */ -#define ZB_APS_AIB_INTERFRAME_DELAY 0xc9U -/** The energy measurement for the channel energy scan performed on the previous channel just before - * a channel change (in accordance with [B1]). */ -#define ZB_APS_AIB_LAST_CHANNEL_ENERGY 0xcaU -/** The latest percentage of transmission network transmission failures for the previous channel - * just before a channel change (in percentage of failed transmissions to the total number of - * transmissions attempted) */ -#define ZB_APS_AIB_LAST_CHANNEL_FAILURE_RATE 0xcbU -/** A countdown timer (in hours) indicating the time to the next permitted frequency agility channel - * change. A value of NULL indicates the channel has not been changed previously. */ -#define ZB_APS_AIB_CHANNEL_TIMER 0xccU -/** A table with the active endpoints and their respective apsMaxWin-dowSize where frag-mentation is - * used (active endpoints not supporting fragmentations shall be omitted from the list). */ -#define ZB_APS_AIB_MAX_WINDOW_SIZE 0xcdU -/** The value of the current countdown timer before the next Parent_annce is sent. */ -#define ZB_APS_AIB_PARENT_ANNOUNCE_TIMER 0xceU -/** @} */ - -/** - * @brief Type for APS Information Base constants. - * - * Holds one of @ref aps_aib_attr_id. Kept for backward compatibility as - * @ref aps_aib_attr_id were declared previously as enum. - */ -typedef zb_uint8_t zb_aps_aib_attr_id_t; - -/*! @} */ /* aps_ib */ -/** @endcond */ /* internals_doc */ - -/** @addtogroup aps_api - * @{ - */ - -/** @addtogroup aps_data_service APS data service - * @{ - */ - -/** @brief Parsed APS header. - */ -typedef ZB_PACKED_PRE struct zb_aps_hdr_s -{ - /* TODO: rearrange fields to make that structure packet and exclude "packed" attribute. Don't forget to update NCP side. */ - zb_uint8_t fc; /*!< Frame control. */ - zb_uint16_t src_addr; /*!< Source address of packet originator. */ - zb_uint16_t dst_addr; /*!< The destination address of the packet. */ - zb_uint16_t group_addr; /*!< If send to group then group address destination else 0. */ - zb_uint8_t dst_endpoint; /*!< The destination endpoint of the packet receiver. */ - zb_uint8_t src_endpoint; /*!< The source endpoint from which that packet was send. */ - zb_uint16_t clusterid; /*!< The identifier of the cluster on the source device. */ - zb_uint16_t profileid; /*!< Profile ID */ - zb_uint8_t aps_counter; /*!< APS Counter for check APS dup command. */ - zb_uint16_t mac_src_addr; /*!< Source address of device that transmit that packet. */ - zb_uint16_t mac_dst_addr; /*!< Next hop address used for frame transmission. */ - zb_uint8_t lqi; - zb_int8_t rssi; - /* attributes of the key used to unsecure this frame */ - zb_bitfield_t aps_key_source:1; /*!< @if ZB_SECUR - * @ref secur_key_sources - * @endif - */ - zb_bitfield_t aps_key_attrs:2; /*!< @if ZB_SECUR - * @ref secur_key_attributes - * @endif - */ - zb_bitfield_t aps_key_from_tc:1; /* Denotes that packet received from TC and properly - * encrypted with TCLK by any appropriate method: - * 1) BDB Request key (with Key Type: TCLK) -> - * Transport Key -> Verify Key - * 2) BDB+SE Mixed CBKE - * 3) SE CBKE */ - zb_bitfield_t extended_fc:2; - zb_bitfield_t reserved:2; - - #define FIRST_INTERNAL_APSIND_FIELD tsn - zb_uint8_t tsn; /*!< Transaction sequence number for ZDO/ZCL command. */ - zb_uint8_t block_num; /*!< Fragmentation: block number. */ - zb_uint8_t block_ack; /*!< Fragmentation: block ack. */ - zb_uint8_t radius; /*!< radius from nwk header */ - zb_uint8_t align[3]; -} ZB_PACKED_STRUCT zb_aps_hdr_t; - - -/** - Parameters of the APSDE-DATA.indication primitive. - - Also used as a parameter in different APS calls. - */ -typedef zb_aps_hdr_t zb_apsde_data_indication_t; -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_apsde_data_indication_t); - -/** @} */ /* APS data service */ -/** @} */ - -/** @addtogroup aps_api - * @{ - */ - -/** @addtogroup aps_management_service APS management service - * @{ - */ - -/** - * @brief APSME binding structure. - * - * This data structure passed to @ref zb_apsme_bind_request() - * and to @ref zb_apsme_unbind_request(). - * - * @deprecated Corresponding function @ref zb_apsme_unbind_request() is deprecated and it will be - * moved to the private header in November 2022. Do not use this structure and corresponding function - * in the applications. - */ -typedef struct zb_apsme_binding_req_s -{ - zb_ieee_addr_t src_addr; /*!< The source IEEE address for the binding entry. */ - zb_uint8_t src_endpoint; /*!< The source endpoint for the binding entry. */ - zb_uint16_t clusterid; /*!< The identifier of the cluster on the source - device that is to be bound to the destination device.*/ - zb_uint8_t addr_mode; /*!< The type of destination address supplied by - the DstAddr parameter - see @ref aps_addr_mode */ - zb_addr_u dst_addr; /*!< The destination address for the binding entry. */ - zb_uint8_t dst_endpoint; /*!< This parameter will be present only if - the DstAddrMode parameter has a value of - 0x03 and, if present, will be the - destination endpoint for the binding entry.*/ -#ifdef SNCP_MODE - zb_uint8_t remote_bind; /*!< Indication if the bind req is local or remote */ - zb_uint8_t id; /*!< unique identifier of the entry for NCP, updated only in - zb_apsme_bind_request and zb_apsme_unbind_request and used to - notify NCP */ - /* confirm_cb is not sent in payload by NCP, keep it in the end of this structure */ -#endif - zb_callback_t confirm_cb; /*!< The callback to be called when the operation is completed. */ -} zb_apsme_binding_req_t; - - -/** - * This data structure passed to @ref zb_zdo_check_binding_request(). - */ -typedef struct zb_aps_check_binding_req_s -{ - zb_uint8_t src_endpoint; /* a source endpoint, if ZB_ZCL_BROADCAST_ENDPOINT - any endpoint */ - zb_uint16_t cluster_id; /* a source cluster ID */ - zb_callback_t response_cb; -} zb_aps_check_binding_req_t; - - -/** - * This data structure passed to callback passed to @ref zb_zdo_check_binding_request(). - */ -typedef struct zb_aps_check_binding_resp_s -{ - zb_uint8_t src_endpoint; /* a source endpoint from the corresponding request */ - zb_uint16_t cluster_id; /* a source cluster ID from the corresponding request */ - zb_bool_t exists; /* whether the binding with specified parameters exists */ -} zb_aps_check_binding_resp_t; - -/** @brief APSME-ADD-GROUP.request primitive parameters, should be passed to @ref zb_zdo_add_group_req() */ -typedef struct zb_apsme_add_group_req_s -{ - zb_uint16_t group_address; /*!< The 16-bit address of the group being added. */ - zb_uint8_t endpoint; /*!< The endpoint to which the given group is being added. */ - zb_callback_t confirm_cb; /*!< The callback to be called when the operation is completed. */ -} zb_apsme_add_group_req_t; - -/** @brief APSME-ADD-GROUP.confirm primitive parameters. */ -typedef struct zb_apsme_add_group_conf_s -{ - zb_uint16_t group_address; /*!< The 16-bit address of the group being added. */ - zb_uint8_t endpoint; /*!< The endpoint to which the given group is being added. */ - zb_ret_t status; /*!< Request send status. */ -} zb_apsme_add_group_conf_t; - -/** @brief APSME-REMOVE-GROUP.request primitive parameters, should be passed to @ref zb_zdo_add_group_req() */ -typedef struct zb_apsme_add_group_req_s zb_apsme_remove_group_req_t; - -/** @brief APSME-REMOVE-GROUP.confirm primitive parameters. */ -typedef struct zb_apsme_add_group_conf_s zb_apsme_remove_group_conf_t; - -/** @brief APSME-REMOVE-ALL-GROUPS.request primitive parameters, should be passed to @ref zb_zdo_remove_all_groups_req(). */ -typedef struct zb_apsme_remove_all_groups_req_s -{ - zb_uint8_t endpoint; /*!< The endpoint to which the given group is being removed. */ - zb_callback_t confirm_cb; /*!< The callback to be called when the operation is completed. */ -} zb_apsme_remove_all_groups_req_t; - -/** @brief APSME-REMOVE-ALL-GROUPS.confirm primitive parameters. */ -typedef struct zb_apsme_remove_all_groups_conf_s -{ - zb_uint8_t endpoint; /*!< The endpoint which is to be removed from all groups. */ - zb_ret_t status; /*!< The status of the request to remove all groups. */ -} zb_apsme_remove_all_groups_conf_t; - -zb_bool_t zb_aps_is_endpoint_in_group( - zb_uint16_t group_id, - zb_uint8_t endpoint); - -/** @cond DOXYGEN_INTERNAL_DOC */ -/** @brief APSME GET request structure. */ -typedef struct zb_apsme_get_request_s -{ - zb_aps_aib_attr_id_t aib_attr; /*!< The identifier of the AIB attribute to read. */ - zb_callback_t confirm_cb; /*!< User's callback to be called as APSME-GET.confirm */ -} zb_apsme_get_request_t; - -/** @brief APSME GET confirm structure. */ -typedef ZB_PACKED_PRE struct zb_apsme_get_confirm_s -{ - zb_ret_t status; /*!< The results of the request to read an AIB attribute value. */ - zb_aps_aib_attr_id_t aib_attr; /*!< The identifier of the AIB attribute that was read.*/ - zb_uint8_t aib_length; /*!< The length, in octets, of the attribute value being returned.*/ - /* Various */ /* The value of the AIB attribute that was read.*/ -} ZB_PACKED_STRUCT zb_apsme_get_confirm_t; - -/** @brief APSME SET request structure. */ -typedef ZB_PACKED_PRE struct zb_apsme_set_request_s -{ - zb_aps_aib_attr_id_t aib_attr; /*!< The identifier of the AIB attribute to be written. */ - zb_uint8_t aib_length; /*!< The length, in octets, of the attribute value being set. */ - zb_callback_t confirm_cb; /*!< User's callback to be called as APSME-SET.confirm */ - /* Various */ /* The value of the AIB attribute that should be written. */ -} ZB_PACKED_STRUCT zb_apsme_set_request_t; - -/** @brief APSME SET confirm structure. */ -typedef ZB_PACKED_PRE struct zb_apsme_set_confirm_s -{ - zb_ret_t status; /*!< The result of the request to write the AIB Attribute. */ - zb_aps_aib_attr_id_t aib_attr; /*!< The identifier of the AIB attribute that was written. */ -} ZB_PACKED_STRUCT zb_apsme_set_confirm_t; - -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** - * @brief APSME-BIND.request primitive. - * @param param - index of buffer containing request data (see @ref - * zb_apsme_binding_req_t). - * - * @deprecated This function will be moved to the private header in November 2022. Use @ref - * zb_zdo_bind_req() instead. - */ -void zb_apsme_bind_request(zb_uint8_t param); - -/** - * @brief APSME-UNBIND.request primitive. - * @param param - index of buffer containing request data (see @ref - * zb_apsme_binding_req_t). - * - * @deprecated This function will be moved to the private header in November 2022. Use @ref - * zb_zdo_unbind_req() instead. - */ -void zb_apsme_unbind_request(zb_uint8_t param); - -/** - *@brief Perform unbind all entries. This custom function and it is not described - * in Zigbee specification. - * @param param - not used. - * - * @deprecated This function will be moved to the private header in November 2022. Use @ref - * zb_zdo_unbind_all_local() instead. - */ -void zb_apsme_unbind_all(zb_uint8_t param); - -/** - * @brief Checks if the binding with specified parameters exists - * - * @deprecated This function will be moved to the private header in November 2022. Use @ref - * zb_zdo_check_binding_request() instead. - */ -void zb_aps_check_binding_request(zb_bufid_t param); - -/** - * @brief APSME-ADD-GROUP.request primitive. - * - * @param param - index of buffer with parameter. See @ref zb_apsme_add_group_req_t. - * - * @deprecated This function will be moved to the private header in November 2022. Use @ref - * zb_zdo_add_group_req() instead. - */ -void zb_apsme_add_group_request(zb_uint8_t param); - -/** - * @brief APSME-REMOVE-GROUP.request primitive. - * - * @internal - * Use macro @ref ZDO_REGISTER_CALLBACK to register APSME-REMOVE-GROUP.confirm callback. - * @endinternal - * @param param - index of buffer with parameter. See @ref zb_apsme_remove_group_req_t. - * - * @deprecated This function will be moved to the private header in November 2022. Use @ref - * zb_zdo_remove_group_req() instead. - * - */ -void zb_apsme_remove_group_request(zb_uint8_t param); - -/** - * @brief APSME-REMOVE-ALL-GROUPS.request primitive. - * - * @internal - * Use macro @ref ZDO_REGISTER_CALLBACK to register APSME-REMOVE-ALL-GROUPS.confirm callback. - * @endinternal - * @param param - index of buffer with parameter. See @ref zb_apsme_remove_all_groups_req_t. - * - * @deprecated This function will be moved to the private header in November 2022. Use @ref - * zb_zdo_remove_all_groups_req() instead. - * - */ -void zb_apsme_remove_all_groups_request(zb_uint8_t param); - -/** @} */ /* APS management service data structures and API. */ - -/*! @} */ /* aps_api */ - - -#ifdef APS_FRAGMENTATION - - -void zb_aps_add_max_trans_size(zb_uint16_t short_addr, zb_uint16_t max_trans_size, zb_uint8_t max_buffer_size); -zb_uint16_t zb_aps_get_max_trans_size(zb_uint16_t short_addr); -zb_uint8_t zb_aps_get_max_buffer_size(zb_uint16_t short_addr); - -#endif - -#ifdef ZB_APS_USER_PAYLOAD -/** @addtogroup aps_api - * @{ - */ - -/** @addtogroup aps_user_payload APS user payload - * @{ - */ - -/*! - * @brief - * Callback to notify an application of sending an APS user payload status - * - * @param param - index of buffer with an APS user payload - */ -typedef void (*zb_aps_user_payload_callback_t)(zb_uint8_t param); - -/*! - * @brief - * APS user payload transmission status - * - * Stored in the buf->u.hdr.status field - */ -typedef enum zb_aps_user_payload_cb_status_e -{ - /*! APS user payload transmission is successful*/ - ZB_APS_USER_PAYLOAD_CB_STATUS_SUCCESS = (zb_uint8_t)0x00, - /* Failed to transmit APS user payload - No confirmation from APS*/ - ZB_APS_USER_PAYLOAD_CB_STATUS_NO_APS_ACK = (zb_uint8_t)0xbe -} zb_aps_user_payload_cb_status_t; - -/*! - * @brief Send user payload using APS - * - * @param param - reference to a buffer - * @param dst_addr - destination address - * @param profile_id - profile ID for which this frame is intended for - * @param cluster_id - object ID for which this frame is intended for - * @param dst_endpoint - either the endpoint ID - * of the entity to which the ASDU is being - * transferred or the broadcast endpoint (0xff) - * @param src_endpoint - the individual endpoint of the entity from - * which the ASDU is being transferred - * @param addr_mode - the type of destination address supplied by - * the dst_addr parameter - see @ref aps_addr_mode - * @param aps_ack_is_enabled - enable (ZB_TRUE) or disable (ZB_FALSE) APS acknowledging - * @param *payload_ptr - pointer to user data - * @param payload_size - size of user data; not more than 82 bytes - * - * @return RET_OK - if transmission was successful scheduled; - * @return RET_INVALID_PARAMETER_1 - if the buffer is invalid - * @return RET_INVALID_PARAMETER_2 - if the payload_ptr parameter is invalid - * @return RET_INVALID_PARAMETER_3 - if the payload_size parameter is too large - */ -zb_ret_t zb_aps_send_user_payload( - zb_uint8_t param, - zb_addr_u dst_addr, - zb_uint16_t profile_id, - zb_uint16_t cluster_id, - zb_uint8_t dst_endpoint, - zb_uint8_t src_endpoint, - zb_uint8_t addr_mode, - zb_bool_t aps_ack_is_enabled, - zb_uint8_t *payload_ptr, - zb_uint8_t payload_size); - -/*! - * @brief Get pointer to an APS payload - * - * @param param - reference to a buffer - * @param aps_payload_size - [out] pointer to a variable to store - * an APS payload size - * - * @return Pointer to an APS payload; - * @return NULL if a buffer is invalid or an aps_payload_size pointer is invalid. - */ -zb_uint8_t *zb_aps_get_aps_payload(zb_uint8_t param, zb_uint8_t *aps_payload_size); - -/*! - * @brief Set callback to notify results of transmitting - * an APS frame with user payload - * - * @param cb - pointer to a callback - */ -void zb_aps_set_user_data_tx_cb(zb_aps_user_payload_callback_t cb); - -/*! - * @brief Set callback to be called when ZDO command packet is sent. - * - * That callback is to be used when application wants to know the fact that ZDO - * command send is completed. - * - * Callback provided to ZBOSS ZDO request function (second parameter of - * zb_zdo_node_desc_req and similar function) not always can be used for that - * purpose. ZBOSS calls ZDO callback immediately when a) unicast transmit of APS - * message failed (no ACK) and b) this is ZDO message that does not suppose to - * have an answer, like broadcast NWK Update req. In other cases if callback is - * set using zb_af_set_zdo_data_conf_cb, it is called when outgoing ZDO command - * is sent; callback passed to zb_zdo_node_desc_req and friends is called when - * ZBOSS got response/responses to ZDO command, or ZDO command is timed out. - * - * @param cb - callback. The buffer passed to the callback has zb_apsde_data_confirm_t in parameters section. - */ -void zb_af_set_zdo_data_conf_cb(zb_callback_t cb); - -/** @} */ /* aps_user_payload */ - -/** @} */ - -#endif /* #ifdef ZB_APS_USER_PAYLOAD */ - -#endif /* #ifndef ZB_ZBOSS_API_APS_H */ diff --git a/zboss/development/include/zboss_api_aps_interpan.h b/zboss/development/include/zboss_api_aps_interpan.h deleted file mode 100644 index 5536fcba12..0000000000 --- a/zboss/development/include/zboss_api_aps_interpan.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Public APS Inter-Pan API -*/ - -#ifndef ZBOSS_API_APS_INTERPAN_H -#define ZBOSS_API_APS_INTERPAN_H 1 - -/** @addtogroup aps_api - * @{ - */ - - -#if defined ZB_ENABLE_INTER_PAN_EXCHANGE || defined DOXYGEN -/** @brief INTRP-DATA.request structure. - * - * This structure passed to @ref zb_intrp_data_request() in the packet buffer parameter. - * @see SE spec, clause B.3. - */ -typedef ZB_PACKED_PRE struct zb_intrp_data_req_s -{ - /** @brief The addressing mode for the destination address used in this primitive. - * - * This parameter can take one of the values from the following list: - * @li 0x01 = 16-bit group address - * @li 0x02 = 16-bit NWK address, normally the broadcast address 0xffff - * @li 0x03 = 64-bit extended address - */ - zb_uint8_t dst_addr_mode; - /** The 16-bit Pan identifier of the entity or entities to which the ASDU is being transferred or - * the broadcast Pan ID 0xffff. - */ - zb_uint16_t dst_pan_id; - /** The address of the entity or entities to which the ASDU is being transferred. */ - zb_addr_u dst_addr; - /** The identifier of the application profile for which this frame is intended. */ - zb_uint16_t profile_id; - /** The identifier of the cluster, within the profile specified by the ProfileId parameter, which - * defines the application semantics of the ASDU. - */ - zb_uint16_t cluster_id; - /** An integer handle associated with the ASDU to be transmitted. */ - zb_uint8_t asdu_handle; -} ZB_PACKED_STRUCT zb_intrp_data_req_t; -#endif /* defined ZB_ENABLE_INTER_PAN_EXCHANGE || defined DOXYGEN */ - -/** @brief Valid values for inter-PAN destination address mode. - * @see SE spec, subclause B.3.1. - */ -enum zb_intrp_addr_mode_e -{ - /** 16-bit group address */ - ZB_INTRP_ADDR_GROUP = 0x01, - /** 16-bit NWK address */ - ZB_INTRP_ADDR_NETWORK = 0x02, - /** 64-bit extended device address */ - ZB_INTRP_ADDR_IEEE = 0x03 -}; - -/** @brief Inter-PAN broadcast short network address */ -#define ZB_INTRP_BROADCAST_SHORT_ADDR 0xffffU - -/** @brief INTRP-DATA.indication parameters. - * @see SE spec, subclause B.3.3. - */ -typedef ZB_PACKED_PRE struct zb_intrp_data_ind_s -{ - /** @brief Destination address mode. - * Valid values are defined by @ref zb_intrp_addr_mode_e enumeration. - */ - zb_uint8_t dst_addr_mode; - /** @brief Destination Pan identifier. - * Should be a valid Pan identifier or a broadcast Pan ID 0xffff. - */ - zb_uint16_t dst_pan_id; - /** @brief Destination address. */ - zb_addr_u dst_addr; - /** @brief Source Pan identifier. - * Assumed to be a valid Pan identifier in all cases. - */ - zb_uint16_t src_pan_id; - /** @brief Source device address. */ - zb_ieee_addr_t src_addr; - /** @brief Profile identifier. */ - zb_uint16_t profile_id; - /** @brief Cluster identifier. */ - zb_uint16_t cluster_id; - /** @brief The link quality observed during the reception of the ASDU. */ - zb_uint8_t link_quality; - zb_int8_t rssi; -} ZB_PACKED_STRUCT zb_intrp_data_ind_t; - -/** @cond DOXYGEN_APS_INTER_PAN_NON_DEFAULT_CHANNEL_FEATURE */ -#if defined ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL || defined DOXYGEN -/** @brief A multi-channel INTRP-DATA.confirm representation structure. - */ -typedef struct zb_mchan_intrp_data_confirm_s -{ - zb_channel_page_t channel_status_page_mask; /*!< Channel Page structure - binary encoded channel page - and channels mask as list of channels, indicating on which - channels the packet was successfully sent. */ - zb_uint8_t asdu_handle; /*!< An integer handle associated with the transmitted frame. */ -} zb_mchan_intrp_data_confirm_t; - -/** - * Inter-pan packet handler - * - * @param param - index of buffer with inter-pan packet command - * @param current_page - channel page at which packet was received - * @param current_channel - channel at which packet was received - * @return status (see @ref zb_bool_t) - */ -typedef zb_uint8_t (*zb_af_inter_pan_handler_t)(zb_uint8_t param, zb_uint8_t current_page, zb_uint8_t current_channel); - -/** @brief Enable interpan procedure. This allows to send interpan frames at multiple channels - * and register handler to receive interpan frames. - */ -void zboss_enable_interpan_with_chan_change(void); - -/** @brief Make INTRP-DATA request at multiple channels with time given as chan_wait_ms - * to wait for response packets. Can be used after zboss_enable_interpan_with_chan_change() - * was called. - * - * Assumes buffer contains data in its main part, and INTRP-DATA.request parameters in buffer's - * parameter (represented as @ref zb_intrp_data_req_s structure). - * @param buffer - reference (index) of the packet buffer. - * @param channel_page_mask - Channel Page structure - binary encoded channel page - * and channels mask as list of channels to send packet at. - * @param chan_wait_ms - time in milliseconds to wait at channel after the packet is sent. - * @param cb - user callback function called after the procedure is finished. - * @return Returns RET_OK if procedure has started successfully, - * RET_BUSY if procedure is on-going, - * RET_ERROR if failed to start or procedure was not enabled, - * RET_INVALID_PARAMETER if one of function's arguments is invalid. - * @note cb buffer's parameter contains status which can be obtained using @ref zb_buf_get_status - * function, RET_OK if packet was successfully sent at at least one channel, RET_ERROR otherwise. - * @ref zb_mchan_intrp_data_confirm_t is put as buffer's parameter. - * User is to free the buffer in the callback, if no callback is given, buffer is freed internally. - */ -zb_ret_t zb_intrp_data_request_with_chan_change(zb_bufid_t buffer, zb_channel_page_t channel_page_mask, zb_uint32_t chan_wait_ms, zb_callback_t cb); - -/** @brief Register inter-pan indication callback, called when inter-pan packet is received. - * Can be used after zboss_enable_interpan_with_chan_change() was called. - * - * @param cb - callback function to be called when inter-pan packet is received. - * @note If packet is processed in the callback function and no longer shall be processed - * by the stack, callback function shall free buffer and return ZB_TRUE. Return ZB_FALSE otherwise. - * Buffer has data put in the beginning of the buffer with inter-pan header truncated - * and contains @ref zb_intrp_data_ind_t given as buffer's parameter. - */ -void zb_af_interpan_set_data_indication(zb_af_inter_pan_handler_t cb); -#endif /* defined ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL || defined DOXYGEN */ -/** @endcond */ /* DOXYGEN_APS_INTER_PAN_NON_DEFAULT_CHANNEL_FEATURE */ - -#if defined ZB_ENABLE_INTER_PAN_EXCHANGE || defined DOXYGEN -/** @brief Make INTRP-DATA request. - * - * Assumes buffer contains data in its main part, and INTRP-DATA.request parameters in buffer's - * parameter (represented as @ref zb_intrp_data_req_s structure). - * @param param - reference (index) of the packet buffer. - * @see SE spec, subclause B.5.1. - */ -void zb_intrp_data_request(zb_uint8_t param); -#endif /* defined ZB_ENABLE_INTER_PAN_EXCHANGE || defined DOXYGEN */ - -/** @} */ - -#endif /* ZBOSS_API_APS_INTERPAN_H */ diff --git a/zboss/development/include/zboss_api_buf.h b/zboss/development/include/zboss_api_buf.h deleted file mode 100644 index 2f07d87d40..0000000000 --- a/zboss/development/include/zboss_api_buf.h +++ /dev/null @@ -1,674 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Public buffer pool API (new version) -*/ -#ifndef ZBOSS_API_BUF_H -#define ZBOSS_API_BUF_H 1 - -/*! \addtogroup buf */ -/*! @{ */ - -#include "zboss_api_core.h" - -/* - Moved here buffer structure to implement configurable mem without enabling legacy buffers - */ - -#define ZB_RESERVED_BUF_TO_ALIGN_HDR_SIZE 1u - -/** - Packet buffer header. - */ -typedef ZB_PACKED_PRE struct zb_buf_hdr_s -{ - zb_ret_t status; /*!< some status to be passed with packet */ - zb_uint16_t len; /*!< current layer buffer length */ - zb_uint16_t data_offset; /*!< data offset in buffer buf*/ - zb_uint8_t multiplicity; /*!< if greater that 1, then the following (multiplicity - 1) buffers - * are occupied with payload data and should not be treated as - * having valid headers, etc. - */ - zb_uint8_t handle; /*!< The handle associated with the NSDU to be - * transmitted by the NWK layer entity. */ - zb_bitfield_t is_in_buf:1; /*!< if 1, this is input buffer */ - - zb_bitfield_t encrypt_type:3; /*!< payload must be encrypted before send, if - * !0. \see zb_secur_buf_encr_type_e. - */ - zb_bitfield_t use_same_key:1; /*!< if 1, use same nwk key packet was - * encrypted by */ - zb_bitfield_t zdo_cmd_no_resp:1; /*!< if 1, this is ZDO command with no - * response - call callback at confirm */ - zb_bitfield_t is_rx_buf:1; /*!< if 1, this is buffer with received packet and - * nwk_mac_addrs_t is at buffer tail */ - zb_bitfield_t has_aps_payload:1; /*!< if 1, than packet comes from APS, the flag is needed - * to increase APS packets counter in diagnostic data on packet sending - */ - zb_bitfield_t has_aps_user_payload:1; /*!< if 1, than packet comes with APS user's payload */ - zb_uint8_t reserved:7; -} ZB_PACKED_STRUCT zb_buf_hdr_t; - -/* if there is a platform with failed assertion, ZB_RESERVED_BUF_TO_ALIGN_HDR_SIZE - should be changed to appropriate value*/ -ZB_ASSERT_COMPILE_DECL((sizeof(zb_buf_hdr_t) % sizeof(zb_uint32_t)) == 0); - -#ifdef ZB_DEBUG_BUFFERS_EXT -#define ZB_LINE_IS_UNDEF 0xFFFFU - -/** - Extended buffer debug: tracking buffer access - */ - -typedef struct zb_buf_usage_s -{ - /* In most cases zb_time_t is zb_uint32_t. - * To save memory we we use zb_uint16_t so store time. */ - zb_uint16_t time; - zb_uint16_t file; - zb_uint16_t line; -} -zb_buf_usage_t; -#endif - - -/** - Packet buffer - */ -typedef struct zb_mult_buf_s -{ -#ifdef ZB_BUF_SHIELD - zb_uint8_t hdr_signature; -#endif -/* 07/12/2019 EE CR:MINOR Lagecy code will access u.hdr, so need to keep u as union or structure - AN: Legacy code inside ZBOSS will use zb_leg_buf_t instead of zb_mult_buf_t. - EE: I mean legacy API for the new bufs implementation. - */ - zb_buf_hdr_t hdr; /*!< Buffer header, if buffer is used */ - zb_uint8_t buf[ZB_IO_BUF_SIZE]; /*!< Data*/ -#ifdef ZB_DEBUG_BUFFERS_EXT - zb_buf_usage_t buf_allocation; - zb_buf_usage_t buf_usages[ZB_DEBUG_BUFFERS_EXT_USAGES_COUNT]; -#endif -#ifdef ZB_BUF_SHIELD - zb_uint8_t tail_signature; -#endif -} zb_mult_buf_t; - -/** - Packet buffer (legacy) - */ -typedef struct zb_leg_buf_s -{ -#ifdef ZB_BUF_SHIELD - zb_uint8_t hdr_signature; -#endif - union - { - zb_buf_hdr_t hdr; /*!< Buffer header, if buffer is used */ -#ifndef ZB_USE_STD_MALLOC - struct zb_buf_s *next; /*!< Ref to next free buffer, if buffer is not used*/ -#endif - } u; /*!< Buffer header */ -#if defined ZB_USE_STD_MALLOC && defined ZB_USE_ALLOC_FOR_PAYLOAD_DATA - zb_uint8_t *buf; /*!< Dynamically allocated buffer for payload */ -#else - zb_uint8_t buf[ZB_IO_BUF_SIZE]; /*!< Data*/ -#endif -#ifdef ZB_DEBUG_BUFFERS_EXT - zb_buf_usage_t buf_allocation; - zb_buf_usage_t buf_usages[ZB_DEBUG_BUFFERS_EXT_USAGES_COUNT]; -#endif -#ifdef ZB_BUF_SHIELD - zb_uint8_t tail_signature; -#endif -} zb_leg_buf_t; - -#ifdef ZB_LEGACY_BUFS -typedef zb_leg_buf_t zb_buf_ent_t; -#else -typedef zb_mult_buf_t zb_buf_ent_t; -#endif - -/** - * @name Buffer type (direction) - * @anchor buffer_types - */ -/** @{ */ -#define ZB_OUT_BUFFER 0U /*!< Out buffer */ -#define ZB_IN_BUFFER 1U /*!< In buffer */ -/** @} */ - -/** - * @brief Type for Buffer type (direction). - * - * Holds one of @ref buffer_types. Kept for backward compatibility as - * @ref buffer_types were declared previously as enum. - */ -typedef zb_uint8_t zb_buffer_types_t; - -/** - @typedef zb_uint8_t zb_bufid_t - Buffer handler - */ -typedef zb_uint8_t zb_bufid_t; - -#define ZB_BUF_INVALID 0U -#define ZB_UNDEFINED_BUFFER 0U - -#ifdef ZB_DEBUG_BUFFERS -#define TRACE_PROTO_VOID zb_uint16_t from_file, zb_uint16_t from_line -#define TRACE_PROTO TRACE_PROTO_VOID , -#define TRACE_CALL_VOID ZB_TRACE_FILE_ID, __LINE__ -#define TRACE_CALL TRACE_CALL_VOID , -#else -#define TRACE_PROTO_VOID void -#define TRACE_PROTO -#define TRACE_CALL_VOID -#define TRACE_CALL -#endif /* ZB_DEBUG_BUFFERS */ - -#ifdef ZB_DEBUG_BUFFERS_EXT - void zb_trace_bufs_usage(void); - #define ZB_TRACE_BUFS_USAGE() zb_trace_bufs_usage() -#else - #define ZB_TRACE_BUFS_USAGE() -#endif - -/** @cond internals_doc */ -zb_bufid_t zb_buf_get_func(TRACE_PROTO zb_bool_t is_in, zb_uint_t max_size); -zb_bufid_t zb_buf_get_out_func(TRACE_PROTO_VOID); -zb_bufid_t zb_buf_get_any_func(TRACE_PROTO_VOID); -zb_bufid_t zb_buf_get_hipri_func(TRACE_PROTO zb_bool_t is_in); -zb_uint_t zb_buf_get_max_size_func(TRACE_PROTO zb_bufid_t buf); -zb_ret_t zb_buf_get_out_delayed_func(TRACE_PROTO zb_callback_t callback); -zb_ret_t zb_buf_get_in_delayed_func(TRACE_PROTO zb_callback_t callback); -zb_ret_t zb_buf_get_out_delayed_ext_func(TRACE_PROTO zb_callback2_t callback, zb_uint16_t arg, zb_uint_t max_size); -zb_ret_t zb_buf_get_in_delayed_ext_func(TRACE_PROTO zb_callback2_t callback, zb_uint16_t arg, zb_uint_t max_size); -void zb_buf_free_func(TRACE_PROTO zb_bufid_t buf); -void* zb_buf_begin_func(TRACE_PROTO zb_bufid_t buf); -void* zb_buf_end_func(TRACE_PROTO zb_bufid_t buf); -zb_uint_t zb_buf_len_func(TRACE_PROTO zb_bufid_t buf); -void zb_buf_copy_func(TRACE_PROTO zb_bufid_t dst_buf, zb_bufid_t src_buf); -void *zb_buf_initial_alloc_func(TRACE_PROTO zb_bufid_t buf, zb_uint_t size); -void *zb_buf_reuse_func(TRACE_PROTO zb_bufid_t buf); -zb_uint_t zb_buf_get_ptr_off_func(TRACE_PROTO zb_bufid_t buf, zb_uint8_t *ptr); -void *zb_buf_alloc_tail_func(TRACE_PROTO zb_bufid_t buf, zb_uint_t size); -void *zb_buf_get_tail_func(TRACE_PROTO zb_bufid_t buf, zb_uint_t size); -void zb_buf_cut_right_func(TRACE_PROTO zb_bufid_t buf, zb_uint_t size); -void *zb_buf_cut_left_func(TRACE_PROTO zb_bufid_t buf, zb_uint_t size); -void *zb_buf_alloc_right_func(TRACE_PROTO zb_bufid_t buf, zb_uint_t size); -void *zb_buf_alloc_left_func(TRACE_PROTO zb_bufid_t buf, zb_uint_t size); -/** @endcond */ /* internals_doc */ - -/** - Synchronous buffer allocation. - If no buffers available, does not block. - Note: this is low-level API. Usually user calls blocked alloc API. - - @param is_in if ZB_TRUE, allocate IN buffer, else allocate OUT buffer - @param max_size required maximum buffer payload size (in bytes). It can be bigger or smaller than - the default buffer size. Depending on the specific value, the buffer pool may decide to use - a fraction of buffer or long buffers. Special value 0 means "single default buffer". - @return buffer ID or ZB_BUF_INVALID if no buffers available - */ -#define zb_buf_get(is_in,max_size) zb_buf_get_func(TRACE_CALL (is_in), (max_size)) - -/** - Allocate OUT buffer of the default size. - */ -#define zb_buf_get_out() zb_buf_get_out_func(TRACE_CALL_VOID) - -/** - Allocate IN or OUT buffer balancing @ of allocated IN and OUT - - To be used at ZBOSS init time. - */ -#define zb_buf_get_any() zb_buf_get_any_func(TRACE_CALL_VOID) - -/** - Synchronous allocation of the high-priority buffer - */ -#define zb_buf_get_hipri(a) zb_buf_get_hipri_func(TRACE_CALL (a)) - -/** - Return maximum data size for that buffer. - */ -#define zb_buf_get_max_size(a) zb_buf_get_max_size_func(TRACE_CALL (a)) - -/** - * @brief Allocate OUT buffer, call a callback when the buffer is available. - * - * Use default buffer size _func(alloc single standard buffer). - * If buffer is available, schedules callback for execution immediately. If no buffers are available now, - * schedule callback later, when buffer will be available. - * - * @param callback - callback to call. - * @return RET_OK or error code. - */ -#ifndef zb_buf_get_out_delayed -#define zb_buf_get_out_delayed(callback) zb_buf_get_out_delayed_func(TRACE_CALL (callback)) -#endif /* zb_buf_get_out_delayed */ - -/** - * @brief Allocate IN buffer, call a callback when the buffer is available. - * - * Use default buffer size _func(alloc single standard buffer). - * If buffer is available, schedules callback for execution immediately. If no buffers are available now, - * schedule callback later, when buffer will be available. - * - * @param callback - callback to call. - * @return RET_OK or error code. - */ -#ifndef zb_buf_get_in_delayed -#define zb_buf_get_in_delayed(callback) zb_buf_get_in_delayed_func(TRACE_CALL (callback)) -#endif /* zb_buf_get_in_delayed */ - -/** - * @brief Allocate OUT buffer, call a callback when the buffer is available. - * - * If buffer is available, schedules callback for execution immediately. If no buffers are available now, - * schedule callback later, when buffer will be available. - * - * @param callback - callback to call. - * @param arg - second argument for a callback - * @param max_size - required maximum buffer payload size (in bytes). The buffer payload size - * is the sum of both data and parameters, so the max_size parameter should - * reflect this. It can be bigger or smaller than the default buffer size. - * Depending on the specific value, the buffer pool may decide to use a fraction - * of buffer or long buffers. If the value is set to 0, the payload size will be equal - * to the size of a single default buffer. - * @return RET_OK or error code. - */ -#ifndef zb_buf_get_out_delayed_ext -#define zb_buf_get_out_delayed_ext(callback,arg,max_size) zb_buf_get_out_delayed_ext_func(TRACE_CALL (callback),(arg),(max_size)) -#endif /* zb_buf_get_out_delayed_ext */ - -/** - * @brief Allocate IN buffer, call a callback when the buffer is available. - * - * If buffer is available, schedules callback for execution immediately. If no buffers are available now, - * schedule callback later, when buffer will be available. - * - * @param callback - callback to call. - * @param arg - second argument for a callback - * @param max_size required maximum buffer payload size (in bytes). The buffer payload size - * is the sum of both data and parameters, so the max_size parameter should - * reflect this. It can be bigger or smaller than the default buffer size. - * Depending on the specific value, the buffer pool may decide to use a fraction - * of buffer or long buffers. If the value is set to 0, the payload size will be equal - * to the size of a single default buffer. - * @return RET_OK or error code. - */ -#ifndef zb_buf_get_in_delayed_ext -#define zb_buf_get_in_delayed_ext(callback,arg,max_size) zb_buf_get_in_delayed_ext_func(TRACE_CALL (callback),(arg),(max_size)) -#endif /* zb_buf_get_in_delayed_ext */ - -/** - * @brief Free packet buffer and put it into free list. - * - * Can be called from the main loop. - * - * @param buf - buffer ID - * - */ -#define zb_buf_free(buf) zb_buf_free_func(TRACE_CALL (buf)) - -/** - * Return pointer to data stored in buffer - * - * @param buf - buffer ID - * - * @return pointer to beginning of data in buffer - * - */ -#define zb_buf_begin(buf) zb_buf_begin_func(TRACE_CALL (buf)) - -/** - Return pointer to the data section end - - @param buf - buffer ID - - @return pointer to the first byte after data in the buffer -*/ -#define zb_buf_end(buf) zb_buf_end_func(TRACE_CALL (buf)) - -/** - * Return current buffer length - * - * @param buf - buffer ID - * - * @return size of data placed in buffer - */ -#define zb_buf_len(buf) zb_buf_len_func(TRACE_CALL (buf)) - - -/** - Copy one buffer to another - - @param dst_buf - destination buffer - @param src_buf - source buffer - */ -#define zb_buf_copy(dst_buf,src_buf) zb_buf_copy_func(TRACE_CALL (dst_buf),(src_buf)) - -/** - @brief Initial data space allocation in buffer. - - Allocate space in the buffer center (keep space in both buffer head - and tail). Use it at upper layers before filling buffer by data. - Old buffer contents is lost. - - @param buf - buffer ID - @param size - size to allocate - @return pointer to buffer data begin - */ -#define zb_buf_initial_alloc(buf,size) zb_buf_initial_alloc_func(TRACE_CALL (buf),(size)) - -/** - Reuse buffer data space by setting data start and length to 0 and zeroing buffer contents - - @param buf - buffer ID - - @return pointer to the buf data buffer begin - */ -#define zb_buf_reuse(buf) zb_buf_reuse_func(TRACE_CALL (buf)) -/** @cond internals_doc */ -/** - Calculate distance between ptr and buffer's data buffer start. - - That function used internally in ZCL. It is not recommended to be used by the application. - - @param buf - buffer ID - @param ptr - user's ptr inside the buffer - - @return offset between ptr and buffer start returned by zb_buf_reuse() - */ -#define zb_buf_get_ptr_off(buf,ptr) zb_buf_get_ptr_off_func(TRACE_CALL (buf),(ptr)) -/** @endcond */ /* internals_doc */ -/** - Alloc buffer tail of size 'size', initialize by zero. - - Usually used to place external information (some parameters) to the buffer. - - @param buf - buffer ID - @param size - requested size. Must met already allocated size. - - @return pointer to the buffer tail or NULL is buffer has no parameter of such size. -*/ -#define zb_buf_alloc_tail(buf,size) zb_buf_alloc_tail_func(TRACE_CALL (buf),(size)) - -/** - Get or allocate buffer tail of size 'size'. Do not initialize. - - Usually used to get or place external information (some parameters) to the buffer. - - @param buf - buffer ID - @param size - requested size - - @return pointer to the buffer tail - */ -#define zb_buf_get_tail(buf,size) zb_buf_get_tail_func(TRACE_CALL (buf),(size)) - -/** - Get buffer tail of size sizeof(type) - - Usually used to place external information _func(some parameters) to the buffer - - @param[in] buf - buffer ID - @param[in] type - data type that will be placed at the buffer end - - @return pointer to the buffer tail casted to _func(type*) - - @b Example - @snippet linky_sample/erl_gw/erl_gw.c zb_buf_get_param_snippet - */ -/* Note: MISRA C-STAT analysis gives false positive for rule 20.7 violation on ZB_BUF_GET_PARAM() - * due to missing parenthesis around "type" on pointer type cast. This is a misinterpretation - * of the rule by C-STAT tool, since this rule refers only to expressions, and not data type casts - * like it is used here. */ -#define ZB_BUF_GET_PARAM(buf, type) ((type *)zb_buf_get_tail_func(TRACE_CALL (buf), sizeof(type))) - -/** - * Cut space at the end of buffer - * - * @param buf - buffer ID - * @param size - size to cut - */ -#define zb_buf_cut_right(buf,size) zb_buf_cut_right_func(TRACE_CALL (buf),(size)) - -/** - * Cut space at the beginning of buffer - * - * @param buf - buffer ID - * @param size - size to cut - * @return pointer to the new data begin -*/ -#define zb_buf_cut_left(buf,size) zb_buf_cut_left_func(TRACE_CALL (buf),(size)) - -/** - * Allocate space at buffer end - * - * @param buf - buffer ID - * @param size - size to allocate - * @return pointer to allocated data data begin - */ -#define zb_buf_alloc_right(buf,size) zb_buf_alloc_right_func(TRACE_CALL (buf),(size)) - -/** - * Allocate space at the beginning of buffer - * - * @param buf - buffer ID - * @param size - size to allocate - * @return pointer to new data begin - */ -#define zb_buf_alloc_left(buf,size) zb_buf_alloc_left_func(TRACE_CALL (buf),(size)) - - -/** - * @name Buffer's internals flags bitmask - * @anchor buf_flags_bm - */ -/** @{ */ -#define ZB_BUF_SECUR_NO_ENCR 0U /*!< No encryption */ -#define ZB_BUF_IS_IN (1U << 0) -/* Encrypt flags. That enum is actually bitmask. */ -#define ZB_BUF_SECUR_NWK_ENCR (1U << 1) /*!< NWK frame encryption */ -#define ZB_BUF_SECUR_APS_ENCR (1U << 2) /*!< APS encryption. Analyze APS header to define which key to use */ -#define ZB_BUF_SECUR_MAC_ENCR (1U << 3) /*!< MAC encryption - for 802.15.4 certification only */ -#define ZB_BUF_SECUR_ALL_ENCR (ZB_BUF_SECUR_NWK_ENCR | ZB_BUF_SECUR_APS_ENCR | ZB_BUF_SECUR_MAC_ENCR) -#define ZB_BUF_USE_SAME_KEY (1U << 4) -#define ZB_BUF_ZDO_CMD_NO_RESP (1U << 5) -#define ZB_BUF_HAS_APS_PAYLOAD (1U << 6) /*!< Flag to indicate whether the buffer contains any APS payload */ -#define ZB_BUF_HAS_APS_USER_PAYLOAD (1U << 7) /*!< Flag to indicate whether the buffer contains APS user payload */ -/** @} */ - -/** - * @brief Type for buffer's internals flags bitmask. - * - * @deprecated holds one of @ref buf_flags_bm. Kept only for backward compatibility as - * @ref buf_flags_bm were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_buf_flags_bm_t; - -/** @cond internals_doc */ -void zb_buf_flags_or_func(TRACE_PROTO zb_bufid_t buf, zb_uint_t val); -void zb_buf_flags_clr_func(TRACE_PROTO zb_bufid_t buf, zb_uint_t mask); -void zb_buf_flags_clr_encr_func(TRACE_PROTO zb_bufid_t buf); -zb_uint_t zb_buf_flags_get_func(TRACE_PROTO zb_bufid_t buf); -/** @endcond */ - -/** - Add bits to the buffer's flags - - @param buf - buffer ID - @param val - value to be ORed with buffer' flags - */ -#define zb_buf_flags_or(buf,val) zb_buf_flags_or_func(TRACE_CALL (buf),(val)) - -/** - Clear buffer' flags by mask by doing flags = flags & ~mask - - @param buf - buffer ID - @param mask - value to be cleared from the flags - @see @ref buf_flags_bm - */ -#define zb_buf_flags_clr(buf,mask) zb_buf_flags_clr_func(TRACE_CALL (buf),(mask)) - - -/** - Clear buffer's flags related to encryption - - That function calls zb_buf_flags_clr(buf, ZB_BUF_SECUR_ALL_ENCR) - @param buf - buffer ID - */ -#define zb_buf_flags_clr_encr(buf) zb_buf_flags_clr_encr_func(TRACE_CALL (buf)) - -/** - Get buffer's flags byte - - @param buf - buffer ID - @return flags value - @see @ref buf_flags_bm - */ -#define zb_buf_flags_get(buf) zb_buf_flags_get_func(TRACE_CALL (buf)) - -/** - Check if buffer pool is in Out Of Memory (OOM) state - - @return ZB_TRUE if ZBOSS is in OOM state - */ -zb_bool_t zb_buf_is_oom_state(void); - -#ifdef ZB_TRACE_LEVEL -/** - Trace buffer statistics into ZBOSS trace - */ -void zb_buf_oom_trace(void); -#endif /* ZB_TRACE_LEVEL */ - -#ifdef ZB_REDUCE_NWK_LOAD_ON_LOW_MEMORY -/** - Check if buffer pool is close to Out Of Memory (OOM) state - - @return ZB_TRUE if ZBOSS is nearly in OOM state - */ -zb_bool_t zb_buf_memory_close_to_low(void); -#endif /* ZB_REDUCE_NWK_LOAD_ON_LOW_MEMORY */ - -/** - Check if buffer pool is close to Out Of Memory (OOM) state - - @return ZB_TRUE if ZBOSS is nearly in OOM state - */ -zb_bool_t zb_buf_memory_low(void); - -/** @cond internals_doc */ -zb_ret_t zb_buf_get_status_func(TRACE_PROTO zb_bufid_t buf); -void zb_buf_set_status_func(TRACE_PROTO zb_bufid_t buf, zb_ret_t status); -zb_uint8_t zb_buf_get_handle_func(TRACE_PROTO zb_bufid_t buf); -void zb_buf_set_handle_func(TRACE_PROTO zb_bufid_t buf, zb_uint8_t handle); -/** @endcond */ - -/** - Get 'status' field of the buffer's header - - @param buf - buffer ID - @return status field value - */ -#define zb_buf_get_status(buf) zb_buf_get_status_func(TRACE_CALL (buf)) - -/** - Set 'status' field of the buffer's header - - @param buf - buffer ID - @param status - new status field value - */ -#define zb_buf_set_status(buf,status) zb_buf_set_status_func(TRACE_CALL (buf), (zb_ret_t)(status)) - -/** - Get 'handle' field of the buffer's header - - @param buf - buffer ID - @return handle field value - */ -#define zb_buf_get_handle(buf) zb_buf_get_handle_func(TRACE_CALL (buf)) - -/** - Set 'handle' field of the buffer's header - - @param buf - buffer ID - @param handle - 'handle' field value - */ -#define zb_buf_set_handle(buf,handle) zb_buf_set_handle_func(TRACE_CALL (buf),(handle)) - -/** - Set or reset "mac needs more buffers" flag. - - To be used internally by ZBOSS. - - @param needs - new "mac needs more buffers" flag value - */ -void zb_buf_set_mac_rx_need(zb_bool_t needs); - -/** - Get "mac needs more buffers" flag. - - To be used internally by ZBOSS. - - @return "mac needs more buffers" flag value - */ -zb_bool_t zb_buf_get_mac_rx_need(void); - -zb_bool_t zb_buf_have_rx_bufs(void); - -#define ZB_BUF_COPY_FLAG_APS_PAYLOAD(dst, src) \ - do { \ - if ((zb_buf_flags_get((src)) & ZB_BUF_HAS_APS_PAYLOAD) != 0U) \ - { \ - zb_buf_flags_or((dst), ZB_BUF_HAS_APS_PAYLOAD); \ - \ - if ((zb_buf_flags_get((src)) & ZB_BUF_HAS_APS_USER_PAYLOAD) != 0U)\ - { \ - zb_buf_flags_or((dst), ZB_BUF_HAS_APS_USER_PAYLOAD); \ - } \ - } \ - } while(0) - -/*! @} */ - -#endif /* ZBOSS_API_BUF_H */ diff --git a/zboss/development/include/zboss_api_core.h b/zboss/development/include/zboss_api_core.h deleted file mode 100644 index 6445984db9..0000000000 --- a/zboss/development/include/zboss_api_core.h +++ /dev/null @@ -1,592 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZBOSS core API header. Time, scheduler and memory buffers API. -*/ - -#ifndef ZB_ZBOSS_API_CORE_H -#define ZB_ZBOSS_API_CORE_H 1 - -#include "zb_vendor.h" -#include "zb_config.h" -#include "zb_types.h" -#include "zb_errors.h" - -/* zb_callback_t is used in osif if we have serial API */ -/*! \addtogroup sched */ -/*! @{ */ - -/** - * Callback function typedef. - * Callback is function planned to execute by another function. - * - * @param param - callback parameter - usually, but not always, ref to packet buf - * - */ -typedef void (ZB_CODE * zb_callback_t)(zb_uint8_t param); - -/** - * Callback function with 2 parameters typedef. - * Callback is function planned to execute by another function. - * - * @param param - callback parameter - usually, but not always, ref to packet buf - * @param cb_param - additional 2-byte callback parameter, user data. - * - */ -typedef void (ZB_CODE * zb_callback2_t)(zb_uint8_t param, zb_uint16_t cb_param); -/*! @} */ - - -/*! \addtogroup time */ -/*! @{ */ - -/** - \par Timer functionality. - - The idea is: platform has some timer which can be stopped or run. - When run, it increments (or decrements - depends on platform) some counter - until counter overflow (underflow), then issues interrupt - wakeups main loop - if it sleeping. - Time stored in ticks; time resolution is platform dependent, its usual value - is 15.36 usec - 1 beacon interval. - @note Time type has limited capacity (usually 16 bits) and can overflow. - Macros which works with time handles overflow. It is supposed that time values will - not differ to more then 1/2 of the maximum time value. - - All that timer macros will not be used directly by the application code - it - is scheduler internals. The only API for timer is ZB_SCHEDULE_ALARM() call. - */ - - -/** - Timer type. - */ - -#ifdef ZB_TIMER_32 - typedef zb_uint32_t zb_time_t; -/** - * Maximum timer value, if 32-bit timer is used. - */ - #define ZB_MAX_TIME_VAL ZB_UINT32_MAX -/** - * Minimum timer value, if 32-bit timer is used. - */ - #define ZB_MIN_TIME_VAL ZB_UINT32_MIN -#else -/* 16 bits for 8051 - it will be hw timer value. */ - typedef zb_uint16_t zb_time_t; -/** - * Maximum timer value, if 16-bit timer is used. - */ - #define ZB_MAX_TIME_VAL ZB_UINT16_MAX -/** - * Minimum timer value, if 16-bit timer is used. - */ - #define ZB_MIN_TIME_VAL ZB_UINT16_MIN -#endif - -/** - * A half of defined maximum timer value. - */ -#define ZB_HALF_MAX_TIME_VAL (ZB_MAX_TIME_VAL / 2U) - -/** @cond internals_doc */ -/** - * @copydoc ZB_TIMER_GET() - * - * @note Don't call directly, use @ref ZB_TIMER_GET() instead - */ -zb_time_t zb_timer_get(void); -/** @endcond */ /* internals_doc */ - -/** - * @return Get current timer value (beacon intervals) - */ -#define ZB_TIMER_GET() (zb_timer_get()) - -/** - Time subtraction: subtract 'b' from 'a' - - Take overflow into account: change sign (subtraction order) if result > - values_diapason/2. - Suppose a always >= b, so result is never negative. - This macro will be used to calculate, for example, amount of time to sleep - - it is positive by definition. - Do not use it to compare time values! Use ZB_TIME_GE() instead. - @note Both a and b is of type @ref zb_time_t. Can't decrease time (subtract - constant from it) using this macro. - - @param a - time to subtract from - @param b - time to subtract - @return subtraction result - */ -#define ZB_TIME_SUBTRACT(a, b) ((zb_time_t)((a) - (b)) < ZB_HALF_MAX_TIME_VAL ? (zb_time_t)((a) - (b)) : (zb_time_t)((b) - (a))) - -/** - Time add: add 'a' to 'b' - - Overflow is possible, but this is ok - it handled by subtraction and compare macros. - - @param a - time to add to - @param b - value to add - @return addition result - */ -#define ZB_TIME_ADD(a, b) (zb_time_t)((a) + (b)) - -/** - Compare times a and b - check that a >= b - - Taking into account overflow and unsigned values arithmetic and supposing - difference between a and b can't be > 1/2 of the overall time values - diapason, - a >= b only if a - b < values_diapason/2 - - @param a - first time value to compare - @param b - second time value to compare - @return 1 is a >= b, 0 otherwise - */ -#define ZB_TIME_GE(a, b) ((zb_time_t)((a) - (b)) < ZB_HALF_MAX_TIME_VAL) - - -/** - One second timeout -*/ -#define ZB_TIME_ONE_SECOND ZB_MILLISECONDS_TO_BEACON_INTERVAL(1000U) - - -#ifdef ZB_TIMER_32 - -/** - Convert time from milliseconds to beacon intervals (32-bit platforms). Round the result up. -*/ -#define ZB_MILLISECONDS_TO_BEACON_INTERVAL_CEIL(ms) (((zb_time_t)(ms) * 1000U + (ZB_BEACON_INTERVAL_USEC - 1U)) / ZB_BEACON_INTERVAL_USEC) - -/** - Convert time from milliseconds to beacon intervals (32-bit platforms). Round the result down. -*/ -#define ZB_MILLISECONDS_TO_BEACON_INTERVAL_FLOOR(ms) ((zb_time_t)(ms) * 1000U / ZB_BEACON_INTERVAL_USEC) - -#else -/** - Convert time from milliseconds to beacon intervals - Try to not cause overflow in 16-bit arithmetic (with some precision lost...). - Round the result down. -*/ -#define ZB_MILLISECONDS_TO_BEACON_INTERVAL_FLOOR(ms) (((10UL * (zb_time_t)(ms) + 0U) / (ZB_BEACON_INTERVAL_USEC / 100U))) - -/** - Convert time from milliseconds to beacon intervals - Try to not cause overflow in 16-bit arithmetic (with some precision lost...). - Round the result up. -*/ -#define ZB_MILLISECONDS_TO_BEACON_INTERVAL_CEIL(ms) (((10UL * (zb_time_t)(ms) + (ZB_BEACON_INTERVAL_USEC / 100U - 1U)) / (ZB_BEACON_INTERVAL_USEC / 100U))) -#endif - -/** - Convert time from milliseconds to beacon intervals. -*/ -#define ZB_MILLISECONDS_TO_BEACON_INTERVAL(ms) ZB_MILLISECONDS_TO_BEACON_INTERVAL_CEIL(ms) - -/** - * Beacon interval in microseconds - * - * 1 beacon interval = aBaseSuperframeDuration * symbol duration - * - * 1 symbol = 16e-6 sec (mac spec 6.5.3.2 Symbol rate) for 2.4GHz ZB. - * 1 beacon interval = 15.360 ms. - */ -#define ZB_BEACON_INTERVAL_USEC (ZB_SYMBOL_DURATION_USEC * ZB_ABASE_SUPERFRAME_DURATION) - - -#ifdef ZB_TIMER_32 -/** - Convert time from beacon intervals to milliseconds (32-bit platform). -*/ -#define ZB_TIME_BEACON_INTERVAL_TO_MSEC(t) ((ZB_BEACON_INTERVAL_USEC * (zb_time_t)(t)) / 1000U) -#else -/** - Convert time from beacon intervals to milliseconds - - Try to not cause overflow in 16-bit arithmetic (with some precision lost...) -*/ -#define ZB_TIME_BEACON_INTERVAL_TO_MSEC(t) ((ZB_BEACON_INTERVAL_USEC / 100U * (t) - 0U) / 10U) -#endif - -/** - Convert time from beacon intervals to microseconds - -*/ -#define ZB_TIME_BEACON_INTERVAL_TO_USEC(t) ((zb_uint64_t)ZB_BEACON_INTERVAL_USEC * (t)) - -/** - Quarterseconds timeout -*/ -#define ZB_TIME_QUARTERECONDS(n) (ZB_TIME_BEACON_INTERVAL_TO_MSEC((n)) / 250U) - -/** - Convert from msec to quarterseconds -*/ -#define ZB_MSEC_TO_QUARTERECONDS(n) ((n) / 250U) - -/** - Convert from quarterseconds to msec -*/ -#define ZB_QUARTERECONDS_TO_MSEC(n) 250UL*(n) - -/** - Convert from quarterseconds to beacon -*/ -#define ZB_QUARTERECONDS_TO_BEACON_INTERVAL(qsec) ZB_MILLISECONDS_TO_BEACON_INTERVAL(250U * (qsec)) - -/** - * Convert from seconds to milliseconds - */ -#define ZB_SECONDS_TO_MILLISECONDS(_s) (1000ul*(_s)) - -/** - Convert from seconds to beacon - - This macro works correctly on 32-bit platforms for intervals smaller than 71 minutes. - The calculation was not tested on 16-bit platforms. -*/ -#define ZB_SECONDS_TO_BEACON_INTERVAL(_s) ZB_MILLISECONDS_TO_BEACON_INTERVAL(1000UL * (_s)) - -/** - Convert from milliseconds to microseconds -*/ -#define ZB_MILLISECONDS_TO_USEC(ms) ((ms) * (1000u)) - -/** - Convert from microseconds to milliseconds -*/ -#define ZB_USECS_TO_MILLISECONDS(usec) ((usec) / (1000u)) - -/*! @} */ - -#include "zb_osif.h" -#include "zb_debug.h" -#include "zb_trace.h" - -#include "zb_pooled_list.h" - -/*! \addtogroup sched */ -/*! @{ */ - -/** @cond internals_doc */ -/** Schedule single-param callback execution. - (use ZB_SCHEDULE_APP_CALLBACK() macro instead of this function). - - Schedule execution of function `func' in the main scheduler loop. - - @param func - function to execute - @param param - callback parameter - usually, but not always ref to packet buffer - - @return RET_OK or error code. - -*/ -zb_ret_t zb_schedule_app_callback(zb_callback_t func, zb_uint8_t param); -/** @endcond */ /* internals_doc */ -/** - Schedule single-param callback execution. - - Schedule execution of function `func' in the main scheduler loop. - - @param func - function to execute - @param param - callback parameter - usually, but not always ref to packet buffer - - @return RET_OK or RET_OVERFLOW. - - */ -#ifndef ZB_SCHEDULE_APP_CALLBACK -#define ZB_SCHEDULE_APP_CALLBACK(func, param) zb_schedule_app_callback(func, param) -#endif /* ZB_SCHEDULE_APP_CALLBACK */ - -/** @cond internals_doc */ -/** Schedule two-param callback execution. - (use ZB_SCHEDULE_APP_CALLBACK2() macro instead of this function). - - Schedule execution of function `func' in the main scheduler loop. - - @param func - function to execute - @param param - callback parameter - usually, but not always ref to packet buffer - @param user_param - zb_uint16_t user parameter - usually, but not always short address - - @return RET_OK or error code. -*/ -zb_ret_t zb_schedule_app_callback2(zb_callback2_t func, zb_uint8_t param, zb_uint16_t user_param); -/** @endcond */ /* internals_doc */ -/** - Schedule two-param callback execution. - Schedule execution of function `func' in the main scheduler loop. - - @param func - function to execute - @param param - zb_uint8_t callback parameter - usually, but not always ref to - packet buffer - @param user_param - zb_uint16_t user parameter - usually, but not always short address - - @return RET_OK or RET_OVERFLOW. - */ -#ifndef ZB_SCHEDULE_APP_CALLBACK2 -#define ZB_SCHEDULE_APP_CALLBACK2(func, param, user_param) zb_schedule_app_callback2(func, param, user_param) -#endif /* ZB_SCHEDULE_APP_CALLBACK2 */ - -/** @cond internals_doc */ -zb_ret_t zb_schedule_app_alarm(zb_callback_t func, zb_uint8_t param, zb_time_t run_after); -/** @endcond */ /* internals_doc */ - -/** - Schedule alarm - callback to be executed after timeout. - - Function will be called via scheduler after timeout expired (maybe, plus some - additional time). - Timer resolution depends on implementation. - Same callback can be scheduled for execution more then once. - - @param func - function to call via scheduler - @param param - parameter to pass to the function - @param timeout_bi - timeout, in beacon intervals - @return RET_OK or RET_OVERFLOW - - */ -#ifndef ZB_SCHEDULE_APP_ALARM -#define ZB_SCHEDULE_APP_ALARM(func, param, timeout_bi) zb_schedule_app_alarm(func, param, timeout_bi) -#endif /* ZB_SCHEDULE_APP_ALARM */ - -/** - Special parameter for zb_schedule_alarm_cancel(): cancel alarm once without - parameter check - - Cancel only one alarm without check for parameter - */ -#define ZB_ALARM_ANY_PARAM (zb_uint8_t)(-1) - -/** - Special parameter for zb_schedule_alarm_cancel(): cancel alarm for all - parameters - */ -#define ZB_ALARM_ALL_CB (zb_uint8_t)(-2) -/** @cond internals_doc */ -/** - Cancel scheduled alarm (use macro ZB_SCHEDULE_APP_ALARM_CANCEL() - instead of this function). - - This function cancel previously scheduled alarm. Function is identified by - the pointer. - - @param func - function to cancel - @param param - parameter to cancel. \see ZB_ALARM_ANY_PARAM. \see ZB_ALARM_ALL_CB - @param p_param - [out] pointer of ref buffer from cancelled flag: free buffer if its alarm will be cancel - @return RET_OK or error code - - */ -zb_ret_t zb_schedule_alarm_cancel(zb_callback_t func, zb_uint8_t param, zb_uint8_t *p_param); -/** @endcond */ /* internals_doc */ -/** - Cancel scheduled alarm. - - This function cancel previously scheduled alarm. Function is identified by - the pointer. - - @param func - function to cancel - @param param - parameter to cancel. \see ZB_ALARM_ANY_PARAM. \see ZB_ALARM_ALL_CB - @return RET_OK or RET_OVERFLOW - - */ -#ifndef ZB_SCHEDULE_APP_ALARM_CANCEL -#define ZB_SCHEDULE_APP_ALARM_CANCEL(func, param) zb_schedule_alarm_cancel((func), (param), NULL) -#endif /* ZB_SCHEDULE_APP_ALARM_CANCEL */ - - -/** @cond internals_doc */ -/** - Get Schedule alarm time - seek alarm and return alarm time - - @param func - function to call via scheduler - @param param - parameter to pass to the function - @param timeout_bi - pointer on alarm timeout, in beacon intervals - @return RET_OK or error code - */ -zb_ret_t zb_schedule_get_alarm_time(zb_callback_t func, zb_uint8_t param, zb_time_t *timeout_bi); -/** @endcond */ /* internals_doc */ - -/** - Get Schedule alarm time - seek alarm and return alarm time - - @param func - function to call via scheduler - @param param - parameter to pass to the function - @param timeout_bi - pointer on alarm timeout, in beacon intervals - @return RET_OK or error code -*/ -#define ZB_SCHEDULE_GET_ALARM_TIME(func, param, timeout_bi) zb_schedule_get_alarm_time(func, param, timeout_bi) - -/** @cond internals_doc */ -/** - Is scheduler stop - Is scheduler running now - - @return ZB_TRUE in case of scheduler is stopped or ZB_FALSE otherwise - */ -zb_bool_t zb_scheduler_is_stop(void); -/** @endcond */ /* internals_doc */ - -/** - Is scheduler stop - Is scheduler running now - - @return ZB_TRUE in case of scheduler is stopped or ZB_FALSE otherwise -*/ -#define ZB_SCHEDULER_IS_STOP() zb_scheduler_is_stop() - -/** - Is scheduler is going to stop/stopped - Is scheduler running now - - @return ZB_TRUE in case of scheduler is going to stop/stopped or ZB_FALSE otherwise - */ -zb_bool_t zb_scheduler_is_going_to_stop(void); -/** @endcond */ /* internals_doc */ - -/** - Is scheduler is going to stop/stopped - Is scheduler running now - - @return ZB_TRUE in case of scheduler is going to stop/stopped or ZB_FALSE otherwise -*/ -#define ZB_SCHEDULER_IS_GOING_TO_STOP() zb_scheduler_is_going_to_stop() - -/*! @} */ - - -/*! \addtogroup rng */ -/*! @{ */ - -/** - * Maximal possible value for randomly generated (32-bit) value - */ -#define ZB_RAND_MAX ((zb_uint32_t)~0U) - -/** - * Generate random 32-bit value - * - * @return random value between 0 to 2^32-1 - */ -zb_uint32_t zb_random(void); - -/** - * Generate random value between 0 to max_value, inclusively. - * - * @return random value between 0 and 'max_value' (32 bits). - */ -zb_uint32_t zb_random_val(zb_uint32_t max_value); - -/** - * Equivalent of zb_random_val(). The macro is left for compatibility reasons. - */ -#define ZB_RANDOM_VALUE(max_value) zb_random_val(max_value) - -/** - * Generate random 8-bit value - * - * @return random value between 0 to 255 - */ -#define ZB_RANDOM_U8() (zb_uint8_t)zb_random_val(0xFFU) - -/** - * Generate random 16-bit value - * - * @return random value between 0 to 0xffff - */ -#define ZB_RANDOM_U16() (zb_uint16_t)zb_random_val(0xFFFFU) - -/** - * Analogue of bzero() for volatile data. - * - * A custom version should be implemented because there is no standard library function for that - * purpose. Also, this function is not platform-dependent in contrast to ZB_BZERO() macro and - * therefore can't be overridden by specific ZBOSS platform. - * - * The function sets individually every byte of provided memory region to zero. - */ -void zb_bzero_volatile(volatile void *s, zb_uint_t size); - -/** @brief Fill in memory with PRBS9 pattern using linear-feedback shift registers. - @param dest - Pointer to the block of memory to fill. - @param cnt - Number of bytes to be set. - @param seed - Random seed - */ -void zb_generate_prbs9(zb_uint8_t *dest, zb_uint16_t cnt, zb_uint16_t seed); - -/*! @} */ - -/** @cond internals_doc */ -/** - Copy 8 byte array (i.e. long address). - */ -void zb_memcpy8(void *vptr, void *vsrc); -/** @endcond */ /* internals_doc */ - -/** - Return absolute value -*/ -#define ZB_ABS(a) ((a) < 0 ? -(a) : (a)) - -/** - * Set of ZB_BITSx() macros return value with bits set in provided positions. - * ZB_BITS1(0) = 1 - * ZB_BITS2(2,3) = 12 - * ZB_BITS3(0,1,2) = 7 - */ -#define ZB_BITS1(_b) (1UL << (_b)) -#define ZB_BITS2(_b1, _b2) ((1UL << (_b1)) | (1UL << (_b2))) -#define ZB_BITS3(_b1, _b2, _b3) ((1UL << (_b1)) | (1UL << (_b2)) | (1UL << (_b3))) -#define ZB_BITS4(_b1, _b2, _b3, _b4) ((1UL << (_b1)) | (1UL << (_b2)) | (1UL << (_b3)) | (1UL << (_b4))) -#define ZB_BITS5(_b1, _b2, _b3, _b4, _b5) ((1UL << (_b1)) | (1UL << (_b2)) | (1UL << (_b3)) | \ - (1UL << (_b4)) | (1UL << (_b5))) - -#define ZB_SET_BIT_IN_BIT_VECTOR(vector, nbit) ( (vector)[ (nbit) / 8U ] |= ( 1U << ( (nbit) % 8U )) ) -#define ZB_CLR_BIT_IN_BIT_VECTOR(vector, nbit) ( (vector)[ (nbit) / 8U ] &= ~( 1U << ( (nbit) % 8U )) ) -#define ZB_CHECK_BIT_IN_BIT_VECTOR(vector, nbit) (ZB_U2B( (vector)[ (nbit) / 8U ] & ( 1U << ( (nbit) % 8U )) )) -#define ZB_SIZE_OF_BIT_VECTOR(bit_count) (bit_count / 8U + !!(bit_count % 8U != 0U)) - -/** - * Checks if the bits specified by 'bitmask' are set in the 'val'. Bit-mask may contain one or - * several bits set. - * - * @return ZB_TRUE if the 'bitmask' is set in 'val'. ZB_FALSE otherwise. - */ -#define ZB_BIT_IS_SET(val, bitmask) (((val) & (bitmask)) != 0U) - -#endif /* ZB_ZBOSS_API_CORE_H */ diff --git a/zboss/development/include/zboss_api_internal.h b/zboss/development/include/zboss_api_internal.h deleted file mode 100644 index 66326ac5ef..0000000000 --- a/zboss/development/include/zboss_api_internal.h +++ /dev/null @@ -1,659 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZBOSS internal data structures required for configurable memory. -*/ - -#ifndef ZB_ZBOSS_API_INTERNAL_H -#define ZB_ZBOSS_API_INTERNAL_H 1 - -#include "zb_vendor.h" -#include "zb_config.h" -#include "zb_types.h" -#include "zb_errors.h" -#include "zb_osif.h" -#include "zb_debug.h" -#include "zb_trace.h" -#include "zb_pooled_list.h" - -#ifndef ZB_MINIMAL_CONTEXT - -#include "zb_address.h" - -/* Data structures moved from subsystem internal headers for configurable memory implementation. */ - -/** - Parameters for storing data in a pending queue - - Moved there from MAC to be able to implement MAC indirect quote size configuration. -*/ -typedef struct zb_mac_pending_data_s -{ - zb_addr_u dst_addr; /**< Destination address */ - zb_uint8_t dst_addr_mode; /**< Destination address mode @ref address_modes */ - zb_uint8_t pending_param; /**< Pointer to pending data */ -} -zb_mac_pending_data_t; - - -/** - APS retransmissions - */ -typedef ZB_PACKED_PRE struct zb_aps_retrans_ent_s -{ - zb_uint16_t addr; /*!< Destination address*/ - zb_uint16_t clusterid; /*!< Cluster ID*/ - zb_uint8_t aps_counter; /*!< APS counter */ - zb_uint8_t src_endpoint; /*!< Source endpoint */ - zb_uint8_t dst_endpoint; /*!< Destination endpoint */ - zb_uint8_t buf; /*!< Buffer index for retranslate */ - - zb_bitfield_t aps_retries:4; /*!< Number of attempts */ - zb_bitfield_t nwk_insecure:1; /*!< Flag 'Is NWK secure' */ - zb_bitfield_t state:3; /*!< @see @ref aps_retrans_ent_state */ -} ZB_PACKED_STRUCT zb_aps_retrans_ent_t; - -#endif /* !ZB_MINIMAL_CONTEXT */ - -typedef ZB_PACKED_PRE struct zb_cb_q_ent_s -{ - union { - zb_callback_t func_ptr; - zb_callback2_t func2_ptr; - } u; /*!< function to call */ - zb_uint16_t user_param; /*!< user parameter */ - zb_uint8_t param; /*!< parameter to pass to 'func' */ -} -ZB_PACKED_STRUCT -zb_cb_q_ent_t; - -/** - Returns 'zb_cb_q_ent_t' members 'func_ptr' or 'func2_ptr' depending on whether the callback - takes one or two parameters. - - @param ent - variable of type 'zb_cb_q_ent_t' - @param is2param - boolean value, ZB_TRUE if the callback takes two parameters, ZB_FALSE otherwise - - @return 'func_ptr' or 'func2_ptr' - */ -#define ZB_CB_QENT_FPTR(ent, is2param) ((!(is2param)) ? (void*)((ent)->u.func_ptr) : (void*)((ent)->u.func2_ptr)) - -typedef ZB_PACKED_PRE struct zb_delayed_buf_q_ent_s -{ - union { - zb_callback_t func_ptr; - zb_callback2_t func2_ptr; - } u; /*!< function to call */ - zb_uint16_t user_param; /*!< user parameter */ - zb_bitfield_t buf_cnt:7; /*!< number of buffers to allocate */ - zb_bitfield_t is_2param:1; /*!< whether this is a 2param callback */ -} -ZB_PACKED_STRUCT -zb_delayed_buf_q_ent_t; - -/** - Returns 'zb_delayed_buf_q_ent_t' members 'func_ptr' or 'func2_ptr' depending on whether the callback - takes one or two parameters. - - @param ent - variable of type 'zb_delayed_buf_q_ent_t' - - @return 'func_ptr' or 'func2_ptr' - */ -#define ZB_DELAYED_BUF_QENT_FPTR(ent) (((ent)->is_2param == 0U) ? (void*)((ent)->u.func_ptr) : (void*)((ent)->u.func2_ptr)) - -/** - Delayed (scheduled to run after timeout) callbacks queue entry. - */ -typedef ZB_PACKED_PRE struct zb_tm_q_ent_s -{ - zb_callback_t func; /*!< function to call */ - zb_time_t run_time; /*!< time to run at */ - zb_uint8_t param; /*!< parameter to pass to 'func' */ - ZB_POOLED_LIST8_FIELD(next); -} -ZB_PACKED_STRUCT -zb_tm_q_ent_t; - -#ifndef ZB_MINIMAL_CONTEXT -/** - Installcode hash for TC - - Do not store installcode itself in RAM - keep only 4 bytes per entry in RAM. - */ -typedef ZB_PACKED_PRE struct zb_aps_installcode_storage_s -{ - zb_uint32_t nvram_offset:28; /*!< offset of zb_aps_installcode_nvram_t - record in nvram. 28 bit supports 256k - page - hope, it is enough */ - zb_bitfield_t nvram_page:4; /*!< nvram page. Hope 16 pages are enough */ -} ZB_PACKED_STRUCT zb_aps_installcode_storage_t; - - -typedef ZB_PACKED_PRE struct zb_aps_device_key_pair_array_s -{ - zb_uint32_t nvram_offset:27; /*!< offset of zb_aps_device_key_pair_storage_t - record in nvram. 27 bit supports 128k - page - hope, it is enough */ - /* Try to fit into 6 bytes instead of 8 */ - zb_lbitfield_t outgoing_frame_counter:21;/*!< Outgoing value for APS frame - * outgoing counter. Used for - * communication with TC only, so - * hope 2^21 ~ 10^10 values are enough - */ -#ifndef ZB_NO_CHECK_INCOMING_SECURE_APS_FRAME_COUNTERS - zb_uint32_t incoming_frame_counter; /*!< Incoming value,for APS frame incoming counter */ -#endif -} ZB_PACKED_STRUCT zb_aps_device_key_pair_array_t; - - - -/** - NWK routing -*/ -typedef ZB_PACKED_PRE struct zb_nwk_routing_s /* do not pack for IAR */ -{ - zb_bitfield_t used:1; /*!< 1 if entry is used, 0 - otherwise */ - zb_bitfield_t status:2; /*!< The status of the route, see @ref nwk_route_state */ -#ifndef ZB_LITE_NO_SOURCE_ROUTING - zb_bitfield_t no_route_cache:1; /*!< Dest does not store source routes. */ - zb_bitfield_t many_to_one:1; /*!< Dest is the concentrator and many-to-one - * request was used */ - zb_bitfield_t route_record_required:1; /*!< Route record command frame should - * be sent to the dest prior to the - * next data packet */ -#endif -#ifndef ZB_NO_NWK_MULTICAST - zb_bitfield_t group_id_flag:1; /*!< Indicates that dest_addr is a Group ID */ -#endif -#if ZB_NWK_ROUTING_TABLE_EXPIRY < 64U - zb_bitfield_t expiry:6; /*!< expiration time. max value - - * ZB_NWK_ROUTING_TABLE_EXPIRY (60) */ -#else - zb_uint8_t expiry; -#endif -#if !defined ZB_CONFIGURABLE_MEM && ZB_IEEE_ADDR_TABLE_SIZE <= 127U - zb_bitfield_t next_hop_addr_ref:7; -#else - zb_uint8_t next_hop_addr_ref; /*!< ref to network address of the next - * hop on the way to the destination */ -#endif - zb_uint16_t dest_addr; /*!< 16-bit network address or Group ID of this route */ -} ZB_PACKED_STRUCT -zb_nwk_routing_t; - -#if defined ZB_PRO_STACK && !defined ZB_LITE_NO_SOURCE_ROUTING -/** - Route Record Table Entry Format, Table 3.45 -*/ -typedef struct zb_nwk_rrec_s /* do not pack for IAR */ -{ - zb_bitfield_t used:1; /*!< Is record used */ - zb_bitfield_t expiry:7; /*!< Expiration time */ - zb_uint8_t count; /*!< Count hops */ - zb_uint16_t addr; /*!< Destination address */ - zb_uint16_t path[ZB_NWK_MAX_PATH_LENGTH]; /*!< Full path */ -} ZB_PACKED_STRUCT zb_nwk_rrec_t; - -#endif - -typedef ZB_PACKED_PRE struct zb_aps_dup_tbl_ent_s -{ - zb_uint8_t addr_ref; /*!< Reference to addr_map */ - zb_uint8_t counter; /*!< APS frame counter */ - zb_bitfield_t clock:6; /*!< Expiry clock counter. Be sure it can hold 2*ZB_APS_DUP_INITIAL_CLOCK */ - zb_bitfield_t is_unicast:1; /*!< Is delivery mode unicast */ - zb_bitfield_t is_command:1; /*!< Is APS command frame */ -} ZB_PACKED_STRUCT zb_aps_dup_tbl_ent_t; - - -/** - Global binding table - source part -*/ -typedef ZB_PACKED_PRE struct zb_aps_bind_src_table_s -{ - zb_address_ieee_ref_t src_addr; /*!< source address as ref from nwkAddressMap */ - zb_uint8_t src_end; /*!< source endpoint */ - zb_uint16_t cluster_id; /*!< cluster id */ -} ZB_PACKED_STRUCT zb_aps_bind_src_table_t; - -/** - Global binding table - destination part with 64-bit address -*/ -typedef ZB_PACKED_PRE struct zb_aps_bind_long_dst_addr_s -{ - zb_address_ieee_ref_t dst_addr; /*!< destination address as ref from nwkAddressMap */ - zb_uint8_t dst_end; /*!< destination endpoint */ -} ZB_PACKED_STRUCT zb_aps_bind_long_dst_addr_t; - -#ifndef ZB_CONFIGURABLE_MEM -#define ZB_APS_BIND_TRANS_TABLE_SIZE ((ZB_IOBUF_POOL_SIZE + 15U)/16U *4U) - -/* it should be 4-byte aligned if it is stored in NVRAM */ -#define ZB_SINGLE_TRANS_INDEX_SIZE (((ZB_APS_BIND_TRANS_TABLE_SIZE + 31U) / 32U) * 4U) -#endif - -/** - Global binding table - destination part -*/ -typedef ZB_PACKED_PRE struct zb_aps_bind_dst_table_s -{ -#ifdef ZB_CONFIGURABLE_MEM - /* WARNING: this field will be rewritten if APS binding dataset is present in NVRAM */ - zb_uint8_t *trans_index; -#endif /* defined ZB_CONFIGURABLE_MEM */ - - ZB_PACKED_PRE union - { - zb_uint16_t group_addr; /*!< group address */ - zb_aps_bind_long_dst_addr_t long_addr; /*!< @see zb_asp_long_dst_addr_t */ - } u; - -#ifndef ZB_CONFIGURABLE_MEM - zb_uint8_t trans_index[ZB_SINGLE_TRANS_INDEX_SIZE]; -#endif /* defined ZB_CONFIGURABLE_MEM */ - - zb_uint8_t dst_addr_mode; /*!< destination address mode flag, 0 - * - group address, otherwise long - * address plus dest endpoint */ - zb_uint8_t src_table_index; /*!< index from zb_asp_src_table_t */ -#ifdef SNCP_MODE - zb_uint8_t id; /* original index position when inserted, to identify - * entry even if moved with the array (on removal of - * other elements) */ - zb_uint8_t align; -#endif -} ZB_PACKED_STRUCT zb_aps_bind_dst_table_t; - -/** - Neighbor table entry - */ -typedef ZB_PACKED_PRE struct zb_neighbor_tbl_ent_s /* not need to pack it at IAR */ -{ - /* 0 */ - zb_bitfield_t used:1; /*!< Record has used */ - zb_bitfield_t ext_neighbor:1; /*!< if 1, this is ext neighbor - * record, else base neighbor */ - - zb_bitfield_t device_type:2; /*!< Neighbor device type - @see @ref nwk_device_type */ - - zb_bitfield_t depth:4; /*!< The network depth of this - device. A value of 0x00 - indicates that this device is the - Zigbee coordinator for the - network. */ - /* 1,2 */ - zb_bitfield_t permit_joining:1; /*!< A value of TRUE indicates that at - least one Zigbee router on the - network currently permits joining, - i.e. its NWK has been issued an - NLME-PERMIT-JOINING - primitive and, the time limit if - given, has not yet expired. */ - - zb_bitfield_t rx_on_when_idle:1; /*!< Indicates if neighbor receiver - enabled during idle periods: - TRUE = Receiver is on - FALSE = Receiver is off - This field should be present for - entries that record the parent or - children of a Zigbee router or - Zigbee coordinator. */ - - zb_bitfield_t relationship:3; /*!< The relationship between the - neighbor and the current device: - 0x00=neighbor is the parent - 0x01=neighbor is a child - 0x02=neighbor is a sibling - 0x03=none of the above - 0x04=previous child - 0x05=unauthenticated child - This field shall be present in every - neighbor table entry. - see @ref nwk_relationship - */ - - zb_bitfield_t need_rejoin:1; /*!< Need send rejoin response without receive request */ - - zb_bitfield_t send_via_routing: 1; /*!< Due to bad link to that device send packets - * via NWK routing. - */ - - zb_bitfield_t keepalive_received:1; /*!< This value indicates at least one keepalive - * has been received from the end device since - * the router has rebooted. - */ - - zb_bitfield_t mac_iface_idx:5; /*!< An index into the MAC Interface Table - * indicating what interface the neighbor or - * child is bound to. */ - - zb_bitfield_t transmit_failure_cnt:4; /*!< Transmit failure counter (used to initiate - * device address - * search). */ - /* 3 */ - zb_uint8_t lqi; /*!< Link quality. Also used to calculate - * incoming cost */ - /* 4 */ - zb_int8_t rssi; /*!< Received signal strength indicator */ - /* 5 */ - ZB_PACKED_PRE union { - ZB_PACKED_PRE struct zb_ext_neighbor_s - { - /* 0 */ - zb_uint16_t short_addr; /*!< 16-bit network address of the - neighboring device */ - /* 2 */ - - zb_ieee_addr_compressed_t long_addr; /*!< 64-bit address (packed) */ - /* 8 */ - zb_uint8_t update_id; /*!< This field reflects the value of nwkUpdateId from the NIB. */ - /* 9 */ - zb_bitfield_t panid_ref:5; /*!< ref to the extended Pan id */ - - zb_bitfield_t router_capacity:1; /*!< This value is set to TRUE if this - device is capable of accepting - join requests from router- - capable devices and is set to - FALSE otherwise. */ - zb_bitfield_t end_device_capacity:1; /*!< This value is set to TRUE if the - device is capable of accepting - join requests from end devices - seeking to join the network and - is set to FALSE otherwise. */ - zb_bitfield_t potential_parent:1; /*!< This field usage - see - 3.6.1.4.1.1 Child Procedure: - If the Status parameter indicates a refusal to permit - joining on the part of the neighboring device (that is, PAN at capacity or PAN - access denied), then the device attempting to join should set the Potential parent - bit to 0 in the corresponding neighbor table entry to indicate a failed join attempt. - */ - /* 10 */ - zb_uint8_t channel_page; /*!< The current channel page occupied by the network. */ - /* 11 */ - zb_bitfield_t logical_channel:6; /*!< The current logical channel - occupied by the network. */ - - zb_bitfield_t stack_profile:2; /*!< A ZBOSS profile identifier. */ - - /* 12 */ - zb_uint8_t classification_mask; - /* 13 */ - } ZB_PACKED_STRUCT ext; - ZB_PACKED_PRE struct zb_base_neighbor_s - { - zb_uint8_t key_seq_number; /*!< key number for which - * incoming_frame_counter is valid */ -#ifndef ZB_ROUTER_ROLE /* no routing at ZED - simplify*/ - zb_address_ieee_ref_t addr_ref; /*!< address translation entry */ - zb_uint8_t nwk_ed_timeout; /*End device timeout - @see @ref nwk_requested_timeout */ -#else /* ZR,ZC */ -#if !defined ZB_CONFIGURABLE_MEM && ZB_IEEE_ADDR_TABLE_SIZE < 128 - /* Won 1 byte here, so base is 11 bytes (== ext) */ - zb_bitfield_t addr_ref:7; /*!< address translation entry */ -#else - /* If configurable mem build, can have >127 addresses, so need a byte here. */ - zb_address_ieee_ref_t addr_ref; -#endif /* if 7 bits are enough */ - - zb_bitfield_t nwk_ed_timeout:4; /*End device timeout - @see @ref nwk_requested_timeout */ - - /* Following fields present only if nwkSymLink = TRUE - this is PRO, not 2007 */ - zb_bitfield_t outgoing_cost:3; /*!< The cost of an outgoing - * link. Got from link status. */ - /* In other words, if a device fails to receive nwkRouterAgeLimit link status - messages from a router neighbor in a row, the old outgoing cost information is - discarded. In this case, the neighbor entry is considered stale and may be reused if - necessary to make room for a new neighbor. */ -#ifndef ZB_LITE_NO_CONFIGURABLE_LINK_STATUS - zb_bitfield_t age:5; /*!< The number of nwkLinkStatusPeriod intervals since a - * link status command was received */ -#else - /* actually ZB_NWK_ROUTER_AGE_LIMIT is 3, so 2 bits is enough */ - zb_bitfield_t age:2; -#endif -#endif /* ZB_ROUTER_ROLE */ - zb_uint32_t incoming_frame_counter; /*!< incoming NWK frame counter - * for this device after - * key change */ - zb_time_t time_to_expire; /*Time stamp for ED aging*/ - } ZB_PACKED_STRUCT base; - } ZB_PACKED_STRUCT u; - /* TODO: move it to base ?? */ -#if !defined ZB_ED_ROLE && defined ZB_MAC_DUTY_CYCLE_MONITORING - zb_bitbool_t is_subghz:1; /*!< if 1, this is Sub-GHz device */ - zb_bitbool_t suspended:1; /*!< if 1, SuspendZCLMessages was sent to the device */ - zb_lbitfield_t pkt_count:22; /*!< count of packets received from this device */ -#define MAX_NBT_PKT_COUNT ((1u<<22U)-1U) - zb_lbitfield_t subghz_ep:8; /*!< endpoint with Sub-GHz cluster on remote device */ -#endif -} ZB_PACKED_STRUCT -zb_neighbor_tbl_ent_t; - -/** - Kind of negotiation before TX -*/ - -/** - * @name MAC TX wait - * @anchor mac_tx_wait - */ -/** @{ */ -#define ZB_MAC_TX_WAIT_ACK 0U -#define ZB_MAC_TX_WAIT_CSMACA 1U -#define ZB_MAC_TX_WAIT_ZGP 2U -#define ZB_MAC_TX_WAIT_NONE 3U -/** @} */ - -/** - * @name MAC TX status - * @anchor mac_tx_status - */ -/** @{ */ -#define ZB_TRANS_TX_OK 0U -#define ZB_TRANS_CHANNEL_BUSY_ERROR 1U -#define ZB_TRANS_TX_RETRY_COUNT_EXCEEDED 2U -#define ZB_TRANS_TX_LBT_TO 3U -#define ZB_TRANS_NO_ACK 4U -/** @} */ - -zb_uint32_t zb_get_channel_mask(void); - -/* MAC diagnostics info */ -typedef ZB_PACKED_PRE struct zb_mac_diagnostic_info_s -{ - zb_uint32_t mac_rx_bcast; /* A counter that is incremented each time - * the MAC layer receives a broadcast. */ - zb_uint32_t mac_tx_bcast; /* A counter that is incremented each time - * the MAC layer transmits a broadcast. */ - zb_uint32_t mac_rx_ucast; /* A counter that is incremented each time the - * MAC layer receives a unicast. */ - - /* These 3 counters are required not to break - * ZDO channel management logic that - * uses normalized counters values. - */ - zb_uint32_t mac_tx_ucast_total_zcl; /* The same as mac_tx_ucast_total, but non-normalized */ - zb_uint16_t mac_tx_ucast_failures_zcl; /* The same as mac_tx_ucast_failures, but non-normalized */ - zb_uint16_t mac_tx_ucast_retries_zcl; /* The same as mac_tx_ucast_retries, but non-normalized*/ - - zb_uint16_t mac_tx_ucast_total; /* Total number of Mac Tx Transactions to - * attempt to send a message (but not - * counting retries) */ - zb_uint16_t mac_tx_ucast_failures; /* Total number of failed Tx - * Transactions. So if the Mac send a - * single packet, it will be retried 4 - * times without ack, that counts as 1 failure */ - zb_uint16_t mac_tx_ucast_retries; /* Total number of Mac Retries regardless of - * whether the transaction resulted in - * success or failure. */ - - zb_uint16_t phy_to_mac_que_lim_reached; /* A counter that is incremented each time when MAC RX queue if full. */ - - zb_uint16_t mac_validate_drop_cnt; /* How many times the packet was dropped at the packet - * validation stage for length or bad formatting. */ - - zb_uint16_t phy_cca_fail_count; /* Number of the PHY layer was unable - * to transmit due to a failed CCA */ - - zb_uint8_t period_of_time; /* Time period over which MACTx results are measured */ - zb_uint8_t last_msg_lqi; /* LQI value of the last received packet */ - zb_int8_t last_msg_rssi; /* RSSI value of the last received packet */ -} ZB_PACKED_STRUCT -zb_mac_diagnostic_info_t; - -/* MAC diagnostics info extended struct */ -typedef ZB_PACKED_PRE struct zb_mac_diagnostic_ex_info_s -{ - zb_mac_diagnostic_info_t mac_diag_info; - /* Internal variables/counters that should be transferred - * from MAC to ZDO and should not go to the NHLE */ - zb_uint32_t mac_tx_for_aps_messages; /* Internal counter used to calculate - average_mac_retry_per_aps_message_sent in ZDO */ -} ZB_PACKED_STRUCT -zb_mac_diagnostic_ex_info_t; - -/*! @brief Structure saved diagnostic counters except MAC - * See the ZCL Diagnostics Cluster -> ZCLr7 spec, chapter 3.15 */ -typedef ZB_PACKED_PRE struct zdo_diagnostics_info_s -{ - /*! @brief An attribute that is incremented - * each time the device resets. */ - zb_uint16_t number_of_resets; - - /*! @brief A counter that is incremented each time - * the APS layer receives a broadcast. */ - zb_uint16_t aps_tx_bcast; - - /*! @brief A counter that is incremented each time - * the APS layer successfully transmits a unicast. */ - zb_uint16_t aps_tx_ucast_success; - - /*! @brief A counter that is incremented each time the - * APS layer retries the sending of a unicast. */ - zb_uint16_t aps_tx_ucast_retry; - - /*! @brief A counter that is incremented each time - * the APS layer fails to send a unicast. */ - zb_uint16_t aps_tx_ucast_fail; - - /*! @brief A counter that is incremented each time the network - * layer submits a route discovery message to the MAC. */ - zb_uint16_t route_disc_initiated; - - /*! @brief A counter that is incremented each time - * an entry is added to the neighbor table. */ - zb_uint16_t nwk_neighbor_added; - - /*! @brief A counter that is incremented each time - * an entry is removed from the neighbor table. */ - zb_uint16_t nwk_neighbor_removed; - - /*! @brief A counter that is incremented each time a neighbor table entry - * becomes stale because the neighbor has not been heard from. */ - zb_uint16_t nwk_neighbor_stale; - - /*! @brief A counter that is incremented each time - * a node joins or rejoins the network via this node. */ - zb_uint16_t join_indication; - - /*! @brief A counter that is incremented each time an entry - * is removed from the child table. */ - zb_uint16_t childs_removed; - - /*! @brief A counter that is incremented each time a message is - * dropped at the network layer because the APS frame counter - * was not higher than the last message seen from that source. */ - zb_uint16_t nwk_fc_failure; - - /*! @brief A counter that is incremented each time a message is - * dropped at the APS layer because the APS frame counter was - * not higher than the last message seen from that source. */ - zb_uint16_t aps_fc_failure; - - /*! @brief A counter that is incremented each time a message is dropped - * at the APS layer because it had APS encryption but the key associated - * with the sender has not been authenticated, and thus the key is not - * authorized for use in APS data messages. */ - zb_uint16_t aps_unauthorized_key; - - /*! @brief A counter that is incremented each time a NWK encrypted message - * was received but dropped because decryption failed. */ - zb_uint16_t nwk_decrypt_failure; - - /*! @brief A counter that is incremented each time an APS encrypted message was - * received but dropped because decryption failed. */ - zb_uint16_t aps_decrypt_failure; - - /*! @brief A counter that is incremented each time - * the stack failed to allocate a packet buffers. */ - zb_uint16_t packet_buffer_allocate_failures; - - /*! @brief A counter that is equal to the average number - * of MAC retries needed to send an APS message. */ - zb_uint16_t average_mac_retry_per_aps_message_sent; - - /*! @brief A counter that is incremented on the NWK layer - * each time tries number of a packet resending are gone. - * - * @note It's a non-stanrad counter that depends on ZB_ENABLE_NWK_RETRANSMIT and - * will be zero always when the macro isn't set. */ - zb_uint16_t nwk_retry_overflow; - - /** A non-standard counter of the number of times the NWK broadcast was - * dropped because the broadcast table was full. - * 01/15/2021 In ZBOSS fired if any of the broadcast_transaction or - * broadcast_retransmission tables are full */ - zb_uint16_t nwk_bcast_table_full; - -} ZB_PACKED_STRUCT zdo_diagnostics_info_t; - -#if defined NCP_MODE && !defined NCP_MODE_HOST -typedef ZB_PACKED_PRE struct zb_ncp_pending_calls_s -{ - zb_uint8_t tsn; - zb_uint16_t call_id; -} ZB_PACKED_STRUCT -zb_ncp_pending_calls_t; - -#endif /* NCP_MODE && !NCP_MODE_HOST */ - -#endif /* !ZB_MINIMAL_CONTEXT */ - -#endif /* ZB_ZBOSS_API_INTERNAL_H */ diff --git a/zboss/development/include/zboss_api_mm.h b/zboss/development/include/zboss_api_mm.h deleted file mode 100644 index 6cd578b3bc..0000000000 --- a/zboss/development/include/zboss_api_mm.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Public Multi-MAC layer API -*/ -#ifndef ZBOSS_API_MM_H -#define ZBOSS_API_MM_H 1 - -/** \addtogroup mm_api */ -/** @{ */ - -enum zb_mac_interfaces_counter_e { - #if defined(ZB_MAC_MONOLITHIC) - ZB_MAC_INTERFACE_MONOLITHIC, - #endif - #if defined(ZB_MAC_BLE) - ZB_MAC_INTERFACE_BLE, - #endif - #if defined(ZB_MAC_SUBGHZ) - ZB_MAC_INTERFACE_SUBGHZ, - #endif - #if defined(ZB_EXTMAC) - ZB_MAC_INTERFACE_EXTMAC, - #endif - ZB_MAC_INTERFACE_MAX -}; - -#if defined(ZB_MAC_MONOLITHIC) - #define ZB_MAC_INTERFACE_MONOLITHIC_ID ((zb_uint8_t)ZB_MAC_INTERFACE_MONOLITHIC) -#endif -#if defined(ZB_EXTMAC) - #define ZB_MAC_INTERFACE_EXTMAC_ID ((zb_uint8_t)ZB_MAC_INTERFACE_EXTMAC) -#endif -#if defined(ZB_MAC_BLE) - #define ZB_MAC_INTERFACE_BLE_ID ((zb_uint8_t)ZB_MAC_INTERFACE_BLE) -#endif -#if defined(ZB_MAC_SUBGHZ) - #define ZB_MAC_INTERFACE_SUBGHZ_ID ((zb_uint8_t)ZB_MAC_INTERFACE_SUBGHZ) -#endif - -/* C-STAT does not allow to assign ZB_MAC_INTERFACE_MAX to ZB_NWK_MAC_IFACE_TBL_SIZE, - * so check configurations manually */ -#if defined(ZB_MAC_MONOLITHIC) && defined(ZB_MAC_BLE) - #define ZB_NWK_MAC_IFACE_TBL_SIZE 2U -#elif defined(ZB_MAC_MONOLITHIC) && !defined(ZB_MACSPLIT_HOST) && !defined(ZB_MAC_BLE) && !defined(ZB_MACSPLIT_DEVICE) && !defined(ZB_MAC_SUBGHZ) - #define ZB_NWK_MAC_IFACE_TBL_SIZE 1U -#elif defined(NCP_MODE_HOST) - /* Preserve default table size to keep previous stack behaviour, but - * do not use any interfaces in that case */ - #define ZB_NWK_MAC_IFACE_TBL_SIZE 1U -#elif defined(ZB_EXTMAC) - #define ZB_NWK_MAC_IFACE_TBL_SIZE 1U -#else - #error Multi-MAC configuration is not supported, at least one interface should be enabled -#endif - -#if ZB_NWK_MAC_IFACE_TBL_SIZE > 1U && defined(ZB_MAC_INTERFACE_SINGLE) - #error ZB_MAC_INTERFACE_SINGLE requires to enable only one interface -#endif - -/** - * @brief Flag that is used to perform some action on all interfaces together - */ -#define ZB_NWK_MULTIMAC_ALL_INTERFACES 0xFFU - -/** @} */ /* mm_api */ - -#endif /*ZBOSS_API_MM_H*/ diff --git a/zboss/development/include/zboss_api_nwk.h b/zboss/development/include/zboss_api_nwk.h deleted file mode 100644 index bf5f1b9b36..0000000000 --- a/zboss/development/include/zboss_api_nwk.h +++ /dev/null @@ -1,870 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Public Network layer API -*/ -#ifndef ZB_ZBOSS_API_NWK_H -#define ZB_ZBOSS_API_NWK_H 1 - -#include "zboss_api_mm.h" - -/** \addtogroup nwk_api */ -/** @{ */ - -/** @addtogroup nwk_common_constants NWK common constants - * @{ - */ - -/** - * @name Network broadcast addresses types - * @anchor nwk_broadcast_addresses -*/ -/** @{ */ -#define ZB_NWK_BROADCAST_ALL_DEVICES 0xFFFFu /**< All devices in PAN */ -#define ZB_NWK_BROADCAST_RX_ON_WHEN_IDLE 0xFFFDu /**< macRxOnWhenIdle = TRUE */ -#define ZB_NWK_BROADCAST_ROUTER_COORDINATOR 0xFFFCu /**< All routers and coordinator */ -#define ZB_NWK_BROADCAST_LOW_POWER_ROUTER 0xFFFBu /**< Low power routers only */ - -#define ZB_NWK_BROADCAST_RESERVED 0xFFF8u /**< Reserved value */ -/** @} */ /* nwk_broadcast_addresses */ - -/** @} */ /* nwk_common_constants */ - -/** @addtogroup nwk_management_service NWK management service - * @{ - */ -/** @brief Check that address is broadcast. - * @param addr - 16-bit address - * @return TRUE if address is broadcast, FALSE otherwise - */ -/* #define ZB_NWK_IS_ADDRESS_BROADCAST(addr) ( ((addr) & 0xFFF0) == 0xFFF0 ) */ -#define ZB_NWK_IS_ADDRESS_BROADCAST(addr) ( (addr) >= ZB_NWK_BROADCAST_RESERVED ) -/** @} */ /* nwk_management_service */ - -/** @addtogroup nwk_common_constants NWK common constants - * @{ - */ - -/** - * @name Network device type - * @anchor nwk_device_type - */ -/** @{ */ -#define ZB_NWK_DEVICE_TYPE_COORDINATOR 0U /*!< Device - Coordinator */ -#define ZB_NWK_DEVICE_TYPE_ROUTER 1U /*!< Device - Router */ -#define ZB_NWK_DEVICE_TYPE_ED 2U /*!< Device - End device */ -#define ZB_NWK_DEVICE_TYPE_NONE 3U /*!< Unknown Device */ -/** @} */ - -/** - * @brief Type for network device type - * - * Holds one of @ref nwk_device_type. Kept for backward compatibility as - * @ref nwk_device_type were declared previously as enum. - */ -typedef zb_uint8_t zb_nwk_device_type_t; - -/** - * @name Leave types - * @anchor nwk_leave_type - */ -/** @{ */ -#define ZB_NWK_LEAVE_TYPE_RESET 0x00U /**< Leave without rejoin */ -#define ZB_NWK_LEAVE_TYPE_REJOIN 0x01U /**< Leave with rejoin */ -/** @} */ - -/** - * @brief Type for leave types - * - * Holds one of @ref nwk_leave_type. Kept for backward compatibility as - * @ref nwk_leave_type were declared previously as enum. - */ -typedef zb_uint8_t zb_nwk_leave_type_t; - - -/** @cond internals_doc */ -/** - * @name Network command status codes - * @anchor nwk_command_status - */ -/** @{ */ -#define ZB_NWK_COMMAND_STATUS_NO_ROUTE_AVAILABLE 0x00U /**< No route available */ -#define ZB_NWK_COMMAND_STATUS_TREE_LINK_FAILURE 0x01U /**< Tree link failure */ -#define ZB_NWK_COMMAND_STATUS_NONE_TREE_LINK_FAILURE 0x02U /**< None-tree link failure */ -#define ZB_NWK_COMMAND_STATUS_LOW_BATTERY_LEVEL 0x03U /**< Low battery level */ -#define ZB_NWK_COMMAND_STATUS_NO_ROUTING_CAPACITY 0x04U /**< No routing capacity */ -#define ZB_NWK_COMMAND_STATUS_NO_INDIRECT_CAPACITY 0x05U /**< No indirect capacity */ -#define ZB_NWK_COMMAND_STATUS_INDIRECT_TRANSACTION_EXPIRY 0x06U /**< Indirect transaction expiry */ -#define ZB_NWK_COMMAND_STATUS_TARGET_DEVICE_UNAVAILABLE 0x07U /**< Target device unavailable */ -#define ZB_NWK_COMMAND_STATUS_TARGET_ADDRESS_UNALLOCATED 0x08U /**< Target address unallocated */ -#define ZB_NWK_COMMAND_STATUS_PARENT_LINK_FAILURE 0x09U /**< Parent link failure */ -#define ZB_NWK_COMMAND_STATUS_VALIDATE_ROUTE 0x0aU /**< Validate route */ -#define ZB_NWK_COMMAND_STATUS_SOURCE_ROUTE_FAILURE 0x0bU /**< Source route failure */ -#define ZB_NWK_COMMAND_STATUS_MANY_TO_ONE_ROUTE_FAILURE 0x0cU /**< Many-to-one route failure */ -#define ZB_NWK_COMMAND_STATUS_ADDRESS_CONFLICT 0x0dU /**< Address conflict */ -#define ZB_NWK_COMMAND_STATUS_VERIFY_ADDRESS 0x0eU /**< Verify address */ -#define ZB_NWK_COMMAND_STATUS_PAN_IDENTIFIER_UPDATE 0x0fU /**< Pan ID update */ -#define ZB_NWK_COMMAND_STATUS_NETWORK_ADDRESS_UPDATE 0x10U /**< Network address update */ -#define ZB_NWK_COMMAND_STATUS_BAD_FRAME_COUNTER 0x11U /**< Bad frame counter */ -#define ZB_NWK_COMMAND_STATUS_BAD_KEY_SEQUENCE_NUMBER 0x12U /**< Bad key sequence number */ -#define ZB_NWK_COMMAND_STATUS_UNKNOWN_COMMAND 0x13U /**< Command received is not known *//** @} */ -/** @} */ - -/** - * @brief Type for network command status codes - * - * Holds one of @ref nwk_command_status. Kept for backward compatibility as - * @ref nwk_command_status were declared previously as enum. - */ -typedef zb_uint8_t zb_nwk_command_status_t; - -/** @endcond */ /* internals_doc */ -/** @} */ /* nwk_common_constants */ - -/** @cond internals_doc */ -/** @brief 3.4.3 Network Status Command: Arguments of the NLME-STATUS.indication routine. */ -typedef ZB_PACKED_PRE struct zb_nlme_status_indication_s -{ - zb_uint8_t status; /**< Error code associated with the failure */ - zb_uint16_t network_addr; /**< Network device address associated with the status information */ - zb_uint8_t unknown_command_id; /**< Unknown command ID - (required for ZB_NWK_COMMAND_STATUS_UNKNOWN_COMMAND) */ -} ZB_PACKED_STRUCT -zb_nlme_status_indication_t; -/** @endcond */ /* internals_doc */ - -/** @addtogroup nwk_common_constants NWK common constants - * @{ - */ -/** - LQI undefined value - */ -#define ZB_MAC_LQI_UNDEFINED 0U -/** - RSSI undefined value - */ -#define ZB_MAC_RSSI_UNDEFINED 0x7fU - -/** - Number of the first channel -*/ -/* #define ZB_MAC_START_CHANNEL_NUMBER 11 */ -/** - Maximal number of the channels - */ -#define ZB_MAC_MAX_CHANNEL_NUMBER 26U -/** - Total number of supported channels - */ -#define ZB_MAC_SUPPORTED_CHANNELS (ZB_MAC_MAX_CHANNEL_NUMBER + 1U) - -/** @cond DOXYGEN_SE_SECTION */ -/* See D.10.2.1.3.2 Channel Pages */ - -/* North America and Mexico region Page 23 */ - -/** - The first logical channel for Page 23 Sub GHz -*/ -#define ZB_PAGE23_SUB_GHZ_START_LOGICAL_CHANNEL 0U - -/** - Number of the first channel in channel mask for Page 23 Sub GHz -*/ -#define ZB_PAGE23_SUB_GHZ_START_CHANNEL_NUMBER 0U -/** - The last logical channel for Page 23 Sub GHz -*/ -#define ZB_PAGE23_SUB_GHZ_MAX_LOGICAL_CHANNEL 24U -/** - Number of the last channel in channel mask for Page 23 Sub GHz -*/ -#define ZB_PAGE23_SUB_GHZ_MAX_CHANNEL_NUMBER (ZB_PAGE23_SUB_GHZ_MAX_LOGICAL_CHANNEL - \ - ZB_PAGE23_SUB_GHZ_START_LOGICAL_CHANNEL) - -/* Europe region Pages 24 - 27 */ - -/** - The first logical channel for Page 24 Sub GHz -*/ -#define ZB_PAGE24_SUB_GHZ_START_LOGICAL_CHANNEL 56U - -/** - Number of the first channel in channel mask for Page 24 Sub GHz -*/ -#define ZB_PAGE24_SUB_GHZ_START_CHANNEL_NUMBER 0U -/** - The last logical channel for Page 24 Sub GHz -*/ -#define ZB_PAGE24_SUB_GHZ_MAX_LOGICAL_CHANNEL 76U -/** - Number of the last channel in channel mask for Page 24 Sub GHz -*/ -#define ZB_PAGE24_SUB_GHZ_MAX_CHANNEL_NUMBER (ZB_PAGE24_SUB_GHZ_MAX_LOGICAL_CHANNEL - \ - ZB_PAGE24_SUB_GHZ_START_LOGICAL_CHANNEL) - -/** - The first logical channel for Page 25 Sub GHz -*/ -#define ZB_PAGE25_SUB_GHZ_START_LOGICAL_CHANNEL 0U - -/** - Number of the first channel in channel mask for Page 25 Sub GHz -*/ -#define ZB_PAGE25_SUB_GHZ_START_CHANNEL_NUMBER 0U -/** - The last logical channel for Page 25 Sub GHz -*/ -#define ZB_PAGE25_SUB_GHZ_MAX_LOGICAL_CHANNEL 26U -/** - Number of the last channel in channel mask for Page 25 Sub GHz -*/ -#define ZB_PAGE25_SUB_GHZ_MAX_CHANNEL_NUMBER (ZB_PAGE25_SUB_GHZ_MAX_LOGICAL_CHANNEL - \ - ZB_PAGE25_SUB_GHZ_START_LOGICAL_CHANNEL) - -/** - The first logical channel for Page 26 Sub GHz -*/ -#define ZB_PAGE26_SUB_GHZ_START_LOGICAL_CHANNEL 27U - -/** - Number of the first channel in channel mask for Page 26 Sub GHz -*/ -#define ZB_PAGE26_SUB_GHZ_START_CHANNEL_NUMBER 0U -/** - The last logical channel for Page 26 Sub GHz -*/ -#define ZB_PAGE26_SUB_GHZ_MAX_LOGICAL_CHANNEL 34U -/** - Number of the last channel in channel mask for Page 26 Sub GHz -*/ -#define ZB_PAGE26_SUB_GHZ_MAX_CHANNEL_NUMBER (ZB_PAGE26_SUB_GHZ_MAX_LOGICAL_CHANNEL - \ - ZB_PAGE26_SUB_GHZ_START_LOGICAL_CHANNEL) - -/** - The first logical channel for Page 27 Sub GHz -*/ -#define ZB_PAGE27_SUB_GHZ_START_LOGICAL_CHANNEL 35U - -/** - Number of the first channel in channel mask for Page 27 Sub GHz -*/ -#define ZB_PAGE27_SUB_GHZ_START_CHANNEL_NUMBER 0U -/** - The last logical channel for Page 27 Sub GHz -*/ -#define ZB_PAGE27_SUB_GHZ_MAX_LOGICAL_CHANNEL 55U -/** - Number of the last channel in channel mask for Page 27 Sub GHz -*/ -#define ZB_PAGE27_SUB_GHZ_MAX_CHANNEL_NUMBER (ZB_PAGE27_SUB_GHZ_MAX_LOGICAL_CHANNEL - \ - ZB_PAGE27_SUB_GHZ_START_LOGICAL_CHANNEL) - -/* Great Britain region Pages 28 - 31 */ - -/** - The first logical channel for Page 28 Sub GHz -*/ -#define ZB_PAGE28_SUB_GHZ_START_LOGICAL_CHANNEL 0U - -/* 08/21/2017 EE CR:MINOR Am I right this value is always 0 for any page? Do we ever need separate constants? */ -/** - Number of the first channel in channel mask for Page 28 Sub GHz -*/ -#define ZB_PAGE28_SUB_GHZ_START_CHANNEL_NUMBER 0U -/** - The last logical channel for Page 28 Sub GHz -*/ -#define ZB_PAGE28_SUB_GHZ_MAX_LOGICAL_CHANNEL 26U -/** - Number of the last channel in channel mask for Page 28 Sub GHz -*/ -#define ZB_PAGE28_SUB_GHZ_MAX_CHANNEL_NUMBER (ZB_PAGE28_SUB_GHZ_MAX_LOGICAL_CHANNEL - \ - ZB_PAGE28_SUB_GHZ_START_LOGICAL_CHANNEL) - -/** - The first logical channel for Page 29 Sub GHz -*/ -#define ZB_PAGE29_SUB_GHZ_START_LOGICAL_CHANNEL 27U -/** - Number of the first channel in channel mask for Page 29 Sub GHz -*/ -#define ZB_PAGE29_SUB_GHZ_START_CHANNEL_NUMBER 0U -/** - The last logical channel for Page 29 Sub GHz (for solid range 27-34) -*/ -#define ZB_PAGE29_SUB_GHZ_PRE_MAX_LOGICAL_CHANNEL 34U -/** - The last logical channel for Page 29 Sub GHz -*/ -#define ZB_PAGE29_SUB_GHZ_MAX_LOGICAL_CHANNEL 62U -/** - Number of the last channel in channel mask for Page 29 Sub GHz -*/ -#define ZB_PAGE29_SUB_GHZ_MAX_CHANNEL_NUMBER (ZB_PAGE29_SUB_GHZ_PRE_MAX_LOGICAL_CHANNEL - \ - ZB_PAGE29_SUB_GHZ_START_LOGICAL_CHANNEL + 1U /* 62 channel */) - -/** - The first logical channel for Page 30 Sub GHz -*/ -#define ZB_PAGE30_SUB_GHZ_START_LOGICAL_CHANNEL 35U -/** - Number of the first channel in channel mask for Page 30 Sub GHz -*/ -#define ZB_PAGE30_SUB_GHZ_START_CHANNEL_NUMBER 0U -/** - The last logical channel for Page 30 Sub GHz -*/ -#define ZB_PAGE30_SUB_GHZ_MAX_LOGICAL_CHANNEL 61U -/** - Number of the last channel in channel mask for Page 30 Sub GHz -*/ -#define ZB_PAGE30_SUB_GHZ_MAX_CHANNEL_NUMBER (ZB_PAGE30_SUB_GHZ_MAX_LOGICAL_CHANNEL - \ - ZB_PAGE30_SUB_GHZ_START_LOGICAL_CHANNEL) - -/** - The first logical channel for Page 31 Sub GHz -*/ -#define ZB_PAGE31_SUB_GHZ_START_LOGICAL_CHANNEL 0U -/** - Number of the first channel in channel mask for Page 31 Sub GHz -*/ -#define ZB_PAGE31_SUB_GHZ_START_CHANNEL_NUMBER 0U -/** - The last logical channel for Page 31 Sub GHz -*/ -#define ZB_PAGE31_SUB_GHZ_MAX_LOGICAL_CHANNEL 26U -/** - Number of the last channel in channel mask for Page 31 Sub GHz -*/ -#define ZB_PAGE31_SUB_GHZ_MAX_CHANNEL_NUMBER (ZB_PAGE31_SUB_GHZ_MAX_LOGICAL_CHANNEL - \ - ZB_PAGE31_SUB_GHZ_START_LOGICAL_CHANNEL) - /** @endcond */ /* DOXYGEN_SE_SECTION */ -/* ZB_MAC_START_CHANNEL_NUMBER */ -/** - The first logical channel for Page 0 2.4GHz -*/ -#define ZB_PAGE0_2_4_GHZ_START_LOGICAL_CHANNEL 11U -/* Let's keep compatibility with bits layout in ZBOSS without sub-gig: start from 11 in 2.4. - Actually, only subgig pages 28 and 31 are ok too (logical == bit#). Pages 29 and 30 are special case. - */ -/** - Number of the first channel in channel mask for Page 0 2.4GHz -*/ -#define ZB_PAGE0_2_4_GHZ_START_CHANNEL_NUMBER ZB_PAGE0_2_4_GHZ_START_LOGICAL_CHANNEL -/** - The last logical channel in channel mask for Page 0 2.4GHz -*/ -#define ZB_PAGE0_2_4_GHZ_MAX_LOGICAL_CHANNEL ZB_MAC_MAX_CHANNEL_NUMBER -/** - Number of the last channel in channel mask for Page 0 2.4GHz -*/ -#define ZB_PAGE0_2_4_GHZ_MAX_CHANNEL_NUMBER ZB_MAC_MAX_CHANNEL_NUMBER -/* (ZB_PAGE0_2_4_GHZ_MAX_LOGICAL_CHANNEL - \ */ -/* ZB_PAGE0_2_4_GHZ_START_LOGICAL_CHANNEL) */ - -/** @cond DOXYGEN_SE_SECTION */ -/** - Maximal number of channels for Page 23 Sub GHz -*/ -#define ZB_PAGE23_SUB_GHZ_MAX_CHANNELS_COUNT (ZB_PAGE23_SUB_GHZ_MAX_CHANNEL_NUMBER - \ - ZB_PAGE23_SUB_GHZ_START_CHANNEL_NUMBER + 1U) -/** - Maximal number of channels for Page 24 Sub GHz -*/ -#define ZB_PAGE24_SUB_GHZ_MAX_CHANNELS_COUNT (ZB_PAGE24_SUB_GHZ_MAX_CHANNEL_NUMBER - \ - ZB_PAGE24_SUB_GHZ_START_CHANNEL_NUMBER + 1U) -/** - Maximal number of channels for Page 25 Sub GHz -*/ -#define ZB_PAGE25_SUB_GHZ_MAX_CHANNELS_COUNT (ZB_PAGE25_SUB_GHZ_MAX_CHANNEL_NUMBER - \ - ZB_PAGE25_SUB_GHZ_START_CHANNEL_NUMBER + 1U) -/** - Maximal number of channels for Page 26 Sub GHz -*/ -#define ZB_PAGE26_SUB_GHZ_MAX_CHANNELS_COUNT (ZB_PAGE26_SUB_GHZ_MAX_CHANNEL_NUMBER - \ - ZB_PAGE26_SUB_GHZ_START_CHANNEL_NUMBER + 1U) -/** - Maximal number of channels for Page 27 Sub GHz -*/ -#define ZB_PAGE27_SUB_GHZ_MAX_CHANNELS_COUNT (ZB_PAGE27_SUB_GHZ_MAX_CHANNEL_NUMBER - \ - ZB_PAGE27_SUB_GHZ_START_CHANNEL_NUMBER + 1U) - -/** - Maximal number of channels for Page 28 Sub GHz -*/ -#define ZB_PAGE28_SUB_GHZ_MAX_CHANNELS_COUNT (ZB_PAGE28_SUB_GHZ_MAX_CHANNEL_NUMBER - \ - ZB_PAGE28_SUB_GHZ_START_CHANNEL_NUMBER + 1U) -/** - Maximal number of channels for Page 29 Sub GHz -*/ -#define ZB_PAGE29_SUB_GHZ_MAX_CHANNELS_COUNT (ZB_PAGE29_SUB_GHZ_MAX_CHANNEL_NUMBER - \ - ZB_PAGE29_SUB_GHZ_START_CHANNEL_NUMBER + 1U) -/** - Maximal number of channels for Page 30 Sub GHz -*/ -#define ZB_PAGE30_SUB_GHZ_MAX_CHANNELS_COUNT (ZB_PAGE30_SUB_GHZ_MAX_CHANNEL_NUMBER - \ - ZB_PAGE30_SUB_GHZ_START_CHANNEL_NUMBER + 1U) -/** - Maximal number of channels for Page 31 Sub GHz -*/ -#define ZB_PAGE31_SUB_GHZ_MAX_CHANNELS_COUNT (ZB_PAGE31_SUB_GHZ_MAX_CHANNEL_NUMBER - \ - ZB_PAGE31_SUB_GHZ_START_CHANNEL_NUMBER + 1U) -/** @endcond */ /* DOXYGEN_SE_SECTION */ -/** - Maximal number of channels for Page 0 2.4GHz -*/ -#define ZB_PAGE0_2_4_GHZ_MAX_CHANNELS_COUNT (ZB_PAGE0_2_4_GHZ_MAX_CHANNEL_NUMBER - \ - ZB_PAGE0_2_4_GHZ_START_CHANNEL_NUMBER + 1U) -/** @cond DOXYGEN_SE_SECTION */ -/** - Maximal number of ed scan channels for all pages -*/ -#define ZB_ED_SCAN_MAX_CHANNELS_COUNT \ - ((ZB_IO_BUF_SIZE - sizeof(zb_uint8_t)) / sizeof(zb_energy_detect_channel_info_t)) -/** - Max # of network descriptors which can fit into a single buffer. -*/ -#define ZB_ACTIVE_SCAN_MAX_NETWORK_COUNT \ - ((ZB_IO_BUF_SIZE - sizeof(zb_nlme_network_discovery_confirm_t)) / sizeof(zb_nlme_network_descriptor_t)) - -#define ZB_CHANNEL_PAGE_MAX_CHANNELS_COUNT ZB_PAGE28_SUB_GHZ_MAX_CHANNELS_COUNT -/** @endcond */ /* DOXYGEN_SE_SECTION */ -/** @} */ /* nwk_common_constants */ - -/** @cond internals_doc */ -/** @addtogroup nwk_pib_cache PIB cache - * @{ - */ - -/** - Data structure used to cache frequently used PIB attributes. - - Useful when using alien MAC layer without direct access to PIB: blockable "get" - interface to PIB is too complex and slow. - */ -typedef struct zb_nwk_pib_cache_s -{ - zb_uint16_t mac_short_address; /*!< The 16-bit address that the device uses - to communicate in the PAN. */ - zb_uint16_t mac_pan_id; /*!< The 16-bit identifier of the PAN on which - the device is operating. If this value is 0xffff, - the device is not associated. */ - zb_ieee_addr_t mac_extended_address; /*!< The 64-bit (IEEE) address assigned to the device. */ - - zb_uint8_t mac_association_permit; /*!< Indication of whether a coordinator is currently - allowing association. A value of TRUE indicates*/ - zb_uint8_t mac_rx_on_when_idle; /*!< Indication of whether the MAC sublayer is to enable - its receiver during idle periods. */ - zb_uint8_t phy_current_page[ZB_NWK_MAC_IFACE_TBL_SIZE]; /*!< Index of current physical channel page */ - zb_uint8_t phy_current_channel[ZB_NWK_MAC_IFACE_TBL_SIZE]; /*!< Index of current physical channel */ - zb_uint8_t phy_primary_iface; /*!< Index of MAC interface that is used for joining */ -} zb_nwk_pib_cache_t; - -/** @} */ - - -/** - * @name PIB cache mirror - * \par Here are cache of PIB / NIB mirror of PIB values. - * - * After that values modified in NWK or upper, must sync it with MAC using MLME-SET. - * - * @{ - */ - -/** - Function used to access PIB cache. - @return pointer to PIB cache. - */ -zb_nwk_pib_cache_t *zb_nwk_get_pib_cache(void); -/** - Macro used to access PIB cache. - @return pointer to PIB cache. - */ - - -/* We get false-positive violations of MISRA rules 5.2 and 5.4 here - * because an internal header redefine ZB_PIB_CACHE macro for - * optimization purposes, and C-STAT can not properly handle - * #undef usage. Only one macro definition is valid at a time, - * but MISRA rules 5.2 and 5.4 prohibit two definitions of a - * symbol simultaneously. - * We ensure that only one instance of the macro is effectively - * defined here. */ -#ifdef ZB_PIB_CACHE -#error Please ensure that you are not including any internal headers which redefine ZB_PIB_CACHE macro before including this file -#else /* ZB_PIB_CACHE */ -/*cstat !MISRAC2012-Rule-5.2_c99 !MISRAC2012-Rule-5.4_c99 */ -#define ZB_PIB_CACHE() zb_nwk_get_pib_cache() -#endif /* ZB_PIB_CACHE */ - -#ifndef NCP_MODE_HOST -/** Cached value of device network address */ -#define ZB_PIBCACHE_NETWORK_ADDRESS() ZB_PIB_CACHE()->mac_short_address -/** Cached value of device Pan ID */ -#define ZB_PIBCACHE_PAN_ID() ZB_PIB_CACHE()->mac_pan_id -/** Cached value of device extended address */ -#define ZB_PIBCACHE_EXTENDED_ADDRESS() ZB_PIB_CACHE()->mac_extended_address -/** Cached value of RxOnWhenIdle attribute */ -#ifdef ZB_ED_RX_OFF_WHEN_IDLE -#define ZB_PIBCACHE_RX_ON_WHEN_IDLE() ZB_B2U(!ZB_IS_DEVICE_ZED()) -#else -#define ZB_PIBCACHE_RX_ON_WHEN_IDLE() ZB_PIB_CACHE()->mac_rx_on_when_idle -#endif -/** Cached value of AssociationPermit attribute */ -#define ZB_PIBCACHE_ASSOCIATION_PERMIT() ZB_PIB_CACHE()->mac_association_permit - -#define ZB_PIBCACHE_PRIMARY_IFACE() ZB_PIB_CACHE()->phy_primary_iface -#define ZB_PIBCACHE_PRIMARY_IFACE_PAGE() ZB_PIB_CACHE()->phy_current_page[ZB_PIB_CACHE()->phy_primary_iface] -#define ZB_PIBCACHE_PRIMARY_IFACE_CHANNEL() ZB_PIB_CACHE()->phy_current_channel[ZB_PIB_CACHE()->phy_primary_iface] - -/** Cached value of CurrentChannel attribute */ -#define ZB_PIBCACHE_CURRENT_CHANNEL() ZB_PIBCACHE_PRIMARY_IFACE_CHANNEL() -#define ZB_PIBCACHE_CURRENT_CHANNEL_BY_IFACE(iface_id) ZB_PIB_CACHE()->phy_current_channel[iface_id] -#define ZB_PIBCACHE_CURRENT_CHANNELS_LIST() ZB_PIB_CACHE()->phy_current_channel -/** Cached value of CurrentPage attribute */ -#define ZB_PIBCACHE_CURRENT_PAGE() ZB_PIBCACHE_PRIMARY_IFACE_PAGE() -#define ZB_PIBCACHE_CURRENT_PAGE_BY_IFACE(iface_id) ZB_PIB_CACHE()->phy_current_page[iface_id] -#define ZB_PIBCACHE_CURRENT_PAGES_LIST() ZB_PIB_CACHE()->phy_current_page - -#else /* NCP_MODE_HOST */ - -/** Cached value of device network address */ -#define ZB_PIBCACHE_NETWORK_ADDRESS() zb_get_short_address() -/** Cached value of RxOnWhenIdle attribute */ -#ifdef ZB_ED_RX_OFF_WHEN_IDLE -/* Make simpler checks if ZED always rx-off-when-idle */ -#undef ZB_PIBCACHE_RX_ON_WHEN_IDLE -#define ZB_PIBCACHE_RX_ON_WHEN_IDLE() ZB_B2U(!ZB_IS_DEVICE_ZED()) -#else -#define ZB_PIBCACHE_RX_ON_WHEN_IDLE() ZB_B2U(zb_get_rx_on_when_idle()) -#endif -#endif /* !NCP_MODE_HOST */ - -/** - Arguments of the NLME-PERMIT_JOINING.request routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_permit_joining_request_s -{ - zb_uint8_t permit_duration; /**< Time in seconds during which the coordinator - * or router will allow associations */ -} ZB_PACKED_STRUCT -zb_nlme_permit_joining_request_t; - -/** - NLME-PERMIT-JOINING.request primitive - - Allow/disallow network joining - - @param param - buffer containing parameters - @see - zb_nlme_network_formation_request_t - @return RET_OK on success, error code otherwise. - - @snippet doxygen_snippets.dox zb_nlme_permit_joining_request - */ -void zb_nlme_permit_joining_request(zb_uint8_t param); - - -/** @} */ -/** @endcond */ /* internals_doc */ - -/** @addtogroup nwk_panid_conflicts NWK PAN ID conflicts - * @{ - */ - -#define ZB_PAN_ID_CONFLICT_INFO_MAX_PANIDS_COUNT 16U - -/** Structure describing a detected PAN ID conflict */ -typedef ZB_PACKED_PRE struct zb_pan_id_conflict_info_s -{ - zb_uint16_t panid_count; /* cb_param.gnr.in = _pvalue) - -/** Set OUTPUT device callback parameter with specific value. */ -#define ZB_ZCL_DEVICE_CMD_PARAM_OUT_SET(_param, _pvalue) \ - ((ZB_ZCL_DEVICE_CMD_PARAM(_param))->cb_param.gnr.out = _pvalue) - -/** Init all fields of device callback params. */ -#define ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(_param, _cb_id, _status, _cmd_info, _in, _out) \ - (ZB_BZERO(ZB_ZCL_DEVICE_CMD_PARAM(_param), sizeof(*ZB_ZCL_DEVICE_CMD_PARAM(_param))), \ - (ZB_ZCL_DEVICE_CMD_PARAM_CB_ID(_param) = _cb_id, \ - (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(_param) = _status, \ - (ZB_ZCL_DEVICE_CMD_PARAM_CMD_INFO(_param) = _cmd_info, \ - (ZB_ZCL_DEVICE_CMD_PARAM_IN_SET(_param, _in), \ - (ZB_ZCL_DEVICE_CMD_PARAM_OUT_SET(_param, _out))))))) -/** @endcond */ /* internals_doc */ - -/** Get INPUT device callback parameter from buffer reference. - * @param _param - Reference to buffer. - * @param _ptype - Target data type. - * @return - Pointer to @e _ptype data. - * @see @ref zb_zcl_device_callback_param_t. - */ -#define ZB_ZCL_DEVICE_CMD_PARAM_IN_GET(_param, _ptype) \ - ((const _ptype *) ((ZB_ZCL_DEVICE_CMD_PARAM(_param))->cb_param.gnr.in)) - -/** Get OUTPUT device callback parameter from buffer reference. - * @param _param - Reference to buffer. - * @param _ptype - Target data type - * @return - Pointer to @e _ptype data. - */ -#define ZB_ZCL_DEVICE_CMD_PARAM_OUT_GET(_param, _ptype) \ - ((_ptype *) ((ZB_ZCL_DEVICE_CMD_PARAM(_param))->cb_param.gnr.out)) - -/** Get access to @ref zb_zcl_parsed_hdr_t data from device callback parameter. - * @param _param - Reference to buffer. - * @return - Pointer to @ref zb_zcl_parsed_hdr_t structure. - */ -#define ZB_ZCL_DEVICE_CMD_PARAM_CMD_INFO(_param) \ - ((ZB_ZCL_DEVICE_CMD_PARAM(_param))->cb_param.gnr.in_cmd_info) - -/** Get access to @ref zb_zcl_device_callback_param_t::device_cb_id of device callback parameters. - * @param _param - Reference to buffer. - */ -#define ZB_ZCL_DEVICE_CMD_PARAM_CB_ID(_param) \ - ((ZB_ZCL_DEVICE_CMD_PARAM(_param))->device_cb_id) - -/** Get access to @ref zb_zcl_device_callback_param_t::status of device callback parameters. - * @param _param - Reference to buffer. - * @return - zb_ret_t value of current status. - */ -#define ZB_ZCL_DEVICE_CMD_PARAM_STATUS(_param) \ - ((ZB_ZCL_DEVICE_CMD_PARAM(_param))->status) - -/** @cond internals_doc */ -/** @brief ZCL default handler. - * - * This function handles ZCL commands which was not processed by application. - * - * @param param - reference to the buffer containing ZCL packet. - * @return @ref ZB_TRUE if packet was processed; @ref ZB_FALSE - otherwise - */ -zb_uint8_t zb_zcl_handle(zb_uint8_t param); -/** - Get ZCL TSN stored in ZCL frame - @param buffer - pointer to a buffer with ZCL frame - @return TSN value -*/ -zb_uint8_t zb_zcl_get_tsn_from_packet(zb_bufid_t buffer); - -#if !(defined ZB_ZCL_DISABLE_REPORTING) - -void zb_zcl_adjust_reporting_timer(zb_uint8_t param); - -void zb_zcl_update_reporting_info(zb_zcl_reporting_info_t *rep_info); - -zb_ret_t zb_zcl_put_default_reporting_info(zb_zcl_reporting_info_t* default_rep_info_ptr); - -void zb_zcl_remove_default_reporting_info(zb_uint16_t cluster_id, zb_uint8_t cluster_role); - -void zb_zcl_mark_report_not_sent(zb_zcl_reporting_info_t *rep_info); - -#endif - -/** - Register device context. - @param _device_ctx - pointer to device context - - Use @ref ZB_AF_REGISTER_DEVICE_CTX. - */ -void zb_zcl_register_device_ctx(zb_af_device_ctx_t *device_ctx); -void zb_zcl_init_endpoint(zb_af_endpoint_desc_t* ep); -zb_bool_t zb_zcl_check_cluster_list(void); -/** @endcond */ /* internals_doc */ -/** @} */ /* ZB_ZCL_INITIALIZATION */ - - -#ifdef ZB_BDB_MODE -/*! \addtogroup zboss_bdb_api -@{ - @defgroup zboss_bdb_comm_params BDB commissioning parameters - @defgroup zboss_bdb_comm_start BDB commissioning start & status - @defgroup zboss_bdb_comm_fb BDB Finding and Binding -@} -*/ - -/** - @addtogroup zboss_bdb_comm_params - @{ -*/ - -/** @cond internals_doc */ -/** - @brief BDB error codes - */ -enum zb_bdb_error_codes_e -{ - ZB_BDB_STATUS_SUCCESS = 0, /*!zcl.selector - -/** - Returns ZCL context. - @return pointer ZCL context - */ -zb_zcl_globals_t *zb_zcl_get_ctx(void); - -/** @endcond */ /* internals_doc */ - -/** Returns pointer to ZCL context */ -#define ZCL_CTX() (*zb_zcl_get_ctx()) - -/*! @} */ /* ZB_ZCL_INITIALIZATION */ - -#define ZB_ZCL_MAX_EP_NUMBER 10U - -typedef zb_uint8_t *(*zb_zcl_put_payload_cb_t)(zb_uint8_t *, const void *); - -void zb_zcl_send_cmd( - zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_zcl_frame_direction_t direction, - zb_uint8_t src_ep, - const void *payload, - zb_uint8_t payload_size, - zb_zcl_put_payload_cb_t put_payload, - zb_zcl_cluster_id_t cluster_id, - zb_zcl_disable_default_response_t def_resp, - zb_uint8_t cmd_id, - zb_callback_t cb -); - -void zb_zcl_send_cmd_tsn( - zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_zcl_frame_direction_t direction, - zb_uint8_t src_ep, - const void *payload, - zb_uint8_t payload_size, - zb_zcl_put_payload_cb_t put_payload, - zb_zcl_cluster_id_t cluster_id, - zb_zcl_disable_default_response_t def_resp, - zb_uint8_t cmd_id, - zb_uint8_t tsn, - zb_callback_t cb -); - -zb_bool_t zb_zcl_send_default_handler(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info, zb_zcl_status_t status); - -void zb_zcl_send_default_resp_ext(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info, zb_zcl_status_t status); - - -/** - Convert deprecated statuses into ZCL8 statuses. - Status enumerations (see ZCL8 spec 2.6.3) list was changed in ZCL8 spec. - LIMIT_REACHED, DUPLICATE_EXISTS, SUCCESS ==> SUCCESS - INCONSISTENT_STARTUP_STATE, DEFINED_OUT_OF_BAND, ACTION_DENIED, HARDWARE_FAILURE, SOFTWARE_FAILURE ==> FAILURE - WRITE_ONLY, NOT_AUTHORIZED ==> NOT_AUTHORIZED - MALFORMED_COMMAND, INVALID_FIELD ==> INVALID_FIELD - UNSUP_CLUSTER_COMMAND, UNSUP_GENERAL_COMMAND, UNSUP_MANUF_CLUSTER_COMMAND, UNSUP_MANUF_GENERAL_COMMAND ==> UNSUP_COMMAND - INCONSISTENT, CALIBRATION_ERROR, RESERVED ==> RESERVED - The function will convert statuses in ZB_ZCL_AUTO_MODE and ZB_ZCL_COMPATIBILITY_MODE ZCL8 backward compatibility modes. - ZB_ZCL_LEGACY_MODE implies that application can still use obsolete statuses, so in that mode the function doesn't make any conversion. - @param status - Status got over the air. - @return - Converted status. -*/ -zb_zcl_status_t zb_zcl_zcl8_statuses_conversion(zb_zcl_status_t status); - -#endif /* ZBOSS_API_ZCL_H */ diff --git a/zboss/development/include/zboss_api_zcl8.h b/zboss/development/include/zboss_api_zcl8.h deleted file mode 100644 index a365c8f799..0000000000 --- a/zboss/development/include/zboss_api_zcl8.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL8 clusters wrappers -*/ -#ifndef ZBOSS_API_ZCL8_H -#define ZBOSS_API_ZCL8_H 1 - -/* Alarms cluster ZCL8 definitions */ -#define ZB_ZCL_ALARMS_SEND_RESET_ALARM_REQ_ZCL8 ZB_ZCL_ALARMS_SEND_RESET_ALARM_REQ -#define ZB_ZCL_ALARMS_SEND_RESET_ALL_ALARMS_REQ_ZCL8 ZB_ZCL_ALARMS_SEND_RESET_ALL_ALARMS_REQ -#define ZB_ZCL_ALARMS_SEND_RESET_ALARM_LOG_REQ_ZCL8 ZB_ZCL_ALARMS_SEND_RESET_ALARM_LOG_REQ - -/* ZCL Basic Cluster ZCL8 definitions */ -#define ZB_ZCL_BASIC_SEND_RESET_REQ_ZCL8 ZB_ZCL_BASIC_SEND_RESET_REQ - -/* Door Lock cluster ZCL8 definitions */ -#define ZB_ZCL_DOOR_LOCK_SEND_LOCK_DOOR_REQ_ZCL8 ZB_ZCL_DOOR_LOCK_SEND_LOCK_DOOR_REQ -#define ZB_ZCL_DOOR_LOCK_SEND_UNLOCK_DOOR_REQ_ZCL8 ZB_ZCL_DOOR_LOCK_SEND_UNLOCK_DOOR_REQ - -/* Groups cluster ZCL8 definitions */ -#define ZB_ZCL_GROUPS_SEND_ADD_GROUP_REQ_ZCL8 ZB_ZCL_GROUPS_SEND_ADD_GROUP_REQ -#define ZB_ZCL_GROUPS_SEND_VIEW_GROUP_REQ_ZCL8 ZB_ZCL_GROUPS_SEND_VIEW_GROUP_REQ -#define ZB_ZCL_GROUPS_SEND_GET_GROUP_MEMBERSHIP_REQ_ZCL8 ZB_ZCL_GROUPS_SEND_GET_GROUP_MEMBERSHIP_REQ -#define ZB_ZCL_GROUPS_SEND_REMOVE_GROUP_REQ_ZCL8 ZB_ZCL_GROUPS_SEND_REMOVE_GROUP_REQ -#define ZB_ZCL_GROUPS_SEND_REMOVE_ALL_GROUPS_REQ_ZCL8 ZB_ZCL_GROUPS_SEND_REMOVE_ALL_GROUPS_REQ -#define ZB_ZCL_GROUPS_SEND_ADD_GROUP_IF_IDENT_REQ_ZCL8 ZB_ZCL_GROUPS_SEND_ADD_GROUP_IF_IDENT_REQ - -/* IAS Ace cluster ZCL8 definitions */ -#define ZB_ZCL_IAS_ACE_SEND_ARM_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_ARM_REQ -#define ZB_ZCL_IAS_ACE_SEND_EMERGENCY_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_EMERGENCY_REQ -#define ZB_ZCL_IAS_ACE_SEND_FIRE_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_FIRE_REQ -#define ZB_ZCL_IAS_ACE_SEND_PANIC_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_PANIC_REQ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_ID_MAP_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_GET_ZONE_ID_MAP_REQ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_INFO_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_GET_ZONE_INFO_REQ -#define ZB_ZCL_IAS_ACE_SEND_GET_PANEL_STATUS_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_GET_PANEL_STATUS_REQ -#define ZB_ZCL_IAS_ACE_SEND_GET_BYPASSED_ZONE_LIST_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_GET_BYPASSED_ZONE_LIST_REQ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_REQ -#define ZB_ZCL_IAS_ACE_SEND_ZONE_STATUS_CHANGED_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_ZONE_STATUS_CHANGED_REQ -#define ZB_ZCL_IAS_ACE_SEND_PANEL_STATUS_CHANGED_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_PANEL_STATUS_CHANGED_REQ -#define ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_START_REQ_ZCL8 ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_START_REQ - -/* IAS WD cluster ZCL8 definitions */ -#define ZB_ZCL_IAS_WD_SEND_START_WARNING_REQ_ZCL8 ZB_ZCL_IAS_WD_SEND_START_WARNING_REQ -#define ZB_ZCL_IAS_WD_SEND_SQUAWK_REQ_ZCL8 ZB_ZCL_IAS_WD_SEND_SQUAWK_REQ - -/* IAS Zone cluster ZCL8 definitions */ -#define ZB_ZCL_IAS_ZONE_SEND_INITIATE_TEST_MODE_REQ_ZCL8 ZB_ZCL_IAS_ZONE_SEND_INITIATE_TEST_MODE_REQ -#define ZB_ZCL_IAS_ZONE_SEND_INITIATE_NORMAL_OPERATION_MODE_REQ_ZCL8 ZB_ZCL_IAS_ZONE_SEND_INITIATE_NORMAL_OPERATION_MODE_REQ -#define ZB_ZCL_IAS_ZONE_SEND_ZONE_ENROLL_REQUEST_REQ_ZCL8 ZB_ZCL_IAS_ZONE_SEND_ZONE_ENROLL_REQUEST_REQ -#define ZB_ZCL_IAS_ZONE_SEND_STATUS_CHANGE_NOTIFICATION_REQ_ZCL8 ZB_ZCL_IAS_ZONE_SEND_STATUS_CHANGE_NOTIFICATION_REQ -#define ZB_ZCL_IAS_ZONE_SEND_STATUS_CHANGE_NOTIFICATION_HA_REQ_ZCL8 ZB_ZCL_IAS_ZONE_SEND_STATUS_CHANGE_NOTIFICATION_HA_REQ - -/* Identify cluster ZCL8 definitions */ -#define ZB_ZCL_IDENTIFY_SEND_TRIGGER_VARIANT_REQ_ZCL8 ZB_ZCL_IDENTIFY_SEND_TRIGGER_VARIANT_REQ -#define ZB_ZCL_IDENTIFY_SEND_IDENTIFY_REQ_ZCL8 ZB_ZCL_IDENTIFY_SEND_IDENTIFY_REQ -#define ZB_ZCL_IDENTIFY_SEND_IDENTIFY_QUERY_REQ_ZCL8 ZB_ZCL_IDENTIFY_SEND_IDENTIFY_QUERY_REQ - -/* On/Off cluster ZCL8 definitions */ -#define ZB_ZCL_ON_OFF_SEND_OFF_REQ_ZCL8 ZB_ZCL_ON_OFF_SEND_OFF_REQ -#define ZB_ZCL_ON_OFF_SEND_ON_REQ_ZCL8 ZB_ZCL_ON_OFF_SEND_ON_REQ -#define ZB_ZCL_ON_OFF_SEND_TOGGLE_REQ_ZCL8 ZB_ZCL_ON_OFF_SEND_TOGGLE_REQ -#define ZB_ZCL_ON_OFF_SEND_OFF_WITH_EFFECT_REQ_ZCL8 ZB_ZCL_ON_OFF_SEND_OFF_WITH_EFFECT_REQ -#define ZB_ZCL_ON_OFF_SEND_ON_WITH_RECALL_GLOBAL_SCENE_REQ_ZCL8 ZB_ZCL_ON_OFF_SEND_ON_WITH_RECALL_GLOBAL_SCENE_REQ -#define ZB_ZCL_ON_OFF_SEND_REQ_ZCL8 ZB_ZCL_ON_OFF_SEND_REQ -#define ZB_ZCL_ON_OFF_SEND_ON_WITH_TIMED_OFF_REQ_ZCL8 ZB_ZCL_ON_OFF_SEND_ON_WITH_TIMED_OFF_REQ - -/* OTA Upgrade cluster ZCL8 definitions */ -#define ZB_ZCL_OTA_UPGRADE_SEND_QUERY_NEXT_IMAGE_REQ_ZCL8 ZB_ZCL_OTA_UPGRADE_SEND_QUERY_NEXT_IMAGE_REQ -#define ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_BLOCK_REQ_ZCL8 ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_BLOCK_REQ -#define ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_PAGE_REQ_ZCL8 ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_PAGE_REQ -#define ZB_ZCL_OTA_UPGRADE_SEND_UPGRADE_END_REQ_ZCL8 ZB_ZCL_OTA_UPGRADE_SEND_UPGRADE_END_REQ -#define ZB_ZCL_OTA_UPGRADE_SEND_QUERY_SPECIFIC_FILE_REQ_ZCL8 ZB_ZCL_OTA_UPGRADE_SEND_QUERY_SPECIFIC_FILE_REQ -#define ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_NOTIFY_REQ_ZCL8 ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_NOTIFY_REQ - -/* Poll Control cluster ZCL8 definitions */ -#define ZB_ZCL_POLL_CONTROL_SEND_CHECK_IN_REQ_ZCL8 ZB_ZCL_POLL_CONTROL_SEND_CHECK_IN_REQ -#define ZB_ZCL_POLL_CONTROL_SEND_FAST_POLL_STOP_REQ_ZCL8 ZB_ZCL_POLL_CONTROL_SEND_FAST_POLL_STOP_REQ -#define ZB_ZCL_POLL_CONTROL_SEND_SET_LONG_POLL_INTERVAL_REQ_ZCL8 ZB_ZCL_POLL_CONTROL_SEND_SET_LONG_POLL_INTERVAL_REQ -#define ZB_ZCL_POLL_CONTROL_SEND_SET_SHORT_POLL_INTERVAL_REQ_ZCL8 ZB_ZCL_POLL_CONTROL_SEND_SET_SHORT_POLL_INTERVAL_REQ - -/* Scenes cluster ZCL8 definitions */ -#define ZB_ZCL_SCENES_SEND_ADD_SCENE_REQ_ZCL8 ZB_ZCL_SCENES_SEND_ADD_SCENE_REQ -#define ZB_ZCL_SCENES_SEND_VIEW_SCENE_REQ_ZCL8 ZB_ZCL_SCENES_SEND_VIEW_SCENE_REQ -#define ZB_ZCL_SCENES_SEND_REMOVE_SCENE_REQ_ZCL8 ZB_ZCL_SCENES_SEND_REMOVE_SCENE_REQ -#define ZB_ZCL_SCENES_SEND_REMOVE_ALL_SCENES_REQ_ZCL8 ZB_ZCL_SCENES_SEND_REMOVE_ALL_SCENES_REQ -#define ZB_ZCL_SCENES_SEND_STORE_SCENE_REQ_ZCL8 ZB_ZCL_SCENES_SEND_STORE_SCENE_REQ -#define ZB_ZCL_SCENES_SEND_GET_SCENE_MEMBERSHIP_REQ_ZCL8 ZB_ZCL_SCENES_SEND_GET_SCENE_MEMBERSHIP_REQ - -/* Thermostat cluster ZCL8 definitions */ -#define ZB_ZCL_THERMOSTAT_SEND_SETPOINT_RAISE_LOWER_REQ_ZCL8 ZB_ZCL_THERMOSTAT_SEND_SETPOINT_RAISE_LOWER_REQ -#define ZB_ZCL_THERMOSTAT_SEND_SET_WEEKLY_SCHEDULE_REQ_ZCL8 ZB_ZCL_THERMOSTAT_SEND_SET_WEEKLY_SCHEDULE_REQ -#define ZB_ZCL_THERMOSTAT_SEND_GET_WEEKLY_SCHEDULE_REQ_ZCL8 ZB_ZCL_THERMOSTAT_SEND_GET_WEEKLY_SCHEDULE_REQ -#define ZB_ZCL_THERMOSTAT_SEND_CLEAR_WEEKLY_SCHEDULE_REQ_ZCL8 ZB_ZCL_THERMOSTAT_SEND_CLEAR_WEEKLY_SCHEDULE_REQ -#define ZB_ZCL_THERMOSTAT_SEND_GET_RELAY_STATUS_LOG_REQ_ZCL8 ZB_ZCL_THERMOSTAT_SEND_GET_RELAY_STATUS_LOG_REQ - -/* ZBOSS specific Tunnel cluster ZCL8 definitions, purpose: general data tunneling. */ -#define ZB_ZCL_TUNNEL_SEND_TRANSFER_REQ_ZCL8 ZB_ZCL_TUNNEL_SEND_TRANSFER_REQ - -/* Window Covering cluster ZCL8 definitions */ -#define ZB_ZCL_WINDOW_COVERING_SEND_UP_OPEN_REQ_ZCL8 ZB_ZCL_WINDOW_COVERING_SEND_UP_OPEN_REQ -#define ZB_ZCL_WINDOW_COVERING_SEND_DOWN_CLOSE_REQ_ZCL8 ZB_ZCL_WINDOW_COVERING_SEND_DOWN_CLOSE_REQ -#define ZB_ZCL_WINDOW_COVERING_SEND_STOP_REQ_ZCL8 ZB_ZCL_WINDOW_COVERING_SEND_STOP_REQ -#define ZB_ZCL_WINDOW_COVERING_SEND_GO_TO_LIFT_PERCENTAGE_REQ_ZCL8 ZB_ZCL_WINDOW_COVERING_SEND_GO_TO_LIFT_PERCENTAGE_REQ -#define ZB_ZCL_WINDOW_COVERING_SEND_GO_TO_TILT_PERCENTAGE_REQ_ZCL8 ZB_ZCL_WINDOW_COVERING_SEND_GO_TO_TILT_PERCENTAGE_REQ - -/* Demand Response and Load Control cluster definitions */ -#define ZB_ZCL_DRLC_SEND_CMD_GET_SCHEDULED_EVENTS_ZCL8 ZB_ZCL_DRLC_SEND_CMD_GET_SCHEDULED_EVENTS - -#endif /* ZBOSS_API_ZCL8_H */ diff --git a/zboss/development/include/zboss_api_zdo.h b/zboss/development/include/zboss_api_zdo.h deleted file mode 100644 index f2ebeaf6fb..0000000000 --- a/zboss/development/include/zboss_api_zdo.h +++ /dev/null @@ -1,3019 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Public ZDO layer API -*/ -#ifndef ZB_ZBOSS_API_ZDO_H -#define ZB_ZBOSS_API_ZDO_H 1 - -#ifdef ZB_ENABLE_ZGP_SINK -#include "zboss_api_zgp.h" -#endif - -/*! \addtogroup zb_comm_signals */ -/*! @{ */ - -/** - * @name ZDP status values - * @anchor zdp_status - * @see 2.4.5 - ZDP Enumeration Description - */ -/** @{ */ -/** The requested operation or transmission was completed successfully. */ -#define ZB_ZDP_STATUS_SUCCESS 0x00U - -/*!< The supplied request type was invalid. */ -#define ZB_ZDP_STATUS_INV_REQUESTTYPE 0x80U - -/*!< The requested device did not exist on a device following a child descriptor request to a - * parent.*/ -#define ZB_ZDP_STATUS_DEVICE_NOT_FOUND 0x81U - -/*!< The supplied endpoint was equal to 0x00 or between 0xf1 and 0xff. */ -#define ZB_ZDP_STATUS_INVALID_EP 0x82U - -/*!< The requested endpoint is not described by simple descriptor. */ -#define ZB_ZDP_STATUS_NOT_ACTIVE 0x83U - -/*!< The requested optional feature is not supported on the target device. */ -#define ZB_ZDP_STATUS_NOT_SUPPORTED 0x84U - -/*!< A timeout has occurred with the requested operation. */ -#define ZB_ZDP_STATUS_TIMEOUT 0x85U - -/*!< The end device bind request was unsuccessful due to a failure to match any suitable clusters.*/ -#define ZB_ZDP_STATUS_NO_MATCH 0x86U - -/*!< The unbind request was unsuccessful due to the coordinator or source device not having an - * entry in its binding table to unbind.*/ -#define ZB_ZDP_STATUS_NO_ENTRY 0x88U - -/*!< A child descriptor was not available following a discovery request to a parent. */ -#define ZB_ZDP_STATUS_NO_DESCRIPTOR 0x89U - -/*!< The device does not have storage space to support the requested operation. */ -#define ZB_ZDP_STATUS_INSUFFICIENT_SPACE 0x8aU - -/*!< The device is not in the proper state to support the requested operation. */ -#define ZB_ZDP_STATUS_NOT_PERMITTED 0x8bU - -/*!< The device does not have table space to support the operation. */ -#define ZB_ZDP_STATUS_TABLE_FULL 0x8cU - -/*!< The permissions configuration table on the target indicates that the request is not authorized - * from this device.*/ -#define ZB_ZDP_STATUS_NOT_AUTHORIZED 0x8dU - -/*!< The index in the received command is out of bounds. */ -#define ZB_ZDP_STATUS_INVALID_INDEX 0x8fU - -/**< Custom internal statuses. */ -#define ZB_ZDP_STATUS_DEV_ANNCE_SENDING_FAILED 0x0feU -#define ZB_ZDP_STATUS_TIMEOUT_BY_STACK 0xffU -/** @} */ - -/** - * @brief Type for ZDP status values. - * - * Holds one of @ref zdp_status. Kept for backward compatibility as - * @ref zdp_status were declared previously as enum. - */ -typedef zb_uint8_t zb_zdp_status_t; - -/** - * @name Signals passed to zboss_signal_handler() - * @anchor zdo_app_signal_type - * - * @note If an application requires the parameters to be passed to the @ref zboss_signal_handler, it - * is recommended to introduce the structure according to the pattern below: - * - * @code - * typedef struct zb_zdo_app_my_custom_signal_s - * { - * zb_zdo_app_signal_type_t super; - * zb_my_custom_data_type_t my_custom_data; - * } - * @endcode - */ -/** @{ */ -/** Obsolete signal, used for pre-R21 ZBOSS API compatibility. Not recommended to use. - * @parblock - * When generated: - * - After the device has been started and the non-BDB commissioning completed. - * - In case of the commissioning error. - * - * Status codes: - * - RET_OK: Device has started and joined the network. - * - RET_ERROR: An error of any type. - * - * Signal parameters: - * - none - * @endparblock */ - #define ZB_ZDO_SIGNAL_DEFAULT_START 0U - -/** Notifies the application that ZBOSS framework (scheduler, buffer pool, etc.) has started, but no - * join/rejoin/formation/BDB initialization has been done yet. - * @parblock - * When generated: - * - When the application calls zboss_start_no_autostart() instead of zboss_start() before the - * zboss_main_loop(). Used when some hardware must be initialized before the Zigbee commissioning, - * but already has ZBOSS scheduler running. Example: sensor connected through UART. - * - * Status codes: - * - RET_OK: Only ZBOSS framework has been initialized. - * - Does not return error status. - * - * Signal parameters: - * - none - * - * @snippet smart_plug_v2/sp_device/sp_device.c signal_skip_startup - * @endparblock */ -#define ZB_ZDO_SIGNAL_SKIP_STARTUP 1U - -/** Notifies the application about the new device appearance. - * @parblock - * When generated: - * - Upon receiving the Device_annce command. - * - * Status codes: - * - RET_OK: Device_annce command was received. - * - Does not return error status. - * - * Signal parameters: - * - @ref zb_zdo_signal_device_annce_params_t - * - * @snippet simple_gw/simple_gw.c signal_device_annce - * @endparblock */ -#define ZB_ZDO_SIGNAL_DEVICE_ANNCE 2U - -/** Notifies the application that the device itself has left the network. - * @parblock - * When generated: - * - Upon sending the "Leave" command. - * - * Status codes: - * - RET_OK: Device has sent the "Leave" command. - * - Does not return error status. - * - * Signal parameters: - * - @ref zb_zdo_signal_leave_params_t - * - * @snippet light_sample/light_control/light_control.c signal_leave - * @endparblock */ -#define ZB_ZDO_SIGNAL_LEAVE 3U - -/** Corrupted or incorrect signal information. - * @parblock - * When generated: - * - Incorrect buffer length detected by zb_get_app_signal (less then zb_zdo_app_signal_hdr_t) - * - * Status codes: - * - none - * - * Signal parameters: - * - none - * @endparblock */ -#define ZB_ZDO_SIGNAL_ERROR 4U - -/** Device started for the first time after the NVRAM erase. - * @parblock - * When generated: - * - Upon completing the typical device startup (network formation for ZC or - * rejoin/discovery/association for ZR and ZED). - * - This signal is exclusive to @ref ZB_BDB_SIGNAL_DEVICE_REBOOT - * - * @note No @ref ZB_BDB_SIGNAL_STEERING or @ref ZB_BDB_SIGNAL_FORMATION signals will be generated. - * - * Status codes: - * - RET_OK: Device started after the NVRAM erase - * - RET_ERROR: An error of any type. - * - * Signal parameters: - * - none - * - * @snippet HA_samples/on_off_switch/sample_zed.c signal_first - * @endparblock */ -#define ZB_BDB_SIGNAL_DEVICE_FIRST_START 5U - -/** Device started using the NVRAM contents. - * @parblock - * When generated: - * - Upon the device joining/rejoining Zigbee network using restored parameters. - * - This signal is exclusive to @ref ZB_BDB_SIGNAL_DEVICE_FIRST_START - * - * @note No @ref ZB_BDB_SIGNAL_STEERING or @ref ZB_BDB_SIGNAL_FORMATION signals will be generated. - * - * Status codes: - * - RET_OK: Device started using configuration stored in NVRAM - * - RET_ERROR: An error of any type. - * - * Signal parameters: - * - none - * - * @snippet HA_samples/on_off_switch/sample_zed.c signal_reboot - * @endparblock */ -#define ZB_BDB_SIGNAL_DEVICE_REBOOT 6U - -/** @cond DOXYGEN_BDB_SECTION */ -#define ZB_SIGNAL_DEVICE_FIRST_START ZB_BDB_SIGNAL_DEVICE_FIRST_START -#define ZB_SIGNAL_DEVICE_REBOOT ZB_BDB_SIGNAL_DEVICE_REBOOT - -/** BDB network steering completed (Network steering only). - * @parblock - * When generated: - * - Upon completing Network steering initiated by - * bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING). - * - * Status codes: - * - RET_OK: Network steering completed. - * - RET_INTERRUPTED: was cancelled with bdb_cancel_joining() - * - * Has additional data of type zb_zdo_signal_leave_indication_params_t. - * - * Signal parameters: - * - none - * @endparblock */ -#define ZB_BDB_SIGNAL_STEERING 10U - -/** BDB network formation completed (Network formation only). - * @parblock - * When generated: - * - Upon completing Network formation initiated by - * bdb_start_top_level_commissioning(ZB_BDB_NETWORK_FORMATION). - * - * Status codes: - * - RET_OK: Network formation completed. - * - RET_INTERRUPTED: was cancelled with bdb_cancel_formation() - * - * Signal parameters: - * - none - * @endparblock */ -#define ZB_BDB_SIGNAL_FORMATION 11U - -/** BDB finding and binding for a target endpoint completed. - * @parblock - * When generated: - * - F&B target timeout expires. - * - * Status codes: - * - RET_OK: F&B target identifying time is expired. - * - RET_CANCELLED: F&B target identifying is cancelled during the IdentifyTime. - * - RET_ERROR: An error of any type. - * - * Signal parameters: - * - @ref zb_uint8_t - endpoint ID - * @endparblock */ -#define ZB_BDB_SIGNAL_FINDING_AND_BINDING_TARGET_FINISHED 12U - -/** BDB finding and binding for an initiator endpoint completed. - * @parblock - * When generated: - * - F&B with a Target succeeded or F&B initiator timeout expired or cancelled. - * - * Status codes: - * - @ref zdo_fb_initiator_finished_status - * - * Signal parameters: - * - @ref zb_zdo_signal_fb_initiator_finished_params_t - * @endparblock */ -#define ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED 13U - - -/** @endcond */ /* DOXYGEN_BDB_SECTION */ - -/** Obsolete signal, used for pre-R21 ZBOSS API compatibility. Use ZB_ZDO_SIGNAL_DEVICE_ANNCE signal - * instead! - * @parblock - * When generated: - * - Indicates that there is a new device associated with Zigbee Coordinator or router. - * - * Status codes: - * - RET_OK: New device associated. - * - Does not return error status. - * - * Signal parameters: - * - @ref zb_nwk_signal_device_associated_params_t - * @endparblock */ -#define ZB_NWK_SIGNAL_DEVICE_ASSOCIATED 18U - -/** Network leave indication. - * @parblock - * When generated: - * - The child device has left the network. - * - * Status codes: - * - RET_OK: Leave command received from the child device. - * - RET_ERROR: An error of any type. - * - * Signal parameters: - * - @ref zb_zdo_signal_leave_indication_params_t - * - * @snippet simple_gw/simple_gw.c signal_leave_ind - * @endparblock */ -#define ZB_ZDO_SIGNAL_LEAVE_INDICATION 19U - -/** WWAH Rejoin start indication. - * @parblock - * When generated: - * - Device lost communication with the parent and started WWAH Rejoin procedure. - * - * Status codes: - * - RET_OK: Leave command received from the child device. - * - Does not return error status. - * - * Signal parameters: no - * @endparblock */ -#define ZB_BDB_SIGNAL_WWAH_REJOIN_STARTED 20U - -/** @cond DOXYGEN_ZGP_SECTION */ -/** ZGP commissioning complete signal. - * @parblock - * When generated: - * - GPCB left the commissioning mode. - * - * Status codes: - * - RET_OK: commissioning complete. - * - RET_ERROR: An error of any type. - * - * Signal parameters: - * - zb_zgp_signal_commissioning_params_s - * - * @snippet light_sample/light_coordinator_combo/light_zc.c signal_zgp_commissioning - * @endparblock */ -#define ZB_ZGP_SIGNAL_COMMISSIONING 21U -/** @endcond */ /* DOXYGEN_ZGP_SECTION */ - -/** Notifies the application that the MCU can sleep for the specified period of time. - * @note Signal will not be generated if the sleep interval is less than sleep threshold - * ZB_SCHED_SLEEP_THRESHOLD_MS. To change the sleep threshold see zb_ret_t zb_sleep_set_threshold(). - * - * @parblock - * When generated: - * - ZBOSS scheduler detects that the sleep mode can be enabled on the device. - * - * Status codes: - * - RET_OK: The sleep mode can be enabled on the device. - * - Does not return error status. - * - * Signal parameters: - * - @ref zb_zdo_signal_can_sleep_params_t - * - * @snippet onoff_server/on_off_switch_zed.c signal_can_sleep - * @endparblock */ -#define ZB_COMMON_SIGNAL_CAN_SLEEP 22U - -/** Notifies the application that the application specific part of the production configuration was - * found and restored and provides the application with this data. - * @parblock - * When generated: - * - After restoring the production configuration. - * - * Status codes: - * - RET_OK: The application specific part of the production configuration exists. - * - RET_ERROR: An error of any type. - * - * Signal parameters: - * - Passed up with application specific data from production configuration. - * @endparblock */ -#define ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY 23U - -/** Notifies the application about the Neighbor Table expiration. - * It means that the neighbor devices did not send the Link Status messages for @ref - * ZB_NWK_ROUTER_AGE_LIMIT * @ref ZB_NWK_LINK_STATUS_PERIOD seconds. - * @parblock - * When generated: - * - All routes expired (usually when the link is down). - * - * Status codes: - * - RET_OK: All routers expired. - * - Does not return error status. - * - * Signal parameters: - * - none - * @endparblock */ -#define ZB_NWK_SIGNAL_NO_ACTIVE_LINKS_LEFT 24U - -#if defined ZB_ENABLE_SE_MIN_CONFIG || defined DOXYGEN -/* SE signals */ -/** @cond DOXYGEN_SE_SECTION */ - -/** Device started. No auto-join/rejoin configured, no join attempts were performed, control is - * passed to application. - * @par Signal parameter - * - N/A - */ -#define ZB_SE_SIGNAL_SKIP_JOIN 25U - -/** We are rejoined - * @par Signal parameter - * - N/A - */ -#define ZB_SE_SIGNAL_REJOIN 26U - -/** Our child rejoined. - * @par Signal parameter - * @ref zb_ieee_addr_t - long remote device address - */ -#define ZB_SE_SIGNAL_CHILD_REJOIN 27U - -/** Some device joined & authenticated in the net, established TCLK using CBKE procedure. Only TC - * can receive that signal. - * @par Signal parameter - * @ref zb_ieee_addr_t - long remote device address - * @par Example - * @snippet se/energy_service_interface/se_esi_zc.c SIGNAL_HANDLER_GET_SIGNAL - * @snippet se/energy_service_interface/se_esi_zc.c SIGNAL_HANDLER_TC_SIGNAL_CHILD_JOIN - */ -#define ZB_SE_TC_SIGNAL_CHILD_JOIN_CBKE 28U - -/** Some device joined & authenticated in the net, established TCLK, but using non-CBKE procedure - * (BDB). Only TC can receive that signal. - * @par Signal parameter - * @ref zb_ieee_addr_t - long remote device address - */ -#define ZB_SE_TC_SIGNAL_CHILD_JOIN_NON_CBKE 29U - -/** CBKE procedure failed. Application may set another certificate & key and retry CBKE procedure. - * @par Signal parameter - * N/A - * @par Example - * Signal processing code for @ref ZB_SE_SIGNAL_CBKE_OK can be used as a template - * @see zb_se_load_ecc_cert - set certificate - * @see zb_se_retry_cbke_with_tc - retry CBKE procedure - */ -#define ZB_SE_SIGNAL_CBKE_FAILED 30U - -/** CBKE procedure with TC succeed. - * Note: TC can't receive that signal. - * @par Signal parameter - * N/A - * @par Example - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_GET_SIGNAL - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_CBKE_OK - */ -#define ZB_SE_SIGNAL_CBKE_OK 31U - -/** Ready to start Service Discovery. Application can issue @ref zb_se_service_discovery_start to - * actually start discovery - * @par Signal parameter - * N/A - * @par Example - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_GET_SIGNAL - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_START_DISCOVERY - */ -#define ZB_SE_SIGNAL_SERVICE_DISCOVERY_START 32U - -/** Service Discovery found a device that can be bound. - * @par Signal parameter - * @ref zb_se_signal_service_discovery_bind_params_t - * @par Example - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_GET_SIGNAL - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_DO_BIND - * @see zb_se_signal_service_discovery_bind_params_t - * @see ZB_ZDO_SIGNAL_GET_PARAMS - * @see zb_se_service_discovery_bind_req - */ -#define ZB_SE_SIGNAL_SERVICE_DISCOVERY_DO_BIND 33U - -/** Bind request initiated by @ref zb_se_service_discovery_bind_req() succeeded. - * @par Signal parameter - * @ref zb_uint16_t - short remote device address - * @par Example - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_GET_SIGNAL - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_BIND_OK - */ -#define ZB_SE_SIGNAL_SERVICE_DISCOVERY_BIND_OK 34U - -/** Bind request failed. - * @par Signal parameter - * @ref zb_uint16_t - short remote device address - * @par Example - * The same code to @ref ZB_SE_SIGNAL_SERVICE_DISCOVERY_BIND_OK can be used for signal processing. - */ -#define ZB_SE_SIGNAL_SERVICE_DISCOVERY_BIND_FAILED 35U - -/** Successful bind initiated by other device. - * @par Signal parameter - * @ref zb_se_signal_service_discovery_bind_params_t - * @par Example - * @snippet se/energy_service_interface/se_esi_zc.c SIGNAL_HANDLER_GET_SIGNAL - * @snippet se/energy_service_interface/se_esi_zc.c SIGNAL_HANDLER_BIND_INDICATION - */ -#define ZB_SE_SIGNAL_SERVICE_DISCOVERY_BIND_INDICATION 36U - -/** Service Discovery succeeded - * @par Signal parameter - * N/A - * @par Example - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_GET_SIGNAL - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_DISCOVERY_OK - */ -#define ZB_SE_SIGNAL_SERVICE_DISCOVERY_OK 37U - -/** Service Discovery failed (no devices found) - * @par Signal parameter - * N/A - * @par Example - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_GET_SIGNAL - * @snippet se/in_home_display/se_ihd_zr.c SIGNAL_HANDLER_DISCOVERY_FAILED - */ -#define ZB_SE_SIGNAL_SERVICE_DISCOVERY_FAILED 38U - -/** Partner link key initiated by @ref zb_se_start_aps_key_establishment is done. Keypair with some - * device is ready. - * @par Signal parameter - * @ref zb_ieee_addr_t - long remote device address - * @see zb_se_start_aps_key_establishment - */ -#define ZB_SE_SIGNAL_APS_KEY_READY 39U - -/** Failed to establish a keypair - * @par Signal parameter - * @ref zb_ieee_addr_t - long remote device address - * @see zb_se_start_aps_key_establishment - */ -#define ZB_SE_SIGNAL_APS_KEY_FAIL 40U - -#endif /* ZB_ENABLE_SE_MIN_CONFIG */ - -/** ZC / our MAC suspended our device tx: out of Duty cycle (sub-ghz only) - * @par Signal parameter - number of minutes to suspend, -1 if unknown - */ -#define ZB_SIGNAL_SUBGHZ_SUSPEND 41U - -/** ZC resumed our device tx (sub-ghz only) */ -#define ZB_SIGNAL_SUBGHZ_RESUME 42U - -/** @endcond */ /* DOXYGEN_SE_SECTION */ - -#ifdef NCP_MODE - -#define ZB_SIGNAL_NWK_INIT_DONE 46U - -#endif /* NCP_MODE */ - -/** Notifies the Zigbee Trust center application about a new device is authorized in the network. - * For Zigbee R21 devices it means that the TCLK exchange procedure was finished, for the legacy - * devices it means that the Transport key was send to the device. - * - * When generated: - * - Authorization success - * - Authorization failed - * - Authorization timeout - * - * Status codes: - * - RET_OK: Device information updated. - * - Does not return error status. - * Signal parameters: - * - @ref zb_zdo_signal_device_authorized_params_t - */ -#define ZB_ZDO_SIGNAL_DEVICE_AUTHORIZED 47U - -/** Notifies the Zigbee Trust center or parent router application about a new device joined, - * rejoined or left the network. - * - * When generated: - * - Standard device secured rejoin - * - Standard device unsecured join - * - Device left - * - Standard device trust center rejoin - * - * Status codes: - * - RET_OK: Device information updated. - * - Does not return error status. - * - * Signal parameters: - * - @ref zb_zdo_signal_device_update_params_t - */ -#define ZB_ZDO_SIGNAL_DEVICE_UPDATE 48U - -/** PAN ID conflict has been detected. Application has to decide whether to initiate its resolution - * or not. - * @par Signal parameter - * @see zb_start_pan_id_conflict_resolution - */ -#define ZB_NWK_SIGNAL_PANID_CONFLICT_DETECTED 49U - -/** NLME status indication. Application may implement additional logic based on receiving some - * statuses. - * @par Signal parameter - * @ref zb_zdo_signal_nlme_status_indication_params_t - * @see zb_nwk_command_status_t is the full list of NLME statuses - */ -#define ZB_NLME_STATUS_INDICATION 50U - -/** @cond internals_doc */ - /** it is time to backup TC database (signal at TC) */ -#define ZB_TCSWAP_DB_BACKUP_REQUIRED_SIGNAL 51U - - /** TC is swapped (signal at Joiner) */ -#define ZB_TC_SWAPPED_SIGNAL 52U -/** @endcond */ /* internals_doc */ - -/** TC rejoin is completed - * @parblock - * When generated: - * - Device completes TC rejoin procedure. - * - * Status codes: - * - RET_OK: TC rejoin completed successful - * - RET_ERROR: An error of any type. - * - * Signal parameters: - * - none - * - * @snippet onoff_server/on_off_switch_zed.c signal_bdb_tc_rejoin_done - * @endparblock */ -#define ZB_BDB_SIGNAL_TC_REJOIN_DONE 53U - - -/** Notifies the Zigbee Trust center or router application about permit join status changed. - * @par When generated: - * - Network was just open - * - Network was just closed - * - * @par Status codes: - * - RET_OK: Device information updated. - * - Does not return error status. - * - * @par Signal parameters: - * - @ref zb_uint8_t - Open time or zero if network closed. Value of @ref zb_zdo_mgmt_permit_joining_req_param_t.permit_duration - * - * @par Signal handling: - * @snippet thermostat/thermostat_zr/thermostat_zr.c zb_zdo_signal_permit_join_status_example - * - * @par Signal generation: - * - To self: - * @snippet thermostat/thermostat_zr/thermostat_zr.c permit_join_request_local_example - * - To other devices: - * @snippet thermostat/thermostat_zr/thermostat_zr.c permit_join_request_broadcast_example - * - */ -#define ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS 54U - - -/** BDB steering cancel request processed - * @parblock - * When generated: - * - after the cancel request called with bdb_cancel_steering() is processed - * - * Status codes: - * - RET_ILLEGAL_REQUEST: device is a ZC - * - RET_INVALID_STATE: steering for a node not a network is not in progress - * - RET_PENDING: it is too late to cancel a steering, it will be completed soon - * - RET_IGNORE: cancellation was already requested - * - RET_OK: steering is cancelled successfully - * - * Signal parameters: - * - none - * - * @endparblock */ -#define ZB_BDB_SIGNAL_STEERING_CANCELLED 55U - - -/** BDB formation cancel request processed - * @parblock - * When generated: - * - after the cancel request called with bdb_cancel_formation() is processed - * - * Status codes: - * - RET_INVALID_STATE: formation is not in progress - * - RET_PENDING: it is too late to cancel a formation, it will be completed soon - * - RET_IGNORE: cancellation was already requested - * - RET_OK: formation is cancelled successfully - * - * Signal parameters: - * - none - * - * @endparblock */ -#define ZB_BDB_SIGNAL_FORMATION_CANCELLED 56U - -/** ZBOSS is ready to shutdown signal - * @parblock - * When generated: - * - after ZBOSS preparations to shutdown initiated by zboss_start_shut() is done - * - * After receiving that signal application MUST complete ZBOSS shutdown by - * calling zboss_complete_shut(). It is impossible to continue ZBOSS work - * without a restart after calling zboss_start_shut(). - * - * Signal parameters: - * - none - * - * @endparblock */ -#define ZB_SIGNAL_READY_TO_SHUT 57U - -/** ZBOSS interpan preinit done signal - * @parblock - * When generated: - * - after ZBOSS preinit enough to send interpan initiated by zboss_preinit_for_interpan() is done - * - * After receiving that signal application can use zb_intrp_data_request_with_chan_change() API - * - * Signal parameters: - * - none - * - * @endparblock */ -#define ZB_SIGNAL_INTERPAN_PREINIT 58U - -/** @} */ - -/** - * @brief Type for signals passed to zboss_signal_handler(). - * - * Holds one of @ref zdo_app_signal_type. - * Previously it was defined as enum but was converted to a set of defines due to MISRA violations. - */ -typedef zb_uint8_t zb_zdo_app_signal_type_t; - -/* Legacy API: zb_zdo_app_signal_type_t == zb_zdo_app_signal_t */ -typedef zb_zdo_app_signal_type_t zb_zdo_app_signal_t; - -/** - Obtains pointer to parameters passed with application signal. - - @param[in] sg_p - pointer to application signal - @param[in] type - parameter type - @return pointer to signal parameters - -@b Example -@snippet linky_sample/erl_interface/erl_interface_zed.c zb_zdo_signal_get_params_snippet - */ -#define ZB_ZDO_SIGNAL_GET_PARAMS(sg_p, type) ((type *)(void *)((((zb_uint8_t *)sg_p) + sizeof(zb_zdo_app_signal_hdr_t)))) - - -/** - @brief Cuts ZBOSS signal headers while keeping the signal parameter (if it was in the buffer). - - @param buf - pointer to a zb_buf_t structure. The buffer must be the one passed into zboss_signal_handler. - */ -#define ZB_ZDO_SIGNAL_CUT_HEADER(buf) zb_buf_cut_left(buf, sizeof(zb_zdo_app_signal_hdr_t)) - -/** - @brief Leave parameters - - Stack passes this parameter to application when device leave the network. - */ -typedef struct zb_zdo_signal_leave_params_s -{ - zb_nwk_leave_type_t leave_type; /** Leave type. @ref nwk_leave_type */ -} zb_zdo_signal_leave_params_t; - -/** - @brief NLME status indication parameters - - Stack passes this parameter to application when NLME status indication is generated. - */ -typedef struct zb_zdo_signal_nlme_status_indication_params_s -{ - zb_nlme_status_indication_t nlme_status; /** NLME status indication payload */ -} zb_zdo_signal_nlme_status_indication_params_t; - -/** - @brief Leave Indication parameters - - Stack passes this parameter to application upon receipt of leave indication - primitive. - */ -typedef struct zb_zdo_signal_leave_indication_params_s -{ - zb_uint16_t short_addr; /*!< Short address of device requested to leave or leaving device*/ - zb_ieee_addr_t device_addr; /*!< Long address of device requested to leave or leaving device*/ - zb_uint8_t rejoin; /*!< 1 if this was leave with rejoin; 0 - otherwise */ -} zb_zdo_signal_leave_indication_params_t; - -/** @cond DOXYGEN_SE_SECTION */ -/** - * @brief Service Discovery Bind signal parameters - * @details Contains info about the device found during Service Discovery. Stack passes this - * parameter to the application with signal @ref ZB_SE_SIGNAL_SERVICE_DISCOVERY_DO_BIND - */ -typedef struct zb_se_signal_service_discovery_bind_params_s -{ - zb_ieee_addr_t device_addr; /**< Long address of the device */ - zb_uint8_t endpoint; /**< Device endpoint */ - zb_uint16_t cluster_id; /**< Discovered cluster */ - zb_uint8_t commodity_type; /**< Commodity type (for multiple commodity networks) */ -} zb_se_signal_service_discovery_bind_params_t; -/** @endcond */ - -#if defined ZB_ENABLE_ZGP_SINK || defined DOXYGEN -/** @cond DOXYGEN_ZGP_SECTION */ -/** - @brief ZGP commissioning parameters - - Stack passes this parameter to application to notify about GPD commissioning - result. - */ -typedef struct zb_zgp_signal_commissioning_params_s -{ - zb_zgpd_id_t zgpd_id; /*!< Pointer to GPD ID */ - zb_zgp_comm_status_t result; /*!< commissioning result, see @ref zb_zgp_comm_status_t */ -} zb_zgp_signal_commissioning_params_t; -/** @endcond */ -#endif /* ZB_ENABLE_ZGP_SINK */ - -/** - @brief Association parameters - - Stack passes this parameter to application when some device associates to that. - */ -typedef struct zb_nwk_signal_device_associated_params_s -{ - zb_ieee_addr_t device_addr; /*!< address of associated device */ -} zb_nwk_signal_device_associated_params_t; - -/** - *@brief Association parameters - * - * Stack passes this parameter to application when some device joins/rejoins to - * network. - */ -typedef struct zb_zdo_signal_device_annce_params_s -{ - zb_uint16_t device_short_addr; /*!< address of device that recently joined to network */ - zb_ieee_addr_t ieee_addr; - zb_uint8_t capability; -} zb_zdo_signal_device_annce_params_t; - -/** @cond DOXYGEN_TOUCHLINK_FEATURE */ -typedef struct zb_bdb_signal_touchlink_nwk_started_params_s -{ - zb_ieee_addr_t device_ieee_addr; /*!< address of device that started the network */ - zb_uint8_t endpoint; - zb_uint16_t profile_id; -} zb_bdb_signal_touchlink_nwk_started_params_t; - -typedef struct zb_bdb_signal_touchlink_nwk_joined_router_s -{ - zb_ieee_addr_t device_ieee_addr; /*!< address of device that started the network */ - zb_uint8_t endpoint; - zb_uint16_t profile_id; -} zb_bdb_signal_touchlink_nwk_joined_router_t; -/** @endcond */ /* DOXYGEN_TOUCHLINK_FEATURE */ - -/** - @brief Sleep signal parameters. - - Stack passes this parameter to application when device ready to sleep. - */ -typedef struct zb_zdo_signal_can_sleep_params_s -{ - zb_uint32_t sleep_tmo; /*!< sleep duration in milliseconds */ -} zb_zdo_signal_can_sleep_params_t; - -/** - @brief Macsplit device boot parameters. - - Macsplit passes this parameter to application when device is booted. - */ -typedef struct zb_zdo_signal_macsplit_dev_boot_params_s -{ - zb_uint32_t dev_version; /*!< macsplit device version */ - zb_ieee_addr_t extended_address; /*!< The 64-bit (IEEE) address assigned to the device. */ -} zb_zdo_signal_macsplit_dev_boot_params_t; - -/** - * @name Status codes for F&B Initiator Finished signal - * @anchor zdo_fb_initiator_finished_status - */ -/** @{ */ -#define ZB_ZDO_FB_INITIATOR_STATUS_SUCCESS 0U /*!< F&B with a Target on the Initiator side is success completed */ -#define ZB_ZDO_FB_INITIATOR_STATUS_CANCEL 1U /*!< F&B on the Initiator side is canceled */ -#define ZB_ZDO_FB_INITIATOR_STATUS_ALARM 2U /*!< F&B on the Initiator side is finished by timeout */ -#define ZB_ZDO_FB_INITIATOR_STATUS_ERROR 3U /*!< F&B on the Initiator side is failure finished */ -/** @} */ - -/** - * @brief Type for Status codes for F&B Initiator Finished signal. - * - * Holds one of @ref zdo_fb_initiator_finished_status. Kept only for backward - * compatibility as - * @ref zdo_fb_initiator_finished_status were declared previously as enum. Can be removed in future - * releases. - */ -typedef zb_uint8_t zb_zdo_fb_initiator_finished_status_t; - -/** - * @brief F&B Initiator Finished signal parameters - */ -typedef struct zb_zdo_signal_fb_initiator_finished_params_s -{ - /*!< Status of the F&B procedure on the Initiator side */ - zb_zdo_fb_initiator_finished_status_t status; -} zb_zdo_signal_fb_initiator_finished_params_t; - - -/* - * Note: These values were members of `enum zb_secur_upd_device_status_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** - * @name Security/rejoin states of the 'status' field of APSME-Update-Device - * @see Table 4.40 - * @anchor secur_upd_device_status - * - */ -/** @{ */ -#define ZB_STD_SEQ_SECURED_REJOIN 0U /*!< Device rejoin with standard security */ -#define ZB_STD_SEQ_UNSECURED_JOIN 1U /*!< Device join without security */ -#define ZB_DEVICE_LEFT 2U /*!< Device left */ -#define ZB_STD_SEQ_UNSECURED_REJOIN 3U /*!< Device rejoin without standard security */ -#define ZB_MAX_USED_UPD_DEV_STATUS ZB_STD_SEQ_UNSECURED_REJOIN -/** @} */ -/* Obsolete values */ -#define ZB_HIGH_SEQ_SECURED_REJOIN 4U /*!< Device rejoin with high security */ -#define ZB_HIGH_SEQ_UNSECURED_JOIN 5U /*!< Device join without high security */ -#define ZB_HIGH_SEQ_UNSECURED_REJOIN 7U /*!< Device rejoin without high security */ - - -/** - * @name TC action on incoming Update Device - * @anchor secur_tc_action - */ -/** @{ */ -#define ZB_TC_ACTION_AUTHORIZE 0u /*!< authorize device */ -#define ZB_TC_ACTION_DENY 1u /*!< deby authorization - msend Remove device */ -#define ZB_TC_ACTION_IGNORE 2u /*!< ignore Update Device - that meay lead to authorization deny */ -/** @} */ - - -/** - * @brief Device Updated signal parameters - */ -typedef struct zb_zdo_signal_device_update_params_s -{ - /*!< Long Address of the updated device */ - zb_ieee_addr_t long_addr; - - /*!< Short Address of the updated device */ - zb_uint16_t short_addr; - - /*!< Indicates the updated status of the device - * - * 0x00 = Standard device secured rejoin - * 0x01 = Standard device unsecured join - * 0x02 = Device left - * 0x03 = Standard device trust center rejoin - * 0x04 – 0x07 = Reserved - * - * @see secur_upd_device_status - * - * see r21 spec, 4.4.3.2 APSME-UPDATE-DEVICE.indication, - * Table 4.15 APSME-UPDATE-DEVICE.indication Parameters - */ - zb_uint8_t status; - /*!< - Action by TC: authorize, send remove dev, ignore - @see secur_tc_action - */ - zb_uint8_t tc_action; - /*!< Short Address of the updated device parent, 0xffff is unknown */ - zb_uint16_t parent_short; -} zb_zdo_signal_device_update_params_t; - - -/** - * @name Authorization types for @ref ZB_ZDO_SIGNAL_DEVICE_AUTHORIZED - * @anchor zdo_authorization_type - */ -/* TODO: add other types if need (SE CBKE, r23 DLK) */ -/** @{ */ -#define ZB_ZDO_AUTHORIZATION_TYPE_LEGACY 0U /*!< Authorization type for legacy devices ( < r21) */ -#define ZB_ZDO_AUTHORIZATION_TYPE_R21_TCLK 1U /*!< Authorization type for r21 device through TCLK */ -#define ZB_ZDO_AUTHORIZATION_TYPE_SE_CBKE 2U /*!< Authorization type for SE through CBKE */ -/** @} */ - -/** - * @brief Type for Authorization types for @ref ZB_ZDO_SIGNAL_DEVICE_AUTHORIZED. - * - * @deprecated holds one of @ref zdo_authorization_type. Kept only for backward compatibility as - * @ref zdo_authorization_type were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_zdo_authorization_type_t; - -/** - * @name Authorization statuses for ZB_ZDO_AUTHORIZATION_TYPE_LEGACY value of @ref - * zdo_authorization_type type. - * @anchor zdo_legacy_device_authorization_status - */ -/** @{ */ -#define ZB_ZDO_LEGACY_DEVICE_AUTHORIZATION_SUCCESS 0U /*!< Authorization success */ -#define ZB_ZDO_LEGACY_DEVICE_AUTHORIZATION_FAILED 1U /*!< Authorization failed */ -/** @} */ - -/** - * @brief Type for Authorization statuses for ZB_ZDO_AUTHORIZATION_TYPE_LEGACY value of @ref - * zdo_authorization_type type. - * - * @deprecated holds one of @ref zdo_legacy_device_authorization_status. Kept only for backward - * compatibility as @ref zdo_legacy_device_authorization_status were declared previously as enum. - * Can be removed in future releases. - */ -typedef zb_uint8_t zb_zdo_legacy_device_authorization_status_t; - -/** - * @name Authorization statuses for ZB_ZDO_AUTHORIZATION_TYPE_R21_TCLK value of @ref - * zdo_authorization_type type - * @anchor zdo_authorization_type_r21_tclk_status - */ -/** @{ */ -#define ZB_ZDO_TCLK_AUTHORIZATION_SUCCESS 0U /*!< Authorization success */ -#define ZB_ZDO_TCLK_AUTHORIZATION_TIMEOUT 1U /*!< Authorization timeout */ -#define ZB_ZDO_TCLK_AUTHORIZATION_FAILED 2U /*!< Authorization failed */ -/** @} */ - -/** - * @name Authorization statuses for ZB_ZDO_AUTHORIZATION_TYPE_SE_CBKE value of @ref - * - * For non-success statuses @see zb_kec_term_status_t - */ -/** @{ */ -#define ZB_ZDO_CBKE_AUTHORIZATION_SUCCESS 0U /*!< Authorization success */ -/** @} */ - -/** - * @brief Type for Authorization types for @ref ZB_ZDO_SIGNAL_DEVICE_AUTHORIZED. - * - * @deprecated holds one of @ref zdo_authorization_type_r21_tclk_status. Kept only for backward compatibility - * as @ref zdo_authorization_type_r21_tclk_status were declared previously as enum. Can be removed in future - * releases. - */ -typedef zb_uint8_t zb_zdo_tclk_authorization_status_t; - -/** - * @brief Device Authorized signal parameters - */ -typedef struct zb_zdo_signal_device_authorized_params_s -{ - /*!< Long Address of the updated device */ - zb_ieee_addr_t long_addr; - - /*!< Short Address of the updated device */ - zb_uint16_t short_addr; - - /*!< Type of the authorization procedure, - * @ref zdo_authorization_type - */ - zb_uint8_t authorization_type; - - /*!< Status of the authorization procedure - * (depends on @ref zdo_authorization_type) - */ - zb_uint8_t authorization_status; -} zb_zdo_signal_device_authorized_params_t; - -/** Application signal header */ -typedef struct zb_zdo_app_signal_hdr_s -{ - /* 32 bit to have data section aligned well */ - zb_uint32_t sig_type; /** Application signal type, @ref zdo_app_signal_type */ -} zb_zdo_app_signal_hdr_t; -/* Legacy API: zb_zdo_app_signal_hdr_t == zb_zdo_app_event_t */ -typedef zb_zdo_app_signal_hdr_t zb_zdo_app_event_t; - -/** @} */ /* comm_signals*/ -/*! \addtogroup zdo_base */ -/*! @{ */ - -#define ZB_ZDO_INVALID_TSN 0xFFU - -typedef ZB_PACKED_PRE struct zb_zdo_callback_info_s -{ - zb_uint8_t tsn; - zb_uint8_t status; -} ZB_PACKED_STRUCT zb_zdo_callback_info_t; - -typedef ZB_PACKED_PRE struct zb_zdo_default_resp_s -{ - zb_uint8_t tsn; - zb_uint8_t status; -} ZB_PACKED_STRUCT zb_zdo_default_resp_t; - -/** @} */ -/*! \addtogroup zb_comm_signals */ -/*! @{ */ - -/** - @brief Unpack application signal buffer in zboss_signal_handler() - - @param param - parameter of zboss_signal_handler() - @param sg_p - pointer to the extended signal info, if application wants it. Can be NULL. - - @return Application signal - */ - -zb_zdo_app_signal_type_t zb_get_app_signal(zb_uint8_t param, zb_zdo_app_signal_hdr_t **sg_p); -/** @cond internals_doc */ -/* Legacy API: zb_get_app_event(param, sg_p) == zb_get_app_signal(param, sg_p) */ -#define zb_get_app_event(param, sg_p) zb_get_app_signal(param, sg_p) -/** @endcond */ /* internals_doc */ - -/** - @brief Get status from the application signal - @param param - buffer reference - @return status zb_ret_t - */ -#define ZB_GET_APP_SIGNAL_STATUS(param) zb_buf_get_status(param) - -/** @} */ -/*! \addtogroup zdo_base */ -/*! @{ */ - - -/** - @brief Obtains last known LQI and RSSI values from device with specified short address - - @param[in] short_address - address of device - @param[in,out] lqi - pointer to @ref zb_uint8_t variable to store lqi value - @param[in,out] rssi - pointer to @ref zb_uint8_t variable to store rssi value - -@b Example: -@snippet thermostat/thermostat_zr/thermostat_zr.c zb_zdo_get_diag_data_snippet - */ -void zb_zdo_get_diag_data(zb_uint16_t short_address, zb_uint8_t *lqi, zb_int8_t *rssi); - -typedef struct zb_zdo_get_diag_data_req_params_s -{ - zb_uint16_t short_address; -} zb_zdo_get_diag_data_req_params_t; - -typedef struct zb_zdo_get_diag_data_resp_params_s -{ - zb_ret_t status; /* RET_OK if lqi and rssi values are available for the requested address, - RET_NOT_FOUND if no values are available for the requested address */ - zb_uint16_t short_address; - zb_uint8_t lqi; - zb_int8_t rssi; -} zb_zdo_get_diag_data_resp_params_t; - -/** - * @brief Obtains last known LQI and RSSI values from the device with the specified short address - * - * @param buf - a buffer with request params, see zb_zdo_get_diag_data_req_params_t - * @param cb - a user's function to call when the response is ready. - * See zb_zdo_get_diag_data_resp_params_t for response params description. - * - * @return status, RET_OK - request successfully sent, - * RET_INVALID_PARAMETER_1 if buf is ZB_BUF_INVALID, - * RET_INVALID_PARAMETER_2 if cb is NULL, - * RET_BUSY if this request can't be served at the moment - * - * Example: - * @snippet onoff_server/on_off_output_zc.c zb_zdo_get_diag_data_async_example - */ -zb_ret_t zb_zdo_get_diag_data_async(zb_bufid_t buf, zb_callback_t cb); - -/*! @} */ - - -/*! \addtogroup zdo_addr */ -/*! @{ */ - - - -#define ZB_ZDO_SINGLE_DEVICE_RESP 0U /*!< Request Type parameter value of @ref zb_zdo_nwk_addr_req_t and @ref zb_zdo_ieee_addr_req_t for receiving a Single device response used in the following commands accordingly: - * - @ref zb_zdo_nwk_addr_req - * - @ref zb_zdo_ieee_addr_req - * @see spec 2.4.3.1, 2.4.4.1 - */ -#define ZB_ZDO_EXTENDED_DEVICE_RESP 1U /*!< Request Type parameter value of @ref zb_zdo_nwk_addr_req_t and @ref zb_zdo_ieee_addr_req_t for receiving an Extended device response used in the following commands accordingly: - * - @ref zb_zdo_nwk_addr_req - * - @ref zb_zdo_ieee_addr_req_t - * @see spec 2.4.3.1, 2.4.4.1 - */ - -/** @brief NWK_addr_req command primitive. */ -typedef ZB_PACKED_PRE struct zb_zdo_nwk_addr_req_s -{ - zb_ieee_addr_t ieee_addr; /*!< IEEE address to be matched by the - Remote Device */ - zb_uint8_t request_type; /*!< Request type for this command: - 0x00 Single device response - 0x01 Extended response */ - zb_uint8_t start_index; /*!< If the Request type for this command is - Extended response, the StartIndex - provides the starting index for the - requested elements of the associated - devices list */ -} ZB_PACKED_STRUCT zb_zdo_nwk_addr_req_t; - -/** @brief Parameters for nwk_addr_req command */ -typedef struct zb_zdo_nwk_addr_req_param_s -{ - zb_uint16_t dst_addr; /*!< Destination address */ - zb_ieee_addr_t ieee_addr; /*!< IEEE address to be matched by the - Remote Device */ - zb_uint8_t request_type; /*!< Request type for this command: - 0x00 Single device response - 0x01 Extended response */ - zb_uint8_t start_index; /*!< If the Request type for this command is - Extended response, the StartIndex - provides the starting index for the - requested elements of the associated - devices list */ -} -zb_zdo_nwk_addr_req_param_t; - -/** @brief NWK_addr_req response frame. */ -typedef ZB_PACKED_PRE struct zb_zdo_nwk_addr_resp_head_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /*!< The status of the NWK_addr_req command. */ - zb_ieee_addr_t ieee_addr; /*!< 64-bit address for the Remote Device. */ - zb_uint16_t nwk_addr; /*!< 16-bit address for the Remote Device. */ -} -ZB_PACKED_STRUCT -zb_zdo_nwk_addr_resp_head_t; - -/** @brief NWK_addr_req response frame tail */ -typedef ZB_PACKED_PRE struct zb_zdo_nwk_addr_resp_ext_s -{ - zb_uint8_t num_assoc_dev; /*!< Count of the ED List. */ -} -ZB_PACKED_STRUCT -zb_zdo_nwk_addr_resp_ext_t; - -/** @brief NWK_addr_req response frame tail */ -typedef ZB_PACKED_PRE struct zb_zdo_nwk_addr_resp_ext2_s -{ - zb_uint8_t start_index; /*!< Starting index to begin reporting for the ED List.*/ -} -ZB_PACKED_STRUCT -zb_zdo_nwk_addr_resp_ext2_t; - -/** @brief Sends NWK_addr_req primitive. - - @param param - index of buffer with primitive parameters - \ref zb_zdo_nwk_addr_req_param_s - @param cb - user's function to call when got response from the - remote. \ref zb_zdo_nwk_addr_resp_head_s passed to cb as parameter. - @return - ZDP transaction sequence number or 0xFF if operation cannot be - performed now (nor enough memory, resources, etc.) - -@b Example: -@snippet lighting/dimmable_light_tl/light_controller_zed.c zb_zdo_nwk_addr_req_snippet - -*/ -zb_uint8_t zb_zdo_nwk_addr_req(zb_uint8_t param, zb_callback_t cb); - -/** @cond internals_doc */ -/** - @brief Broadcast NWK_addr_req primitive. - Used internally in stack. - - @param param - index of buffer with primitive parameters - \ref zb_zdo_nwk_addr_req_param_s - @param ieee_addr - IEEE address to be matched by the Remote Device -*/ -zb_uint8_t zb_zdo_initiate_nwk_addr_req(zb_uint8_t param, zb_ieee_addr_t ieee_addr); -/* Used internally in stack. */ -void zb_zdo_initiate_nwk_addr_req_2param(zb_uint8_t param, zb_uint16_t user_param); -void zb_zdo_init_node_desc_req_2param(zb_uint8_t param, zb_uint16_t user_param); -zb_ret_t zb_zdo_init_node_desc_req_direct(zb_uint16_t addr, zb_callback_t user_cb); -/** @endcond */ /* internals_doc */ - -/** @brief Parameters of IEEE_addr_req primitive. - - To be put into buffer as data (means - after space alloc). - */ -typedef ZB_PACKED_PRE struct zb_zdo_ieee_addr_req_s -{ - zb_uint16_t nwk_addr; /*!< NWK address that is used for IEEE - address mapping. */ - zb_uint8_t request_type; /*!< Request type for this command: - 0x00 Single device response - 0x01 Extended response */ - zb_uint8_t start_index; /*!< If the Request type for this command is - Extended response, the StartIndex - provides the starting index for the - requested elements of the associated - devices list */ -} ZB_PACKED_STRUCT zb_zdo_ieee_addr_req_t; - -/** @brief Parameters for ieee_addr_req command */ -typedef struct zb_zdo_ieee_addr_req_param_s -{ - zb_uint16_t dst_addr; /*!< Destination address */ - zb_uint16_t nwk_addr; /*!< NWK address that is used for IEEE - address mapping. */ - zb_uint8_t request_type; /*!< Request type for this command: - 0x00 Single device response - 0x01 Extended response */ - zb_uint8_t start_index; /*!< If the Request type for this command is - Extended response, the StartIndex - provides the starting index for the - requested elements of the associated - devices list */ -} -zb_zdo_ieee_addr_req_param_t; - -/** brief ZDO IEEE address response frame */ -typedef ZB_PACKED_PRE struct zb_zdo_ieee_addr_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /*!< The status of the NWK_addr_req command. */ - zb_ieee_addr_t ieee_addr_remote_dev; /*!< 64-bit address for the Remote Device. */ - zb_uint16_t nwk_addr_remote_dev; /*!< 16-bit address for the Remote Device. */ -} -ZB_PACKED_STRUCT -zb_zdo_ieee_addr_resp_t; - -/** @brief ZDO IEEE address response frame tail */ -typedef ZB_PACKED_PRE struct zb_zdo_ieee_addr_resp_ext_s -{ - zb_uint8_t num_assoc_dev; /*!< Count of the ED List. */ -} -ZB_PACKED_STRUCT -zb_zdo_ieee_addr_resp_ext_t; - -/** @brief ZDO IEEE address response frame tail */ -typedef ZB_PACKED_PRE struct zb_zdo_ieee_addr_resp_ext2_s -{ - zb_uint8_t start_index; /*!< Starting index to begin reporting for the ED List.*/ -} -ZB_PACKED_STRUCT -zb_zdo_ieee_addr_resp_ext2_t; - -/** @brief IEEE_addr_req primitive. - * - * @param param - index of buffer with primitive parameters \ref zb_zdo_ieee_addr_req_s. - * Parameters must be put into the buffer as data (allocated). - * @param cb - user's function to call when got response from the remote. - * @return - ZDP transaction sequence number or 0xFF if operation cannot be - * performed now (nor enough memory, resources, etc.) - * - * @b Example: - * @snippet simple_gw/simple_gw.c zb_zdo_ieee_addr_req_snippet - * - */ -zb_uint8_t zb_zdo_ieee_addr_req(zb_uint8_t param, zb_callback_t cb); - -/** @cond internals_doc */ -/* Used internally in stack. */ -zb_uint8_t zb_zdo_initiate_ieee_addr_req_broadcast(zb_uint8_t param, zb_uint16_t nwk_addr); -/** @endcond */ /* internals_doc */ - -/** @} */ - -/** - @addtogroup zdo_disc - @{ -*/ - -/** @brief Parameters of Node_desc_req primitive. - - To be put into buffer as data (means - after space alloc). - */ -typedef ZB_PACKED_PRE struct zb_zdo_node_desc_req_s -{ - zb_uint16_t nwk_addr; /*!< NWK address that is used for IEEE - address mapping. */ -} ZB_PACKED_STRUCT zb_zdo_node_desc_req_t; - - -/** @brief Header of Node_desc_resp primitive. */ -typedef ZB_PACKED_PRE struct zb_zdo_desc_resp_hdr_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /*!< The status of the Desc_req command. @ref zdp_status */ - zb_uint16_t nwk_addr; /*!< NWK address for the request */ -} ZB_PACKED_STRUCT -zb_zdo_desc_resp_hdr_t; - -/** @brief Parameters of Node_desc_resp primitive. */ -typedef ZB_PACKED_PRE struct zb_zdo_node_desc_resp_s -{ - zb_zdo_desc_resp_hdr_t hdr; /*!< header for response */ - zb_af_node_desc_t node_desc; /*!< Node Descriptor */ -} ZB_PACKED_STRUCT -zb_zdo_node_desc_resp_t; - -/** @brief Header of simple_desc_resp primitive. */ -typedef ZB_PACKED_PRE struct zb_zdo_simple_desc_resp_hdr_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /*!< The status of the Desc_req command. @ref zdp_status */ - zb_uint16_t nwk_addr; /*!< NWK address for the request */ - zb_uint8_t length; /*!< Length of the simple descriptor */ -} ZB_PACKED_STRUCT -zb_zdo_simple_desc_resp_hdr_t; - -#ifdef ZB_FIXED_OPTIONAL_DESC_RESPONSES -typedef zb_zdo_simple_desc_resp_hdr_t zb_zdo_complex_desc_resp_hdr_t; -typedef zb_zdo_simple_desc_resp_hdr_t zb_zdo_user_desc_resp_hdr_t; -typedef zb_zdo_desc_resp_hdr_t zb_zdo_user_desc_conf_hdr_t; -#endif - -/** @brief Parameters of simple_desc_resp primitive. */ -typedef ZB_PACKED_PRE struct zb_zdo_simple_desc_resp_s -{ - zb_zdo_simple_desc_resp_hdr_t hdr; /*!< header for response */ - zb_af_simple_desc_1_1_t simple_desc; /*!< Simple Descriptor */ -} ZB_PACKED_STRUCT -zb_zdo_simple_desc_resp_t; - - -typedef ZB_PACKED_PRE struct zb_zdo_child_info_s -{ - zb_ieee_addr_t ext_addr; /*!< 64-bit IEEE address that is - * unique to every device.*/ -}ZB_PACKED_STRUCT -zb_zdo_child_info_t; - -/** @brief Jitter used for sending Parent Annce */ -#define ZB_PARENT_ANNCE_JITTER() (ZB_APS_PARENT_ANNOUNCE_BASE_TIMER + ZB_RANDOM_JTR(ZB_APS_PARENT_ANNOUNCE_JITTER_MAX)) - - -/** @brief Header of parent_annce primitive. */ -typedef ZB_PACKED_PRE struct zb_zdo_parent_annce_s -{ - zb_uint8_t tsn; /*!< ZDO sequence number */ - zb_uint8_t num_of_children; /*!< Length of the simple descriptor */ -} ZB_PACKED_STRUCT -zb_zdo_parent_annce_t; - - -/** @brief Header of parent_annce_rsp primitive. */ -typedef ZB_PACKED_PRE struct zb_zdo_parent_annce_rsp_hdr_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /*!< The status of the Desc_req command. @ref zdp_status */ - zb_uint8_t num_of_children; /*!< Length of the simple descriptor */ -} ZB_PACKED_STRUCT -zb_zdo_parent_annce_rsp_hdr_t; - -/** @brief Parameters of parent_annce_rsp primitive. */ -typedef ZB_PACKED_PRE struct zb_zdo_parent_annce_rsp_s -{ - zb_zdo_parent_annce_rsp_hdr_t hdr; /*!< header for response */ -} ZB_PACKED_STRUCT -zb_zdo_parent_annce_rsp_t; - -/** @brief Parameters of Power_desc_resp primitive. */ -typedef ZB_PACKED_PRE struct zb_zdo_power_desc_resp_s -{ - zb_zdo_desc_resp_hdr_t hdr; /*!< header for response */ - zb_af_node_power_desc_t power_desc; /*!< Power Descriptor */ -} ZB_PACKED_STRUCT -zb_zdo_power_desc_resp_t; - -/** @brief Node_desc_req primitive. - * - * @param param - index of buffer with primitive parameters \ref zb_zdo_node_desc_req_s. - * Parameters must be put into buffer as data (allocated). - * @param cb - user's function to call when got response from the remote. - * @return - ZDP transaction sequence number or 0xFF if operation cannot be - * performed now (nor enough memory, resources, etc.) - * - * @b Example: - * @snippet onoff_server/on_off_switch_zed.c send_node_desc_req - * @snippet onoff_server/on_off_switch_zed.c node_req_cb - * - */ -zb_uint8_t zb_zdo_node_desc_req(zb_uint8_t param, zb_callback_t cb); - - -/** @brief Parameters of Power_desc_req primitive. - - To be put into buffer as data (means - after space alloc). - */ -typedef ZB_PACKED_PRE struct zb_zdo_power_desc_req_s -{ - zb_uint16_t nwk_addr; /*!< NWK address that is used for IEEE - address mapping. */ -} ZB_PACKED_STRUCT zb_zdo_power_desc_req_t; - -/** @brief Power_desc_req primitive. - * - * @param param - index of buffer with primitive parameters \ref zb_zdo_power_desc_req_s. - * Parameters must be put into buffer as data (allocated). - * @param cb - user's function to call when got response from the remote. - * @return - ZDP transaction sequence number or 0xFF if operation cannot be - * performed now (nor enough memory, resources, etc.) - * - * @b Example: - * @snippet onoff_server/on_off_switch_zed.c send_power_desc_req - * @snippet onoff_server/on_off_switch_zed.c power_desc_cb - * - */ -zb_uint8_t zb_zdo_power_desc_req(zb_uint8_t param, zb_callback_t cb); - - - -/** @brief Parameters of Simple_desc_req primitive. - - To be put into buffer as data (means - after space alloc). - */ -typedef ZB_PACKED_PRE struct zb_zdo_simple_desc_req_s -{ - zb_uint16_t nwk_addr; /*!< NWK address that is used for IEEE - address mapping. */ - zb_uint8_t endpoint; /*!< The endpoint on the destination */ -} ZB_PACKED_STRUCT zb_zdo_simple_desc_req_t; - -/** @brief Simple_desc_req primitive. - * - * @param param - index of buffer with primitive parameters \ref zb_zdo_simple_desc_req_s. - * @param cb - user's function to call when got response from the remote. - * @return - ZDP transaction sequence number or 0xFF if operation cannot be - * performed now (nor enough memory, resources, etc.) - * - * @b Example: - * @snippet onoff_server/on_off_switch_zed.c send_simple_desc_req - * @snippet onoff_server/on_off_switch_zed.c simple_desc_cb - * - */ -zb_uint8_t zb_zdo_simple_desc_req(zb_uint8_t param, zb_callback_t cb); - - -/** @brief Parameters of Active_desc_req primitive. - - To be put into buffer as data (means - after space alloc). - */ -typedef ZB_PACKED_PRE struct zb_zdo_active_ep_req_s -{ - zb_uint16_t nwk_addr; /*!< NWK address that is used for IEEE - address mapping. */ -} ZB_PACKED_STRUCT zb_zdo_active_ep_req_t; - - -/** @brief Active EP response */ -typedef ZB_PACKED_PRE struct zb_zdo_ep_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /*!< The status of the Active_EP_req command. */ - zb_uint16_t nwk_addr; /*!< NWK address for the request. */ - zb_uint8_t ep_count; /*!< The count of active endpoints on the Remote Device. */ -} -ZB_PACKED_STRUCT -zb_zdo_ep_resp_t; - -/** - * @brief Active_desc_req primitive. - * - * @param param - index of buffer with primitive parameters \ref zb_zdo_active_ep_req_s. Parameters must be - * put into buffer as data (allocated). - * @param cb - user's function to call when got response from the remote. - * @return - ZDP transaction sequence number or 0xFF if operation cannot be - * performed now (nor enough memory, resources, etc.) - * - * @b Example: - * @snippet onoff_server/on_off_switch_zed.c send_active_ep_req - * @snippet onoff_server/on_off_switch_zed.c active_ep_cb - * - */ -zb_uint8_t zb_zdo_active_ep_req(zb_uint8_t param, zb_callback_t cb); - -/** @brief Parameters of match_desc_req primitive. - - To be put into buffer as data (means - after space alloc). - */ -typedef ZB_PACKED_PRE struct zb_zdo_match_desc_param_s -{ - zb_uint16_t nwk_addr; /*!< NWK address that is used for IEEE - address mapping. */ - zb_uint16_t addr_of_interest; /*!< NWK address of interest */ - - zb_uint16_t profile_id; /*!< Profile ID to be matched at the - destination. */ - zb_uint8_t num_in_clusters; /*!< The number of Input Clusters - provided for matching within the - InClusterList. */ - zb_uint8_t num_out_clusters; /*!< The number of Output Clusters - provided for matching within - OutClusterList. */ - zb_uint16_t cluster_list[1]; /*!< Variable size: [num_in_clusters] + [num_out_clusters] - List of Input ClusterIDs to be used - for matching; the InClusterList is - the desired list to be matched by - the Remote Device (the elements - of the InClusterList are the - supported output clusters of the - Local Device). - List of Output ClusterIDs to be - used for matching; the - OutClusterList is the desired list to - be matched by the Remote Device - (the elements of the - OutClusterList are the supported - input clusters of the Local - Device). */ -} -ZB_PACKED_STRUCT -zb_zdo_match_desc_param_t; - -/** @brief Match_desc_req head */ -typedef ZB_PACKED_PRE struct zb_zdo_match_desc_req_head_s -{ - zb_uint16_t nwk_addr; /*!< NWK address that is used for IEEE - address mapping. */ - zb_uint16_t profile_id; /*!< Profile ID to be matched at the - destination. */ - zb_uint8_t num_in_clusters; /*!< The number of Input Clusters - provided for matching within the - InClusterList. */ -} -ZB_PACKED_STRUCT -zb_zdo_match_desc_req_head_t; - -/** @brief Match_desc_req tail */ -typedef ZB_PACKED_PRE struct zb_zdo_match_desc_req_tail_s -{ - zb_uint8_t num_out_clusters; /*!< The number of Output Clusters - provided for matching within - OutClusterList. */ -} -ZB_PACKED_STRUCT -zb_zdo_match_desc_req_tail_t; - -/** @brief Match_Desc_rsp response structure - * @see ZB spec, subclause 2.4.4.1.7 - */ -typedef ZB_PACKED_PRE struct zb_zdo_match_desc_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /*!< The status of the Match_Desc_req command.*/ - zb_uint16_t nwk_addr; /*!< NWK address for the request. */ - zb_uint8_t match_len; /*!< The count of endpoints on the Remote Device that match the - request criteria.*/ -} -ZB_PACKED_STRUCT -zb_zdo_match_desc_resp_t; - - -/** @brief Match_desc_req primitive. - - @param param - index of buffer with primitive parameters \ref zb_zdo_match_desc_param_s. - @param cb - user's function to call when got response from the remote. If command is \n - broadcast, then user's function will be called as many times as number of \n - responses received plus one more time with status \ref ZB_ZDP_STATUS_TIMEOUT - to indicate that no more responses will be received. - @return - ZDP transaction sequence number or 0xFF if operation cannot be - performed now (nor enough memory, resources, etc.) - - @b Example: - @snippet light_sample/light_control/light_control.c zdo_match_desc_req -*/ -zb_uint8_t zb_zdo_match_desc_req(zb_uint8_t param, zb_callback_t cb); - - -#ifndef ZB_LITE_NO_ZDO_SYSTEM_SERVER_DISCOVERY -/** @brief Request parameters for System_Server_Discovery_req. - * @see ZB spec, subclause 2.4.3.1.13. - */ -typedef ZB_PACKED_PRE struct zb_zdo_system_server_discovery_req_s -{ - zb_uint16_t server_mask; /*!< Server mask for device discovery */ -} -ZB_PACKED_STRUCT -zb_zdo_system_server_discovery_req_t; - -/** @brief Parameters for System_Server_Discovery_req call. - * @see ZB spec, subclause 2.4.3.1.13. - */ -typedef zb_zdo_system_server_discovery_req_t zb_zdo_system_server_discovery_param_t; - - -/** @brief Response parameters for System_Server_Discovery_rsp. - * @see ZB spec, subclause 2.4.4.1.10. - */ -typedef ZB_PACKED_PRE struct zb_zdo_system_server_discovery_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /*!< Status of the operation */ - zb_uint16_t server_mask; /*!< Mask of the supported features */ -} -ZB_PACKED_STRUCT -zb_zdo_system_server_discovery_resp_t; - - -/** - * @brief Performs System_Server_Discovery_req - * @param param - index of buffer with request parameters - * @ref zb_zdo_system_server_discovery_param_t - * @param cb - user's function to call when got response from the remote. \ref - * zb_zdo_system_server_discovery_resp_s - * - * @return ZDP transaction sequence number - * @return 0xFF if operation cannot be - * performed now (nor enough memory, resources, etc.) - * - * @b Example: - * @snippet onoff_server/on_off_switch_zed.c system_server_discovery_req - * @snippet onoff_server/on_off_switch_zed.c system_server_discovery_cb - * - */ -zb_uint8_t zb_zdo_system_server_discovery_req(zb_uint8_t param, zb_callback_t cb); -#endif /*ZB_LITE_NO_ZDO_SYSTEM_SERVER_DISCOVERY */ - -/*! @} */ - -/*! \addtogroup zdo_mgmt */ -/*! @{ */ - - -/** @brief Header of parameters for Mgmt_NWK_Update_req */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_nwk_update_req_hdr_s -{ - zb_uint32_t scan_channels; /*!< Channels bitmask */ - zb_uint8_t scan_duration; /*!< A value used to calculate the - * length of time to spend scanning - * each channel. */ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_nwk_update_req_hdr_t; - -/** @brief Parameters for Mgmt_NWK_Update_req */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_nwk_update_req_s -{ - zb_zdo_mgmt_nwk_update_req_hdr_t hdr; /*!< Request header */ - zb_uint8_t scan_count; /*!< This field represents the number - * of energy scans to be conducted and reported */ - zb_uint16_t manager_addr; /*!< This field shall be present only - * if the ScanDuration is set to 0xff, - * and, where present, indicates the - * NWK address for the device with the - * Network Manager bit set in its Node Descriptor. */ - zb_uint16_t dst_addr; /*!< Destination address */ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_nwk_update_req_t; - -#ifdef ZB_MGMT_NWK_ENHANCED_UPDATE_ENABLED - -/** @brief Parameters for Mgmt_NWK_Update_req internal call*/ -typedef struct zb_zdo_mgmt_nwk_enhanced_update_req_param_s -{ - zb_channel_list_t channel_list; /*!< ZBOSS internal channel list */ - zb_uint8_t scan_duration; /*!< A value used to calculate the - * length of time to spend scanning - * each channel. */ - zb_uint8_t scan_count; /*!< This field represents the number - * of energy scans to be conducted and reported */ - zb_uint16_t manager_addr; /*!< This field shall be present only - * if the ScanDuration is set to 0xff, - * and, where present, indicates the - * NWK address for the device with the - * Network Manager bit set in its Node Descriptor. */ - zb_uint16_t dst_addr; /*!< Destination address */ -} zb_zdo_mgmt_nwk_enhanced_update_req_param_t; - -/** @brief Header of parameters for Mgmt_NWK_Update_req */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_nwk_enhanced_update_req_hdr_s -{ - zb_uint8_t channel_page_count; /* The number of Channel Page Structures - * contained within the Channel List Structure */ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_nwk_enhanced_update_req_hdr_t; - -#endif /* ZB_MGMT_NWK_ENHANCED_UPDATE_ENABLED */ - -/** @brief Header parameters for mgmt_nwk_update_notify */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_nwk_update_notify_hdr_s -{ - zb_uint8_t tsn; /*!< tsn value */ - zb_uint8_t status; /*!< The status of the Mgmt_NWK_Update_notify command. */ - zb_uint32_t scanned_channels; /*!< List of channels scanned by the request */ - zb_uint16_t total_transmissions; /*!< Count of the total transmissions reported by the device */ - zb_uint16_t transmission_failures; /*!< Sum of the total transmission failures reported by the - device */ - zb_uint8_t scanned_channels_list_count; /*!< The list shall contain the number of records - * contained in the EnergyValues parameter. */ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_nwk_update_notify_hdr_t; - -/** @brief Parameters for mgmt_nwk_update_notify */ -typedef struct zb_zdo_mgmt_nwk_update_notify_param_s -{ - zb_zdo_mgmt_nwk_update_notify_hdr_t hdr; /*!< Fixed parameters set */ - zb_uint8_t energy_values[ZB_MAC_SUPPORTED_CHANNELS]; /*!< ed scan values */ - zb_uint16_t dst_addr; /*!< destination address */ - zb_uint8_t enhanced; /*!< If set to one, send Enhanced notify command */ -} -zb_zdo_mgmt_nwk_update_notify_param_t; - -#ifdef ZB_MGMT_NWK_ENHANCED_UPDATE_ENABLED - -typedef zb_zdo_mgmt_nwk_update_notify_param_t zb_zdo_mgmt_nwk_enhanced_update_notify_param_t; - -#endif /* ZB_MGMT_NWK_ENHANCED_UPDATE_ENABLED */ - -/** @brief Performs Mgmt_NWK_Update_req request - - @param param - index of buffer with call parameters. Parameters must be - put into buffer as parameters. \ref zb_zdo_mgmt_nwk_update_req_s - @param cb - user's function to call when got response from the remote. - \ref zb_zdo_mgmt_nwk_update_notify_hdr_s - @return - ZDP transaction sequence number or 0xFF if operation cannot be - performed now (nor enough memory, resources, etc.) - - @b Example: -@code -{ - zb_uint8_t tsn; - zb_zdo_mgmt_nwk_update_req_t *req; - - req = ZB_BUF_GET_PARAM(buf, zb_zdo_mgmt_nwk_update_req_t); - - req->hdr.scan_channels = ZB_MAC_ALL_CHANNELS_MASK; - req->hdr.scan_duration = TEST_SCAN_DURATION; - req->scan_count = TEST_SCAN_COUNT; - - req->dst_addr = 0; - - tsn = zb_zdo_mgmt_nwk_update_req(param, mgmt_nwk_update_ok_cb); -} - - -void mgmt_nwk_update_ok_cb(zb_uint8_t param) -{ - zb_bufid_t buf = param; - zb_uint8_t *zdp_cmd = zb_buf_begin(buf); - zb_zdo_mgmt_nwk_update_notify_hdr_t *notify_resp = (zb_zdo_mgmt_nwk_update_notify_hdr_t *)zdp_cmd; - - TRACE_MSG(TRACE_APS3, - "notify_resp status %hd, scanned_channels %x %x, total_transmissions %hd, " - "transmission_failures %hd, scanned_channels_list_count %hd, buf len %hd", - (FMT__H_D_D_H_H_H_H, notify_resp->status, (zb_uint16_t)notify_resp->scanned_channels, - *((zb_uint16_t*)¬ify_resp->scanned_channels + 1), - notify_resp->total_transmissions, notify_resp->transmission_failures, - notify_resp->scanned_channels_list_count, zb_buf_len(buf))); - - if (notify_resp->status == ZB_ZDP_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_APS3, "mgmt_nwk_update_notify received, Ok", (FMT__0)); - } - else - { - TRACE_MSG(TRACE_ERROR, "mgmt_nwk_update_notify received, ERROR incorrect status %x", - (FMT__D, notify_resp->status)); - } - - zb_buf_free(buf); -} -@endcode - - - */ -zb_uint8_t zb_zdo_mgmt_nwk_update_req(zb_uint8_t param, zb_callback_t cb); - -#ifdef ZB_MGMT_NWK_ENHANCED_UPDATE_ENABLED -/** @brief Performs Mgmt_NWK_Enhanced_Update_req request - - @param param - index of buffer with call parameters. Parameters must be - put into buffer as parameters. \ref zb_zdo_mgmt_nwk_enhanced_update_req_param_s - @param cb - user's function to call when got response from the remote. - \ref zb_zdo_mgmt_nwk_update_notify_hdr_s - @return - ZDP transaction sequence number or 0xFF if operation cannot be - performed now (nor enough memory, resources, etc.) - -*/ -zb_uint8_t zb_zdo_mgmt_nwk_enh_update_req(zb_uint8_t param, zb_callback_t cb); - -#ifdef ZB_DEPRECATED_API - -/** @brief Performs Mgmt_NWK_Update_req request - - @deprecated This function is deprecated and will be removed in a future release. - Use zb_zdo_mgmt_nwk_enh_update_req() instead. -*/ -zb_uint8_t zb_zdo_mgmt_nwk_enhanced_update_req(zb_uint8_t param, zb_callback_t cb) ZB_DEPRECATED; - -#endif /* ZB_DEPRECATED_API */ - - -/** @brief Notification for Mgmt_NWK_Unsolicited_Enhanced_Update_Notify - * @see ZB spec, subclause 2.4.4.4.12 - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_nwk_unsol_enh_update_notify_s -{ - zb_uint8_t status; - zb_channel_page_t channel_in_use; - zb_uint16_t mac_tx_ucast_total; - zb_uint16_t mac_tx_ucast_failures; - zb_uint16_t mac_tx_ucast_retries; - zb_uint8_t period; -} ZB_PACKED_STRUCT -zb_zdo_mgmt_nwk_unsol_enh_update_notify_t; - -/** @brief Parameters for Mgmt_NWK_Unsolicited_Enhanced_Update_Notify - * @see ZB spec, subclause 2.4.4.4.12 - */ -typedef struct zb_zdo_mgmt_nwk_unsol_enh_update_notify_param_s -{ - zb_zdo_mgmt_nwk_unsol_enh_update_notify_t notification; - zb_uint16_t addr; -} -zb_zdo_mgmt_nwk_unsol_enh_update_notify_param_t; - -/** @brief Performs Mgmt_NWK_Enhanced_Update_req request - - @param param - index of buffer with call parameters. Parameters must be - put into buffer as parameters. \ref zb_zdo_mgmt_nwk_unsol_enh_update_notify_param_t - @param cb - user's function to call when the notification has been sent. -*/ -void zb_zdo_mgmt_nwk_unsol_enh_update_notify(zb_uint8_t param, zb_callback_t cb); - -#endif /* ZB_MGMT_NWK_ENHANCED_UPDATE_ENABLED */ - -/** @brief Parameters for Mgmt_Lqi_req. - * @see ZB spec, subclause 2.4.3.3.2. - */ -typedef struct zb_zdo_mgmt_lqi_param_s -{ - zb_uint8_t start_index; /*!< Starting Index for the requested elements - * of the Neighbor Table */ - zb_uint16_t dst_addr; /*!< destination address */ -} -zb_zdo_mgmt_lqi_param_t; - -/** @brief Request for Mgmt_Lqi_req. - * @see ZB spec, subclause 2.4.3.3.2. - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_lqi_req_s -{ - zb_uint8_t start_index; /*!< Starting Index for the requested elements - * of the Neighbor Table */ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_lqi_req_t; - -/** @brief Response for Mgmt_Lqi_rsp. - * @see ZB spec, subclause 2.4.4.3.2. - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_lqi_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /*!< The status of the Mgmt_Lqi_req command.*/ - zb_uint8_t neighbor_table_entries; /*!< Total number of Neighbor - * Table entries within the Remote Device */ - zb_uint8_t start_index; /*!< Starting index within the Neighbor - * Table to begin reporting for the NeighborTableList.*/ - zb_uint8_t neighbor_table_list_count; /*!< Number of Neighbor Table - * entries included within NeighborTableList*/ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_lqi_resp_t; - - -/* bits 0 - 1, mask 0x3 */ -/** - Set device type of neighbor table record to type 'type': bits 0 - 1, mask 0x3; - - @param var - neighbor table record type_flags - @param type - Zigbee device type value - - @ref zb_zdo_neighbor_table_record_s - */ -#define ZB_ZDO_RECORD_SET_DEVICE_TYPE(var, type) ( ( var ) &= ~3U, ( var ) |= ( type ) ) -/** - Get device type of neighbor table record. - - @param var - neighbor table record type_flags - - @ref zb_zdo_neighbor_table_record_s - */ -#define ZB_ZDO_RECORD_GET_DEVICE_TYPE(var) ( var & 3U ) - -/* bits 2 - 3, mask 0xC */ -/** - Set RxOnWhenIdle attribute of neighbor table record to type 'type': - bits 2 - 3, mask 0xC; - - @param var - neighbor table record type_flags - @param type - RxOnWhenIdle value - - @ref zb_zdo_neighbor_table_record_s - */ -#define ZB_ZDO_RECORD_SET_RX_ON_WHEN_IDLE(var, type) ( ( var ) &= ~0xCU, ( var ) |= (( type ) << 2U) ) -/** - Get RxOnWhenIdle of neighbor table record. - - @param var - neighbor table record type_flags - - @ref zb_zdo_neighbor_table_record_s - */ -#define ZB_ZDO_RECORD_GET_RX_ON_WHEN_IDLE(var) ( (var & 0xCU) >> 2U ) - -/* bits 4 - 6, mask 0x70 */ -/** - Set relationship attribute of neighbor table record to type 'type': - bits 4 - 6, mask 0x70; - - @param var - neighbor table record type_flags - @param type - Zigbee relationship value - - @ref zb_zdo_neighbor_table_record_s - */ -#define ZB_ZDO_RECORD_SET_RELATIONSHIP(var, type) ( ( var ) &= ~0x70U, ( var ) |= (( type ) << 4U) ) -/** - Get relationship of neighbor table record. - - @param var - neighbor table record type_flags - - @ref zb_zdo_neighbor_table_record_s - */ -#define ZB_ZDO_RECORD_GET_RELATIONSHIP(var) ( (var & 0x70) >> 4 ) - -/** @brief NeighborTableList Record Format for Mgmt_Lqi_resp */ -typedef ZB_PACKED_PRE struct zb_zdo_neighbor_table_record_s -{ - zb_ext_pan_id_t ext_pan_id; /*!< 64-bit extended Pan - * ID of the neighboring device.*/ - zb_ieee_addr_t ext_addr; /*!< 64-bit IEEE address that is - * unique to every device.*/ - zb_uint16_t network_addr; /*!< The 16-bit network address of the - * neighboring device */ - zb_uint8_t type_flags; /*!< device type, rx_on_when_idle, - * relationship */ - zb_uint8_t permit_join; /*!< An indication of whether the - * neighbor device is accepting join requests*/ - zb_uint8_t depth; /*!< The tree depth of the neighbor device. */ - zb_uint8_t lqi; /*!< The estimated link quality for RF - * transmissions from this device */ -} -ZB_PACKED_STRUCT -zb_zdo_neighbor_table_record_t; - - -/** @brief Sends Mgmt_Lqi_req (see Zigbee spec 2.4.3.3.2) - @param param - index of buffer with Lqi request parameters. \ref zb_zdo_mgmt_lqi_param_s - @param cb - user's function to call when got response from the remote. - @return - ZDP transaction sequence number or 0xFF if operation cannot be - performed now (nor enough memory, resources, etc.) - @ref zb_zdo_mgmt_lqi_resp_s, \ref zb_zdo_neighbor_table_record_s - - @b Example: -@snippet doxygen_snippets.dox zboss_api_zdo_h_2 - -*/ -zb_uint8_t zb_zdo_mgmt_lqi_req(zb_uint8_t param, zb_callback_t cb); - -/** @brief RoutingTableList Record Format for mgmt_rtg_resp */ -typedef ZB_PACKED_PRE struct zb_zdo_routing_table_record_s -{ - zb_uint16_t dest_addr; /*!< The 16-bit network address of the - * destination device */ - zb_uint8_t flags; /*!< Routing flags */ - zb_uint16_t next_hop_addr; /*!< The 16-bit network address of the - * next-hop device */ -} -ZB_PACKED_STRUCT -zb_zdo_routing_table_record_t; - -/** @} */ /* zdo_mgmt */ -/** @addtogroup zdo_bind - @{ - */ - -/** - * @name Bind destination address mode - * @brief The addressing mode for the destination address used in @ref - * zb_zdo_binding_table_record_s, @ref zb_zdo_bind_req_param_s, @ref zb_zdo_bind_req_head_s command. - * This field can take one of the non-reserved values from the list of defines below (@ref bind_dst_addr_mode). - * Values 0x00, 0x02, 0x04-0xff are reserved. - * @anchor bind_dst_addr_mode - * @see ZB Spec, subclause 2.4.3.2.2. - */ -/** @{ */ -/** 16-bit group address for DstAddress and DstEndp not present */ -#define ZB_BIND_DST_ADDR_MODE_16_BIT_GROUP 0x01U -/** 64-bit extended address for DstAddress and DstEndp present */ -#define ZB_BIND_DST_ADDR_MODE_64_BIT_EXTENDED 0x03U -/** @} */ - -/** - * @brief Type for bind destination address mode. - * - * @deprecated holds one of @ref bind_dst_addr_mode. Kept only for backward compatibility as - * @ref bind_dst_addr_mode were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_bind_dst_addr_mode_t; - -/** @brief Parameters for Mgmt_Bind_req. - * @see ZB spec, subclause 2.4.3.3.4. - */ -typedef struct zb_zdo_mgmt_bind_param_s -{ - zb_uint8_t start_index; /*!< Starting Index for the requested elements - * of the Binding Table */ - zb_uint16_t dst_addr; /*!< destination address */ -} -zb_zdo_mgmt_bind_param_t; - -/** @brief Request for Mgmt_Bind_req. - * @see ZB spec, subclause 2.4.3.3.4. - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_bind_req_s -{ - zb_uint8_t start_index; /*!< Starting Index for the requested elements - * of the Binding Table */ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_bind_req_t; - -/** @brief Response for Mgmt_Bind_rsp. - * @see ZB spec, subclause 2.4.4.3.4. - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_bind_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /*!< The status of the Mgmt_Rtg_req command.*/ - zb_uint8_t binding_table_entries; /*!< Total number of Binding Table - * entries within the Remote Device*/ - zb_uint8_t start_index; /*!< Starting index within the Binding - * Table to begin reporting for the BindingTableList.*/ - zb_uint8_t binding_table_list_count; /*!< Number of Binding Table - * entries included within BindingTableList*/ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_bind_resp_t; - - -/** @brief BindingTableList Record Format for mgmt_bind_resp. See ZB - * spec, Table 2.131 */ -typedef ZB_PACKED_PRE struct zb_zdo_binding_table_record_s -{ - zb_ieee_addr_t src_address; /*!< The source IEEE address for the binding entry. */ - zb_uint8_t src_endp; /*!< The source endpoint for the binding entry. */ - zb_uint16_t cluster_id; /*!< The identifier of the cluster on the - * source device that is bound to the - * destination device. */ - zb_uint8_t dst_addr_mode; /*!< Destination address mode @ref bind_dst_addr_mode */ - zb_addr_u dst_address; /*!< The destination address for the - * binding entry.16 or 64 bit. As specified by the - * dst_addr_mode field.*/ - zb_uint8_t dst_endp; /*!< This field shall be present only if the - * DstAddrMode field has a value of - * ZB_BIND_DST_ADDR_MODE_64_BIT_EXTENDED @ref bind_dst_addr_mode - * and, if present, shall be the - * destination endpoint for the binding - * entry. */ -} -ZB_PACKED_STRUCT -zb_zdo_binding_table_record_t; - - -/** @brief Sends Mgmt_Bind_req request. - * @param param reference to the buffer to put request data to. - * @param cb callback to be called on operation finish. - * @return ZDP transaction sequence number - * @return 0xFF if operation cannot be - * performed now (nor enough memory, resources, etc.) - * - */ -zb_uint8_t zb_zdo_mgmt_bind_req(zb_uint8_t param, zb_callback_t cb); - -/** - @brief Sends 2.4.4.3.4 Mgmt_Bind_rsp - @param param - index of buffer with Mgmt_Bind request - */ -void zdo_mgmt_bind_resp(zb_uint8_t param); - - /** @brief Parameters for zb_zdo_raw_req call - */ -typedef struct zb_zdo_raw_req_param_s -{ - zb_uint16_t cluster_id; /*!< The identifier of the object for which this - frame is intended. */ - zb_uint16_t dst_addr; /*!< Destination address */ -} -zb_zdo_raw_req_param_t; - - /** @brief Parameters of zb_zdo_raw_resp call - */ -typedef struct zb_zdo_raw_resp_param_s -{ - zb_uint16_t cluster_id; /*!< The identifier of the object in the response. */ - zb_uint16_t src_addr; /*!< Source address of a device that sent a response */ -} -zb_zdo_raw_resp_param_t; - -/** @brief Response by Raw_req. */ -typedef ZB_PACKED_PRE struct zb_zdo_raw_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /**< Operation status. */ - zb_uint8_t payload[ZB_ZDO_MAX_PAYLOAD_SIZE - 1U]; /**< Raw response payload. */ -} -ZB_PACKED_STRUCT -zb_zdo_raw_resp_t; - -#ifdef ZB_NCP_ENABLE_ZDO_RAW_CMD -/** @brief Raw ZDO request. - - @param param - index of buffer with request. @ref zb_zdo_raw_req_param_s - @param cb - user's function to call when got response from the - remote. @ref zb_zdo_raw_resp_param_s - @return ZDP transaction sequence number - @return 0xFF if operation cannot be performed now (nor enough memory, resources, etc.) - */ -zb_uint8_t zb_zdo_raw_req(zb_uint8_t param, zb_callback_t cb); -#endif /* ZB_NCP_ENABLE_ZDO_RAW_CMD */ - -/** @brief Parameters for Bind_req API call - * @see ZB spec, subclause 2.4.3.2.2. - */ -typedef struct zb_zdo_bind_req_param_s -{ - zb_ieee_addr_t src_address; /*!< The IEEE address for the source. */ - zb_uint8_t src_endp; /*!< The source endpoint for the binding entry. */ - zb_uint16_t cluster_id; /*!< The identifier of the cluster on the - * source device that is bound to the destination. */ - zb_uint8_t dst_addr_mode; /*!< Destination address mode @ref bind_dst_addr_mode */ - zb_addr_u dst_address; /*!< The destination address for the - * binding entry. */ - zb_uint8_t dst_endp; /*!< This field shall be present only if the - * DstAddrMode field has a value of - * @ref ZB_BIND_DST_ADDR_MODE_64_BIT_EXTENDED @ref bind_dst_addr_mode - * and, if present, shall be the - * destination endpoint for the binding - * entry. */ - zb_uint16_t req_dst_addr; /*!< Destination address of the request */ -} -zb_zdo_bind_req_param_t; - - -/** @brief Bind_req request head send to the remote. - * @see ZB spec, subclause 2.4.3.2.2. - */ -typedef ZB_PACKED_PRE struct zb_zdo_bind_req_head_s -{ - zb_ieee_addr_t src_address; /*!< The IEEE address for the source. */ - zb_uint8_t src_endp; /*!< The source endpoint for the binding entry. */ - zb_uint16_t cluster_id; /*!< The identifier of the cluster on the - * source device that is bound to the destination. */ - zb_uint8_t dst_addr_mode; /*!< Destination address mode @ref bind_dst_addr_mode */ -} -ZB_PACKED_STRUCT -zb_zdo_bind_req_head_t; - -/** @brief Bind_req request tail 1st variant send to the remote. - * @see ZB spec, subclause 2.4.3.2.2. - */ -typedef ZB_PACKED_PRE struct zb_zdo_bind_req_tail_1_s -{ - zb_uint16_t dst_addr; /*!< The destination address for the - * binding entry. */ -} -ZB_PACKED_STRUCT -zb_zdo_bind_req_tail_1_t; - -/** @brief Bind_req request tail 2nd variant send to the remote. - * @see ZB spec, subclause 2.4.3.2.2. - */ -typedef ZB_PACKED_PRE struct zb_zdo_bind_req_tail_2_s -{ - zb_ieee_addr_t dst_addr; /*!< The destination address for the - * binding entry. */ - zb_uint8_t dst_endp; /*!< The destination address for the - * binding entry. */ -} -ZB_PACKED_STRUCT -zb_zdo_bind_req_tail_2_t; - -/** @brief Response by Bind_req. */ -typedef ZB_PACKED_PRE struct zb_zdo_bind_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /**< Operation status. */ -} -ZB_PACKED_STRUCT -zb_zdo_bind_resp_t; - - -/** @brief Bind_req request. - - @param param - index of buffer with request. @ref zb_zdo_bind_req_param_s - @param cb - user's function to call when got response from the - remote. @ref zb_zdo_bind_resp_s - @return ZDP transaction sequence number - @return 0xFF if operation cannot be performed now (nor enough memory, resources, etc.) - - @b Example: -@snippet simple_gw/simple_gw.c zb_zdo_bind_req_snippet - - */ -zb_uint8_t zb_zdo_bind_req(zb_uint8_t param, zb_callback_t cb); - - -/** @brief Unbind_req request. - - @param param - index of buffer with request. @ref zb_zdo_bind_req_param_s - @param cb - user's function to call when got response from the - remote. @ref zb_zdo_bind_resp_s - @return ZDP transaction sequence number - @return 0xFF if operation cannot be performed now (nor enough memory, resources, etc.) - - @b Example: -@code -{ - zb_bufid_t buf = param; - zb_zdo_bind_req_param_t *bind_param; - - TRACE_MSG(TRACE_COMMON1, "unbind_device_1", (FMT__0)); - - zb_buf_initial_alloc(buf, 0); - bind_param = ZB_BUF_GET_PARAM(buf, zb_zdo_bind_req_param_t); - ZB_MEMCPY(bind_param->src_address, g_ieee_addr_ed1, sizeof(zb_ieee_addr_t)); - bind_param->src_endp = TEST_ED1_EP; - bind_param->cluster_id = TP_BUFFER_TEST_REQUEST_CLID; - bind_param->dst_addr_mode = ZB_APS_ADDR_MODE_64_ENDP_PRESENT; - ZB_MEMCPY(bind_param->dst_address.addr_long, g_ieee_addr_ed2, sizeof(zb_ieee_addr_t)); - bind_param->dst_endp = TEST_ED2_EP; - bind_param->req_dst_addr = zb_address_short_by_ieee(g_ieee_addr_ed1); - TRACE_MSG(TRACE_COMMON1, "dst addr %d", (FMT__D, bind_param->req_dst_addr)); - - zb_zdo_unbind_req(buf, unbind_device1_cb); -} - - -void unbind_device1_cb(zb_uint8_t param) -{ - zb_bufid_t buf = ZB_BUF_FROM_REF(param); - zb_zdo_bind_resp_t *bind_resp = (zb_zdo_bind_resp_t*)zb_buf_begin(buf); - - TRACE_MSG(TRACE_COMMON1, "unbind_device1_cb resp status %hd", (FMT__H, bind_resp->status)); - if (bind_resp->status != ZB_ZDP_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_COMMON1, "Error bind device 1. Test status failed", (FMT__0)); - } - zb_free_buf(buf); - -} -@endcode - -*/ -zb_uint8_t zb_zdo_unbind_req(zb_uint8_t param, zb_callback_t cb); - - -/** @brief Perform unbind all entries locally. This custom function and it is not described - * in Zigbee specification. - * @param param - not used. - */ -void zb_zdo_unbind_all_local(zb_uint8_t param); - -/** - * @brief Checks if the binding with specified parameters exists - * - */ -void zb_zdo_check_binding_request(zb_bufid_t param); -/** @} */ - -/** @addtogroup zdo_mgmt - @{ -*/ - -/** @brief Request for Mgmt_Leave_req - @see ZB spec, subclause 2.4.3.3.5. - - Problem in the specification: - in 2.4.3.3.5 Mgmt_Leave_req only one DeviceAddress exists. - But, in such case it is impossible to satisfy 2.4.3.3.5.1: - "The Mgmt_Leave_req is generated from a Local Device requesting that a Remote - Device leave the network or to request that another device leave the network." - Also, in the PRO TC document, 14.2TP/NWK/BV-04 ZR-ZDO-APL RX Join/Leave is - following note: - "gZC sends Mgmt_Leave.request with DevAddr=all zero, DstAddr=ZR" - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_leave_param_s -{ - zb_ieee_addr_t device_address; /*!< 64-bit IEEE address */ - zb_uint16_t dst_addr; /*!< Destination address. Not defined in - * the specification - let's it be short address */ - zb_bitfield_t reserved:6; /*!< Reserve */ - zb_bitfield_t remove_children:1; /*!< Obsolete field */ - zb_bitfield_t rejoin:1; /*!< Rejoin */ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_leave_param_t; - -/** Request for Mgmt_Leave_req. - * @see ZB spec, subclause 2.4.3.3.5. - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_leave_req_s -{ - zb_ieee_addr_t device_address; /*!< 64-bit IEEE address */ - zb_bitfield_t reserved:6; /*!< Reserve */ - zb_bitfield_t remove_children:1; /*!< Obsolete field, should be always 0 according to CSA */ - zb_bitfield_t rejoin:1; /*!< Rejoin */ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_leave_req_t; - -/** @brief Response for Mgmt_Leave_rsp. - * @see ZB spec, subclause 2.4.4.3.5. - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_leave_res_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /**< Operation status. */ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_leave_res_t; - -/** @brief Sends Mgmt_Leave_req - @see ZB spec, subclause 2.4.3.3.2. - - @param param - index of buffer with Lqi request parameters. @ref zb_zdo_mgmt_leave_param_s - @param cb - user's function to call when got response from the remote. - @return - transaction sequence number of request or 0xFF if operation can't be - performed right now (if there is no free slot for registering the callback) - - @b Example: -@code -{ - zb_bufid_t buf = param; - zb_zdo_mgmt_leave_param_t *req = NULL; - zb_ret_t ret = RET_OK; - zb_uint8_t tsn; - - TRACE_MSG(TRACE_ERROR, "zb_leave_req", (FMT__0)); - - req = ZB_BUF_GET_PARAM(buf, zb_zdo_mgmt_leave_param_t); - - ZB_MEMSET(req->device_address, 0, sizeof(zb_ieee_addr_t)); - req->remove_children = ZB_FALSE; - req->rejoin = ZB_FALSE; - req->dst_addr = 1; - tsn = zdo_mgmt_leave_req(param, leave_callback); -} - -void leave_callback(zb_uint8_t param) -{ - zb_zdo_mgmt_leave_res_t *resp = (zb_zdo_mgmt_leave_res_t *)zb_buf_begin(param); - - TRACE_MSG(TRACE_ERROR, "LEAVE CALLBACK status %hd", (FMT__H, resp->status)); -} -@endcode - -*/ -zb_uint8_t zdo_mgmt_leave_req(zb_uint8_t param, zb_callback_t cb); - -/** @} */ -/** @addtogroup zdo_bind - @{ -*/ - - -/** @brief End_Device_Bind_req command head. - * @see ZB spec, subclause 2.4.3.2.1. - */ -typedef ZB_PACKED_PRE struct zb_zdo_end_device_bind_req_head_s -{ - zb_uint16_t binding_target; /*!< The address of the target for the - * binding. This can be either the - * primary binding cache device or the - * short address of the local device. */ - zb_ieee_addr_t src_ieee_addr; /*!< IEEE address of the device generating the request */ - zb_uint8_t src_endp; /*!< The endpoint on the device generating the request */ - zb_uint16_t profile_id; /*!< ProfileID which is to be matched - * between two End_Device_Bind_req - * received at the Zigbee Coordinator */ - zb_uint8_t num_in_cluster; /*!< The number of Input Clusters - * provided for end device binding - * within the InClusterList. */ -} -ZB_PACKED_STRUCT -zb_zdo_end_device_bind_req_head_t; - -/** @brief End_Device_Bind_req command head. - * @see ZB spec, subclause 2.4.3.2.1. - */ -typedef ZB_PACKED_PRE struct zb_zdo_end_device_bind_req_tail_s -{ - zb_uint8_t num_out_cluster; /*!< The number of Output Clusters - * provided for matching within OutClusterList */ -} -ZB_PACKED_STRUCT -zb_zdo_end_device_bind_req_tail_t; - -/** @brief Parameters for End_Device_Bind_req. - * @see ZB spec, subclause 2.4.3.2.1. - */ -typedef ZB_PACKED_PRE struct zb_end_device_bind_req_param_s -{ - zb_uint16_t dst_addr; /*!< Destination address */ - zb_zdo_end_device_bind_req_head_t head_param; /*!< Parameters for command head */ - zb_zdo_end_device_bind_req_tail_t tail_param; /*!< Parameters for command tail */ - zb_uint16_t cluster_list[1]; /*!< List of Input and Output - * ClusterIDs to be used for matching */ -} ZB_PACKED_STRUCT -zb_end_device_bind_req_param_t; - -/** - sends 2.4.3.2.1 End_Device_Bind_req command - @param param - index of buffer with request - @param cb - user's function to call when got response from the remote. - @return ZDP transaction sequence number or - @return 0xFF if operation cannot be performed now (nor enough memory, resources, etc.) -*/ -zb_uint8_t zb_end_device_bind_req(zb_uint8_t param, zb_callback_t cb); - - -/** @brief Response from End_Device_Bind_req. - * @see ZB spec, subclause 2.4.3.2.1. - */ -typedef ZB_PACKED_PRE struct zb_zdo_end_device_bind_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /**< Operation status. */ -} -ZB_PACKED_STRUCT -zb_zdo_end_device_bind_resp_t; - -/** @} */ -/** @addtogroup zdo_mgmt - @{ -*/ - -/** @brief Parameters for Mgmt_Permit_Joining_req. - * @see ZB spec, subclause 2.4.3.3.7. - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_permit_joining_req_s -{ - zb_uint8_t permit_duration; /**< The length of time in seconds. 0x00 and 0xff indicate that - * permission is disabled or enabled - */ - zb_uint8_t tc_significance; /**< If this is set to 0x01 and the remote device is the Trust - * Center, the command affects the - * Trust Center authentication policy as described in the - * sub-clauses below; According to - * r21, should be always set to 0x01. - */ -} ZB_PACKED_STRUCT -zb_zdo_mgmt_permit_joining_req_t; - -/** @brief Parameters for zb_zdo_mgmt_permit_joining_req. */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_permit_joining_req_param_s -{ - zb_uint16_t dest_addr; /**< Destination address */ - zb_uint8_t permit_duration; /**< The length of time in seconds. 0x00 and 0xff indicate that - * permission is disabled or enabled - */ - zb_uint8_t tc_significance; /**< If this is set to 0x01 and the remote device is the Trust - * Center, the command affects the Trust Center authentication - * policy as described in the sub-clauses below; If this is set to - * 0x00, there is no effect on the Trust - * Center. - * Ignored for r21. - */ -} ZB_PACKED_STRUCT -zb_zdo_mgmt_permit_joining_req_param_t; - -/** - @brief sends Mgmt_Permit_Joining_req (See Zigbee spec 2.4.3.3.7) - @param param - Index of buffer with request - @param cb - user's function to call when got response from the remote. - @return ZDP transaction sequence number - @return 0xFF if operation cannot be performed now (nor enough memory, resources, etc.) - - @snippet onoff_server/on_off_switch_zed.c zdo_mgmt_permit_joining_req - - */ -zb_uint8_t zb_zdo_mgmt_permit_joining_req(zb_uint8_t param, zb_callback_t cb); - -/** @} */ -/** @addtogroup zdo_groups - @{ -*/ - - -/** @brief Response from zb_zdo_mgmt_permit_joining_req. */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_permit_joining_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /**< Operation status. */ -} -ZB_PACKED_STRUCT -zb_zdo_mgmt_permit_joining_resp_t; - -/** @brief Not Supported Response */ -typedef ZB_PACKED_PRE struct zb_zdo_not_supported_resp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - zb_uint8_t status; /**< Operation status. */ -} -ZB_PACKED_STRUCT -zb_zdo_not_supported_resp_t; - -/** - * @brief Parameters for Mgmt_NWK_IEEE_Joining_List_req. - * @see ZB r22 spec, subclause 2.4.3.3.11. - */ -typedef struct zb_zdo_mgmt_nwk_ieee_joining_list_param_s -{ - zb_uint8_t start_index; /*!< Starting Index for nwkIeeeJoiningList to be returned */ - zb_uint16_t dst_addr; /*!< destination address */ -} -zb_zdo_mgmt_nwk_ieee_joining_list_param_t; - -/** - * @brief Request for Mgmt_NWK_IEEE_Joining_List_req. - * @see ZB r22 spec, subclause 2.4.3.3.11. - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_nwk_ieee_joining_list_req_s -{ - zb_uint8_t start_index; /*!< Starting Index for nwkIeeeJoiningList to be returned */ -} -ZB_PACKED_STRUCT zb_zdo_mgmt_nwk_ieee_joining_list_req_t; - - -/** - * @brief Response for Mgmt_NWK_IEEE_Joining_List_rsp. - * @see ZB spec, subclause 2.4.4.4.11. - */ -typedef ZB_PACKED_PRE struct zb_zdo_mgmt_nwk_ieee_joining_list_rsp_s -{ - zb_uint8_t tsn; /*!< ZDP transaction sequence number */ - - zb_uint8_t status; /*!< The status of the Mgmt_NWK_IEEE_Joining_List_req command. */ - - zb_uint8_t ieee_joining_list_update_id; - - zb_uint8_t joining_policy; /*profileid == TEST_CUSTOM_PROFILE_ID) - * { - * ptr = ZB_APS_HDR_CUT(param); - * - * TRACE_MSG(TRACE_APS3, "apsde_data_indication: packet %p len %hd status 0x%hx from %d", - * (FMT__P_D_D_D, param, zb_buf_len(param), zb_buf_get_status(param), ind->src_addr)); - * - * for (i = 0 ; i < zb_buf_len(param) ; ++i) - * { - * TRACE_MSG(TRACE_APS3, "%x %c", (FMT__D_C, (int)ptr[i], ptr[i])); - * } - * zb_buf_free(param); - * return ZB_TRUE; - * } - * return ZB_FALSE; - * } - * @endcode - */ -void zb_af_set_data_indication(zb_device_handler_t cb); - -/** - * @brief Perform "Reset with a Local Action" procedure (as described in BDB spec, chapter 9.5). - * The device will perform the NLME leave and clean all Zigbee persistent data except the outgoing NWK - * frame counter and application datasets (if any). - * The reset can be performed at any time once the device is started (see @ref zboss_start). - * After the reset, the application will receive the @ref ZB_ZDO_SIGNAL_LEAVE signal. - * - * @param param - buffer reference (if 0, buffer will be allocated automatically) - */ -void zb_bdb_reset_via_local_action(zb_uint8_t param); - -#if defined ZB_BDB_MODE && !defined BDB_OLD -/** - * @brief Starts TC rejoin procedure - * - * If device doesn't have a TCLK and UnsecureTcRejoinEnabled policy - * is set to ZB_FALSE (this is the default setting), TC rejoin won't - * be performed and ZB_BDB_SIGNAL_TC_REJOIN_DONE signal with RET_ERROR - * status will be raised. - * - * @param param - buffer reference (if 0, buffer will be allocated automatically) - */ -void zb_bdb_initiate_tc_rejoin(zb_uint8_t param); -#endif /* ZB_BDB_MODE && !BDB_OLD */ - -/** @} */ /* af_management_service */ -/*! @} */ - -#endif /* ZB_ZBOSS_API_ZDO_H */ diff --git a/zboss/development/include/zboss_api_zgp.h b/zboss/development/include/zboss_api_zgp.h deleted file mode 100644 index 05b1a93371..0000000000 --- a/zboss/development/include/zboss_api_zgp.h +++ /dev/null @@ -1,2087 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: common definitions for ZGP profile -*/ - -#ifndef ZBOSS_API_ZGP_H -#define ZBOSS_API_ZGP_H 1 - -#include "zb_config.h" -#include "zb_address.h" -#include "zboss_api_buf.h" -#include "zb_types.h" - -/********************************************************************/ -/********* Type declarations specific to ZGP profile ****************/ -/********************************************************************/ - -/** - @addtogroup zgp_common - @{ -*/ - -#define ZGP_ENDPOINT 242 - -/** @brief ZGPD application ID */ -typedef enum zb_zgp_app_id_e -{ - ZB_ZGP_APP_ID_0000 = 0x00, /**< ApplicationID value 0b000 - usage of the SrcID */ - ZB_ZGP_APP_ID_0001 = 0x01, /**< ApplicationID value 0b001 - LPED */ - ZB_ZGP_APP_ID_0010 = 0x02, /**< ApplicationID value 0b010 - usage of the GPD IEEE address.*/ - ZB_ZGP_APP_ID_INVALID = 0x07, /**< Invalid ApplicationID */ -} -zb_zgp_app_id_t; - -/** - * @brief ZGPD address - * - * ZGPD is identified in network whether by SrcId or its IEEE address. */ -typedef ZB_PACKED_PRE union zb_zgpd_addr_u -{ - zb_uint32_t src_id; /**< ZGPD SrcId @see ZGP spec, A.1.4.1.4 */ - zb_ieee_addr_t ieee_addr; /**< ZGPD IEEE address */ -} ZB_PACKED_STRUCT -zb_zgpd_addr_t; - -enum zb_zgp_endpoint_e -{ - ZB_ZGP_COMMUNICATION_ENDPOINT, - ZB_ZGP_ALL_ENDPOINTS = 255 -}; - -/** - * @brief ZGPD identification info (ZGPD ID) - * - * ZGPD is identified by SrcId if ApplicationID is @ref ZB_ZGP_APP_ID_0000. - * Otherwise, ZGPD is identified by its IEEE address. */ -typedef ZB_PACKED_PRE struct zb_zgpd_id_s -{ - zb_uint8_t app_id; /**< One of the @ref zb_zgp_app_id_t values */ - zb_uint8_t endpoint;/**< Identifier of the GPD endpoint, which jointly with the GPD IEEE address identifies a unique logical GPD device.*/ - zb_zgpd_addr_t addr; /**< ZGPD SrcId or IEEE address */ -} ZB_PACKED_STRUCT -zb_zgpd_id_t; - -#define ZGP_ATTR_OPT_GET_REMAINING_LEN(opt) ((opt) & 0xFU) -#define ZGP_ATTR_OPT_GET_REPORTED(opt) (((opt) >> 4U) & 0x1U) -#define ZGP_ATTR_OPT_GET_VAL_PRESENT(opt) (((opt) >> 5U) & 0x1U) - -#define ZB_APP_DESCR_ATTR_VAL_SIZE 8U -typedef struct zgp_attr_record_s -{ - zb_uint16_t id; - zb_uint8_t data_type; - - /* - zb_bitfield_t remaining_len:4; - - 7344 The Reported sub-field is a Boolean flag which indicates if the attribute as identified by the AttributeID - 7345 field is reported by the GPD in operation, or if it is background data required for processing of a report- - 7346 ed attribute only conveyed once at commissioning time. - 7350 If Reported = 0b1, Attribute Offset within Report field is present, otherwise it is absent - - zb_bitfield_t reported:1; - zb_bitfield_t attr_val_present:1; - zb_bitfield_t reserved:2; - */ - zb_uint8_t options; - - /* - 7358 The Attribute Offset within Report field, when present, carries the start position (in bytes) of the data - 7359 point identified by the AttributeID of the ClusterID in the report payload. The Attribute Offset within - 7360 Report = 0x00 corresponds to the octet immediately following the Report identifier field in the pay- - 7361 load of the GPD Compact Attribute Reporting command. - */ - zb_uint8_t offset; - - /* - 7362 The Attribute value field, when present, carries the actual fixed value of that attribute; *the length and - 7363 type of this field are determined by the AttributeID of the ClusterID (in case of manufacturer-specific - 7364 attributes or clusters, corresponding to the ManufacturerID). - */ - zb_uint8_t value[ZB_APP_DESCR_ATTR_VAL_SIZE]; -}zgp_attr_record_t; - -typedef struct zgp_data_point_desc_options_s -{ - zb_bitfield_t attr_records_num:3; - zb_bitfield_t cluster_type:1; /* server == 1, client == 0 */ - zb_bitfield_t manuf_id_present:1; - zb_bitfield_t reserved:3; -}zgp_data_point_desc_options_t; - -#define ZB_APP_DESCR_ATTR_REC_SIZE 4U -typedef struct zgp_data_point_desc_s -{ - zgp_data_point_desc_options_t options; - zb_uint16_t cluster_id; - zb_uint16_t manuf_id; - zgp_attr_record_t attr_records_data[ZB_APP_DESCR_ATTR_REC_SIZE]; /* contains array of not parsed zgp_attr_record_t */ -}zgp_data_point_desc_t; - -typedef struct zgp_report_desc_options_s -{ - zb_bitfield_t timeout_present:1; - zb_bitfield_t reserved:7; -}zgp_report_desc_options_t; - -#define ZB_APP_DESCR_REPORT_DATA_SIZE 32U -typedef ZB_PACKED_PRE struct zgp_report_desc_s -{ - zgp_report_desc_options_t options; - zb_uint16_t timeout; - zb_uint8_t point_descs_data_len; - zb_uint8_t point_descs_data[ZB_APP_DESCR_REPORT_DATA_SIZE]; /* contains array of not parsed zgp_data_point_desc_t */ -}ZB_PACKED_STRUCT zgp_report_desc_t; - -#define SIZE_BY_APP_ID(app_id) (((app_id) == ZB_ZGP_APP_ID_0000) ? 4U : 8U) -#define ZGPD_ID_SIZE(zgpd_id) SIZE_BY_APP_ID((zgpd_id)->app_id) - -#define ZB_ZGPD_IDS_ARE_EQUAL(id1, id2) \ - (((id1)->app_id == (id2)->app_id) && \ - (((id1)->app_id == ZB_ZGP_APP_ID_0000) ? \ - ((id1)->addr.src_id == (id2)->addr.src_id) : \ - (!ZB_MEMCMP(&(id1)->addr.ieee_addr, &(id2)->addr.ieee_addr, sizeof(zb_ieee_addr_t)) &&\ - ((id1)->endpoint == (id2)->endpoint)))) - -/* From ZGP spec, A. 1.4.1.4: - * ZGPD ID value of 0x00000000 indicates unspecified. - * ... 0xffffffff indicates all. - */ -#define ZB_ZGP_SRC_ID_UNSPECIFIED 0x00000000U -#define ZB_ZGP_SRC_ID_ALL (zb_uint32_t)(~0u) - -#define ZB_INIT_ZGPD_ID(zgpd_id) \ -{ \ - (zgpd_id)->app_id = ZB_ZGP_APP_ID_0000; \ - (zgpd_id)->addr.src_id = ZB_ZGP_SRC_ID_UNSPECIFIED; \ -} - -#define ZB_ZGPD_IS_SPECIFIED(zgpd_id) \ - (((zgpd_id)->app_id != ZB_ZGP_APP_ID_0000) \ - || ((zgpd_id)->addr.src_id != ZB_ZGP_SRC_ID_UNSPECIFIED)) - -#define ZB_MAKE_ZGPD_ID(zgpd_id, s_app_id, s_endpoint, s_addr)\ - {\ - (zgpd_id).app_id = (s_app_id);\ - (zgpd_id).endpoint = (s_endpoint);\ - (zgpd_id).addr = (s_addr);\ - } - -/** - * @brief ZGP security level type - * @see ZGP spec, A.1.5.3.2 */ -enum zb_zgp_security_level_e -{ - ZB_ZGP_SEC_LEVEL_NO_SECURITY = 0x00, /**< No security */ - ZB_ZGP_SEC_LEVEL_REDUCED = 0x01, /**< 1LSB of frame counter and short (2B) MIC */ - ZB_ZGP_SEC_LEVEL_FULL_NO_ENC = 0x02, /**< Full (4B) frame counter and full (4B) MIC */ - ZB_ZGP_SEC_LEVEL_FULL_WITH_ENC = 0x03, /**< Encryption & full (4B) frame counter and - full (4B) MIC */ -}; - -/** -The gpSharedSecurityKeyType attribute can take the following values from Table 48: -Table 48 - Values of gpSecurityKeyType - -See also Table 12 - Mapping between the gpSecurityKeyType and the SecurityKey -sub-field of the Extended NWK Frame Control field -*/ -enum zb_zgp_security_key_type_e -{ - ZB_ZGP_SEC_KEY_TYPE_NO_KEY = 0x00, /**< No key */ - ZB_ZGP_SEC_KEY_TYPE_NWK = 0x01, /**< Zigbee NWK key */ - ZB_ZGP_SEC_KEY_TYPE_GROUP = 0x02, /**< ZGPD group key */ - ZB_ZGP_SEC_KEY_TYPE_GROUP_NWK_DERIVED = 0x03, /**< NWK-key derived ZGPD group key */ - ZB_ZGP_SEC_KEY_TYPE_ZGPD_INDIVIDUAL = 0x04, /**< (Individual) out-of-the-box ZGPD key */ - ZB_ZGP_SEC_KEY_TYPE_DERIVED_INDIVIDUAL = 0x07, /**< Derived individual ZGPD key */ -}; - -/********************************************************************/ -/******** ZGP Device Type declarations and configuration ************/ -/********************************************************************/ - -/** - * @brief Possible ZGPD device identifiers - * @see ZGP spec, A.4.3 */ -typedef enum zb_zgpd_dev_id_e -{ - ZB_ZGP_SIMPLE_GEN_1_STATE_SWITCH_DEV_ID = 0x00, /**< Simple Generic 1-state ZGP switch */ - ZB_ZGP_ON_OFF_SWITCH_DEV_ID = 0x02, /**< ZGP On/Off switch */ - ZB_ZGP_LEVEL_CONTROL_SWITCH_DEV_ID = 0x03, /**< ZGP Level Control Switch */ -#define ZB_ZGP_LVL_CTRL_SWITCH_DEV_ID ZB_ZGP_LEVEL_CONTROL_SWITCH_DEV_ID - ZB_ZGP_TEMPERATURE_SENSOR_DEV_ID = 0x30, /**< ZGP temperature sensor */ - ZB_ZGP_ENVIRONMENT_SENSOR_DEV_ID = 0x33, /**< ZGP Temperature + Humidity sensor */ - ZB_ZGP_MANUF_SPECIFIC_DEV_ID = 0xfe, /**< Manufactures-specific; 2 - * more fields in the - * Commissioning frame. See 4.1 - * Manufacturer Specific Green - * Power Device Type Use case - * in Green Power Device - * Manufacturer Specific Device & Command - * Definition Proposal - */ - ZB_ZGP_UNDEFINED_DEV_ID = 0xff, /**< Undefined device type */ -} -zb_zgpd_dev_id_t; - -/** - * @brief Manufacturer-specific device identifiers for GreanPeak - * @see ZGP spec, A.4.3 */ -typedef enum zb_zgpd_manuf_specific_dev_id_e -{ - /* TODO: ZB_ZGP_MS_DOOR_SENSOR_DEV_ID is deprecated. Remove it when there will be - * no testing devices using this type. GreanPeak door sensors use - * ZB_ZGP_MS_DOOR_WINDOW_SENSOR_DEV_ID now. */ - ZB_ZGP_MS_DOOR_SENSOR_DEV_ID = 0x00, /**< IAS Zone - Door Sensor*/ - ZB_ZGP_MS_DOOR_WINDOW_SENSOR_DEV_ID = 0x01, /**< IAS Zone - Door/Window Sensor*/ - ZB_ZGP_MS_LEAKAGE_SENSOR_DEV_ID = 0x02, /**< IAS Zone - Leakage Sensor */ - ZB_ZGP_MS_HUMIDITY_SENSOR_DEV_ID = 0x03, /**< Relative Humidity Sensor */ - ZB_ZGP_MS_MOTION_SENSOR_DEV_ID = 0x05, /**< IAS Zone - Motion sensor */ - ZB_ZGP_MS_MOVEMENT_SENSOR_DEV_ID = 0x07, /**< IAS Zone - Movement sensor */ - ZB_ZGP_MS_SMART_PLUG_DEV_ID = 0X08, /**< GreenPeak Greenpower smart plug */ - ZB_ZGP_MS_KEY_FOB_DEV_ID = 0x0A, /**< GreenPeak Greenpower IAS Zone - Key fob */ - ZB_ZGP_MS_SMOKE_DETECTOR_DEV_ID = 0x0b, /**< IAS Zone - Smoke Detector */ - ZB_ZGP_MS_BED_SENSOR_DEV_ID = 0x0c, /**< IAS Zone - Bed Sensor */ - ZB_ZGP_MS_PARKING_SENSOR_DEV_ID = 0xc0, /**< Occupancy - Parking sensor */ -} -zb_zgpd_manuf_specific_dev_id_t; - -/** - @} -*/ - -/********************************************************************/ -/*********************** Sink definitions ***************************/ -/********************************************************************/ -#if defined ZB_ENABLE_ZGP_SINK || defined DOXYGEN -/** - @addtogroup zgp_sink - @{ -*/ -/** - * @brief Mapping of ZGPD command ID to Zigbee ZCL command ID - */ -typedef struct zgp_to_zb_cmd_mapping_s -{ - zb_uint8_t zgp_cmd_id; /**< ZGPD command ID */ - zb_uint8_t zb_cmd_id; /**< Zigbee ZCL command ID */ -} -zgp_to_zb_cmd_mapping_t; - -#ifdef ZB_ZGP_SINK_SUPPORT_LEGACY_MATCH_INFO -typedef struct zgps_cluster_rec_s -{ - zb_uint16_t cluster_id; /** Cluster ID to which specified ZGPD commands are translated - (see @ref zcl_cluster_id) */ -/** - * Options field of cluster table entry - * - * [0-1] role mask client/server/both. - * Note: this role specifies the original cluster role, not - * the cluster role to which this command will be addressed. - * E.g. for On/Off/Toggle commands it should be client role - * (these command send from client to server). - * - */ - zb_uint8_t options; - zb_uint8_t cmd_ids[ZB_ZGP_MATCH_TBL_MAX_CMDS_FOR_MATCH]; /**< Supported commands by sink */ -} -zgps_dev_cluster_rec_t; - -/** @cond DOXYGEN_INTERNAL_DOC */ -#define GET_CLUSTER_ROLE(cluster) \ - (cluster->options & 0x03U) - -typedef ZB_PACKED_PRE union zgps_device_id_u -{ - /* dev_id.zgpd_dev_id matches with ZGPD Device ID from Commissioning frame @see zb_zgpd_dev_id_t */ - zb_uint8_t zgpd_dev_id; - /* match with app_info.manuf_model_id. */ - zb_uint16_t zgpd_manuf_model; -} -zgps_device_id_t; - -typedef ZB_PACKED_PRE struct zgps_dev_match_rec_s -{ - /* Cluster idxes possible for that device id. Not used slots must be filled by ZB_ZCL_CLUSTER_IDX_UNDEFINED. - Cluster idx - index in zgps_dev_cluster_rec_t clusters_tbl[]. - */ - zb_uint16_t clusters[ZB_ZGP_TBL_MAX_CLUSTERS]; - zb_uint16_t manuf_id; - /* match with device info from Commissioning frame: - if zgpd_dev_id != ZB_ZGP_MANUF_SPECIFIC_DEV_ID, match by GPD Device id - if zgpd_dev_id == ZB_ZGP_MANUF_SPECIFIC_DEV_ID, match by app_info.manuf_model_id - */ - zgps_device_id_t dev_id; -} -ZB_PACKED_STRUCT zgps_dev_match_rec_t; - -#define IS_STANDART_ZGPS_DEVICE(dev_match_rec) \ - (dev_match_rec->manuf_id == ZB_ZGPD_MANUF_ID_UNSPEC) -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - - -/* - Using of match table. - - Match table is a static const data declared in the application. - - During GPD commissioning, using information from Commissiponing frame, ZBOSS seeks for matched entry in match_tbl. - Match is done by device id or model id - see calls to zb_zgps_get_dev_matching_tbl_index() - Entry index is written into the Sink table. - - Command translation (without details about attr reporting): - - get Sink table entry by GPD address - - get matxh_tbl entry by index in Sink table. - - scan entire match_tbl[]: use match_tbl[i].clusters as an index in clusters_tbl. - - in each clusters_tbl entry scan clusters_tbl[i].cmd_ids[] for matching GPD command - - seek for appropriate clister in out local Simple desc (decide which EP to map to) - - map GPD command to ZCL command by scanning cmd_mapping[] - */ - -/** - * @brief Necessary information for filling translation table for any ZGPD - * during commissioning - * - * Includes matching table and command ID mappings. Given some ZGPD device ID it is - * possible to fill translation table entry with help of this structure. - */ -typedef struct zb_zgps_match_info_s -{ - const zb_uint8_t match_tbl_size; - /* clusters list to be matched by device id or manufacturer id got from Commissioning frame. */ - const ZB_CODE zgps_dev_match_rec_t *match_tbl; - const zb_uint8_t cmd_mappings_count; - const ZB_CODE zgp_to_zb_cmd_mapping_t *cmd_mapping; - const zb_uint8_t clusters_tbl_size; - /* clusters table used to translate ZB_GPDF_CMD_ATTR_REPORT / ZB_GPDF_CMD_MANUF_SPEC_ATTR_REPORT */ - const ZB_CODE zgps_dev_cluster_rec_t *clusters_tbl; -} -zb_zgps_match_info_t; -#endif /* ZB_ZGP_SINK_SUPPORT_LEGACY_MATCH_INFO */ - -/* - Using of Translation Table. - - By default, ZBOSS contains generic translation rules functionality according to the specification. - - Translation Table is a specific translation rules declared in the application. - The specific translation supersedes the generic one. - - The application MAY or MAY not to declare Translation Table. - If application declares Translation Table it SHOULD persist this data by its own. - - Translation Table entries SHALL be added upon successful completion of proximity and multi-hop commissioning, - and upon reception of GP Pairing Configuration leading to Sink Table entry creation (as described in A.3.5.2.5); - those entries SHALL then contain the ApplicationID and GPD ID type and value of the GPD ID (and GPD Endpoint, - matching or 0x00 or 0xff, if ApplicationID = 0b010) for which they are created; - mapping the GPD commands to their ZCL equivalents. - - Supported features: - - - There SHOULD be only one entry in the GPD Command Translation Table for each - (GPD ID, GPD Endpoint, GPD Command, EndPoint, Zigbee Profile, Zigbee Cluster) tuple. - - For a single GPD ID (and GPD Endpoint, if ApplicationID = 0b010), there MAY be multiple - entries, e.g. for multiple GPD commands. - - GPD Command: - - If the GPD Command field is set to 0xAF, all of the following GPD sensor report commands: 0xA0 – 0xA3 are supported. - - If the GPD Command field is set to 0xFF, it indicates all GPD commands. - - Zigbee Endpoint: - - If the EndPoint field is set to 0xfd, there are no paired endpoints. - - If the EndPoint field is set to 0xff, all matching endpoints are paired. - - If the EndPoint field is set to 0xfc, the raw GPD command is passed up to the application, - and no translation is performed in the GPEP. - - Zigbee Cluster: - - If the Zigbee Cluster field is set to 0xffff, the ClusterID from the triggering GPD command is to be used. - - If the Zigbee Cluster field is set to value other than 0xffff, then for GPD command carrying - a ClusterID field (as e.g. for the GPD commands 0xA0 – 0xA3), the two ClusterID values SHALL exactly match. - - ZCL Payload Length: - - If the Length sub-field of the Zigbee Command payload field is set to 0x00, - the Payload sub-field is not present, and the Zigbee command is sent without payload. - - If the Length sub-field of the Zigbee Command payload field is set to 0xff, - the Payload sub-field is not present, and the payload from the triggering GPD command - is to be copied verbatim into the Zigbee command. - - If the Length sub-field of the Zigbee Command payload field is set to 0xfe, - the Payload sub-field is not present, and the payload from the triggering GPD command needs to be parsed. - - For all other values of the Length sub-field, the Payload sub-field is present, - has a length as defined in the Length sub-field and specifies the payload to be used. - - Not supported features: - - - For a single GPD ID (and GPD Endpoint, if ApplicationID = 0b010), - the same GPD Command could result in different translated Zigbee CommandIDs, - for different EndPoint, Profile and Cluster values. - - For a single GPD ID, if ApplicationID = 0b010, there MAY be multiple entries, - for multiple GPD Endpoints, even for identical GPD commands. - - The Additional information block field is not supported yet. - */ - -#define ZB_ZGP_TRANSLATION_ENTRY_ENDPOINT_PASS_RAW_GPDF_TO_APP (0xfc) -#define ZB_ZGP_TRANSLATION_ENTRY_ENDPOINT_NO_PAIRS (0xfd) -#define ZB_ZGP_TRANSLATION_ENTRY_ENDPOINT_ALL_ARE_MATCHED (0xff) - -#define ZB_ZGP_TRANSLATION_ENTRY_NO_PAYLOAD (0x00) -#define ZB_ZGP_TRANSLATION_ENTRY_GPDF_PAYLOAD (0xff) -#define ZB_ZGP_TRANSLATION_ENTRY_PARSED_PAYLOAD (0xfe) - -typedef ZB_PACKED_PRE struct zb_zgps_translation_payload_s -{ - zb_uint8_t length; - zb_uint8_t data[]; -} ZB_PACKED_STRUCT zb_zgps_translation_payload_t; - -/** - * @brief Translation table entry structure - */ -typedef ZB_PACKED_PRE struct zb_zgps_translation_entry_s -{ - zb_uint8_t options; /**< Options related to this table entry */ - zb_zgpd_addr_t gpd_id; /**< Identifier of the GPD */ - zb_uint8_t gpd_endpoint; - zb_uint8_t gpd_command; /**< The GPD command to be translated */ - zb_uint8_t endpoint; /**< The EndPoint for which the translation is valid */ - zb_uint16_t profile; /**< The Profile of the command after translation */ - zb_uint16_t cluster; /**< The cluster of the Profile on the endpoint */ - zb_uint8_t zcl_command; /**< The Command ID of the Cluster into which GP Command is translated */ - zb_zgps_translation_payload_t zcl_payload; /**< The payload for the Zigbee Command */ -} ZB_PACKED_STRUCT zb_zgps_translation_entry_t; - -/** @cond DOXYGEN_INTERNAL_DOC */ -void zb_zgps_set_translation_table(const zb_zgps_translation_entry_t * table, zb_uint_t table_size); -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** - * @ingroup zgp_sink - * @brief Set translation table information that is used to fill ZGP command - ZCL - * cluster translation table. - * @param [in] table Translation information, array of type @ref zb_zgps_translation_entry_t - * @param [in] table_size Size if the table in count of entries that can be iterated - */ -#define ZB_ZGP_SET_TRANSLATION_TABLE(table, table_size) \ -{ \ - zb_zgps_set_translation_table((table), (table_size)); \ -} -/** @} */ /* zgp_sink */ -#endif /* ZB_ENABLE_ZGP_SINK */ - -#ifdef ZB_ENABLE_ZGP_DIRECT -enum zb_zgp_data_handle_e -{ - ZB_ZGP_HANDLE_DEFAULT_HANDLE, - ZB_ZGP_HANDLE_REMOVE_CHANNEL_CONFIG, - ZB_ZGP_HANDLE_REMOVE_COMMISSIONING_REPLY, - ZB_ZGP_HANDLE_ADD_COMMISSIONING_REPLY, - ZB_ZGP_HANDLE_ADD_CHANNEL_CONFIG, - ZB_ZGP_HANDLE_REMOVE_AFTER_FAILED_COMM, - ZB_ZGP_HANDLE_REMOVE_BY_USER_REQ, - -/** - * The first handle that can be used by application for gp-data.req primitives. - * Application may use any greater or equal handle value to match request with - * confirmation. - * - * @see zb_zgps_send_data(). - */ - ZB_ZGP_HANDLE_APP_DATA, -}; - -#define ZB_GP_TX_QUEUE_ENTRY_LIFETIME_NONE ZB_MIN_TIME_VAL -#define ZB_GP_TX_QUEUE_ENTRY_LIFETIME_INF ZB_MAX_TIME_VAL - -#define ZB_GP_DATA_REQ_USE_GP_TX_QUEUE 0x01U -#define ZB_GP_DATA_REQ_USE_CSMA_CA_BIT 0x02U -#define ZB_GP_DATA_REQ_USE_MAC_ACK_BIT 0x04U -#define ZB_GP_DATA_REQ_MAINT_FRAME_TYPE 0x08U - -#define ZB_GP_DATA_REQ_FRAME_TYPE(tx_opt) \ - ((tx_opt >> 3) & 0x03) - -#define ZB_GP_DATA_REQ_ACTION_REMOVE_GPDF ZB_FALSE -#define ZB_GP_DATA_REQ_ACTION_ADD_GPDF ZB_TRUE - -#define ZB_CGP_DATA_REQ_USE_CSMA_CA_BIT 0x01 -#define ZB_CGP_DATA_REQ_USE_MAC_ACK_BIT 0X02 - -#endif /* ZB_ENABLE_ZGP_DIRECT */ - -/********************************************************************/ -/*********************** Proxy definitions **************************/ -/********************************************************************/ - -/** - @addtogroup zgp_common - @{ -*/ - -/** Values of gpsCommunicationMode attribute - * Table 27 -*/ -typedef enum zgp_communication_mode_e -{ - ZGP_COMMUNICATION_MODE_FULL_UNICAST = 0, - /*Groupcast - one of the communication modes used for tunneling GPD commands between the - proxies and sinks. In Zigbee terms, it is the APS level multicast, with NWK level broadcast to the - RxOnWhenIdle=TRUE (0xfffd) broadcast address.*/ - ZGP_COMMUNICATION_MODE_GROUPCAST_DERIVED = 1, - ZGP_COMMUNICATION_MODE_GROUPCAST_PRECOMMISSIONED = 2, - ZGP_COMMUNICATION_MODE_LIGHTWEIGHT_UNICAST = 3 -} zgp_communication_mode_t; - -/* A.3.3.2.4 gpsCommissioningExitMode attribute */ -typedef enum zgp_commissioning_exit_mode_e -{ - ZGP_COMMISSIONING_EXIT_MODE_ON_COMMISSIONING_WINDOW_EXPIRATION = (1<<0), - ZGP_COMMISSIONING_EXIT_MODE_ON_PAIRING_SUCCESS = (1<<1), - ZGP_COMMISSIONING_EXIT_MODE_ON_GP_PROXY_COMMISSIONING_MODE_EXIT = (1<<2), - ZGP_COMMISSIONING_EXIT_MODE_ON_CWE_OR_PS = (ZGP_COMMISSIONING_EXIT_MODE_ON_COMMISSIONING_WINDOW_EXPIRATION | - ZGP_COMMISSIONING_EXIT_MODE_ON_PAIRING_SUCCESS), - ZGP_COMMISSIONING_EXIT_MODE_ON_CWE_OR_PCM = (ZGP_COMMISSIONING_EXIT_MODE_ON_COMMISSIONING_WINDOW_EXPIRATION | - ZGP_COMMISSIONING_EXIT_MODE_ON_GP_PROXY_COMMISSIONING_MODE_EXIT), - ZGP_COMMISSIONING_EXIT_MODE_ALL = (ZGP_COMMISSIONING_EXIT_MODE_ON_COMMISSIONING_WINDOW_EXPIRATION | - ZGP_COMMISSIONING_EXIT_MODE_ON_PAIRING_SUCCESS | - ZGP_COMMISSIONING_EXIT_MODE_ON_GP_PROXY_COMMISSIONING_MODE_EXIT) -} zgp_commissioning_exit_mode_t; - -/*! @} */ - -/********************************************************************/ -/******************** Commissioning definitions *********************/ -/********************************************************************/ - -/** - @addtogroup zgp_common - @{ -*/ - -/** - * @brief Possible commissioning result - */ -typedef enum zb_zgp_comm_status_e -{ - /** Commissioning with some device completed successfully */ - ZB_ZGP_COMMISSIONING_COMPLETED, - /** Commissioning failed. The reason can be: - * - parameters of connection can't be negotiated - * - ZGPD device behaves incorrectly - * - Maximum number of connected ZGPDs is reached */ - ZB_ZGP_COMMISSIONING_FAILED, - /** Commissioning failed, because of timeout */ - ZB_ZGP_COMMISSIONING_TIMED_OUT, - /** No functionality match with commissioning device is found. - * Maybe matching table is not provided by user application */ - ZB_ZGP_COMMISSIONING_NO_MATCH_ERROR, - /** Commissioning failed, because some internal error occurred in stack. - * This type of error is recoverable, so next commissioning attempt can - * be successful */ - ZB_ZGP_COMMISSIONING_INTERNAL_ERROR, - /** Commissioning failed, because some critical error has occurred. - * Normal functioning of ZGP subsystem is not possible - * (e.g. physical operational channel can't be changed) */ - ZB_ZGP_COMMISSIONING_CRITICAL_ERROR, - /** User cancelled commissioning by calling zb_zgps_stop_commissioning() */ - ZB_ZGP_COMMISSIONING_CANCELLED_BY_USER, - /** ZGPD sent Decommissioning command */ - ZB_ZGP_ZGPD_DECOMMISSIONED, -} -zb_zgp_comm_status_t; - -#if defined ZB_ENABLE_ZGP_SINK || defined DOXYGEN -/** @cond DOXYGEN_INTERNAL_DOC */ -/** - * @brief Commissioning callback type - * - * @note this is legacy API. Use ZB_ZGP_SIGNAL_COMMISSIONING signal passed to - * zboss_signal_handler instead! - * - * Commissioning callback notifies user about commissioning complete. So, ZGP - * device is in the operational mode at the time of calling this callback. - * Result variable carries the status of commissioning: whether some device - * successfully commissioned or not. - */ -typedef void (ZB_CODE * zb_zgp_comm_completed_cb_t)( - zb_zgpd_id_t *zgpd_id, - zb_zgp_comm_status_t result); -/** @endcond */ - -/** - * @brief Commissioning request callback type - * - * Commissioning request callback notifies application about commissioning - * attempt from ZGPD. Callback is called when ZGPD sends commissioning frame. - * Callback provides to user ZGPD ID and ZGPD Device ID. Based on these - * parameters user application should decide whether commissioning procedure - * should be continued or not. - * - * Commissioning request callback should be set during ZGP initialization using - * @ref ZB_ZGP_REGISTER_COMM_REQ_CB macro. If callback is not registered, then - * ZBOSS accepts all incoming commissioning attempts. - * - * @param zgpd_id [in] ZGPD ID - * @param device_id [in] ZGPD device ID - * @param manuf_id [in] Manufacturer ID (meaningful if device_id = 0xFE or 0xFF) - * @param manuf_model_id [in] Manufacturer model ID (meaningful if device_id = 0xFE or 0xFF) - * @param ieee_addr [in] ZGPD long IEEE address if available, otherwise filled with zeroes - * - * @see zb_zgps_accept_commissioning - * @see ZB_IS_64BIT_ADDR_ZERO - */ -typedef void (ZB_CODE * zb_zgp_comm_req_cb_t)( - zb_zgpd_id_t *zgpd_id, - zb_uint8_t device_id, - zb_uint16_t manuf_id, - zb_uint16_t manuf_model_id, - zb_ieee_addr_t ieee_addr); - -/*! @} */ - -/** - @cond internals_doc - @addtogroup zgp_internal - @{ -*/ - -/** - * @brief Application confirm callback type - * - * Application confirm callback notifies application about data - * request attempt to ZGPD. Callback is called when data frame is sent - * to ZGPD. Callback provides to command ID and its status. Based on these - * parameters user application should decide further actions. - * - * Application confirm callback should be set during ZGP initialization using - * @ref ZB_ZGP_REGISTER_APP_CFM_CB macro. - * - * @param cmd_id [in] Command ID - * @param status [in] Confirmation status - * @param data_ptr [in] Pointer to data payload - * @param zgpd_id [in] ZGPD ID - * @param handle [in] ZGP handle - */ -typedef void (ZB_CODE * zb_zgp_app_cfm_cb_t)( - zb_uint8_t cmd_id, - zb_int16_t status, - zb_uint8_t *data_ptr, - zb_zgpd_id_t *zgpd_id, - zb_uint8_t handle); - -/*! @} */ -/*! @endcond */ - - -/** - @addtogroup zgp_sink - @{ -*/ - - /** - * @brief Application callback, indication of the attempted commissioning in GPS operational mode. - * - * Application commissioning indication callback notifies application about commissioning - * attempt from ZGPD. Callback is called when commissioning frame or notification is received - * from ZGPD. Callback provides to zgpd_id and full incoming packet's data. Based on these - * parameters user application should decide further actions. - * - * Application commissioning indication callback should be set during ZGP initialization using - * @ref ZB_ZGP_REGISTER_APP_CIC_CB macro. - * - * @param zgpd_id [in] ZGPD ID - * @param param [in] buffer index, containing GPDF - */ -typedef void (ZB_CODE * zb_zgp_app_comm_ind_cb_t)( - zb_zgpd_id_t *zgpd_id, - zb_uint8_t param); - - -/*! @} */ - -/** - @addtogroup zgp_sink - @{ -*/ -#ifdef ZB_ZGP_SINK_SUPPORT_LEGACY_MATCH_INFO -/** @cond DOXYGEN_INTERNAL_DOC */ -void zb_zgps_set_match_info(const zb_zgps_match_info_t *info); -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -/** - * @ingroup zgp_sink - * @brief Set matching information that is used to fill ZGP command - ZCL - * cluster translation table. - * @param [in] info Matching information of type @ref zb_zgps_match_info_t - */ -#define ZB_ZGP_SET_MATCH_INFO(info) \ -{ \ - zb_zgps_set_match_info((info)); \ -} -#endif /* ZB_ZGP_SINK_SUPPORT_LEGACY_MATCH_INFO */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -void zb_zgps_register_comm_req_cb(zb_zgp_comm_req_cb_t cb); -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -/** - * @ingroup zgp_sink - * @brief Register commissioning request callback - * - * @param cb [in] Commissioning request callback (@ref zb_zgp_comm_req_cb_t) - * - * @if DOXIGEN_INTERNAL_DOC - * @snippet tests/zgp/gppb/test_gps_decommissioning/dut_gps.c accept_comm - * @endif - */ -#define ZB_ZGP_REGISTER_COMM_REQ_CB(cb) \ -{ \ - zb_zgps_register_comm_req_cb((cb)); \ -} - -/** @cond DOXYGEN_INTERNAL_DOC */ -void zb_zgps_register_app_cic_cb(zb_zgp_app_comm_ind_cb_t cb); -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ -/** - * @ingroup zgp_sink - * @brief Register application commissioning indication callback - * - * @param cb [in] Application commissioning indication callback (@ref zb_zgp_app_comm_ind_cb_t) - */ -#define ZB_ZGP_REGISTER_APP_CIC_CB(cb) \ -{ \ - zb_zgps_register_app_cic_cb((cb)); \ -} - -/*! @} */ -/** - @cond internals_doc - @addtogroup zgp_internal - @{ -*/ - -/** - * @brief Register application confirm callback - * - * @param cb [in] Application confirm callback (@ref zb_zgp_app_cfm_cb_t) - */ -void zb_zgps_register_app_cfm_cb(zb_zgp_app_cfm_cb_t cb); -#define ZB_ZGP_REGISTER_APP_CFM_CB(cb) \ -{ \ - zb_zgps_register_app_cfm_cb((cb)); \ -} - -/*! @} */ -/*! @endcond */ - -/** - @addtogroup zgp_common - @{ -*/ -#endif /* ZB_ENABLE_ZGP_SINK */ - -enum zb_zgpd_switch_type_e -{ - ZB_GPD_SWITCH_TYPE_BUTTON = 0x01, /* 0b01 */ - ZB_GPD_SWITCH_TYPE_ROCKER = 0x02, /* 0b10 */ -}; -/********************************************************************/ -/********************* GPDF command IDs *****************************/ -/********************************************************************/ - -/** - * @brief Command identifiers sent from or to ZGPD */ -enum zb_zgpd_cmd_id_e -{ - /* identify */ - ZB_GPDF_CMD_IDENTIFY = 0x00, - /* 0x01 – 0x0F: Reserved */ - /* scenes */ - ZB_GPDF_CMD_RECALL_SCENE0 = 0x10, - ZB_GPDF_CMD_RECALL_SCENE1 = 0x11, - ZB_GPDF_CMD_RECALL_SCENE2 = 0x12, - ZB_GPDF_CMD_RECALL_SCENE3 = 0x13, - ZB_GPDF_CMD_RECALL_SCENE4 = 0x14, - ZB_GPDF_CMD_RECALL_SCENE5 = 0x15, - ZB_GPDF_CMD_RECALL_SCENE6 = 0x16, - ZB_GPDF_CMD_RECALL_SCENE7 = 0x17, - /* @note recall scene 8-11 are got from LCGW. But GPPB specification - * does not define recall scenes 8-11. Only 8 scenes are - * supported. See Table 49 Payloadless GPDF commands 6236 sent by - * GPD */ - ZB_GPDF_CMD_RECALL_SCENE8 = 0x18, - ZB_GPDF_CMD_RECALL_SCENE9 = 0x19, - ZB_GPDF_CMD_RECALL_SCENE10 = 0x1A, - ZB_GPDF_CMD_RECALL_SCENE11 = 0x1B, -#define ZB_GPDF_CMD_STORE_SCENE0 ZB_GPDF_CMD_RECALL_SCENE8 -#define ZB_GPDF_CMD_STORE_SCENE1 ZB_GPDF_CMD_RECALL_SCENE9 -#define ZB_GPDF_CMD_STORE_SCENE2 ZB_GPDF_CMD_RECALL_SCENE10 -#define ZB_GPDF_CMD_STORE_SCENE3 ZB_GPDF_CMD_RECALL_SCENE11 - ZB_GPDF_CMD_STORE_SCENE4 = 0x1C, - ZB_GPDF_CMD_STORE_SCENE5 = 0x1D, - ZB_GPDF_CMD_STORE_SCENE6 = 0x1E, - ZB_GPDF_CMD_STORE_SCENE7 = 0x1F, - /* on/off */ - ZB_GPDF_CMD_OFF = 0x20, - ZB_GPDF_CMD_ON = 0x21, - ZB_GPDF_CMD_TOGGLE = 0x22, - /* ------- */ - ZB_GPDF_CMD_RELEASE = 0x23, - /* 0x24 – 0x2F: Reserved */ - /* level control */ - ZB_GPDF_CMD_MOVE_UP = 0x30, - ZB_GPDF_CMD_MOVE_DOWN = 0x31, - ZB_GPDF_CMD_STEP_UP = 0x32, - ZB_GPDF_CMD_STEP_DOWN = 0x33, - ZB_GPDF_CMD_LC_STOP = 0x34, -#define ZB_GPDF_CMD_LVL_CTRL_STOP ZB_GPDF_CMD_LC_STOP - ZB_GPDF_CMD_MOVE_UP_W_ONOFF = 0x35, -#define ZB_GPDF_CMD_MOVE_UP_WITH_ON_OFF ZB_GPDF_CMD_MOVE_UP_W_ONOFF - ZB_GPDF_CMD_MOVE_DOWN_W_ONOFF = 0x36, -#define ZB_GPDF_CMD_MOVE_DOWN_WITH_ON_OFF ZB_GPDF_CMD_MOVE_DOWN_W_ONOFF - ZB_GPDF_CMD_STEP_UP_W_ONOFF = 0x37, -#define ZB_GPDF_CMD_MOVE_STEP_ON ZB_GPDF_CMD_STEP_UP_W_ONOFF - ZB_GPDF_CMD_STEP_DOWN_W_ONOFF = 0x38, -#define ZB_GPDF_CMD_MOVE_STEP_OFF ZB_GPDF_CMD_STEP_DOWN_W_ONOFF - /* 0x39 – 0x3F: Reserved */ - /* Color Control */ - ZB_GPDF_CMD_MOVE_HUE_STOP = 0x40, - ZB_GPDF_CMD_MOVE_HUE_UP = 0x41, - ZB_GPDF_CMD_MOVE_HUE_DOWN = 0x42, - ZB_GPDF_CMD_STEP_HUE_UP = 0x43, - ZB_GPDF_CMD_STEP_HUE_DOWN = 0x44, - ZB_GPDF_CMD_MOVE_SATURATION_STOP = 0x45, - ZB_GPDF_CMD_MOVE_SATURATION_UP = 0x46, - ZB_GPDF_CMD_MOVE_SATURATION_DOWN = 0x47, - ZB_GPDF_CMD_STEP_SATURATION_UP = 0x48, - ZB_GPDF_CMD_STEP_SATURATION_DOWN = 0x49, - ZB_GPDF_CMD_MOVE_COLOR = 0x4A, - ZB_GPDF_CMD_STEP_COLOR = 0x4B, - /* 0x4C – 0x4F: Reserved */ - /* Door Lock */ - ZB_GPDF_CMD_LOCK_DOOR = 0x50, - ZB_GPDF_CMD_UNLOCK_DOOR = 0x51, - /* 0x52 – 0x5F: Reserved */ - /* Simple Generic Switch */ - ZB_GPDF_CMD_PRESS_1_OF_1 = 0x60, - ZB_GPDF_CMD_RELEASE_1_OF_1 = 0x61, - ZB_GPDF_CMD_PRESS_1_OF_2 = 0x62, - ZB_GPDF_CMD_RELEASE_1_OF_2 = 0x63, - ZB_GPDF_CMD_PRESS_2_OF_2 = 0x64, - ZB_GPDF_CMD_RELEASE_2_OF_2 = 0x65, - ZB_GPDF_CMD_SHORT_PRESS_1_OF_1 = 0x66, - ZB_GPDF_CMD_SHORT_PRESS_1_OF_2 = 0x67, - ZB_GPDF_CMD_SHORT_PRESS_2_OF_2 = 0x68, - - ZB_GPDF_CMD_8BIT_VECTOR_PRESS = 0x69, - ZB_GPDF_CMD_8BIT_VECTOR_RELEASE = 0x6A, - /* 0x6b-0x6f: Reserved */ - /* 0x70-0x9f: Reserved */ - ZB_GPDF_CMD_ATTR_REPORT = 0xA0, - ZB_GPDF_CMD_MANUF_SPEC_ATTR_REPORT = 0xA1, - ZB_GPDF_CMD_MULTI_CLUSTER_ATTR_REPORT = 0xA2, - ZB_GPDF_CMD_MANUF_SPEC_MULTI_CLUSTER_ATTR_REPORT = 0xA3, - ZB_GPDF_CMD_REQUEST_ATTRIBUTES = 0xA4, - ZB_GPDF_CMD_READ_ATTR_RESP = 0xA5, - - ZB_GPDF_CMD_ZCL_TUNNELING_FROM_ZGPD = 0xA6, - /* 0xA7: Reserved */ - ZB_GPDF_CMD_COMPACT_ATTR_REPORTING = 0xA8, - /* 0xA9 – 0xAE: Reserved */ - ZB_GPDF_CMD_ATTR_REPORT_ANY = 0xAF, - /* Manufacturer-defined GPD commands (payload is manufacturer-specific) */ - ZB_GPDF_CMD_MANUF_DEFINED_B0 = 0xB0, - /* 0xB1 - 0xBE: Manufacturer-defined GPD commands (payload is manufacturer-specific) */ - ZB_GPDF_CMD_MANUF_DEFINED_BF = 0xBF, - /* 0xC0 - 0xDF: Reserved */ - /* commissioning from ZGPD */ - ZB_GPDF_CMD_COMMISSIONING = 0xE0, - ZB_GPDF_CMD_DECOMMISSIONING = 0xE1, - ZB_GPDF_CMD_SUCCESS = 0xE2, - ZB_GPDF_CMD_CHANNEL_REQUEST = 0xE3, - ZB_GPDF_CMD_APPLICATION_DESCR = 0xE4, - /* 0xE5 – 0xEF: Reserved */ - /* GPDF commands sent to GPD */ - ZB_GPDF_CMD_COMMISSIONING_REPLY = 0xF0, - ZB_GPDF_CMD_WRITE_ATTRIBUTES = 0xF1, - ZB_GPDF_CMD_READ_ATTRIBUTES = 0xF2, - ZB_GPDF_CMD_CHANNEL_CONFIGURATION = 0xF3, - /* 0xF4 – 0xF5: Reserved for other commands sent to the GPD */ - ZB_GPDF_CMD_ZCL_TUNNELING_TO_ZGPD = 0xF6, - /* 0xF7 – 0xFF: Reserved for other commands sent to the GPD */ -}; - -#define ZB_GPDF_CMD_IS_SCENE_CMD(_cmd_id) \ - ((_cmd_id) >= ZB_GPDF_CMD_RECALL_SCENE0 && \ - (_cmd_id) <= ZB_GPDF_CMD_STORE_SCENE7) - -#define ZB_GPDF_CMD_IS_RECALL_SCENE(_cmd_id) \ - ((_cmd_id) >= ZB_GPDF_CMD_RECALL_SCENE0 && \ - (_cmd_id) <= ZB_GPDF_CMD_RECALL_SCENE7) - -#define ZB_GPDF_CMD_IS_STORE_SCENE(_cmd_id) \ - ((_cmd_id) >= ZB_GPDF_CMD_STORE_SCENE0 && \ - (_cmd_id) <= ZB_GPDF_CMD_STORE_SCENE1) - -/*! @} */ - -/********************************************************************/ -/**************** Macros for sending GPDF packets *******************/ -/********************************************************************/ - -/** - @cond internal - @addtogroup zgp_internal - @{ -*/ - - -/** - * @brief Start constructing GPDF packet - * - * @param [in] zbbuf Buffer for GPDF packet - */ -#define ZB_START_GPDF_PACKET(zbbuf) \ - zb_buf_reuse(zbbuf) - -/** - * @brief Put 1 byte into GPDF packet - * - * @param ptr [in] Destination memory address, where val should be copied - * @param val [in] Pointer to 1-byte value to be put in packet - */ -#define ZB_GPDF_PUT_UINT8(ptr, val) \ - ( *(ptr) = (val), (ptr)++ ) - -/** - * @brief Put 2 bytes into GPDF packet - * - * @param ptr [in] Destination memory address, where val should be copied - * @param val [in] Pointer to 2-byte value to be put in packet - */ -#define ZB_GPDF_PUT_UINT16(ptr, val) \ - ( ZB_HTOLE16((ptr), (val)), (ptr) += 2 ) - - -/** - * @brief Put 4 bytes into GPDF packet - * - * @param ptr [in] Destination memory address, where val should be copied - * @param val [in] Pointer to 4-byte value to be put in packet - */ -#define ZB_GPDF_PUT_UINT32(ptr, val) \ - ( ZB_HTOLE32((ptr), (val)), (ptr) += 4 ) - - -/** - * @brief Finish constructing GPDF frame - * - * @param zbbuf [in] Buffer with GPDF - * @param ptr [in] Pointer to the GPDF tail - */ -void zb_finish_gpdf_packet(zb_bufid_t buf_ref, zb_uint8_t** ptr); -#define ZB_FINISH_GPDF_PACKET(zbbuf, ptr) zb_finish_gpdf_packet(zbbuf, &ptr) - - -/** - * @brief RX channel in the next attempt parameter of ZGPD Channel request command - * @see ZGP spec, A.4.2.1.4 - */ -#define ZB_GPDF_CHANNEL_REQ_NEXT_RX_CHANNEL(par) \ - ((par) & 0x0FU) - - -typedef struct zb_gpdf_comm_app_info_options_s -{ - zb_bitfield_t manuf_id_present:1; - zb_bitfield_t manuf_model_id_present:1; - zb_bitfield_t gpd_cmds_present:1; - zb_bitfield_t cluster_list_present:1; - zb_bitfield_t switch_info_present:1; - zb_bitfield_t app_descr_flw:1; - zb_bitfield_t reserved:2; -}zb_gpdf_comm_app_info_options_t; - -typedef ZB_PACKED_PRE struct zb_gpdf_comm_switch_gen_cfg_s -{ - zb_bitfield_t num_of_contacts:4; - zb_bitfield_t switch_type:2; - zb_bitfield_t reserved:2; -}ZB_PACKED_STRUCT zb_gpdf_comm_switch_gen_cfg_t; - -/* DEPRECATED: Typo in structure field was fixes - - * old name, with the typo, will be removed in the next Major release */ -#define num_of_contacs num_of_contacts - -typedef struct zb_gpdf_comm_switch_info_s -{ - zb_uint8_t len; /**< Length of switch info */ - zb_gpdf_comm_switch_gen_cfg_t configuration; - zb_uint8_t current_contact_status; -}zb_gpdf_comm_switch_info_t; - -typedef struct zb_gpdf_comm_app_info_s -{ - zb_gpdf_comm_app_info_options_t options; - - zb_uint16_t manuf_id; /**< Manufacturer ID */ - zb_uint16_t manuf_model_id; /**< Manufacturer model ID */ - - zb_uint8_t gpd_cmds_len; /**< Number of GPD commands */ - /* ToDo: implement GPD commands list */ - - zb_bitfield_t srv_cluster_num:4; /**< Number of server clusterIDs */ - zb_bitfield_t client_cluster_num:4; /**< Number of client clusterIDs */ - /* ToDo: implement server/client cluster list */ - - zb_gpdf_comm_switch_info_t switch_info; -}zb_gpdf_comm_app_info_t; - -/** - * @brief ZGPD Commissioning command parameters - * @see ZGP spec, A.4.2.1.1 - */ -typedef struct zb_gpdf_comm_params_s -{ - zb_uint8_t zgpd_device_id; /**< ZGPD Device ID */ - zb_uint8_t options; /**< Options */ - zb_uint8_t ext_options; /**< Extended options */ - zb_gpdf_comm_app_info_t app_info; /**< Application information */ - - /* TODO: Add fields "Number of GP commands", "GP command ID list", - * "Number of cluster reports", "ClusterReportN" */ -} -zb_gpdf_comm_params_t; - -/** - * @brief ZGPD Commissioning reply parameters - * @see ZGP spec, A.4.2.1.1 - */ -typedef struct zb_gpdf_comm_reply_s -{ - zb_uint8_t options; /**< Options */ - zb_uint16_t pan_id; /**< Pan ID if requested */ - zb_uint8_t security_key[ZB_CCM_KEY_SIZE]; /**< ZGPD key */ - zb_uint8_t key_mic[ZB_CCM_M]; /**< ZGPD key MIC */ - zb_uint32_t frame_counter; /**< ZGPD key encryption counter */ -} -zb_gpdf_comm_reply_t; - -#define ZB_GPDF_COMM_REPLY_PAN_ID_PRESENT(options) ((options) & 0x01U) -#define ZB_GPDF_COMM_REPLY_SEC_KEY_PRESENT(options) (((options) >> 1U) & 0x01U) -#define ZB_GPDF_COMM_REPLY_SEC_KEY_ENCRYPTED(options) (((options) >> 2U) & 0x01U) -#define ZB_GPDF_COMM_REPLY_SEC_LEVEL(options) (((options) >> 3U) & 0x03U) -#define ZB_GPDF_COMM_REPLY_SEC_KEY_TYPE(options) (((options) >> 5U) & 0x07U) - -/** - * @brief Construct options field of commissioning command from given values - * @see ZGP spec, A.4.2.1.1.2 - */ -#define ZB_GPDF_COMM_OPT_FLD(sn_cap, rx_cap, ms_ext, pan_id_req, \ - sec_key_req, fixed_loc, ext_opt) \ - ( (sn_cap) \ - | ((rx_cap) << 1U) \ - | ((ms_ext) << 2U) \ - | ((pan_id_req) << 4U) \ - | ((sec_key_req) << 5U) \ - | ((fixed_loc) << 6U) \ - | ((ext_opt) << 7U) ) - -/** - * @brief Value of Extended Options bit in - * options field of commissioning command - */ -#define ZB_GPDF_COMM_EXT_OPT_PRESENT(options) \ - ((options) >> 7U) - -/** - * @brief Value of GP security Key request bit in - * options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_SEC_KEY_REQ(options) \ - (((options) >> 5U) & 0x01U) - -/** - * @brief Value of Pan ID request bit in - * options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_PAN_ID_REQ(options) \ - (((options) >> 4U) & 0x01U) - -/** - * @brief Value of MAC sequence number capability bit in - * options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_SEQ_NUM_CAPS(options) \ - ((options) & 0x01U) - -/** - * @brief Value of RxOnCapability bit in - * options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_RX_CAPABILITY(options) \ - (((options) >> 1U) & 0x01U) - -/** - * @brief Value of Fixed location bit in - * options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_FIX_LOC(options) \ - (((options) >> 6U) & 0x01U) - -/** - * @brief Value of GPD MS extensions present bit in - * Options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_APP_INF_PRESENT(options) \ - (((options) >> 2U) & 0x01U) - -/** - * @brief Construct Extended Options field of commissioning command - * @see ZGP spec, A.4.2.1.1.3 - */ -#define ZB_GPDF_COMM_EXT_OPT_FLD(sec_cap, key_type, key_present, \ - key_enc, out_counter) \ - ( (sec_cap) \ - | ((key_type) << 2U) \ - | ((key_present) << 5U) \ - | ((key_enc) << 6U) \ - | ((out_counter) << 7U)) - -/** - * @brief Value of GPD Key present bit in - * Extended options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_ZGPD_KEY_PRESENT(ext_options) \ - (((ext_options) >> 5U) & 0x01U) - -/** - * @brief Value of GPD Key encryption bit in - * Extended options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_ZGPD_KEY_ENCRYPTED(ext_options) \ - (((ext_options) >> 6U) & 0x01U) - -/** - * @brief Value of GPD outgoing counter present bit in - * Extended options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_ZGPD_OUT_COUNTER_PRESENT(ext_options) \ - ((ext_options) >> 7U) - -/** - * @brief Value of SecurityLevel capabilities bits in - * Extended options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_SEC_LEVEL_CAPS(ext_options) \ - ((ext_options) & 0x03U) - -/** - * @brief Value of SecurityKey type bits in - * Extended options field of commissioning command - */ -#define ZB_GPDF_COMM_OPT_SEC_KEY_TYPE(ext_options) \ - ((ext_options >> 2U) & 0x07U) - -/** - * @brief Construct MS extensions field of commissioning command - * @see docs-13-0146-04-batt-green-powermanufacturer-specific-device-type-command.docx - */ -#define ZB_GPDF_COMM_MS_EXT_FLD(_manuf_id, _manuf_model_id, _gp_cmd_list, _clstr_reports) \ - ( (_manuf_id) \ - | ((_manuf_model_id) << 1U) \ - | ((_gp_cmd_list) << 2U) \ - | ((_clstr_reports) << 3U)) - -/** - * @brief Construct Options field of commissioning reply command - * @see ZGP spec, A.4.2.1.2.1 - */ -#define ZB_GPDF_COMM_REPLY_OPT_FLD(pan_id_present, key_present, \ - key_enc, sec_level, key_type) \ - ( (pan_id_present) \ - | ((key_present) << 1U) \ - | ((key_enc) << 2U) \ - | ((sec_level) << 3U) \ - | ((key_type) << 5U)) - -/** @} */ -/*! @endcond */ - - -/** - @cond internals_doc - @addtogroup zgp_internal - @{ -*/ - -/** - * @brief Send commissioning GPDF with ZGPD securityLevel capabilities set to 0 - */ -#define ZB_SEND_COMMISSIONING_GPDF_WITHOUT_SEC(buf, device_id, sn_cap, rx_cap) \ -{ \ - zb_uint8_t* ptr = (zb_uint8_t*)ZB_START_GPDF_PACKET(buf); \ - (void)zb_buf_alloc_left(buf, 3U, ptr); \ - ZB_GPDF_PUT_UINT8(ptr, ZB_GPDF_CMD_COMMISSIONING); \ - ZB_GPDF_PUT_UINT8(ptr, device_id); \ - ZB_GPDF_PUT_UINT8(ptr, ZB_GPDF_COMM_OPT_FLD(sn_cap, rx_cap, 0U, 0U, 0U, 0U, 0U)); \ - ZB_SEND_GPDF_CMD(ZB_REF_FROM_BUF(buf)); \ -} - -/** - * @brief Attribute report field of attribute reporting command - * @see ZGP spec, A.4.2.3.1 - */ -typedef struct zb_gpdf_attr_report_fld_s -{ - zb_uint16_t attr_id; /**< Attribute ID specific to cluster */ - zb_uint8_t attr_type; /**< Attribute type (see @ref zcl_attr_type) */ - void* data_p; /**< Attribute data */ -} -zb_gpdf_attr_report_fld_t; - -/** - * @brief Start constructing ZGPD attribute reporting command - * - * @param buf [in] Buffer for GPDF command - * @param cluster_id [in] Cluster ID of attributes being reported - * @param ptr [out] Pointer to the current tail of GPDF - */ -#define ZB_ZGPD_ATTR_REPORTING_CMD_INIT(buf, cluster_id, ptr) \ -{ \ - ptr = ZB_START_GPDF_PACKET(buf); \ - ZB_GPDF_PUT_UINT8(ptr, ZB_GPDF_CMD_ATTR_REPORT); \ - ZB_GPDF_PUT_UINT16(ptr, &cluster_id); \ -} - -/** - * @brief Put attribute report field into attribute reporting command - * - * Macro should be called only after attribute reporting command is - * initialized with @ref ZB_ZGPD_ATTR_REPORTING_CMD_INIT - * @param ptr [in,out] Pointer to the tail of attribute reporting command - * @param attr [in] Attribute report field (see @zb_gpdf_attr_report_fld_t) - */ -#define ZB_ZGPD_ATTR_REPORTING_CMD_NEXT(ptr, attr) \ -{ \ - ZB_GPDF_PUT_UINT16(ptr, &attr.attr_id); \ - ZB_GPDF_PUT_UINT8(ptr, attr.attr_type); \ - ptr = zb_zcl_put_value_to_packet(ptr, attr.attr_type, (zb_uint8_t *)attr.data_p); \ -} - -/** - * @brief Finish constructing ZGPD attribute reporting command - * - * @param buf [in] Buffer for GPDF command - * @param ptr [in] Pointer to the tail of GPDF - */ -#define ZB_ZGPD_ATTR_REPORTING_CMD_FINISH(buf, ptr) \ -{ \ - ZB_FINISH_GPDF_PACKET(buf, ptr); \ -} - -/** - * @brief Value of multi-record bit of options field - * in ZGPD Request attributes or Write attributes command - * (ZGP spec, rev. 26 A.4.2.6.1) - */ -#define ZB_GPDF_REQUEST_ATTR_IS_MULTI_RECORD(opts) \ - (opts & 0x01U) - -/** - * @brief Value of multi-record bit of options field - * in ZGPD Write attributes command - * (ZGP spec, rev. 26 A.4.2.6.1) - */ -#define ZB_GPDF_WRITE_ATTR_IS_MULTI_RECORD \ - ZB_GPDF_REQUEST_ATTR_IS_MULTI_RECORD - -/** - * @brief Value of "manufacturer field present" bit of options field - * in ZGPD Request attributes command - * (ZGP spec, rev. 26 A.4.2.6.1) - */ -#define ZB_GPDF_REQUEST_ATTR_MANUF_FIELD_PRESENT(opts) \ - ((opts >> 1U) & 0x01U) - -/** - * @brief Value of "manufacturer field present" bit of options field - * in ZGPD Write attributes command - * (ZGP spec, rev. 26 A.4.2.6.1) - */ -#define ZB_GPDF_WRITE_ATTR_MANUF_FIELD_PRESENT \ - ZB_GPDF_REQUEST_ATTR_MANUF_FIELD_PRESENT - -/** - * @brief Construct value of options field - * in ZGPD Request attributes or Write attributes command - * (ZGP spec, rev. 26 A.4.2.6.1) - */ -#define ZB_GPDF_REQUEST_ATTR_OPTIONS_FLD(multi_record, manuf_present) \ - ((multi_record) | (manuf_present << 1U)) - -/** - * @brief Construct value of options field - * in ZGPD Write attributes command - * (ZGP spec, rev. 26 A.4.2.6.3) - */ -#define ZB_GPDF_WRITE_ATTR_OPTIONS_FLD \ - ZB_GPDF_REQUEST_ATTR_OPTIONS_FLD - -/** - * @brief Parse one Cluster Record request field of - * ZGPD Request attributes command - * @param rec pointer to record to parse of type zb_uint8_t* - * @param cluster_id Cluster ID (out) - * @param attr_count Attribute count (out) - * @param attrs Pointer to attributes list (out) - */ -#define ZB_GPDF_REQUEST_ATTR_PARSE_RECORD(rec, cluster_id, attr_count, attrs) \ -{ \ - ZB_LETOH16((cluster_id), (rec)); \ - *(attr_count) = (rec)[2]/sizeof(zb_uint16_t); \ - *(attrs) = (zb_uint16_t *)(void *)(&(rec)[3]); \ -} - -/** - * @brief Start constructing ZGP write attribute command - * - * @param buf [in] Buffer for GPDF command - * @param cluster_id [in] Cluster ID of attributes being reported - * @param ptr [out] Pointer to the current tail of GPDF - */ -#define ZB_ZGPD_WRITE_ATTR_CMD_INIT(buf, ptr) \ -{ \ - ptr = ZB_START_GPDF_PACKET(buf); \ - ZB_GPDF_PUT_UINT8(ptr, ZB_GPDF_WRITE_ATTR_OPTIONS_FLD(0,0)); \ -} - -/** - * @brief Start constructing ZGP write attribute command - * - * @param buf [in] Buffer for GPDF command - * @param manuf_id [in] Manufacturer ID - * @param ptr [out] Pointer to the current tail of GPDF - */ -#define ZB_ZGPD_WRITE_ATTR_MANUF_CMD_INIT(buf, manuf_id, ptr) \ -{ \ - ptr = ZB_START_GPDF_PACKET(buf); \ - ZB_GPDF_PUT_UINT8(ptr, ZB_GPDF_WRITE_ATTR_OPTIONS_FLD(0,1)); \ - ZB_GPDF_PUT_UINT16(ptr, &(manuf_id)); \ -} - -/** - * @brief Start cluster record field in write attributes command - * - * Macro should be called only after write attributes command is - * initialized with @ref ZB_ZGPD_WRITE_ATTR_MANUF_CMD_INIT or - * @ref ZB_ZGPD_WRITE_ATTR_CMD_INIT - * @param ptr [in,out] Pointer to the tail of write attributes command - * @param cluster_id [in] Cluster ID - * @param record_list_len [in] Length in bytes of following Write Attribute Records list - */ -#define ZB_ZGPD_WRITE_ATTR_NEW_CLUSTER_RECORD(ptr, cluster_id, record_list_len) \ -{ \ - ZB_GPDF_PUT_UINT16(ptr, &cluster_id); \ - ZB_GPDF_PUT_UINT8(ptr, (record_list_len)); \ -} - -/** - * @brief Put write attribute record into write attributes command - * - * Macro should be called only after new cluster record is - * initialized with @ref ZB_ZGPD_WRITE_ATTR_NEXT_CLUSTER_RECORD - * @param ptr [in,out] Pointer to the tail of write attributes command - * @param attr_id [in] Attribute ID - * @param attr_type [in] Attribute type - * @param value [in] Pointer to attribute value - */ -#define ZB_ZGPD_WRITE_ATTR_CMD_NEXT_ATTR(ptr, attr_id, attr_type, value) \ -{ \ - ZB_GPDF_PUT_UINT16(ptr, &attr_id); \ - ZB_GPDF_PUT_UINT8(ptr, attr_type); \ - ptr = zb_zcl_put_value_to_packet(ptr, attr_type, (zb_uint8_t *)(value)); \ -} - -/** - * @brief Finish constructing ZGPD write attributes command - * - * @param buf [in] Buffer for GPDF command - * @param ptr [in] Pointer to the tail of GPDF - */ -#define ZB_ZGPD_WRITE_ATTR_CMD_FINISH(buf, ptr) \ -{ \ - ZB_FINISH_GPDF_PACKET(buf, ptr); \ -} - -/* [AV] tmm it'll be better to name macros like this once - and don't rename them like #def macro_write_init(...) macro_read_init(...), - because there is no difference -*/ -#define ZB_ZGPD_CLUSTER_CMD_INIT(_buf, _ptr) \ - ZB_ZGPD_WRITE_ATTR_CMD_INIT(_buf, _ptr) -#define ZB_ZGPD_CLUSTER_CMD_MANUF_INIT(_buf, _manuf_id, _ptr) \ - ZB_ZGPD_WRITE_ATTR_MANUF_CMD_INIT(_buf, _manuf_id, _ptr) -#define ZB_ZGPD_NEW_CLUSTER_RECORD(_ptr, _cluster_id, _record_list_len) \ - ZB_ZGPD_WRITE_ATTR_NEW_CLUSTER_RECORD(_ptr, _cluster_id, _record_list_len) -#define ZB_ZGPD_READ_ATTR_CMD_NEXT_ATTR(_ptr, _attr_id) \ -{ \ - ZB_GPDF_PUT_UINT16(_ptr, &_attr_id); \ -} -#define ZB_ZGPD_CLUSTER_CMD_FINISH(_buf, _ptr) \ -{ \ - ZB_FINISH_GPDF_PACKET(_buf, _ptr); \ -} - -#ifdef ZB_ENABLE_ZGP_DIRECT -typedef struct zb_zgps_send_cmd_params_s -{ - zb_uint8_t cmd_id; - zb_zgpd_id_t zgpd_id; - zb_ieee_addr_t ieee_addr; - zb_time_t lifetime; - zb_uint8_t tx_options; - zb_uint8_t handle; -} -zb_zgps_send_cmd_params_t; - -/** - * @brief Send provided packet to ZGPD - * - * Buffer data is command payload to send. - * Other parameters are in the buffer tail (see @ref zb_zgps_send_cmd_params_t). - * - * @param param[in, out] Reference to buffer. - * - * @note maximum length of data payload is @ref ZB_ZGP_TX_CMD_PLD_MAX_SIZE - * - * @note zb_gp_data_cfm is called from: - * - gp_data_req_send_cnf to notify about status of adding data to tx_packet_info_queue; - * - notify_about_expired_entry to notify about expired entry; - * - zb_cgp_data_cfm to notify about status from MAC layer. - * - * @note Status of confirm (ZGP TX queue is used) can be: - * ZB_ZGP_STATUS_ENTRY_REPLACED - * ZB_ZGP_STATUS_ENTRY_ADDED - * ZB_ZGP_STATUS_ENTRY_EXPIRED - * ZB_ZGP_STATUS_ENTRY_REMOVED - * ZB_ZGP_STATUS_TX_QUEUE_FULL - * - * MAC_SUCCESS - * - * @note Status of confirm (ZGP TX queue is not used) can be: - * ZB_ZGP_STATUS_TX_QUEUE_FULL - * - * MAC_SUCCESS - * MAC_NO_ACK - * - */ -void zb_zgps_send_data(zb_uint8_t param); -#endif /* ZB_ENABLE_ZGP_DIRECT */ -/*! @} - * @endcond */ - -/** - @addtogroup zgp_sink - @{ -*/ - -/** - * @brief Put ZGPS into commissioning mode - * - * It is safe to call this function when device is already in - * commissioning mode. In this case function does nothing. - * - * @param[in] timeout Maximum commissioning time in beacon intervals. \n - * 0 means no timeout. \n - * If timeout occurs, then result of commissioning is - * @ref ZB_ZGP_COMMISSIONING_TIMED_OUT - * - * @snippet light_sample/light_coordinator_combo/light_zc.c zgps_start_comm - */ -void zb_zgps_start_commissioning(zb_time_t timeout); - -/** - * @brief Switch ZGPS back to operational mode from commissioning - * - * @cond DOXYGEN_INTERNAL_DOC - * After commissioning is cancelled, user is notified with - * @ref zb_zgp_comm_completed_cb_t with ZB_ZGP_COMMISSIONING_CANCELLED_BY_USER - * status. - * @endcond - * - * @snippet light_sample/light_coordinator_combo/light_zc.c zgps_stop_comm - */ -void zb_zgps_stop_commissioning(void); - -/** - * @brief Accept/reject ZGPD commissioning attempt - * - * This function should be called as an answer to commissioning request made by - * stack via @ref zb_zgp_comm_req_cb_t. Also, it can be called from @ref - * zb_zgp_comm_req_cb_t callback as well as outside it. - * - * @param[in] accept - If ZB_TRUE, then stack will continue ongoing commissioning - * process with ZGPD \n - * Otherwise ongoing commissioning process will be - * terminated - * @if DOXIGEN_INTERNAL_DOC - * @snippet tests/zgp/gppb/test_gps_decommissioning/dut_gps.c accept_comm - * @endif - */ -void zb_zgps_accept_commissioning(zb_bool_t accept); - -/** - * @brief Remove all the information about ZGPD from stack - * - * In ZGP there is no way to say ZGPD to leave the network. - * ZGPD can leave network by itself using "Decommissioning" command, - * but ZGPS can miss this command if it was not in commissioning state. - * - * This function removes all the information related to specified ZGPD - * from stack. - * - * @param buf_ref reference to the free buffer - * @param zgpd_id identifier of ZGPD to be removed - * - * @note It is safe to free or overwrite memory pointed by zgpd_id - * after call - */ -void zb_zgps_delete_zgpd(zb_uint8_t buf_ref, zb_zgpd_id_t *zgpd_id); - -/** - * @brief Remove all the information about ALL ZGPD from stack - * - */ -void zb_zgps_delete_all_zgpd(void); - -/** - Get LQI and RSSI last time received from that ZGPD. - */ -void zb_zgps_get_diag_data(zb_zgpd_id_t *zgpd_id, zb_uint8_t *lqi, zb_int8_t *rssi); - -/*! @} */ - -/** - @addtogroup zgp_sink - @{ -*/ - -/** - Fill security level constant to be passed to zb_zgps_set_security_level() - - Described in A.3.3.2.6 gpsSecurityLevel attribute. - - @param sec_lvl @ref zb_zgp_security_level_e Minimal GPD Security Level sub-field contains the minimum gpdSecurityLevel this sink accepts - @param with_link_key 1 bit - Protection with the gpLinkKey sub-field, indicates if - the GPDs attempting the pairing are required to support protecting the - over-the-air exchange of the GPD Key - @param involve_tc always zero for the current GPPB specification - - @snippet light_sample/light_coordinator_combo/light_zc.c zgps_set_secur_level - */ -#define ZB_ZGP_FILL_GPS_SECURITY_LEVEL(sec_lvl, with_link_key, involve_tc)\ - (((sec_lvl) & 3U) | ((!!(with_link_key)) << 2U) | ((!!(involve_tc)) << 3U)) - - -/** - Set gpsSecurityLevel GP cluster attribute of gpcb - - Described in A.3.3.2.6 gpsSecurityLevel attribute. - - @param level Security level to set - - @snippet light_sample/light_coordinator_combo/light_zc.c zgps_set_secur_level - */ -void zb_zgps_set_security_level(zb_uint_t level); - -/** - Set gpSharedSecurityKeyType GP cluster attribute - - Described in A.3.3.3.1 gpSharedSecurityKeyType attribute. - - @param key_type Security key type to set (@see zb_zgp_security_key_type_e) - */ -void zb_zgp_set_shared_security_key_type(zb_uint_t key_type); - -/** - Set gpSharedSecurityKey GP cluster attribute - - Described in A.3.3.3.1 gpSharedSecurityKey attribute. - - @param key Security key to set - */ -void zb_zgp_set_shared_security_key(zb_uint8_t *key); - -/** - Set gpsCommissioningExitMode GP cluster attribute - - Described in A.3.3.2.4 gpsCommissioningExitMode attribute. - - @param cem Commissioning exit mode to set (@see zgp_commissioning_exit_mode_t) - */ -void zb_zgps_set_commissioning_exit_mode(zb_uint_t cem); - -/** - Set gpsCommunicationMode GP cluster attribute of gpcb - - Described in A.3.3.2.3 gpsCommunicationMode attribute - - @param mode @ref zgp_communication_mode_t communication mode - - @snippet light_sample/light_coordinator_combo/light_zc.c set_comm_mode - */ -void zb_zgps_set_communication_mode(zgp_communication_mode_t mode); - -/** - * Application function to override translation of 8-bit vector command (generic switch) - * - * If this function is not implemented in the application, then ZBOSS - * performs a default translation as recommended by ZGP spec (see Green Power - * Basic specification v1.1.1, tables 51, 52). If there is no default - * translation found, then the received command is dropped. - * - * If this function is implemented by the the application, then application is - * fully responsible for a translation of GPD 8-bit vector commands. For any - * return code but RET_OK, ZBOSS will stop command processing and drop it. - * - * Note: The translation is done to GPDF command ID, not to ZCL command ID. - * - * @param[in] vector_8bit_cmd_id incoming command ID: press (0x69) or release(0x6a) - * @param[in] switch_type switch type of the command's originator (see ZGP spec. A.4.2.1.1.10) - * @param[in] num_of_contacts number of contacts command's originator provides - * @param[in] contact_status contacts status from the payload of the received command - * @param[out] zgp_cmd_out GPDF command ID to which incoming command should be translated - * @return RET_OK if translation is successful. - * - * See Green Power Basic specification v1.1.1, chapters A.3.6.2.2.2, A.4.2.2.1 for more information. - * - * @snippet simple_combo/zc_combo.c convert_8bit_vector - */ -zb_ret_t zb_zgp_convert_8bit_vector(zb_uint8_t vector_8bit_cmd_id, /* press or release cmd */ - zb_uint8_t switch_type, /* see zb_zgpd_switch_type_e */ - zb_uint8_t num_of_contacts, - zb_uint8_t contact_status, - zb_uint8_t *zgp_cmd_out); - -/** - * @brief Application function to override allows custom handling incoming raw GPDF packet - * - * If this function os not implemented by the application, then ZBOSS - * drops the buffer without any additional handling. - * - * If this function is implemented by the application, the application itself - * shall carry to free this resource. - * - * @param buf_ref - */ -void zb_zgp_gpdf_raw_indication(zb_bufid_t buf_ref); - -#ifdef ZB_ENABLE_ZGP_DIRECT -/** - Set ZBOSS to skip all incoming GPDF. - - To be used for testing only. - Use that function with ZB_TRUE parameter to prevent Combo device from - receiving GPDFS thus always working thru Proxy device. - - @param skip if ZB_TRUE, skip incoming GP frames - */ - -void zb_zgp_set_skip_gpdf(zb_uint8_t skip); -zb_uint8_t zb_zgp_get_skip_gpdf(void); -void zb_zgp_sync_pib(zb_uint8_t param); - -#endif /* ZB_ENABLE_ZGP_DIRECT */ - -/*! @} */ - -#ifndef ZB_ZGPD_ROLE - -typedef enum zgp_proxy_comm_mode_action_e -{ - ZGP_PROXY_COMM_MODE_LEAVE, - ZGP_PROXY_COMM_MODE_ENTER -} zgp_proxy_comm_mode_action_t; - -typedef enum zgp_proxy_comm_mode_ch_present_e -{ - ZGP_PROXY_COMM_MODE_CHANNEL_PRESENT, - ZGP_PROXY_COMM_MODE_CHANNEL_NOT_PRESENT -} zgp_proxy_comm_mode_ch_present_t; - -typedef enum zgp_proxy_comm_mode_communication_e -{ - ZGP_PROXY_COMM_MODE_BROADCAST, - ZGP_PROXY_COMM_MODE_UNICAST -} zgp_proxy_comm_mode_communication_t; - -/** - * @brief Setup options for zb_zgp_cluster_proxy_commissioning_mode_req() - * - * @param action [in] enter/exit (see @ref zgp_proxy_comm_mode_action_t) - * @param exit_mode [in] exit mode (see @ref zgp_commissioning_exit_mode_t) - * @param ch_present [in] is channel present (see @ref zgp_proxy_comm_mode_ch_present_t) - * @param communication [in] communication type (see @ref zgp_proxy_comm_mode_communication_t) - */ -#define ZB_ZGP_FILL_PROXY_COMM_MODE_OPTIONS(action, exit_mode, ch_present, communication) \ - ((!!(action)) | (((exit_mode) & 7) << 1) | ((!!(ch_present)) << 4) | (((communication)&3) << 5)) - -/** - * @brief Perform Proxy Commissioning mode request - * - * @param param [in] Buffer reference - * @param options [in] Request options (see @ref ZB_ZGP_FILL_PROXY_COMM_MODE_OPTIONS) - * @param comm_wind [in] Commissioning window - * @param channel [in] Channel where perform commissioning (0x0b for channel 11) - * @param cb [in] Callback call if needed after send request - * - * @see ZGP spec, A.3.3.5.3 -*/ -void zb_zgp_cluster_proxy_commissioning_mode_req(zb_uint8_t param, - zb_uint8_t options, - zb_uint16_t comm_wind, - zb_uint8_t channel, - zb_callback_t cb); - -/** - * @brief Perform Proxy Commissioning mode enter request - * - * @param param [in] Buffer reference - * @param exit_mode [in] exit mode (see @ref zgp_commissioning_exit_mode_t) - * @param comm_wind [in] Commissioning window - * @param cb [in] Callback call if needed after send request - * - * @see ZGP spec, A.3.3.5.3 - */ -void zgp_cluster_send_proxy_commissioning_mode_enter_req(zb_uint8_t param, - zb_uint8_t exit_mode, - zb_uint16_t comm_window, - zb_callback_t cb); - -/** - * @brief Perform Proxy Commissioning mode leave request - * - * @param param [in] Buffer reference - * @param cb [in] Callback call if needed after send request - * - * @see ZGP spec, A.3.3.5.3 - */ -void zgp_cluster_send_proxy_commissioning_mode_leave_req(zb_uint8_t param, zb_callback_t cb); - -/** - * @brief Setup options for zb_zgp_cluster_gp_pairing_req() - * - * @param app_id [in] ZGPD application id (@see zb_zgp_app_id_t) - * @param add_sink [in] Add sink flag - * @param remove_gpd [in] Remove GPD flag - * @param comm_mode [in] Communication mode (@see zgp_communication_mode_t) - * @param gpd_fixed [in] ZGPD is fixed - * @param gpd_mac_sec_num_cap [in] MAC sequence number capability - * @param sec_lvl [in] SecurityLevel (@see zb_zgp_security_level_e) - * @param sec_key_type [in] SecurityKeyType (@see zb_zgp_security_key_type_e) - * @param gpd_sec_key_prsnt [in] Is key presented - * @param assigned_alias_prsnt [in] Is assigned alias presented - * @param frwrd_radius_prsnt [in] Is radius in the groupcast forwarding presented - * - * @see ZGP spec, A.3.3.5.2 - */ -#define ZB_ZGP_FILL_GP_PAIRING_OPTIONS(app_id, add_sink, remove_gpd, comm_mode,\ - gpd_fixed, gpd_mac_sec_num_cap, sec_lvl,\ - sec_key_type, frame_cnt_prsnt,\ - gpd_sec_key_prsnt, assigned_alias_prsnt, \ - frwrd_radius_prsnt)\ - (((app_id) & 7) | ((!!(add_sink)) << 3) | ((!!(remove_gpd)) << 4) | (((comm_mode) & 3) << 5) | (((!!(add_sink)) ? (!!(gpd_fixed)) : 0) << 7) | (((!!(add_sink)) ? (!!(gpd_mac_sec_num_cap)) : 0) << 8) | (((!!(add_sink)) ? ((sec_lvl) & 3) : 0) << 9) | (((!!(add_sink)) ? ((sec_key_type) & 7) : 0) << 11) | ((!!(frame_cnt_prsnt)) << 14) | (((!!(add_sink)) ? (!!(gpd_sec_key_prsnt)) : 0) << 15) | (((!!(add_sink)) ? (!!(assigned_alias_prsnt)) : 0) << 16) | (((!!(add_sink)) ? (!!(frwrd_radius_prsnt)) : 0) << 17)) - -/** - * @brief Perform GP Pairing request - * - * @param param [in] Buffer reference - * @param dst_addr [in] Destination address - * @param dst_addr_mode [in] Destination address mode - * @param options [in] Request options - * @param gpd_id [in] ZGPD ID - * @param endpoint [in] Endpoint of ZGPD if APP_ID eq 0010 - * @param dev_id [in] Device ID - * @param sec_frame_counter [in] Security frame counter of ZGPD - * @param key [in] Pointer to the security key - * @param assigned_alias [in] Assigned alias in the groupcast forwarding of the GPDF packet - * @param frwd_radius [in] Radius in the groupcast forwarding of the GPDF packet - * @param cb [in] Callback call if needed after send request - * - * @see ZGP spec, A.3.3.5.2 - */ -void zb_zgp_cluster_gp_pairing_req(zb_uint8_t param, - zb_uint16_t dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint32_t options, - zb_zgpd_addr_t gpd_id, - zb_uint8_t endpoint, - zb_uint8_t dev_id, - zb_uint32_t sec_frame_counter, - zb_uint8_t *key, - zb_uint16_t assigned_alias, - zb_uint8_t frwd_radius, - zb_uint16_t group_id, - zb_callback_t cb); - -/** - * @brief Perform send zcl gp sink table request for ZGP cluster - * - * @param buf_ref [in] Buffer reference - * @param dst_addr [in] Destination address - * @param dst_addr_mode [in] Destination address mode - * @param options [in] Request options - * @param zgpd_id [in] Pointer to ZGPD ID - * @param index [in] The Index field carries the index value of the Sink Table entry is requested - * @param cb [in] Call callback if needed after sending request - * - * @see ZGP spec, A.3.3.4.7 - * - */ -void zgp_cluster_send_gp_sink_table_request(zb_uint8_t buf_ref, - zb_uint16_t dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint8_t options, - zb_zgpd_id_t *zgpd_id, - zb_uint8_t index, - zb_callback_t cb); - -/** - * @brief Perform send zcl gp proxy table request for ZGP cluster - * - * @param buf_ref [in] Buffer reference - * @param dst_addr [in] Destination address - * @param dst_addr_mode [in] Destination address mode - * @param options [in] Request options - * @param zgpd_id [in] Pointer to ZGPD ID - * @param index [in] The Index field carries the index value of the Proxy Table entry is requested - * @param cb [in] Call callback if needed after sending request - * - * @see ZGP spec, A.3.4.3.1 - * - */ -void zgp_cluster_send_gp_proxy_table_request(zb_uint8_t buf_ref, - zb_uint16_t dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint8_t options, - zb_zgpd_id_t *zgpd_id, - zb_uint8_t index, - zb_callback_t cb); - -typedef ZB_PACKED_PRE struct zb_zgp_cluster_list_s -{ - zb_uint8_t server_cl_num; - zb_uint8_t client_cl_num; - zb_uint16_t server_clusters[ZB_ZGP_MAX_PAIRED_CONF_CLUSTERS]; - zb_uint16_t client_clusters[ZB_ZGP_MAX_PAIRED_CONF_CLUSTERS]; -} -ZB_PACKED_STRUCT zb_zgp_cluster_list_t; - -typedef ZB_PACKED_PRE struct zgp_pair_group_list_s -{ - zb_uint16_t sink_group; - zb_uint16_t alias; -} -ZB_PACKED_STRUCT zgp_pair_group_list_t; - -/* >> Data structures for Application Description */ -typedef enum zgp_app_descr_status_e -{ - ZGP_APP_TBL_ENT_STATUS_FREE = 0, - ZGP_APP_TBL_ENT_STATUS_INIT_WITH_SW_INFO = 1, - ZGP_APP_TBL_ENT_STATUS_INIT = 2, - ZGP_APP_TBL_ENT_STATUS_APP_DESCR_PROCESS = 3, - ZGP_APP_TBL_ENT_STATUS_COMPLETE = 4 -} zgp_app_descr_status_t; - -typedef ZB_PACKED_PRE struct zgp_app_tbl_ent_options_s -{ - zb_bitfield_t ieee_addr_present:1; - zb_bitfield_t switch_info_present:1; - zb_bitfield_t reserved:6; -}ZB_PACKED_STRUCT zgp_app_tbl_ent_options_t; - -typedef ZB_PACKED_PRE struct zgp_app_tbl_ent_info_s -{ - zb_zgpd_addr_t addr; - zgp_app_tbl_ent_options_t options; - zb_uint8_t total_reports_num; - zb_gpdf_comm_switch_gen_cfg_t switch_info_configuration; - zb_uint8_t reserved; -}ZB_PACKED_STRUCT zgp_app_tbl_ent_info_t; - - -#define ZB_APP_DESCR_REPORTS_NUM 4 -typedef ZB_PACKED_PRE struct zgp_app_tbl_ent_s -{ - zgp_app_tbl_ent_info_t info; - zgp_report_desc_t reports[ZB_APP_DESCR_REPORTS_NUM]; -}ZB_PACKED_STRUCT zgp_app_tbl_ent_t; - -typedef struct zgp_runtime_app_tbl_ent_s -{ - zb_uint8_t status; /* zgp_app_descr_status_t */ - zb_uint8_t receive_reports_num; - zb_uint8_t reply_buf; - zb_bool_t need_reply; - zgp_app_tbl_ent_t base; -}zgp_runtime_app_tbl_ent_t; - -/* << Data structures for Application Description */ - -typedef struct zgp_tbl_ent_s -{ - zb_zgpd_addr_t zgpd_id; /**< ID of the paired ZGPD */ - zb_uint16_t options; /**< The options for the reception from ZGPD */ - zb_uint16_t zgpd_assigned_alias; /**< The commissioned 16-bit ID to be used - as alias for ZGPD */ - - zb_uint32_t security_counter; /**< The incoming security frame counter for ZGPD */ - zb_uint8_t zgpd_key[ZB_CCM_KEY_SIZE]; /**< Security key for the GPD */ - zb_uint8_t endpoint; /**< Endpoint pair of IEEE:EP if App ID is 010. */ - zb_uint8_t sec_options; /**< Security options */ - zb_uint8_t groupcast_radius; /**< To limit the range of the groupcast */ - - zb_uint8_t is_sink; - - union - { - struct zgp_proxy_tbl_ent_s - { - zb_uint16_t ext_options; - struct zgp_lwsink_addr_list_s - { - zb_address_ieee_ref_t addr_ref; - } lwsaddr[ZB_ZGP_MAX_LW_UNICAST_ADDR_PER_GPD]; - zgp_pair_group_list_t sgrp[ZB_ZGP_MAX_SINK_GROUP_PER_GPD]; - } proxy; - struct zgp_sink_tbl_ent_s - { - zb_uint8_t device_id; /**< ZGPD Device ID from Commissioning frame @see zb_zgpd_dev_id_t */ - zgp_pair_group_list_t sgrp[ZB_ZGP_MAX_SINK_GROUP_PER_GPD]; - zb_uint8_t match_dev_tbl_idx; /**< index in matching table matched by device_id or app_info.manuf_model_id */ - /** - * Extension to the table (field is not presented in specification). - * - * Dest IEEE address to use in GPT to GPD packets even if GPD is identified by SrcID - */ - zb_ieee_addr_t ieee_addr; - } sink; - } u; -} zgp_tbl_ent_t; - -#if defined ZB_ENABLE_ZGP_SINK || defined ZGP_COMMISSIONING_TOOL -typedef zgp_tbl_ent_t zb_zgp_sink_tbl_ent_t; -#endif /* defined ZB_ENABLE_ZGP_SINK || defined ZGP_COMMISSIONING_TOOL */ -#ifdef ZB_ENABLE_ZGP_PROXY -typedef zgp_tbl_ent_t zb_zgp_proxy_tbl_ent_t; -#endif /* ZB_ENABLE_ZGP_PROXY */ - -#if defined ZB_ENABLE_ZGP_SINK || defined ZGP_COMMISSIONING_TOOL -/* TODO: update description */ -/** - * @brief Perform send zcl gp pairing configuration command for ZGP cluster - * - * @param buf_ref [in] Buffer reference - * @param dst_addr [in] Destination address - * @param dst_addr_mode [in] Destination address mode - * @param actions [in] Actions - * @param ent [in] Sink table entry - * @param def_resp [in] Enable ZCL default response if TRUE - * @param cb [in] Call callback if needed after sending request - * - * @see ZGP spec, A.3.3.4.6 - * - */ -void zgp_cluster_send_pairing_configuration(zb_uint8_t buf_ref, - zb_uint16_t dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint8_t actions, - zb_zgp_sink_tbl_ent_t *ent, - zb_uint8_t num_paired_endpoints, - zb_uint8_t *paired_endpoints, - zb_uint8_t app_info, - zb_uint16_t manuf_id, - zb_uint16_t model_id, - zb_uint8_t num_gpd_commands, - zb_uint8_t *gpd_commands, - zb_zgp_cluster_list_t *cluster_list, - zb_callback_t cb); -#endif /* defined ZB_ENABLE_ZGP_SINK || defined ZGP_COMMISSIONING_TOOL */ - -#ifdef ZGP_COMMISSIONING_TOOL -/** - * @brief Perform send zcl gp sink commissioning mode command for ZGP cluster - * - * @param buf_ref [in] Buffer reference - * @param dst_addr [in] Destination address - * @param dst_addr_mode [in] Destination address mode - * @param options [in] Options - * @param endpoint [in] Endpoint - * @param cb [in] Call callback if needed after sending request - * - * @see ZGP spec, A.3.3.4.8 - * - */ -void zgp_cluster_send_gp_sink_commissioning_mode(zb_uint8_t buf_ref, - zb_uint16_t dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint8_t options, - zb_uint8_t endpoint, - zb_callback_t cb); -#endif /* ZGP_COMMISSIONING_TOOL */ - -void zgp_gp_set_shared_security_key_type(enum zb_zgp_security_key_type_e type); -#define ZGP_GP_SET_SHARED_SECURITY_KEY_TYPE(type) zgp_gp_set_shared_security_key_type(type) - -#ifdef ZGP_CLUSTER_TEST -/* Application specific zcl command handler for test purposes */ -typedef zb_uint8_t (*zgp_cluster_app_zcl_cmd_handler_t)(zb_uint8_t buf_ref); - -/** - * @brief Setup specific application zcl command handler for test purpose - * - * @param handler [in] Specific application zcl command handler pointer - */ -void zgp_cluster_set_app_zcl_cmd_handler(zgp_cluster_app_zcl_cmd_handler_t handler); -#endif /* ZGP_CLUSTER_TEST */ -#endif /* !ZB_ZGPD_ROLE */ - -#endif /* ZBOSS_API_ZGP_H */ diff --git a/zboss/development/include/zcl/zb_zcl_alarms.h b/zboss/development/include/zcl/zb_zcl_alarms.h deleted file mode 100644 index 7953d32be0..0000000000 --- a/zboss/development/include/zcl/zb_zcl_alarms.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Alarms cluster definitions -*/ - -#ifndef ZB_ZCL_ALARMS_H -#define ZB_ZCL_ALARMS_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_ALARMS - * @{ - */ - - -/* Cluster ZB_ZCL_CLUSTER_ID_ALARMS */ - -/*! @name Alarms cluster attributes - @{ -*/ - -/*! @brief Alarms cluster attribute identifiers - @see ZCL spec, subclause 3.11.2.2 -*/ -enum zb_zcl_alarms_attr_e -{ - /*! @brief AlarmCount attribute */ - ZB_ZCL_ATTR_ALARMS_ALARM_COUNT_ID = 0x0000 -}; - -/*! @} */ /* Alarms cluster attributes */ - -/** @brief Default value for Alarms cluster revision global attribute */ -#define ZB_ZCL_ALARMS_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/*! - @brief Declare attribute list for Alarms cluster (only cluster revision attribute) - @param attr_list - attribute list name -*/ -#define ZB_ZCL_DECLARE_ALARMS_ATTR_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_ALARMS) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @name Alarms cluster commands - @{ -*/ - -/*! @brief Alarms cluster command identifiers - @see ZCL spec, subclause 3.11.2.4 -*/ -enum zb_zcl_alarms_cmd_e -{ - ZB_ZCL_CMD_ALARMS_RESET_ALARM_ID = 0x00, /**< "Reset alarm" command. */ - ZB_ZCL_CMD_ALARMS_RESET_ALL_ALARMS_ID = 0x01, /**< "Reset all alarms" command. */ - ZB_ZCL_CMD_ALARMS_GET_ALARM_ID = 0x02, /**< "Get alarms" command. */ - ZB_ZCL_CMD_ALARMS_RESET_ALARM_LOG_ID = 0x03 /**< "Reset alarm log" command. */ -}; - -/*! @brief Structured representation of Reset alarm command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_alarms_reset_alarm_req_s -{ - /** Alarm Code field */ - zb_uint8_t alarm_code; - /** Cluster ID field */ - zb_uint16_t cluster_id; -} ZB_PACKED_STRUCT zb_zcl_alarms_reset_alarm_req_t; - -/** @brief Reset alarm payload length macro */ -#define ZB_ZCL_ALARMS_RESET_ALARM_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_alarms_reset_alarm_req_t) - -/*! @brief Send Reset alarm command - @param buffer to put data to - @param addr - address of the device to send command to - @param dst_addr_mode - addressing mode - @param dst_ep destination endpoint - @param ep - current endpoint - @param prof_id - profile identifier - @param dis_default_resp - "Disable default response" flag - @param cb - callback to call to report send status - @param alarm_code - Alarm Code field - @param cluster_id - Cluster ID field -*/ -#define ZB_ZCL_ALARMS_SEND_RESET_ALARM_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, cb, alarm_code, cluster_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_ALARMS_RESET_ALARM_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (alarm_code)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (cluster_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_ALARMS, cb); \ -} - -/** @brief Parses Reset alarm command and fills in data request - structure. If request contains invalid data, status will set to ZB_FALSE. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param reset_alarm_req - variable to save command request - @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - @note data_buf buffer should contain command request payload without ZCL header. - */ -#define ZB_ZCL_ALARMS_GET_RESET_ALARM_REQ(data_buf, reset_alarm_req, status) \ -{ \ - zb_zcl_alarms_reset_alarm_req_t *reset_alarm_req_ptr; \ - (reset_alarm_req_ptr) = zb_buf_len(data_buf) >= \ - ZB_ZCL_ALARMS_RESET_ALARM_REQ_PAYLOAD_LEN ? \ - (zb_zcl_alarms_reset_alarm_req_t*)zb_buf_begin(data_buf) : NULL; \ - if (reset_alarm_req_ptr != NULL) \ - { \ - reset_alarm_req.alarm_code = reset_alarm_req_ptr->alarm_code; \ - ZB_HTOLE16(&(reset_alarm_req).cluster_id, &(reset_alarm_req_ptr->cluster_id)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/*! @brief Send Reset all alarms command - @param buffer to put data to - @param addr - address of the device to send command to - @param dst_addr_mode - addressing mode - @param dst_ep destination endpoint - @param ep - current endpoint - @param prof_id - profile identifier - @param dis_default_resp - "Disable default response" flag - @param cb - callback to call to report send status -*/ -#define ZB_ZCL_ALARMS_SEND_RESET_ALL_ALARMS_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_ALARMS_RESET_ALL_ALARMS_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_ALARMS, cb); \ -} - -/*! @brief Send Get alarm command - @param buffer to put data to - @param addr - address of the device to send command to - @param dst_addr_mode - addressing mode - @param dst_ep destination endpoint - @param ep - current endpoint - @param prof_id - profile identifier - @param dis_default_resp - "Disable default response" flag - @param cb - callback to call to report send status -*/ -#define ZB_ZCL_ALARMS_SEND_GET_ALARM_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_ALARMS_GET_ALARM_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_ALARMS, cb); \ -} - -/*! @brief Send Reset alarm log command - @param buffer to put data to - @param addr - address of the device to send command to - @param dst_addr_mode - addressing mode - @param dst_ep destination endpoint - @param ep - current endpoint - @param prof_id - profile identifier - @param dis_default_resp - "Disable default response" flag - @param cb - callback to call to report send status -*/ -#define ZB_ZCL_ALARMS_SEND_RESET_ALARM_LOG_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_ALARMS_RESET_ALARM_LOG_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_ALARMS, cb); \ -} - -/********************************** Responses *******************/ - -/** @brief Alarms cluster response command identifiers - @see ZCL spec, subclause 3.6.2.3 -*/ -enum zb_zcl_alarms_cmd_resp_e -{ - ZB_ZCL_CMD_ALARMS_ALARM_ID = 0x00, /**< Alarm command identifier. */ - ZB_ZCL_CMD_ALARMS_GET_ALARM_RES_ID = 0x01 /**< Get alarm response command identifier. */ -}; - -/** @cond internals_doc */ -/* Alarms cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_ALARMS_SERVER_ROLE_GENERATED_CMD_LIST ZB_ZCL_CMD_ALARMS_ALARM_ID - -#define ZB_ZCL_CLUSTER_ID_ALARMS_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_ALARMS_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_ALARMS_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_ALARMS_RESET_ALARM_ID, \ - ZB_ZCL_CMD_ALARMS_RESET_ALL_ALARMS_ID - -#define ZB_ZCL_CLUSTER_ID_ALARMS_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_ALARMS_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/*! @brief Structured representation of Alarm command payload */ -typedef zb_zcl_alarms_reset_alarm_req_t zb_zcl_alarms_alarm_res_t; - -typedef ZB_PACKED_PRE struct zb_zcl_alarm_get_alarm_hdr_res_s -{ - zb_uint8_t status; /**< Status field */ -} ZB_PACKED_STRUCT zb_zcl_alarm_get_alarm_hdr_res_t; - -/** @brief Get alarm response command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_alarm_get_alarm_res_s -{ - zb_uint8_t status; /**< Status field */ - zb_uint8_t alarm_code; /**< Alarm code field */ - zb_uint16_t cluster_id; /**< Cluster ID field */ - zb_uint32_t timestamp; /**< TimeStamp field */ -} ZB_PACKED_STRUCT zb_zcl_alarm_get_alarm_res_t; - -/** @internal Get alarm response size */ -#define ZB_ZCL_ALARM_GET_ALARM_RES_SIZE \ - sizeof(zb_zcl_alarm_get_alarm_res_t) - -/** @internal Get alarm response header size */ -#define ZB_ZCL_ALARM_GET_ALARM_HDR_RES_SIZE \ - sizeof(zb_zcl_alarm_get_alarm_hdr_res_t) - -/*! @brief Send Alarm command (to client) - @param buffer to put data to - @param addr - address of the device to send command to - @param dst_addr_mode - addressing mode - @param dst_ep destination endpoint - @param ep - current endpoint - @param prof_id - profile identifier - @param cb - callback to call to report send status - @param alarm_code - Alarm Code - @param cluster_id - Cluster Id -*/ -#define ZB_ZCL_ALARMS_SEND_ALARM_RES( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cb, alarm_code, cluster_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_ALARMS_ALARM_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (alarm_code)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (cluster_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_ALARMS, cb); \ -} - -/** @brief Parses Reset alarm command and fills in data request - structure. If request contains invalid data, status will set to ZB_FALSE. - @param data_ptr - pointer to a variable of type @ref zb_zcl_alarms_alarm_res_t. - @param buffer containing the packet (by pointer). - @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_ALARMS_GET_ALARM_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_alarms_alarm_res_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_alarms_alarm_res_t *src_ptr = \ - (zb_zcl_alarms_alarm_res_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->alarm_code = src_ptr->alarm_code; \ - ZB_HTOLE16(&((data_ptr)->cluster_id), &(src_ptr->cluster_id)); \ - } \ -} - - -/** @brief Parses Get alarm response command and returns response data - structure or status = ZB_FALSE if request contains invalid data. - @param data_buf - pointer to zb_buf_t buffer containing command response data - @param get_alarm_res - command response record - @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t) - @note data_buf buffer should contain response command payload without ZCL header - */ -#define ZB_ZCL_ALARMS_GET_GET_ALARM_RES(data_buf, get_alarm_res, status) \ -{ \ - zb_zcl_alarm_get_alarm_res_t *get_alarm_res_ptr; \ - if (zb_buf_len(data_buf) >= ZB_ZCL_ALARM_GET_ALARM_HDR_RES_SIZE) \ - { \ - (get_alarm_res_ptr) = zb_buf_begin(data_buf); \ - get_alarm_res.status = get_alarm_res_ptr->status; \ - if (zb_buf_len(data_buf) >= ZB_ZCL_ALARM_GET_ALARM_RES_SIZE) \ - { \ - get_alarm_res.alarms_code = get_alarm_res_ptr->alarm_code; \ - ZB_HTOLE16(&(get_alarm_res).cluster_id, &(get_alarm_res_ptr->cluster_id)); \ - ZB_HTOLE32(&(get_alarm_res).timestamp, &(get_alarm_res_ptr->timestamp)); \ - } \ - status = ZB_TRUE; \ - } \ - else \ - { \ - status = ZB_FALSE; \ - } \ -} - -/*! @} */ /* Alarms cluster commands */ - -/*! @internal @name Alarms cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -/*! @internal Number of attributes mandatory for reporting in Alarms cluster */ -#define ZB_ZCL_ALARMS_REPORT_ATTR_COUNT 0 - - -/*! @} */ /* Alarms cluster internals */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_alarms_init_server(void); -void zb_zcl_alarms_init_client(void); - -#define ZB_ZCL_CLUSTER_ID_ALARMS_SERVER_ROLE_INIT zb_zcl_alarms_init_server -#define ZB_ZCL_CLUSTER_ID_ALARMS_CLIENT_ROLE_INIT zb_zcl_alarms_init_client - -#endif /* ZB_ZCL_ALARMS_H */ diff --git a/zboss/development/include/zcl/zb_zcl_basic.h b/zboss/development/include/zcl/zb_zcl_basic.h deleted file mode 100644 index cb12571ab2..0000000000 --- a/zboss/development/include/zcl/zb_zcl_basic.h +++ /dev/null @@ -1,586 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Basic Cluster definitions -*/ -#ifndef ZB_ZCL_BASIC_H -#define ZB_ZCL_BASIC_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_BASIC - * @{ - * @details - * According to ZCL spec, clause 3.2, Basic cluster contains attributes only. These attributes - * could be queried with @ref ZB_ZCL_COMMANDS "general ZCL commands". - */ - -/** @name Basic cluster attributes - * @{ - */ - -/** @brief Basic cluster information attribute set identifiers - @see ZCL spec, subclauses 3.2.2.2.1 to 3.2.2.2.9 -*/ -enum zb_zcl_basic_info_attr_e -{ - /** ZCL version attribute */ - ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID = 0x0000, - /** Application version attribute */ - ZB_ZCL_ATTR_BASIC_APPLICATION_VERSION_ID = 0x0001, - /** Stack version attribute */ - ZB_ZCL_ATTR_BASIC_STACK_VERSION_ID = 0x0002, - /** Hardware version attribute */ - ZB_ZCL_ATTR_BASIC_HW_VERSION_ID = 0x0003, - /** Manufacturer name attribute */ - ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID = 0x0004, - /** Model identifier attribute */ - ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID = 0x0005, - /** Date code attribute */ - ZB_ZCL_ATTR_BASIC_DATE_CODE_ID = 0x0006, - /** Power source attribute */ - ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID = 0x0007, - /** The GenericDeviceClass attribute defines the field of application of the - * GenericDeviceType attribute. */ - ZB_ZCL_ATTR_BASIC_GENERIC_DEVICE_CLASS_ID = 0x0008, - /** The GenericDeviceType attribute allows an application to show an icon on - * a rich user interface (e.g. smartphone app). */ - ZB_ZCL_ATTR_BASIC_GENERIC_DEVICE_TYPE_ID = 0x0009, - /** The ProductCode attribute allows an application to specify a code for - * the product. */ - ZB_ZCL_ATTR_BASIC_PRODUCT_CODE_ID = 0x000a, - /** The ProductURL attribute specifies a link to a web page containing specific - * product information. */ - ZB_ZCL_ATTR_BASIC_PRODUCT_URL_ID = 0x000b, - /** Vendor specific human readable (displayable) string representing the versions - * of one of more program images supported on the device. */ - ZB_ZCL_ATTR_BASIC_MANUFACTURER_VERSION_DETAILS_ID = 0x000c, - /** Vendor specific human readable (displayable) serial number. */ - ZB_ZCL_ATTR_BASIC_SERIAL_NUMBER_ID = 0x000d, - /** Vendor specific human readable (displayable) product label. */ - ZB_ZCL_ATTR_BASIC_PRODUCT_LABEL_ID = 0x000e, - /** Manufacturer-specific reference to the version of the software. */ - ZB_ZCL_ATTR_BASIC_SW_BUILD_ID = 0x4000, -}; - -/** @brief Basic cluster settings attribute set identifiers - @see ZCL spec, subclauses 3.2.2.2.10 to 3.2.2.2.15 -*/ -enum zb_zcl_basic_settings_attr_e -{ - /*! Location description attribute */ - ZB_ZCL_ATTR_BASIC_LOCATION_DESCRIPTION_ID = 0x0010, - /*! Physical environment attribute */ - ZB_ZCL_ATTR_BASIC_PHYSICAL_ENVIRONMENT_ID = 0x0011, - /*! Device enabled attribute */ - ZB_ZCL_ATTR_BASIC_DEVICE_ENABLED_ID = 0x0012, - /*! Alarm mask attribute */ - ZB_ZCL_ATTR_BASIC_ALARM_MASK_ID = 0x0013, - /*! Disable local config attribute */ - ZB_ZCL_ATTR_BASIC_DISABLE_LOCAL_CONFIG_ID = 0x0014 -}; - -/** - * @brief Permitted values for "Power source" attribute. - * @see ZCL spec, subclauses 3.2.2.2.9. - */ -enum zb_zcl_basic_power_source_e -{ - ZB_ZCL_BASIC_POWER_SOURCE_UNKNOWN = 0x00, /**< Power source unknown. */ - ZB_ZCL_BASIC_POWER_SOURCE_MAINS_SINGLE_PHASE = 0x01, /**< Single-phase mains. */ - ZB_ZCL_BASIC_POWER_SOURCE_MAINS_THREE_PHASE = 0x02, /**< 3-phase mains. */ - ZB_ZCL_BASIC_POWER_SOURCE_BATTERY = 0x03, /**< Battery source. */ - ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE = 0x04, /**< DC source. */ - ZB_ZCL_BASIC_POWER_SOURCE_EMERGENCY_MAINS_CONST = 0x05, /**< Emergency mains constantly - powered. */ - ZB_ZCL_BASIC_POWER_SOURCE_EMERGENCY_MAINS_TRANSF = 0x06 /**< Emergency mains and transfer - switch. */ -}; - -/** @brief Basic permitted values for "Physical environment" attribute. - @note most of values are profile-specific. - @see ZCL spec, subclause 3.2.2.2.12 -*/ -enum zb_zcl_basic_physical_env_e -{ - /*! Environment unspecified */ - ZB_ZCL_BASIC_ENV_UNSPECIFIED = 0, - /*! Environment unknown */ - ZB_ZCL_BASIC_ENV_UNKNOWN = 0xff -}; - -/** @brief Permitted bits for "Alarm mask" attribute - @see ZCL spec, subclause 3.2.2.2.14 -*/ -enum zb_zcl_basic_alarm_mask_e -{ - /*! General hardware fault */ - ZB_ZCL_BASIC_ALARM_MASK_HW_FAULT = 0, - /*! General software fault */ - ZB_ZCL_BASIC_ALARM_MASK_SW_FAULT = 1 -}; - -/** @brief Value structure for "Disable local config" attribute - @see ZCL spec, subclause 3.2.2.2.15 -*/ -typedef struct zb_zcl_basic_disable_local_conf_s -{ - /*! Reset to factory defaults disabled */ - zb_bitfield_t reset_disabled : 1; - /*! Device configuration enabled */ - zb_bitfield_t config_enabled : 1; - /*! Reserved bits */ - zb_bitfield_t reserved : 6; -} zb_zcl_basic_disable_local_conf_t; - -/** @brief Default value for Basic cluster revision global attribute */ -#define ZB_ZCL_BASIC_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/** @brief Default value for ZCL version attribute */ -#define ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE ((zb_uint8_t)ZB_ZCL_VERSION) - -/** @brief Default value for Application version attribute */ -#define ZB_ZCL_BASIC_APPLICATION_VERSION_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for Stack version attribute */ -#define ZB_ZCL_BASIC_STACK_VERSION_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for Hardware version attribute */ -#define ZB_ZCL_BASIC_HW_VERSION_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for Manufacturer name attribute */ -#define ZB_ZCL_BASIC_MANUFACTURER_NAME_DEFAULT_VALUE {0} - -/** @brief Default value for Model identifier attribute */ -#define ZB_ZCL_BASIC_MODEL_IDENTIFIER_DEFAULT_VALUE {0} - -/** @brief Default value for Date code attribute */ -#define ZB_ZCL_BASIC_DATE_CODE_DEFAULT_VALUE {0} - -/** @brief Default value for Power source attribute */ -#define ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE (ZB_ZCL_BASIC_POWER_SOURCE_UNKNOWN) - -/** @brief Default value for GenericDeviceClass attribute */ -#define ZB_ZCL_BASIC_GENERIC_DEVICE_CLASS_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for GenericDeviceType attribute */ -#define ZB_ZCL_BASIC_GENERIC_DEVICE_TYPE_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for ProductCode attribute */ -#define ZB_ZCL_BASIC_PRODUCT_CODE_DEFAULT_VALUE {0} - -/** @brief Default value for ProductURL attribute */ -#define ZB_ZCL_BASIC_PRODUCT_URL_DEFAULT_VALUE {0} -/** @brief Default value for ManufacturerVersionDetails attribute */ - -#define ZB_ZCL_BASIC_MANUFACTURER_VERSION_DETAILS_DEFAULT_VALUE {0} -/** @brief Default value for SerialNumber attribute */ - -#define ZB_ZCL_BASIC_SERIAL_NUMBER_DEFAULT_VALUE {0} -/** @brief Default value for ProductLabel attribute */ - -#define ZB_ZCL_BASIC_PRODUCT_LABEL_DEFAULT_VALUE {0} - -/** @brief Default value for location description attribute */ -#define ZB_ZCL_BASIC_LOCATION_DESCRIPTION_DEFAULT_VALUE {0} - -/** @brief Default value for Physical environment attribute */ -#define ZB_ZCL_BASIC_PHYSICAL_ENVIRONMENT_DEFAULT_VALUE (ZB_ZCL_BASIC_ENV_UNSPECIFIED) - -/** @brief Default value for Device enabled attribute */ -#define ZB_ZCL_BASIC_DEVICE_ENABLED_DEFAULT_VALUE ((zb_uint8_t)0x01) - -/** @brief Default value for Alarm mask attribute */ -#define ZB_ZCL_BASIC_ALARM_MASK_DEFAULT_VALUE (ZB_ZCL_BASIC_ALARM_MASK_HW_FAULT) - -/** @brief Default value for Disable local config attribute */ -#define ZB_ZCL_BASIC_DISABLE_LOCAL_CONFIG_DEFAULT_VALUE ((zb_zcl_basic_disable_local_conf_t){0,0,0}) - -/** - * @brief Default value for SWBuildId attribute. - * @note Default value supposes that attribute will be stored as Pascal-style string (i. e. - * length-byte, then content). - */ -#define ZB_ZCL_BASIC_SW_BUILD_ID_DEFAULT_VALUE {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_APPLICATION_VERSION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_APPLICATION_VERSION_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_STACK_VERSION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_STACK_VERSION_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_HW_VERSION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_HW_VERSION_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_DATE_CODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_DATE_CODE_ID, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_LOCATION_DESCRIPTION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_LOCATION_DESCRIPTION_ID, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_PHYSICAL_ENVIRONMENT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_PHYSICAL_ENVIRONMENT_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_DEVICE_ENABLED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_DEVICE_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BASIC_SW_BUILD_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BASIC_SW_BUILD_ID, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#if defined ZB_ZCL_SUPPORT_CLUSTER_SCENES -/*! Scenes field set length for Basic cluster */ -#define ZB_ZCL_CLUSTER_ID_BASIC_SCENE_FIELD_SETS_LENGTH 0 -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_SCENES */ - -/** @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for Basic cluster - @param attr_list - attribute list name - @param zcl_version - pointer to variable to store zcl version attribute value - @param power_source - pointer to variable to store power source attribute value - - @snippet lighting/dimmable_light_tl/light_device_zr.c BASIC_CLUSTER_DECLARE -*/ -#define ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST(attr_list, zcl_version, power_source) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_BASIC) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID, (zcl_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, (power_source)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @brief Declare attribute list for Basic cluster - @param attr_list - attribute list name - @param zcl_version - pointer to variable to store zcl version attribute value - @param power_source - pointer to variable to store power source attribute value - @param device_enabled - pointer to variable to store device enabled attribute value -*/ -#define ZB_ZCL_DECLARE_BASIC_WITH_DEVICE_ENABLED_ATTRIB_LIST(attr_list, zcl_version, power_source, device_enabled) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_BASIC) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID, (zcl_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, (power_source)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_DEVICE_ENABLED_ID, (device_enabled)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** - * @brief Declare attribute list for Basic cluster (extended attribute set). - * @param attr_list [IN] - attribute list name. - * @param zcl_version [IN] - pointer to variable storing ZCL version attribute value. - * @param app_version [IN] - pointer to the variable storing application version. - * @param stack_version [IN] - pointer to the variable storing stack version. - * @param hardware_version [IN] - pointer to the variable storing hardware version. - * @param manufacturer_name [IN] - pointer to the variable storing manufacturer name. - * @param model_id [IN] - pointer to the variable storing model identifier. - * @param date_code [IN] - pointer to the variable storing date code. - * @param power_source [IN] - pointer to variable storing power source attribute value. - * @param location_id [IN] - pointer to variable storing location description attribute value. - * @param ph_env [IN] - pointer to variable storing physical environment attribute value. - * @param sw_build_id [IN] - pointer to the variable storing software version reference. - */ -#define ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT( \ - attr_list, \ - zcl_version, \ - app_version, \ - stack_version, \ - hardware_version, \ - manufacturer_name, \ - model_id, \ - date_code, \ - power_source, \ - location_id, \ - ph_env, \ - sw_build_id) \ - zb_bool_t device_enable_##attr_list = ZB_TRUE; \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_BASIC) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID, (zcl_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_APPLICATION_VERSION_ID, (app_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_STACK_VERSION_ID, (stack_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_HW_VERSION_ID, (hardware_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (manufacturer_name))\ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (model_id)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_DATE_CODE_ID, (date_code)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, (power_source)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_SW_BUILD_ID, (sw_build_id)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_DEVICE_ENABLED_ID, \ - &(device_enable_##attr_list)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_LOCATION_DESCRIPTION_ID, (location_id)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_PHYSICAL_ENVIRONMENT_ID, (ph_env)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** - * @brief Declare attribute list for Basic cluster (extended attribute set). - * @param attr_list [IN] - attribute list name. - * @param zcl_version [IN] - pointer to variable storing ZCL version attribute value. - * @param app_version [IN] - pointer to the variable storing application version. - * @param stack_version [IN] - pointer to the variable storing stack version. - * @param hardware_version [IN] - pointer to the variable storing hardware version. - * @param manufacturer_name [IN] - pointer to the variable storing manufacturer name. - * @param model_id [IN] - pointer to the variable storing model identifier. - * @param date_code [IN] - pointer to the variable storing date code. - * @param power_source [IN] - pointer to variable storing power source attribute value. - * @param location_id [IN] - pointer to variable storing location description attribute value. - * @param ph_env [IN] - pointer to variable storing physical environment attribute value. - * @param sw_build_id [IN] - pointer to the variable storing software version reference. - * @param device_enabled - pointer to the variable storing device enabled reference. - */ -#define ZB_ZCL_DECLARE_BASIC_WITH_DEVICE_ENABLED_ATTRIB_LIST_EXT( \ - attr_list, \ - zcl_version, \ - app_version, \ - stack_version, \ - hardware_version, \ - manufacturer_name, \ - model_id, \ - date_code, \ - power_source, \ - location_id, \ - ph_env, \ - sw_build_id, \ - device_enabled) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_BASIC) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID, (zcl_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_APPLICATION_VERSION_ID, (app_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_STACK_VERSION_ID, (stack_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_HW_VERSION_ID, (hardware_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (manufacturer_name))\ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (model_id)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_DATE_CODE_ID, (date_code)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, (power_source)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_SW_BUILD_ID, (sw_build_id)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_DEVICE_ENABLED_ID, (device_enabled)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_LOCATION_DESCRIPTION_ID, (location_id)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BASIC_PHYSICAL_ENVIRONMENT_ID, (ph_env)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! Maximum length of ManufacturerName string field */ -#define ZB_ZCL_CLUSTER_ID_BASIC_MANUFACTURER_NAME_MAX_LEN 32 - -/*! Maximum length of ModelIdentifier string field */ -#define ZB_ZCL_CLUSTER_ID_BASIC_MODEL_IDENTIFIER_MAX_LEN 32 - -/** - * @brief Basic cluster attributes - */ -typedef struct zb_zcl_basic_attrs_s -{ - /** @copydoc ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID - * @see ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID - */ - zb_uint8_t zcl_version; - - /** @copydoc ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID - * @see ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID - */ - zb_uint8_t power_source; -} zb_zcl_basic_attrs_t; - - -/** @brief Declare attribute list for Basic cluster cluster - * @param[in] attr_list - attribute list variable name - * @param[in] attrs - variable of @ref zb_zcl_basic_attrs_t type (containing Basic cluster attributes) - */ -#define ZB_ZCL_DECLARE_BASIC_ATTR_LIST(attr_list, attrs) \ - ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST(attr_list, &attrs.zcl_version, &attrs.power_source) - -/** @} */ /* Basic cluster attributes */ - -/*! @name Alarms cluster commands - @{ -*/ - -/*! @brief Basic cluster command identifiers - @see ZCL spec, subclause 3.2.2.3 -*/ -enum zb_zcl_basic_cmd_e -{ - ZB_ZCL_CMD_BASIC_RESET_ID = 0x00, /**< "Reset to Factory Defaults" command. */ -}; - -/** @cond internals_doc */ -/* Basic cluster commands lists : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_BASIC_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CMD_BASIC_RESET_ID - -#define ZB_ZCL_CLUSTER_ID_BASIC_CLIENT_ROLE_GENERATED_CMD_LIST ZB_ZCL_CLUSTER_ID_BASIC_SERVER_ROLE_RECEIVED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -//////////////////////////////////////// - -/*! @brief Send Reset to Factory Defaults command - @param buffer to put data to - @param addr - address of the device to send command to - @param dst_addr_mode - addressing mode - @param dst_ep destination endpoint - @param ep - current endpoint - @param prof_id - profile identifier - @param dis_default_resp - "Disable default response" flag - @param cb - callback to call to report send status -*/ -#define ZB_ZCL_BASIC_SEND_RESET_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_BASIC_RESET_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_BASIC, cb); \ -} - - -/** Call device callback in user application to reset application settings to defaults. - * @param[in] buffer - pointer to buffer for callback - * @param[in] ep - current endpoint - * @param[out] result - callback status - */ -#define ZB_ZCL_RESET_TO_FACTORY_DEFAULTS_USER_APP(buffer, ep, result) \ -{ \ - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_RESET_TO_FACTORY_DEFAULTS_USER_APP", (FMT__0)); \ - if (ZCL_CTX().device_cb) \ - { \ - zb_zcl_device_callback_param_t *user_app_data = \ - ZB_BUF_GET_PARAM(buffer, zb_zcl_device_callback_param_t); \ - user_app_data->device_cb_id = ZB_ZCL_BASIC_RESET_CB_ID; \ - user_app_data->endpoint = (ep); \ - user_app_data->status = RET_OK; \ - (ZCL_CTX().device_cb)(param); \ - result = user_app_data->status; \ - } \ -} - -/*! @brief Check Device Enabled attribute value and should the stack process command or not. - @see ZCL spec, subclause 3.2.2.2.18 DeviceEnabled Attribute - @param ep_id Endpoint ID - @param cmd_id Command ID - @param cluster_id Cluster ID - @param is_common_command Is command common or cluster specific - @return ZB_TRUE if command should be processed or sent, ZB_FALSE otherwise -*/ -zb_bool_t zb_zcl_check_is_device_enabled(zb_uint8_t ep_id, zb_uint8_t cmd_id, zb_uint16_t cluster_id, zb_bool_t is_common_command); - -/** @} */ /* Basic cluster commands */ - -/*! @} */ /* ZCL Basic cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_basic_init_server(void); -void zb_zcl_basic_init_client(void); - -#define ZB_ZCL_CLUSTER_ID_BASIC_SERVER_ROLE_INIT zb_zcl_basic_init_server -#define ZB_ZCL_CLUSTER_ID_BASIC_CLIENT_ROLE_INIT zb_zcl_basic_init_client - -#endif /* ZB_ZCL_BASIC_H */ diff --git a/zboss/development/include/zcl/zb_zcl_binary_input.h b/zboss/development/include/zcl/zb_zcl_binary_input.h deleted file mode 100644 index 8a6a3e54eb..0000000000 --- a/zboss/development/include/zcl/zb_zcl_binary_input.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Binary Input cluster -*/ - -#ifndef ZB_ZCL_BINARY_INPUT_H -#define ZB_ZCL_BINARY_INPUT_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_BINARY_INPUT - * @{ - * @details - * According to ZCL spec, subclause 3.14.4, Binary Input (Basic) cluster has no cluster-specific - * commands. Cluster attributes could be queried with - * @ref ZB_ZCL_COMMANDS "general ZCL commands". - * - * - */ - -/* ZB_ZCL_CLUSTER_ID_BINARY_INPUT = 0x000f defined in zb_zcl_common.h ZCL spec 3.14.4 */ - -/*! @name Binary Input cluster attributes - @{ -*/ - -/** @brief Binary Input cluster attribute identifiers. */ -enum zb_zcl_binary_input_attr_e -{ - /** This attribute, of type Character string, MAY be used to hold a human readable - * description of the ACTIVE state of a binary PresentValue. */ - ZB_ZCL_ATTR_BINARY_INPUT_ACTIVE_TEXT_ID = 0x0004, - /** The Description attribute, of type Character string, MAY be used to hold a - * description of the usage of the input, output or value, as appropriate - * to the cluster. */ - ZB_ZCL_ATTR_BINARY_INPUT_DESCRIPTION_ID = 0x001C, - /** This attribute, of type Character string, MAY be used to hold a human readable - * description of the INACTIVE state of a binary PresentValue. */ - ZB_ZCL_ATTR_BINARY_INPUT_INACTIVE_TEXT_ID = 0x002E, - - /** @brief OutOfService attribute */ - ZB_ZCL_ATTR_BINARY_INPUT_OUT_OF_SERVICE_ID = 0x0051, - /** This attribute, of type enumeration, indicates the relationship between - * the physical state of the input (or output as appropriate for the cluster) - * and the logical state represented by a binary PresentValue attribute, - * when OutOfService is FALSE. */ - ZB_ZCL_ATTR_BINARY_INPUT_POLARITY_ID = 0x0054, - - /** @brief PresentValue attribute */ - ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID = 0x0055, - -// adding GP specific attributes - ZB_ZCL_ATTR_GP_ATTR_BINARY_INPUT_BATTERY_VALUE_ID = 0x0056, - ZB_ZCL_ATTR_GP_ATTR_BINARY_INPUT_TEMPERATURE_VALUE_ID = 0x0057, - ZB_ZCL_ATTR_GP_ATTR_BINARY_INPUT_TAMPER_VALUE_ID = 0x0058, -// end GP specific attributes - /** The Reliability attribute, of type 8-bit enumeration, provides an indication - * of whether the PresentValue or the operation of the physical input, - * output or value in question (as appropriate for the cluster) is reliable - * as far as can be determined and, if not, why not. */ - ZB_ZCL_ATTR_BINARY_INPUT_RELIABILITY_ID = 0x0067, - - /** @brief StatusFlag attribute */ - ZB_ZCL_ATTR_BINARY_INPUT_STATUS_FLAG_ID = 0x006F, - /** The ApplicationType attribute is an unsigned 32-bit integer that indicates - * the specific application usage for this cluster. */ - ZB_ZCL_ATTR_BINARY_INPUT_APPLICATION_TYPE_ID = 0x0100, -}; - -/** - * @brief StatusFlag attribute values. - * @see ZCL spec 3.14.10.3. - */ -enum zb_zcl_binary_input_status_flag_value_e -{ - ZB_ZCL_BINARY_INPUT_STATUS_FLAG_NORMAL = 0x00, /**< Normal (default) state. */ - ZB_ZCL_BINARY_INPUT_STATUS_FLAG_IN_ALARM = 0x01, /**< In alarm bit. */ - ZB_ZCL_BINARY_INPUT_STATUS_FLAG_FAULT = 0x02, /**< Fault bit. */ - ZB_ZCL_BINARY_INPUT_STATUS_FLAG_OVERRIDEN = 0x04, /**< Overridden bit. */ - ZB_ZCL_BINARY_INPUT_STATUS_FLAG_OUT_OF_SERVICE = 0x08, /**< Out of service bit. */ -}; - -/** @brief Default value for Binary Input cluster revision global attribute */ -#define ZB_ZCL_BINARY_INPUT_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/** @brief Default value for ActiveText attribute */ -#define ZB_ZCL_BINARY_INPUT_ACTIVE_TEXT_DEFAULT_VALUE {0} - -/** @brief Default value for Description attribute */ -#define ZB_ZCL_BINARY_INPUT_DESCRIPTION_DEFAULT_VALUE {0} - -/** @brief Default value for InactiveText attribute */ -#define ZB_ZCL_BINARY_INPUT_INACTIVE_TEXT_DEFAULT_VALUE {0} - -/*! @brief OutOfService attribute default value */ -#define ZB_ZCL_BINARY_INPUT_OUT_OF_SERVICE_DEFAULT_VALUE ZB_FALSE - -/** @brief Default value for Polarity attribute */ -#define ZB_ZCL_BINARY_INPUT_POLARITY_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for Reliability attribute */ -#define ZB_ZCL_BINARY_INPUT_RELIABILITY_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/*! @brief StatusFlag attribute default value */ -#define ZB_ZCL_BINARY_INPUT_STATUS_FLAG_DEFAULT_VALUE ZB_ZCL_BINARY_INPUT_STATUS_FLAG_NORMAL - -/*! @brief StatusFlag attribute minimum value */ -#define ZB_ZCL_BINARY_INPUT_STATUS_FLAG_MIN_VALUE 0 - -/*! @brief StatusFlag attribute maximum value */ -#define ZB_ZCL_BINARY_INPUT_STATUS_FLAG_MAX_VALUE 0x0F - -/** @brief Declare attribute list for Binary Input cluster - @param attr_list - attribute list name - @param out_of_service - pointer to variable to store OutOfService attribute value - @param present_value - pointer to variable to store PresentValue attribute value - @param status_flag - pointer to variable to store StatusFlag attribute value -*/ -#define ZB_ZCL_DECLARE_BINARY_INPUT_ATTRIB_LIST( \ - attr_list, out_of_service, present_value, status_flag) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_BINARY_INPUT) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BINARY_INPUT_OUT_OF_SERVICE_ID, (out_of_service)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID, (present_value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BINARY_INPUT_STATUS_FLAG_ID, (status_flag)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Binary Input cluster attributes */ - -/*! @name Binary input attribute value manipulation API - @{ -*/ - -/** @brief Set normal operating mode - @param ep - endpoint number -*/ -#define ZB_ZCL_BINARY_INPUT_SET_NORMAL_MODE(ep) \ -{ \ - zb_uint8_t val; \ - \ - val = ZB_FALSE; \ - ZB_ZCL_SET_ATTRIBUTE(ep, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - ZB_ZCL_ATTR_BINARY_INPUT_OUT_OF_SERVICE_ID, \ - &val, ZB_FALSE); \ - \ - val = ZB_ZCL_BINARY_INPUT_STATUS_FLAG_NORMAL; \ - ZB_ZCL_SET_ATTRIBUTE(ep, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - ZB_ZCL_ATTR_BINARY_INPUT_STATUS_FLAG_ID, \ - &val, ZB_FALSE); \ -} - -/** @brief Set Out of service operating mode - @param ep - endpoint number -*/ -#define ZB_ZCL_BINARY_INPUT_SET_OUT_OF_SERVICE(ep) \ -{ \ - zb_zcl_attr_t *attr_desc; \ - zb_uint8_t val; \ - \ - val = ZB_TRUE; \ - ZB_ZCL_SET_ATTRIBUTE(ep, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - ZB_ZCL_ATTR_BINARY_INPUT_OUT_OF_SERVICE_ID, \ - &val, ZB_FALSE); \ - \ - attr_desc = zb_zcl_get_attr_desc_a(ep, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - ZB_ZCL_ATTR_BINARY_INPUT_STATUS_FLAG_ID); \ - if (attr_desc) \ - { \ - val = *(zb_uint8_t*)attr_desc->data_p | ZB_ZCL_BINARY_INPUT_STATUS_FLAG_OUT_OF_SERVICE; \ - ZB_ZCL_SET_ATTRIBUTE(ep, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - ZB_ZCL_ATTR_BINARY_INPUT_STATUS_FLAG_ID, \ - &val, ZB_FALSE); \ - } \ -} - -/** @brief Set overridden operating mode - @param ep - endpoint number -*/ -#define ZB_ZCL_BINARY_INPUT_SET_OVERRIDEN_MODE(ep) \ -{ \ - zb_zcl_attr_t *attr_desc; \ - zb_uint8_t val; \ - \ - attr_desc = zb_zcl_get_attr_desc_a(ep, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - ZB_ZCL_ATTR_BINARY_INPUT_STATUS_FLAG_ID); \ - if (attr_desc) \ - { \ - val = *(zb_uint8_t*)attr_desc->data_p | ZB_ZCL_BINARY_INPUT_STATUS_FLAG_OVERRIDEN; \ - ZB_ZCL_SET_ATTRIBUTE(ep, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - ZB_ZCL_ATTR_BINARY_INPUT_STATUS_FLAG_ID, \ - &val, ZB_FALSE); \ - } \ -} - -/*! @} */ /* Binary input cluster commands */ - -/** @cond internals_doc */ -/** @name Binary Input cluster internals - Internal structures for Binary Input cluster - @{ -*/ - -/* Optionally, access to this attribute may be changed to READ_WRITE */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BINARY_INPUT_OUT_OF_SERVICE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BINARY_INPUT_OUT_OF_SERVICE_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL, \ - (void*) data_ptr \ -} - -/* Optionally, access to this attribute may be changed to READ_WRITE */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BINARY_INPUT_STATUS_FLAG_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_BINARY_INPUT_STATUS_FLAG_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -/*! Number of attributes mandatory for reporting in Binary Input cluster */ -#define ZB_ZCL_BINARY_INPUT_REPORT_ATTR_COUNT 2 - -/*! @} - * @endcond */ /* Binary Input cluster internals */ - - -/*! @} */ /* ZCL Binary Input cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_binary_input_init_server(void); -void zb_zcl_binary_input_init_client(void); -#define ZB_ZCL_CLUSTER_ID_BINARY_INPUT_SERVER_ROLE_INIT zb_zcl_binary_input_init_server -#define ZB_ZCL_CLUSTER_ID_BINARY_INPUT_CLIENT_ROLE_INIT zb_zcl_binary_input_init_client - -#endif /* ZB_ZCL_BINARY_INPUT_H */ diff --git a/zboss/development/include/zcl/zb_zcl_color_control.h b/zboss/development/include/zcl/zb_zcl_color_control.h deleted file mode 100644 index 5074aa61cb..0000000000 --- a/zboss/development/include/zcl/zb_zcl_color_control.h +++ /dev/null @@ -1,3440 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Color control cluster definitions -*/ - -#ifndef ZB_ZCL_COLOR_CONTROL_H -#define ZB_ZCL_COLOR_CONTROL_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_COLOR_CONTROL - @{ -*/ - -/* ZB_ZCL_CLUSTER_ID_COLOR_CONTROL = 0x0300 defined in zb_zcl_common.h */ - -/*! @name Color Control cluster attributes - @{ -*/ - -/** @brief Color Control cluster information attribute identifiers - @see ZCL spec, subclause 5.2.2.2.3 -*/ - -/** - * @brief Color control attribute list - */ -enum zb_zcl_color_control_attr_e -{ - /** @internal Current_HUE attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID = 0x0000, - /** @internal Current Saturation attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID = 0x0001, - /** @internal Remaining Time attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_REMAINING_TIME_ID = 0x0002, - /** @internal CurrentX attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID = 0x0003, - /** @internal CurrentY attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID = 0x0004, - /** The DriftCompensation attribute indicates what mechanism, if any, is in use for - * compensation for color/intensity drift over time. */ - ZB_ZCL_ATTR_COLOR_CONTROL_DRIFT_COMPENSATION_ID = 0x0005, - /** The CompensationText attribute holds a textual indication of what mechanism, - * if any, is in use to compensate for color/intensity drift over time. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COMPENSATION_TEXT_ID = 0x0006, - /** @internal Color Temperature Mireds attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID = 0x0007, - /** @internal Color Mode attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_MODE_ID = 0x0008, - /** The Options attribute is a bitmap that determines the default behavior of some - * cluster commands. */ - ZB_ZCL_ATTR_COLOR_CONTROL_OPTIONS_ID = 0x000f, - /** The EnhancedCurrentHue attribute represents non-equidistant steps along the - * CIE 1931 color triangle, and it provides 16-bits precision. */ - ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID = 0x4000, - /** The EnhancedColorMode attribute specifies which attributes are currently - * determining the color of the device. */ - ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID = 0x4001, - /** The ColorLoopActive attribute specifies the current active status of the color - * loop. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_ACTIVE_ID = 0x4002, - /** The ColorLoopDirection attribute specifies the current direction of the color - * loop. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_DIRECTION_ID = 0x4003, - /** The ColorLoopTime attribute specifies the number of seconds it SHALL take to - * perform a full color loop, i.e., to cycle all values of the EnhancedCurrentHue - * attribute (between 0x0000 and 0xffff). */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_TIME_ID = 0x4004, - /** The ColorLoopStartEnhancedHue attribute specifies the value of the - * EnhancedCurrentHue attribute from which the color loop SHALL be started. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_START_ENHANCED_HUE_ID = 0x4005, - /** The ColorLoopStoredEnhancedHue attribute specifies the value of the - * EnhancedCurrentHue attribute before the color loop was started. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_STORED_ENHANCED_HUE_ID = 0x4006, - /** The ColorCapabilities attribute specifies the color capabilities of the device - * supporting the color control cluster. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_CAPABILITIES_ID = 0x400a, - /** The ColorTempPhysicalMinMireds attribute indicates the minimum mired value - * supported by the hardware. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_ID = 0x400b, - /** The ColorTempPhysicalMaxMireds attribute indicates the maximum mired value - * supported by the hardware. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_ID = 0x400c, - /** The CoupleColorTempToLevelMinMireds attribute specifies a lower bound on the - * value of the ColorTemperatureMireds attribute for the purposes of coupling - * the ColorTemperatureMireds attribute to the CurrentLevel attribute when the - * CoupleColorTempToLevel bit of the Options attribute of the Level Control cluster - * is equal to 1. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COUPLE_COLOR_TEMP_TO_LEVEL_MIN_MIREDS_ID = 0x400d, - /** The StartUpColorTemperatureMireds attribute SHALL define the desired startup color - * temperature value a lamp SHALL use when it is supplied with power and this value - * SHALL be reflected in the ColorTemperatureMireds attribute. */ - ZB_ZCL_ATTR_COLOR_CONTROL_START_UP_COLOR_TEMPERATURE_MIREDS_ID = 0x4010, - /** @internal Number Of Primaries attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_NUMBER_OF_PRIMARIES_ID = 0x0010, - /** @internal Primary 1 X attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_X_ID = 0x0011, - /** @internal Primary 1 Y attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_Y_ID = 0x0012, - /** @internal Primary 1 Intensity attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_INTENSITY_ID = 0x0013, - /** @internal Primary 2 X attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_X_ID = 0x0015, - /** @internal Primary 2 Y attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_Y_ID = 0x0016, - /** @internal Primary 2 Intensity attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_INTENSITY_ID = 0x0017, - /** @internal Primary 3 X attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_X_ID = 0x0019, - /** @internal Primary 3 Y attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_Y_ID = 0x001a, - /** @internal Primary 3 Intensity attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_INTENSITY_ID = 0x001b, - /** @internal Primary 4 X attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_X_ID = 0x0020, - /** @internal Primary 4 Y attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_Y_ID = 0x0021, - /** @internal Primary 4 Intensity attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_INTENSITY_ID = 0x0022, - /** @internal Primary 5 X attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_X_ID = 0x0024, - /** @internal Primary 5 Y attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_Y_ID = 0x0025, - /** @internal Primary 5 Intensity attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_INTENSITY_ID = 0x0026, - /** @internal Primary 6 X attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_X_ID = 0x0028, - /** @internal Primary 6 Y attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_Y_ID = 0x0029, - /** @internal Primary 6 Intensity attribute */ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_INTENSITY_ID = 0x002a, - /** The WhitePointX attribute contains the normalized chromaticity value x, as defined - * in the CIE xyY Color Space, of the current white point of the device. */ - ZB_ZCL_ATTR_COLOR_CONTROL_WHITE_POINT_X_ID = 0x0030, - /** The WhitePointY attribute contains the normalized chromaticity value y, as defined - * in the CIE xyY Color Space, of the current white point of the device. */ - ZB_ZCL_ATTR_COLOR_CONTROL_WHITE_POINT_Y_ID = 0x0031, - /** The ColorPointRX attribute contains the normalized chromaticity value x, as defined - * in the CIE xyY Color Space, of the red color point of the device. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_POINT_RX_ID = 0x0032, - /** The ColorPointRY attribute contains the normalized chromaticity value y, as defined - * in the CIE xyY Color Space, of the red color point of the device. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_POINT_RY_ID = 0x0033, - /** The ColorPointRIntensity attribute contains a representation of the relative - * intensity of the red color point as defined in the Dimming Light Curve in the - * Ballast Configuration cluster. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_POINT_R_INTENSITY_ID = 0x0034, - /** The ColorPointGX attribute contains the normalized chromaticity value x, as defined - * in the CIE xyY Color Space, of the green color point of the device. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_POINT_GX_ID = 0x0036, - /** The ColorPointGY attribute contains the normalized chromaticity value y, as defined - * in the CIE xyY Color Space, of the green color point of the device. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_POINT_GY_ID = 0x0037, - /** The ColorPointGIntensity attribute contains a representation of the relative - * intensity of the green color point as defined in the Dimming Light Curve in the - * Ballast Configuration cluster. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_POINT_G_INTENSITY_ID = 0x0038, - /** The ColorPointBX attribute contains the normalized chromaticity value x, as defined - * in the CIE xyY Color Space, of the blue color point of the device. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_POINT_BX_ID = 0x003a, - /** The ColorPointBY attribute contains the normalized chromaticity value y, as defined - * in the CIE xyY Color Space, of the blue color point of the device. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_POINT_BY_ID = 0x003b, - /** The ColorPointBIntensity attribute contains a representation of the relative - * intensity of the blue color point as defined in the Dimming Light Curve in the - * Ballast Configuration cluster. */ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_POINT_B_INTENSITY_ID = 0x003c, -}; - -/** @brief Default value for Color control cluster revision global attribute */ -#define ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/** @brief Maximal value for implemented Color control cluster revision global attribute */ -#define ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_DEFAULT - -/** @brief Current Hue attribute minimum value */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_HUE_MIN_VALUE 0 - -/** @brief Current Hue attribute maximum value */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_HUE_MAX_VALUE 0xfe - -/** Default OptionsMask value */ -#define ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE ((zb_uint8_t)0x00) - -/** Default OptionsOverride value */ -#define ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE ((zb_uint8_t)0x00) - -/** - * @brief Color control Hue value - */ -enum zb_zcl_color_control_hue_e -{ -/** @brief Current Hue attribute red value */ - ZB_ZCL_COLOR_CONTROL_HUE_RED = 0, - -/** @brief Current Hue attribute green value */ - ZB_ZCL_COLOR_CONTROL_HUE_GREEN = 85 /*254 / 3*/, - -/** @brief Current Hue attribute blue value */ - ZB_ZCL_COLOR_CONTROL_HUE_BLUE = 169/*2*254 / 3*/ -}; - -/** @brief Current Saturation attribute minimum value */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_SATURATION_MIN_VALUE 0 - -/** @brief Current Saturation attribute maximum value */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_SATURATION_MAX_VALUE 0xfe - -/** @brief Remaining Time attribute minimum value */ -#define ZB_ZCL_COLOR_CONTROL_REMAINING_TIME_MIN_VALUE 0 - -/** @brief Remaining Time attribute maximum value */ -#define ZB_ZCL_COLOR_CONTROL_REMAINING_TIME_MAX_VALUE 0xfffe - - -/** @brief Current X attribute default value */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_X_DEF_VALUE 0x616b - -/** @brief Default value for CurrentHue attribute */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_HUE_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for CurrentSaturation attribute */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_SATURATION_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for RemainingTime attribute */ -#define ZB_ZCL_COLOR_CONTROL_REMAINING_TIME_DEFAULT_VALUE ((zb_uint16_t)0x00) - -/** @brief Current X attribute minimum value */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_X_MIN_VALUE 0 - -/** @brief Current X attribute maximum value */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_X_MAX_VALUE 0xfeff - -/** @brief Current Y attribute default value */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_Y_DEF_VALUE 0x607d - -/** @brief Current Y attribute minimum value */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_Y_MIN_VALUE 0 - -/** @brief Current Y attribute maximum value */ -#define ZB_ZCL_COLOR_CONTROL_CURRENT_Y_MAX_VALUE 0xfeff - -/** @brief Current Hue attribute red value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_X_RED (zb_uint16_t)(0.735484*ZB_ZCL_COLOR_CONTROL_CURRENT_X_MAX_VALUE) - -/** @brief Current Hue attribute green value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_X_GREEN (zb_uint16_t)(0.0138702*ZB_ZCL_COLOR_CONTROL_CURRENT_X_MAX_VALUE) - -/** @brief Current Hue attribute blue value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_X_BLUE (zb_uint16_t)(0.0995467*ZB_ZCL_COLOR_CONTROL_CURRENT_X_MAX_VALUE) - - -/** @brief Current Hue attribute red value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_Y_RED (zb_uint16_t)(0.264516*ZB_ZCL_COLOR_CONTROL_CURRENT_Y_MAX_VALUE) - -/** @brief Current Hue attribute green value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_Y_GREEN (zb_uint16_t)(0.750186*ZB_ZCL_COLOR_CONTROL_CURRENT_Y_MAX_VALUE) - -/** @brief Current Hue attribute blue value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_Y_BLUE (zb_uint16_t)(0.11196*ZB_ZCL_COLOR_CONTROL_CURRENT_Y_MAX_VALUE) - - -/** @brief Color Temperature default value (4000K) */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_TEMPERATURE_DEF_VALUE 0x00fa - -/** @brief Color Temperature minimum value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_TEMPERATURE_MIN_VALUE 0 - -/** @brief Color Temperature maximum value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_TEMPERATURE_MAX_VALUE 0xfeff - -/** @brief Default value for ColorMode attribute */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_MODE_DEFAULT_VALUE ((zb_uint8_t)0x01) - -/** @brief Default value for Options attribute */ -#define ZB_ZCL_COLOR_CONTROL_OPTIONS_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for EnhancedCurrentHue attribute */ -#define ZB_ZCL_COLOR_CONTROL_ENHANCED_CURRENT_HUE_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for EnhancedColorMode attribute */ -#define ZB_ZCL_COLOR_CONTROL_ENHANCED_COLOR_MODE_DEFAULT_VALUE ((zb_uint8_t)0x01) - -/** @brief Default value for ColorLoopActive attribute */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_LOOP_ACTIVE_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for ColorLoopDirection attribute */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_LOOP_DIRECTION_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Invalid value for Physical Mireds attribute */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIREDS_INVALID_VALUE ((zb_uint16_t)0xffff) - -/*! @brief Color Mode attribute enumeration - @see ZCL spec, subclause 5.2.2.2.1.9 -*/ -enum zb_zcl_color_control_color_mode_e -{ - /** CurrentHue and CurrentSaturation */ - ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION = 0x00, - /** CurrentX and CurrentY */ - ZB_ZCL_COLOR_CONTROL_COLOR_MODE_CURRENT_X_Y = 0x01, - /** ColorTemperature */ - ZB_ZCL_COLOR_CONTROL_COLOR_MODE_TEMPERATURE = 0x02, -}; - - -/** @brief Number Of Primaries attribute maximum value */ -#define ZB_ZCL_COLOR_CONTROL_NUMBER_OF_PRIMARIES_MAX_VALUE 6 - -/** @brief Primary X attribute maximum value */ -#define ZB_ZCL_COLOR_CONTROL_PRIMARY_X_MAX_VALUE 0xfeff - -/** @brief Primary Y attribute maximum value */ -#define ZB_ZCL_COLOR_CONTROL_PRIMARY_Y_MAX_VALUE 0xfeff - -/** @brief Primary Intensity attribute maximum value */ -#define ZB_ZCL_COLOR_CONTROL_PRIMARY_INTENSITY_MAX_VALUE 0xfe - -/** @brief Primary Intensity attribute not used value */ -#define ZB_ZCL_COLOR_CONTROL_PRIMARY_INTENSITY_NON_USED_VALUE 0xff - - -/** @brief Enhanced Hue Max attribute default value */ -#define ZB_ZCL_COLOR_CONTROL_ENHANCED_HUE_MAX_DEF_VALUE 0xffff - -/** @brief Current Hue attribute red value */ -#define ZB_ZCL_COLOR_CONTROL_ENHANCED_HUE_RED (zb_uint16_t)(ZB_ZCL_COLOR_CONTROL_HUE_RED << 8) - -/** @brief Current Hue attribute green value */ -#define ZB_ZCL_COLOR_CONTROL_ENHANCED_GREEN (zb_uint16_t)(ZB_ZCL_COLOR_CONTROL_HUE_GREEN << 8) - -/** @brief Current Hue attribute blue value */ -#define ZB_ZCL_COLOR_CONTROL_ENHANCED_BLUE (zb_uint16_t)(ZB_ZCL_COLOR_CONTROL_HUE_BLUE << 8) - -/** @brief Color Loop Time attribute default value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_LOOP_TIME_DEF_VALUE 0x0019 - -/** @brief Color Loop Start Enhanced Hue attribute default value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_LOOP_START_DEF_VALUE 0x2300 - -/** @brief Default value for ColorLoopStoredEnhancedHue attribute */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_LOOP_STORED_ENHANCED_HUE_DEFAULT_VALUE ((zb_uint16_t)0x0000) -/** @brief Default value for ColorCapabilities attribute */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_CAPABILITIES_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for ColorTempPhysicalMinMireds attribute */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for ColorTempPhysicalMaxMireds attribute */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_DEFAULT_VALUE ((zb_uint16_t)0xFEFF) - -/** @brief Color Capabilities attribute maximum value */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_CAPABILITIES_MAX_VALUE 0x001f - -/** @brief Start Up Color Temperature Mireds Max value */ -#define ZB_ZCL_COLOR_CONTROL_START_UP_COLOR_TEMPERATURE_MAX_VALUE ZB_ZCL_COLOR_CONTROL_COLOR_TEMPERATURE_MAX_VALUE - -/** @brief Start Up Color Temperature Mireds Use Previous value */ -#define ZB_ZCL_COLOR_CONTROL_START_UP_COLOR_TEMPERATURE_USE_PREVIOUS_VALUE 0xffff - -/*! @brief Options attribute flags - @see ZCL spec, subclause 5.2.2.1.1.10 -*/ -enum zb_zcl_color_control_options_e -{ - /** Execute command if the On/Off cluster, OnOff attribute is 0x00 (FALSE) */ - ZB_ZCL_COLOR_CONTROL_OPTIONS_EXECUTE_IF_OFF = 0, -}; - -/*! @brief Enhanced Color Mode attribute enumeration - @see ZCL spec, subclause 5.2.2.2.1.2 -*/ -enum zb_zcl_color_control_enhanced_color_mode_e -{ - /** CurrentHue and CurrentSaturation */ - ZB_ZCL_COLOR_CONTROL_COLOR_EX_MODE_HUE_SATURATION = 0x00, - /** CurrentX and CurrentY */ - ZB_ZCL_COLOR_CONTROL_COLOR_EX_MODE_CURRENT_X_Y = 0x01, - /** ColorTemperature */ - ZB_ZCL_COLOR_CONTROL_COLOR_EX_MODE_TEMPERATURE = 0x02, - /** EnhancedCurrentHue and EnhancedCurrentSaturation */ - ZB_ZCL_COLOR_CONTROL_COLOR_EX_MODE_HUE_SATURATION_EX = 0x03, -}; - -/*! @brief Enhanced Color Capabilities attribute flags - @see ZCL spec, subclause 5.2.2.2.1.8 -*/ -enum zb_zcl_color_control_color_capabilities_e -{ - /** Hue/saturation supported*/ - ZB_ZCL_COLOR_CONTROL_CAPABILITIES_HUE_SATURATION = 1 << 0, - /** Enhanced hue supported*/ - ZB_ZCL_COLOR_CONTROL_CAPABILITIES_EX_HUE = 1 << 1, - /** Color loop supported*/ - ZB_ZCL_COLOR_CONTROL_CAPABILITIES_COLOR_LOOP = 1 << 2, - /** XY supported*/ - ZB_ZCL_COLOR_CONTROL_CAPABILITIES_X_Y = 1 << 3, - /** Color temperature supported*/ - ZB_ZCL_COLOR_CONTROL_CAPABILITIES_COLOR_TEMP = 1 << 4, -}; - -/*! - @brief Declare attribute list for Color Control cluster (extended attribute set) - @param attr_list - attribute list name - @param current_hue - pointer to variable to store current_hue attribute value - @param current_saturation - pointer to variable to store current_saturation attribute value - @param remaining_time - pointer to variable to store remaining_time attribute value - @param current_X - pointer to variable to store current_X attribute value - @param current_Y - pointer to variable to store current_Y attribute value - @param color_temperature - pointer to variable to store color_temperature attribute value - @param color_mode - pointer to variable to store color_mode attribute value - @param options - pointer to variable to store options attribute value - @param number_primaries - pointer to variable to store number_primaries attribute value - @param primary_1_X - pointer to variable to store primary_1_X attribute value - @param primary_1_Y - pointer to variable to store primary_1_Y attribute value - @param primary_1_intensity - pointer to variable to store primary_1_intensity attribute value - @param primary_2_X - pointer to variable to store primary_2_X attribute value - @param primary_2_Y - pointer to variable to store primary_2_Y attribute value - @param primary_2_intensity - pointer to variable to store primary_2_intensity attribute value - @param primary_3_X - pointer to variable to store primary_3_X attribute value - @param primary_3_Y - pointer to variable to store primary_3_Y attribute value - @param primary_3_intensity - pointer to variable to store primary_3_intensity attribute value - @param primary_4_X - pointer to variable to store primary_4_X attribute value - @param primary_4_Y - pointer to variable to store primary_4_Y attribute value - @param primary_4_intensity - pointer to variable to store primary_4_intensity attribute value - @param primary_5_X - pointer to variable to store primary_5_X attribute value - @param primary_5_Y - pointer to variable to store primary_5_Y attribute value - @param primary_5_intensity - pointer to variable to store primary_5_intensity attribute value - @param primary_6_X - pointer to variable to store primary_6_X attribute value - @param primary_6_Y - pointer to variable to store primary_6_Y attribute value - @param primary_6_intensity - pointer to variable to store primary_6_intensity attribute value - @param enhanced_current_hue - pointer to variable to store Enhanced Current Hue attribute value - @param enhanced_color_mode - pointer to variable to store Enhanced Color Mode attribute value - @param color_loop_active - pointer to variable to store Color Loop Active attribute value - @param color_loop_direction - pointer to variable to store Color Loop Direction attribute value - @param color_loop_time - pointer to variable to store Color Loop Time attribute value - @param color_loop_start - pointer to variable to store Color Loop Start Enhanced Hue attribute value - @param color_loop_stored - pointer to variable to store Color Loop Stored Enhanced Hue attribute value - @param color_capabilities - pointer to variable to store Color Capabilities attribute value - @param color_temp_physical_min - pointer to variable to store Color Temp Physical Min attribute value - @param color_temp_physical_max - pointer to variable to store Color Temp Physical Max attribute value - @param couple_color_temp_to_level_min - pointer to variable to store Couple Color Temp To Level Min Mireds attribute value - @param start_up_color_temp - pointer to variable to store Start Up Color Temperature Mireds attribute value -*/ -#define ZB_ZCL_DECLARE_COLOR_CONTROL_ATTRIB_LIST_EXT(attr_list, current_hue, \ - current_saturation, remaining_time, current_X, current_Y, color_temperature, \ - color_mode, options, number_primaries, primary_1_X, primary_1_Y, primary_1_intensity, \ - primary_2_X, primary_2_Y, primary_2_intensity, primary_3_X, primary_3_Y, \ - primary_3_intensity, primary_4_X, primary_4_Y, primary_4_intensity, primary_5_X, \ - primary_5_Y, primary_5_intensity, primary_6_X, primary_6_Y, primary_6_intensity, \ - enhanced_current_hue, enhanced_color_mode, color_loop_active, color_loop_direction, \ - color_loop_time, color_loop_start, color_loop_stored, color_capabilities, \ - color_temp_physical_min, color_temp_physical_max, \ - couple_color_temp_to_level_min, start_up_color_temp) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_COLOR_CONTROL) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, (current_hue)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, (current_saturation)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_REMAINING_TIME_ID, (remaining_time)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, (current_X)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID, (current_Y)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, (color_temperature)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_MODE_ID, (color_mode)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_OPTIONS_ID, (options)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_NUMBER_OF_PRIMARIES_ID, (number_primaries)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_X_ID, (primary_1_X)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_Y_ID, (primary_1_Y)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_INTENSITY_ID, (primary_1_intensity)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_X_ID, (primary_2_X)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_Y_ID, (primary_2_Y)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_INTENSITY_ID, (primary_2_intensity)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_X_ID, (primary_3_X)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_Y_ID, (primary_3_Y)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_INTENSITY_ID, (primary_3_intensity)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_X_ID, (primary_4_X)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_Y_ID, (primary_4_Y)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_INTENSITY_ID, (primary_4_intensity)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_X_ID, (primary_5_X)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_Y_ID, (primary_5_Y)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_INTENSITY_ID, (primary_5_intensity)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_X_ID, (primary_6_X)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_Y_ID, (primary_6_Y)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_INTENSITY_ID, (primary_6_intensity)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID, (enhanced_current_hue)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID, (enhanced_color_mode)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_ACTIVE_ID, (color_loop_active)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_DIRECTION_ID, (color_loop_direction)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_TIME_ID, (color_loop_time)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_START_ENHANCED_HUE_ID, (color_loop_start)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_STORED_ENHANCED_HUE_ID, (color_loop_stored)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_CAPABILITIES_ID, (color_capabilities)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_ID, (color_temp_physical_min)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_ID, (color_temp_physical_max)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_COUPLE_COLOR_TEMP_TO_LEVEL_MIN_MIREDS_ID, (couple_color_temp_to_level_min)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_START_UP_COLOR_TEMPERATURE_MIREDS_ID, (start_up_color_temp)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! - @brief Declare attribute list for Color Control cluster (mandatory attribute set) - @param attr_list - attribute list name - @param current_X - pointer to variable to store current_X attribute value - @param current_Y - pointer to variable to store current_Y attribute value -*/ -#define ZB_ZCL_DECLARE_COLOR_CONTROL_ATTRIB_LIST(attr_list, current_X, current_Y) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_COLOR_CONTROL) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, (current_X)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID, (current_Y)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Color Control cluster attributes */ - -/** @cond internals_doc */ -/*! @name Color Control cluster internals - Internal structures for Color Control cluster - @internal - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_REMAINING_TIME_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_REMAINING_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_DRIFT_COMPENSATION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_DRIFT_COMPENSATION_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COMPENSATION_TEXT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COMPENSATION_TEXT_ID, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_MODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_MODE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_OPTIONS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_OPTIONS_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_ACTIVE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_ACTIVE_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_DIRECTION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_DIRECTION_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_TIME_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_START_ENHANCED_HUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_START_ENHANCED_HUE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_STORED_ENHANCED_HUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_STORED_ENHANCED_HUE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_CAPABILITIES_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_CAPABILITIES_ID, \ - ZB_ZCL_ATTR_TYPE_16BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_COUPLE_COLOR_TEMP_TO_LEVEL_MIN_MIREDS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_COUPLE_COLOR_TEMP_TO_LEVEL_MIN_MIREDS_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_START_UP_COLOR_TEMPERATURE_MIREDS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_START_UP_COLOR_TEMPERATURE_MIREDS_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_NUMBER_OF_PRIMARIES_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_NUMBER_OF_PRIMARIES_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_X_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_X_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_Y_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_Y_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_INTENSITY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_1_INTENSITY_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_X_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_X_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_Y_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_Y_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_INTENSITY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_2_INTENSITY_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_X_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_X_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_Y_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_Y_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_INTENSITY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_3_INTENSITY_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_X_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_X_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_Y_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_Y_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_INTENSITY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_4_INTENSITY_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_X_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_X_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_Y_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_Y_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_INTENSITY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_5_INTENSITY_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_X_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_X_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_Y_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_Y_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_INTENSITY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_COLOR_CONTROL_PRIMARY_6_INTENSITY_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/** @internal Structure of Move variables for Move alarm - */ -typedef struct zb_zcl_color_control_move_loop_s -{ - /** Command header */ - zb_zcl_parsed_hdr_t cmd_info; - - /** @brief Time for last process move loop command */ - zb_time_t time_last; - - /** @brief attribute id */ - zb_uint16_t attr_id; - /** @brief rate */ - zb_int16_t rate; - /** @brief limit */ - zb_uint16_t limit; - /** @brief time mod - different last time - process time*/ - zb_uint16_t time_mod; - - /** @brief attribute id2 */ - zb_uint16_t attr_id2; - /** @brief rate2 */ - zb_int16_t rate2; - /** @brief limit2 */ - zb_uint16_t limit2; - /** @brief time mod - different last time - process time*/ - zb_uint16_t time_mod2; - -} zb_zcl_color_control_move_loop_t; - -#define ZB_ZCL_COLOR_CONTROL_FILL_MOVE_DATA(buf, cmd_info_, \ - attr_id_, rate_, limit_) \ -{ \ - zb_zcl_color_control_move_loop_t *loop_data = \ - ZB_BUF_GET_PARAM((buf), zb_zcl_color_control_move_loop_t); \ - ZB_MEMMOVE(&(loop_data->cmd_info), (cmd_info_), sizeof(zb_zcl_parsed_hdr_t)); \ - loop_data->time_last = ZB_TIMER_GET(); \ - loop_data->attr_id = (attr_id_); \ - loop_data->rate = (rate_); \ - loop_data->limit = (limit_); \ - loop_data->time_mod = 0; \ - loop_data->attr_id2 = 0; \ - loop_data->time_mod2 = 0; \ -} - -/*! @internal - * @brief Structure for loop of move to command */ -typedef struct zb_zcl_color_control_move_to_loop_s -{ - /** Command header */ - zb_zcl_parsed_hdr_t cmd_info; - - /** Attribute_ID */ - zb_uint16_t attr_id; - /** Start value */ - zb_uint16_t start_value; - /** Finish value */ - zb_uint16_t finish_value; - /** Is increment direction */ - zb_bool_t incr_direction; - - /** Attribute_ID */ - zb_uint16_t attr_id2; - /** Start value */ - zb_uint16_t start_value2; - /** Finish value */ - zb_uint16_t finish_value2; - - /** Start time - beacon interval */ - zb_time_t start_time; - /** transition time - time unit = 1/10sec */ - zb_time_t transition_time; -} zb_zcl_color_control_move_to_loop_t; - -#define ZB_ZCL_COLOR_CONTROL_FILL_MOVE_TO_DATA(buf, cmd_info_, \ - attr_id_, start_, finish_, incr_direction_, transition_time_) \ -{ \ - zb_zcl_color_control_move_to_loop_t *loop_data = \ - ZB_BUF_GET_PARAM((buf), zb_zcl_color_control_move_to_loop_t); \ - ZB_MEMMOVE(&(loop_data->cmd_info), (cmd_info_), sizeof(zb_zcl_parsed_hdr_t)); \ - loop_data->attr_id = (attr_id_); \ - loop_data->start_value = start_; \ - loop_data->finish_value = finish_; \ - loop_data->attr_id2 = 0; \ - loop_data->incr_direction = (zb_bool_t)(incr_direction_); \ - loop_data->start_time = ZB_TIMER_GET(); \ - loop_data->transition_time = transition_time_; \ -} - -/*! @internal - * @brief Structure for loop of step command */ -typedef struct zb_zcl_color_control_step_loop_s -{ - /** Command header */ - zb_zcl_parsed_hdr_t cmd_info; - - /** Attribute_ID */ - zb_uint16_t attr_id; - /** Rate value */ - zb_uint16_t rate; - /** @brief limit */ - zb_uint16_t limit; - - /** last time - beacon interval */ - zb_time_t last_time; - /** time bitween two steps - beacon interval */ - zb_time_t step_time; - - /** Attribute_ID second */ - zb_uint16_t attr_id2; - /** Rate value second */ - zb_uint16_t rate2; - /** @brief limit2 */ - zb_uint16_t limit2; - -} zb_zcl_color_control_step_loop_t; - -#define ZB_ZCL_COLOR_CONTROL_FILL_STEP_DATA(buf, cmd_info_, attr_id_, rate_, \ - transition_time, limit_) \ -{ \ - zb_zcl_color_control_step_loop_t *loop_data = \ - ZB_BUF_GET_PARAM((buf), zb_zcl_color_control_step_loop_t); \ - ZB_MEMMOVE(&(loop_data->cmd_info), (cmd_info_), sizeof(zb_zcl_parsed_hdr_t)); \ - loop_data->attr_id = (attr_id_); \ - loop_data->attr_id2 = 0; \ - loop_data->rate = (rate_); \ - loop_data->last_time = ZB_TIMER_GET(); \ - loop_data->step_time = ZB_TIME_UNITS_TO_BEACON_INTERVAL(transition_time); \ - loop_data->limit = (limit_); \ -} - -/*! Number of attributes mandatory for reporting in Color Control cluster - * Attribute: CurrentX, CurrentY, CurrentHue, CurrentSaturation, ColorTemperature - * */ -#define ZB_ZCL_COLOR_CONTROL_REPORT_ATTR_COUNT 5 - -/*! @} */ /* Color Control cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/*! @name Color Control cluster commands - @{ -*/ - -/************************** Color Control cluster command definitions ****************************/ - -/*! @brief Color control cluster command identifiers - @see ZCL spec, subclause 5.2.2.3 -*/ -enum zb_zcl_color_control_cmd_e -{ - /** Move To Hue command */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE = 0x00, - /** Move Hue command */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_HUE = 0x01, - /** Step Hue command */ - ZB_ZCL_CMD_COLOR_CONTROL_STEP_HUE = 0x02, - /** Move To Saturation command */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_SATURATION = 0x03, - /** Move Saturation command */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_SATURATION = 0x04, - /** Step Saturation command */ - ZB_ZCL_CMD_COLOR_CONTROL_STEP_SATURATION = 0x05, - /** Move To Hue and Saturation command */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SATURATION = 0x06, - /** Move To Color command */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR = 0x07, - /** Move Color command */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR = 0x08, - /** Step Color command */ - ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR = 0x09, - /** Move to color temperature command */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR_TEMPERATURE = 0x0a, - /** Enhanced move to hue command */ - ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE = 0x40, - /** Enhanced move hue command */ - ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_HUE = 0x41, - /** Enhanced step hue command */ - ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_STEP_HUE = 0x42, - /** Enhanced move to hue and saturation command */ - ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_SATURATION = 0x43, - /** Color loop set command */ - ZB_ZCL_CMD_COLOR_CONTROL_COLOR_LOOP_SET = 0x44, - /** Stop move step command */ - ZB_ZCL_CMD_COLOR_CONTROL_STOP_MOVE_STEP = 0x47, - /** Move color temperature command */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR_TEMPERATURE = 0x4b, - /** Step color temperature command */ - ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR_TEMPERATURE = 0x4c, -}; - -/** @cond internals_doc */ -/* Color control cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_COLOR_CONTROL_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_COLOR_CONTROL_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_COLOR_CONTROL_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_COLOR_CONTROL_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE, \ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_HUE, \ - ZB_ZCL_CMD_COLOR_CONTROL_STEP_HUE, \ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_SATURATION, \ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_SATURATION, \ - ZB_ZCL_CMD_COLOR_CONTROL_STEP_SATURATION, \ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SATURATION, \ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR, \ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR, \ - ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR, \ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR_TEMPERATURE, \ - ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE, \ - ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_HUE, \ - ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_STEP_HUE, \ - ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_SATURATION, \ - ZB_ZCL_CMD_COLOR_CONTROL_COLOR_LOOP_SET, \ - ZB_ZCL_CMD_COLOR_CONTROL_STOP_MOVE_STEP, \ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR_TEMPERATURE, \ - ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR_TEMPERATURE - -#define ZB_ZCL_CLUSTER_ID_COLOR_CONTROL_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_COLOR_CONTROL_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - - -/* command parameters enumerates */ - -/** @brief Direction of Move Hue command. - * See specs 5.2.2.3.3.2, 5.2.2.3.6.2 */ -enum zb_zcl_color_control_move_direction_e -{ - /** Stop */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_STOP = 0x00, - /** Up */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_UP = 0x01, - /** Down */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_DOWN = 0x03 -}; - -/** @brief Direction of Step command. - * See specs 5.2.2.3.4.2, 5.2.2.3.7.2 */ -enum zb_zcl_color_control_step_mode_e -{ - /** Up */ - ZB_ZCL_CMD_COLOR_CONTROL_STEP_UP = 0x01, - /** Down */ - ZB_ZCL_CMD_COLOR_CONTROL_STEP_DOWN = 0x03 -}; - - -/* command request structure */ - -/*! @brief Structured representation of Level Control command payload (optional part) - @see ZCL spec, subclause 3.10.2.3.1.1*/ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_req_options_s -{ - /** OptionsMask field */ - zb_uint8_t options_mask; - /** OptionsOverride field */ - zb_uint8_t options_override; -} ZB_PACKED_STRUCT zb_zcl_color_control_req_options_t; - -/** @brief Move to Level payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_REQ_OPTIONS_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_req_options_t) - -/** @internal Macro for getting Move to Color command */ -#define ZB_ZCL_COLOR_CONTROL_GET_CMD_OPTIONS(data_buf, req_options) \ -{ \ - zb_zcl_color_control_req_options_t *req_options_ptr; \ - (req_options_ptr) = zb_buf_len(data_buf) >= \ - ZB_ZCL_COLOR_CONTROL_REQ_OPTIONS_PAYLOAD_LEN ? \ - (zb_zcl_color_control_req_options_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_options_ptr != NULL) \ - { \ - req_options.options_mask = req_options_ptr->options_mask; \ - req_options.options_override = req_options_ptr->options_override; \ - (void)zb_buf_cut_left(data_buf, sizeof(zb_zcl_color_control_req_options_t)); \ - } \ - else \ - { \ - req_options.options_mask = (zb_uint8_t)0x00; \ - req_options.options_override = (zb_uint8_t)0x00; \ - } \ -} - -/******************************* MOVE_TO_HUE ******************************/ - -/** @brief Direction of Move to Hue command. - * See ZCL8 spec 5.2.2.3.4.3 */ -enum zb_zcl_color_control_move_to_hue_direction_e -{ - /** Shortest distance */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SHORTEST = 0x00, - /** Longest distance */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_LONGEST = 0x01, - /** Up */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_UP = 0x02, - /** Down */ - ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_DOWN = 0x03 -}; - -/*! @brief Structure representation of Move To Hue command payload - @see ZCL8 spec, subclause 5.2.2.3.4.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_move_to_hue_req_s -{ - /** Hue */ - zb_uint8_t hue; - /** Direction, see @ref zb_zcl_color_control_move_to_hue_direction_e */ - zb_uint8_t direction; - /** Transition time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_move_to_hue_req_t; - -/** @brief Move Hue payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_MOVE_TO_HUE_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_move_to_hue_req_t) - -/*! @brief Send Move to Hue command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param hue - Hue value - @param direction - Direction value, see @ref zb_zcl_color_control_move_to_hue_direction_e - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_move_to_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, zb_uint8_t direction, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Move to Hue command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_move_to_hue_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param hue - Hue value - @param direction - Direction value, see @ref zb_zcl_color_control_move_to_hue_direction_e - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_move_to_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, zb_uint8_t direction, - zb_uint16_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_move_to_hue_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_HUE_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, hue, direction, \ - transition_time, options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_move_to_hue_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, hue, direction, \ - transition_time, options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_move_to_hue_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_HUE_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, hue, direction, \ - transition_time) \ -{ \ - zb_zcl_color_control_send_move_to_hue_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, hue, direction, \ - transition_time); \ -} - -/** @brief Macro for getting Move to Hue command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param move_to_hue_req - pointer to a variable of type @ref - * zb_zcl_color_control_move_to_hue_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_HUE_REQ(buffer, move_to_hue_req, status) \ -{ \ - zb_zcl_color_control_move_to_hue_req_t *move_to_hue_req_ptr; \ - (move_to_hue_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_MOVE_TO_HUE_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_move_to_hue_req_t*)zb_buf_begin(buffer) : NULL; \ - if (move_to_hue_req_ptr != NULL) \ - { \ - move_to_hue_req.hue = move_to_hue_req_ptr->hue; \ - move_to_hue_req.direction = move_to_hue_req_ptr->direction; \ - ZB_HTOLE16(&(move_to_hue_req).transition_time, &(move_to_hue_req_ptr->transition_time)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_MOVE_TO_HUE_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} -/******************************* MOVE_HUE ******************************/ - -/*! @brief Structure representation of Move Hue command payload - @see ZCL8 spec, subclause 5.2.2.3.5.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_move_hue_req_s -{ - /** Move mode, see @ref zb_zcl_color_control_move_direction_e */ - zb_uint8_t move_mode; - /** Rate */ - zb_uint8_t rate; -} ZB_PACKED_STRUCT zb_zcl_color_control_move_hue_req_t; - -/** @brief Move Hue payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_MOVE_HUE_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_move_hue_req_t) - -/*! @brief Send Move Hue command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move mode, see @ref zb_zcl_color_control_move_direction_e - @param rate - Rate - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_move_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Move Hue command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_move_hue_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move mode, see @ref zb_zcl_color_control_move_direction_e - @param rate - Rate -*/ -void zb_zcl_color_control_send_move_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate); - -/** Macro for calling @ref zb_zcl_color_control_send_move_hue_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_HUE_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, \ - rate, options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_move_hue_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, \ - rate, options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_move_hue_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_HUE_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate) \ -{ \ - zb_zcl_color_control_send_move_hue_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate); \ -} - -/** @brief Macro for getting Move Hue command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param move_hue_req - variable of type @ref - * zb_zcl_color_control_move_hue_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_MOVE_HUE_REQ(buffer, move_hue_req, status) \ -{ \ - zb_zcl_color_control_move_hue_req_t *move_hue_req_ptr; \ - (move_hue_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_MOVE_HUE_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_move_hue_req_t*)zb_buf_begin(buffer) : NULL; \ - if (move_hue_req_ptr != NULL) \ - { \ - move_hue_req.move_mode = move_hue_req_ptr->move_mode; \ - move_hue_req.rate = move_hue_req_ptr->rate; \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_MOVE_HUE_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* STEP_HUE ******************************/ - -/*! @brief Structure representation of Step Hue command payload - @see ZCL8 spec, subclause 5.2.2.3.6.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_step_hue_req_s -{ - /** Step mode, see @ref zb_zcl_color_control_step_mode_e */ - zb_uint8_t step_mode; - /** Step size */ - zb_uint8_t step_size; - /** Transition time field */ - zb_uint8_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_step_hue_req_t; - -/** @brief Step Hue payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_STEP_HUE_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_step_hue_req_t) - -/*! @brief Send Step Hue command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - step mode value, see @ref zb_zcl_color_control_step_mode_e - @param step_size - step size value - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_step_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Step Hue command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_step_hue_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - step mode value, see @ref zb_zcl_color_control_step_mode_e - @param step_size - step size value - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_step_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_step_hue_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_STEP_HUE_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, \ - step_size, transition_time, options_mask, \ - options_override) \ -{ \ - zb_zcl_color_control_send_step_hue_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, \ - step_size, transition_time, options_mask, \ - options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_step_hue_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_STEP_HUE_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, step_size, transition_time) \ -{ \ - zb_zcl_color_control_send_step_hue_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, step_size, transition_time); \ -} - -/** @brief Macro for getting Step Hue command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param step_hue_req - pointer to a variable of type @ref - * zb_zcl_color_control_step_hue_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_STEP_HUE_REQ(buffer, step_hue_req, status) \ -{ \ - zb_zcl_color_control_step_hue_req_t *step_hue_req_ptr; \ - (step_hue_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_STEP_HUE_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_step_hue_req_t*)zb_buf_begin(buffer) : NULL; \ - if (step_hue_req_ptr != NULL) \ - { \ - step_hue_req.step_mode = step_hue_req_ptr->step_mode; \ - step_hue_req.step_size = step_hue_req_ptr->step_size; \ - step_hue_req.transition_time = step_hue_req_ptr->transition_time; \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_STEP_HUE_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* Move to Saturation ******************************/ - -/*! @brief Structure representation of Move To Saturation command payload - @see ZCL8 spec, subclause 5.2.2.3.7.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_move_to_saturation_req_s -{ - /** Saturation */ - zb_uint8_t saturation; - /** Transition time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_move_to_saturation_req_t; - -/** @brief Move To Saturation payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_MOVE_TO_SATURATION_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_move_to_saturation_req_t) - -/*! @brief Send Move to Saturation command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param saturation - saturation - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_move_to_saturation_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t saturation, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Move to Saturation command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_move_to_saturation_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param saturation - saturation - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_move_to_saturation_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t saturation, - zb_uint16_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_move_to_saturation_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_SATURATION_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - saturation, transition_time, options_mask, \ - options_override) \ -{ \ - zb_zcl_color_control_send_move_to_saturation_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - saturation, transition_time, options_mask, \ - options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_move_to_saturation_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_SATURATION_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, saturation, transition_time) \ -{ \ - zb_zcl_color_control_send_move_to_saturation_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, saturation, transition_time); \ -} - -/** @brief Macro for getting Move To Saturation command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param move_to_saturation_req - variable of type @ref - * zb_zcl_color_control_move_to_saturation_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_SATURATION_REQ(buffer, move_to_saturation_req, status) \ -{ \ - zb_zcl_color_control_move_to_saturation_req_t *move_to_saturation_req_ptr; \ - (move_to_saturation_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_MOVE_TO_SATURATION_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_move_to_saturation_req_t*)zb_buf_begin(buffer) : NULL; \ - if (move_to_saturation_req_ptr != NULL) \ - { \ - move_to_saturation_req.saturation = move_to_saturation_req_ptr->saturation; \ - ZB_HTOLE16(&(move_to_saturation_req).transition_time, &(move_to_saturation_req_ptr->transition_time)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_MOVE_TO_SATURATION_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} -/******************************* Move Saturation ******************************/ - -/*! @brief Structure representation of Move Saturation command payload - @see ZCL8 spec, subclause 5.2.2.3.8.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_move_saturation_req_s -{ - /** Move mode, see @ref zb_zcl_color_control_move_direction_e */ - zb_uint8_t move_mode; - /** Rate */ - zb_uint8_t rate; -} ZB_PACKED_STRUCT zb_zcl_color_control_move_saturation_req_t; - -/** @brief Move Saturation payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_MOVE_SATURATION_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_move_saturation_req_t) - -/*! @brief Send Move Saturation command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move mode, see @ref zb_zcl_color_control_move_direction_e - @param rate - Rate - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_move_saturation_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Move Saturation command (pew-ZCL8) - Use @ref zb_zcl_color_control_send_move_saturation_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move mode, see @ref zb_zcl_color_control_move_direction_e - @param rate - Rate -*/ -void zb_zcl_color_control_send_move_saturation_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate); - -/** Macro for calling @ref zb_zcl_color_control_send_move_saturation_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_SATURATION_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, \ - rate, options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_move_saturation_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, \ - rate, options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_move_saturation_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_SATURATION_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate) \ -{ \ - zb_zcl_color_control_send_move_saturation_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate); \ -} - -/** @brief Macro for getting Move Saturation command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param move_saturation_req - variable of type @ref - * zb_zcl_color_control_move_saturation_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_MOVE_SATURATION_REQ(buffer, move_saturation_req, status) \ -{ \ - zb_zcl_color_control_move_saturation_req_t *move_saturation_req_ptr; \ - (move_saturation_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_MOVE_SATURATION_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_move_saturation_req_t*)zb_buf_begin(buffer) : NULL; \ - if (move_saturation_req_ptr != NULL) \ - { \ - move_saturation_req.move_mode = move_saturation_req_ptr->move_mode; \ - move_saturation_req.rate = move_saturation_req_ptr->rate; \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_MOVE_SATURATION_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* STEP_SATURATION ******************************/ - -/*! @brief Structure representation of Step Saturation command payload - @see ZCL8 spec, subclause 5.2.2.3.9.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_step_saturation_req_s -{ - /** Step mode, see @ref zb_zcl_color_control_step_mode_e */ - zb_uint8_t step_mode; - /** Step size */ - zb_uint8_t step_size; - /** Transition time field */ - zb_uint8_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_step_saturation_req_t; - -/** @brief Move Saturation payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_STEP_SATURATION_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_step_saturation_req_t) - -/*! @brief Send Step Saturation command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - step mode value, see @ref zb_zcl_color_control_step_mode_e - @param step_size - step size value - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_step_saturation_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Step Saturation command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_step_saturation_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - step mode value, see @ref zb_zcl_color_control_step_mode_e - @param step_size - step size value - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_step_saturation_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_step_saturation_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_STEP_SATURATION_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, \ - step_size, transition_time, options_mask, \ - options_override) \ -{ \ - zb_zcl_color_control_send_step_saturation_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, \ - step_size, transition_time, options_mask, \ - options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_step_saturation_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_STEP_SATURATION_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, step_size, transition_time) \ -{ \ - zb_zcl_color_control_send_step_saturation_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, step_size, transition_time); \ -} - -/** @brief Macro for getting Step Saturation command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param step_saturation_req - variable of type @ref - * zb_zcl_color_control_step_saturation_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_STEP_SATURATION_REQ(buffer, step_saturation_req, status) \ -{ \ - zb_zcl_color_control_step_saturation_req_t *step_saturation_req_ptr; \ - (step_saturation_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_STEP_SATURATION_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_step_saturation_req_t*)zb_buf_begin(buffer) : NULL; \ - if (step_saturation_req_ptr != NULL) \ - { \ - step_saturation_req.step_mode = step_saturation_req_ptr->step_mode; \ - step_saturation_req.step_size = step_saturation_req_ptr->step_size; \ - step_saturation_req.transition_time = step_saturation_req_ptr->transition_time; \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_STEP_SATURATION_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* Move to Hue and Saturation ******************************/ - -/*! @brief Structure representation of Move To Hue and Saturation command payload - @see ZCL8 spec, subclause 5.2.2.3.10.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_move_to_hue_saturation_req_s -{ - /** Hue */ - zb_uint8_t hue; - /** Saturation */ - zb_uint8_t saturation; - /** Transition time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_move_to_hue_saturation_req_t; - -/** @brief Move to Hue and Saturation payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_MOVE_TO_HUE_SATURATION_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_move_to_hue_saturation_req_t) - -/*! @brief Send Move to Hue and Saturation command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param hue - hue - @param saturation - saturation - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_move_to_hue_saturation_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, - zb_uint8_t saturation, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Move to Hue and Saturation command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_move_to_hue_saturation_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param hue - hue - @param saturation - saturation - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_move_to_hue_saturation_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, - zb_uint8_t saturation, - zb_uint16_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_move_to_hue_saturation_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_HUE_SATURATION_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - hue, saturation, transition_time, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_move_to_hue_saturation_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - hue, saturation, transition_time, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_move_to_hue_saturation_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_HUE_SATURATION_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, hue, saturation, transition_time) \ -{ \ - zb_zcl_color_control_send_move_to_hue_saturation_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, hue, saturation, transition_time); \ -} - -/** @brief Macro for getting Move To Hue and Saturation command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param move_to_hue_saturation_req - pointer to a variable of type @ref - * zb_zcl_color_control_move_to_hue_saturation_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_HUE_SATURATION_REQ(buffer, move_to_hue_saturation_req, status) \ -{ \ - zb_zcl_color_control_move_to_hue_saturation_req_t *move_to_hue_saturation_req_ptr; \ - (move_to_hue_saturation_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_MOVE_TO_HUE_SATURATION_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_move_to_hue_saturation_req_t*)zb_buf_begin(buffer) : NULL; \ - if (move_to_hue_saturation_req_ptr != NULL) \ - { \ - move_to_hue_saturation_req.hue = move_to_hue_saturation_req_ptr->hue; \ - move_to_hue_saturation_req.saturation = move_to_hue_saturation_req_ptr->saturation; \ - ZB_HTOLE16(&(move_to_hue_saturation_req).transition_time, &(move_to_hue_saturation_req_ptr->transition_time)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_MOVE_TO_HUE_SATURATION_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* Move to Color ******************************/ - -/*! @brief Structure representation of Move To Color command payload - @see ZCL8 spec, subclause 5.2.2.3.11.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_move_to_color_req_s -{ - /** ColorX */ - zb_uint16_t color_x; - /** ColorY */ - zb_uint16_t color_y; - /** Transition time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_move_to_color_req_t; - -/** @brief Move to Color payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_MOVE_TO_COLOR_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_move_to_color_req_t) - -/*! @brief Send Move to Color command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param color_x - colorX - @param color_y - colorY - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_move_to_color_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_x, - zb_uint16_t color_y, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Move to Color command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_move_to_color_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param color_x - colorX - @param color_y - colorY - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_move_to_color_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_x, - zb_uint16_t color_y, - zb_uint16_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_move_to_color_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_COLOR_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, color_x, \ - color_y, transition_time, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_move_to_color_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, color_x, \ - color_y, transition_time, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_move_to_color_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_COLOR_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, color_x, color_y, transition_time) \ -{ \ - zb_zcl_color_control_send_move_to_color_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, color_x, color_y, transition_time); \ -} - - -/** @brief Macro for getting Move To Color command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * zb_zcl_color_control_move_to_color_req_s. - * @param move_to_color_req containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_COLOR_REQ(buffer, move_to_color_req, status) \ -{ \ - zb_zcl_color_control_move_to_color_req_t *move_to_color_req_ptr; \ - (move_to_color_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_MOVE_TO_COLOR_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_move_to_color_req_t*)zb_buf_begin(buffer) : NULL; \ - if (move_to_color_req_ptr != NULL) \ - { \ - ZB_HTOLE16(&(move_to_color_req).color_x, &(move_to_color_req_ptr->color_x)); \ - ZB_HTOLE16(&(move_to_color_req).color_y, &(move_to_color_req_ptr->color_y)); \ - ZB_HTOLE16(&(move_to_color_req).transition_time, &(move_to_color_req_ptr->transition_time)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_MOVE_TO_COLOR_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* Move Color ******************************/ - -/*! @brief Structure representation of Move Color command payload - @see ZCL8 spec, subclause 5.2.2.3.12.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_move_color_req_s -{ - /** RateX */ - zb_int16_t rate_x; - /** RateY */ - zb_int16_t rate_y; -} ZB_PACKED_STRUCT zb_zcl_color_control_move_color_req_t; - -/** @brief Move Color payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_MOVE_COLOR_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_move_color_req_t) - -/*! @brief Send Move Color command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param rate_x - RateX - @param rate_y - RateY - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_move_color_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t rate_x, - zb_uint16_t rate_y, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Move Color command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_move_color_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param rate_x - RateX - @param rate_y - RateY -*/ -void zb_zcl_color_control_send_move_color_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t rate_x, - zb_uint16_t rate_y); - -/** Macro for calling @ref zb_zcl_color_control_send_move_color_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_COLOR_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, rate_x, rate_y, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_move_color_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, rate_x, rate_y, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_move_color_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_COLOR_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, rate_x, rate_y) \ -{ \ - zb_zcl_color_control_send_move_color_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, rate_x, rate_y); \ -} - -/** @brief Macro for getting Move Color command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param move_color_req - variable of type @ref - * zb_zcl_color_control_move_color_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_MOVE_COLOR_REQ(buffer, move_color_req, status) \ -{ \ - zb_zcl_color_control_move_color_req_t *move_color_req_ptr; \ - (move_color_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_MOVE_COLOR_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_move_color_req_t*)zb_buf_begin(buffer) : NULL; \ - if (move_color_req_ptr != NULL) \ - { \ - ZB_HTOLE16(&(move_color_req).rate_x, &(move_color_req_ptr->rate_x)); \ - ZB_HTOLE16(&(move_color_req).rate_y, &(move_color_req_ptr->rate_y)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_MOVE_COLOR_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* Step Color ******************************/ - -/*! @brief Structure representation of Step Color command payload - @see ZCL8 spec, subclause 5.2.2.3.13.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_step_color_req_s -{ - /** StepX */ - zb_uint16_t step_x; - /** StepY */ - zb_uint16_t step_y; - /** Transition time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_step_color_req_t; - -/** @brief Step Color payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_STEP_COLOR_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_step_color_req_t) - -/*! @brief Send Step Color command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_x - StepX - @param step_y - StepY - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_step_color_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t step_x, - zb_uint16_t step_y, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Step Color command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_step_color_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_x - StepX - @param step_y - StepY - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_step_color_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t step_x, - zb_uint16_t step_y, - zb_uint16_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_step_color_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_STEP_COLOR_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_x, step_y,\ - transition_time, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_step_color_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_x, step_y, \ - transition_time, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_step_color_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_STEP_COLOR_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_x, step_y, transition_time) \ -{ \ - zb_zcl_color_control_send_step_color_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_x, step_y, transition_time); \ -} - -/** @brief Macro for getting Move Color command - * @attention Assumes that ZCL header already cut. - * @param buffer Buffer containing the packet. - * @param step_color_req - variable of type @ref zb_zcl_color_control_step_color_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_STEP_COLOR_REQ(buffer, step_color_req, status) \ -{ \ - zb_zcl_color_control_step_color_req_t *step_color_req_ptr; \ - (step_color_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_STEP_COLOR_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_step_color_req_t*)zb_buf_begin(buffer) : NULL; \ - if (step_color_req_ptr != NULL) \ - { \ - ZB_HTOLE16(&(step_color_req).step_x, &(step_color_req_ptr->step_x)); \ - ZB_HTOLE16(&(step_color_req).step_y, &(step_color_req_ptr->step_y)); \ - ZB_HTOLE16(&(step_color_req).transition_time, &(step_color_req_ptr->transition_time)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_STEP_COLOR_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* Move to Color Temperature ******************************/ - -/*! @brief Structure representation of Move To Color Temperature command payload - @see ZCL8 spec, subclause 5.2.2.3.14.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_move_to_color_temperature_req_s -{ - /** Color Temperature */ - zb_uint16_t color_temperature; - /** Transition time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_move_to_color_temperature_req_t; - -/** @brief Move to Color Temperature payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_MOVE_TO_COLOR_TEMP_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_move_to_color_temperature_req_t) - -/*! @brief Send Move To Color Temperature command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param color_temperature - Color Temperature - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_move_to_color_temperature_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_temperature, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Move To Color Temperature command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_move_to_color_temperature_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param color_temperature - Color Temperature - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_move_to_color_temperature_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_temperature, - zb_uint16_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_move_to_color_temperature_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_COLOR_TEMPERATURE_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - color_temperature, transition_time, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_move_to_color_temperature_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - color_temperature, transition_time, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_move_to_color_temperature_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_TO_COLOR_TEMPERATURE_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, color_temperature, transition_time) \ -{ \ - zb_zcl_color_control_send_move_to_color_temperature_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, color_temperature, transition_time); \ -} - -/** @brief Macro for getting Move to Color Temperature command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param move_to_color_temperature_req - variable of type @ref - * zb_zcl_color_control_move_to_color_temperature_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_COLOR_TEMPERATURE_REQ(buffer, move_to_color_temperature_req, status) \ -{ \ - zb_zcl_color_control_move_to_color_temperature_req_t *move_to_color_temp_req_ptr; \ - (move_to_color_temp_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_MOVE_TO_COLOR_TEMP_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_move_to_color_temperature_req_t*)zb_buf_begin(buffer) : NULL; \ - if (move_to_color_temp_req_ptr != NULL) \ - { \ - ZB_HTOLE16(&(move_to_color_temperature_req).color_temperature, &(move_to_color_temp_req_ptr->color_temperature)); \ - ZB_HTOLE16(&(move_to_color_temperature_req).transition_time, &(move_to_color_temp_req_ptr->transition_time)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_MOVE_TO_COLOR_TEMP_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* ENHANCED_MOVE_TO_HUE ******************************/ - -/*! @brief Structure representation of Enhanced Move To Hue command payload - @see ZCL8 spec, subclause 5.2.2.3.15.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_enhanced_move_to_hue_req_s -{ - /** Enhanced Hue */ - zb_uint16_t enhanced_hue; - /** Direction, see @ref zb_zcl_color_control_move_to_hue_direction_e */ - zb_uint8_t direction; - /** Transition time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_enhanced_move_to_hue_req_t; - -/** @brief Enhanced Move to Hue payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_enhanced_move_to_hue_req_t) - -/*! @brief Send Enhanced Move to Hue command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param enhanced_hue - Enhanced Hue value - @param direction - Direction value, see @ref zb_zcl_color_control_move_to_hue_direction_e - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_enhanced_move_to_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t direction, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Enhanced Move to Hue command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_enhanced_move_to_hue_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param enhanced_hue - Enhanced Hue value - @param direction - Direction value, see @ref zb_zcl_color_control_move_to_hue_direction_e - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_enhanced_move_to_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t direction, - zb_uint16_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_enhanced_move_to_hue_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_ENHANCED_MOVE_TO_HUE_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - ex_hue, direction, transition_time, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_enhanced_move_to_hue_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode,\ - dst_ep, ep, prfl_id, def_resp, cb, \ - ex_hue, direction, transition_time, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_enhanced_move_to_hue_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_ENHANCED_MOVE_TO_HUE_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, ex_hue, direction, transition_time) \ -{ \ - zb_zcl_color_control_send_enhanced_move_to_hue_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, ex_hue, direction, transition_time); \ -} - -/** @brief Macro for getting Enhanced Move to Hue command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param enhanced_move_to_hue_req - variable of type @ref - * zb_zcl_color_control_enhanced_move_to_hue_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_MOVE_TO_HUE_REQ(buffer, enhanced_move_to_hue_req, status) \ -{ \ - zb_zcl_color_control_enhanced_move_to_hue_req_t *enhanced_move_to_hue_req_ptr; \ - (enhanced_move_to_hue_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_enhanced_move_to_hue_req_t*)zb_buf_begin(buffer) : NULL; \ - if (enhanced_move_to_hue_req_ptr != NULL) \ - { \ - ZB_HTOLE16(&(enhanced_move_to_hue_req).enhanced_hue, &(enhanced_move_to_hue_req_ptr->enhanced_hue)); \ - enhanced_move_to_hue_req.direction = enhanced_move_to_hue_req_ptr->direction; \ - ZB_HTOLE16(&(enhanced_move_to_hue_req).transition_time, &(enhanced_move_to_hue_req_ptr->transition_time)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* ENHANCED_MOVE_HUE ******************************/ - -/*! @brief Structure representation of Enhanced Move Hue command payload - @see ZCL8 spec, subclause 5.2.2.3.16 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_enhanced_move_hue_req_s -{ - /** Move mode, see @ref zb_zcl_color_control_move_direction_e */ - zb_uint8_t move_mode; - /** Rate */ - zb_uint16_t rate; -} ZB_PACKED_STRUCT zb_zcl_color_control_enhanced_move_hue_req_t; - -/** @brief Enhanced Move to Hue payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_ENHANCED_MOVE_HUE_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_enhanced_move_hue_req_t) - -/*! @brief Send Enhanced Move Hue command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move mode, see @ref zb_zcl_color_control_move_direction_e - @param rate - Rate - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_enhanced_move_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Enhanced Move Hue command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_enhanced_move_hue_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move mode, see @ref zb_zcl_color_control_move_direction_e - @param rate - Rate -*/ -void zb_zcl_color_control_send_enhanced_move_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate); - -/** Macro for calling @ref zb_zcl_color_control_send_enhanced_move_hue_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_ENHANCED_MOVE_HUE_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - move_mode, rate, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_enhanced_move_hue_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - move_mode, rate, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_enhanced_move_hue_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_ENHANCED_MOVE_HUE_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate) \ -{ \ - zb_zcl_color_control_send_enhanced_move_hue_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate); \ -} - -/** @brief Macro for getting Enhanced Move Hue command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param enhanced_move_hue_req - variable of type @ref - * zb_zcl_color_control_enhanced_move_hue_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_MOVE_HUE_REQ(buffer, enhanced_move_hue_req, status) \ -{ \ - zb_zcl_color_control_enhanced_move_hue_req_t *enhanced_move_hue_req_ptr; \ - (enhanced_move_hue_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_ENHANCED_MOVE_HUE_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_enhanced_move_hue_req_t*)zb_buf_begin(buffer) : NULL; \ - if (enhanced_move_hue_req_ptr != NULL) \ - { \ - enhanced_move_hue_req.move_mode = enhanced_move_hue_req_ptr->move_mode; \ - ZB_HTOLE16(&(enhanced_move_hue_req).rate, &(enhanced_move_hue_req_ptr->rate)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_ENHANCED_MOVE_HUE_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* ENHANCED_STEP_HUE ******************************/ - -/*! @brief Structure representation of Enhanced Step Hue command payload - @see ZCL8 spec, subclause 5.2.2.3.17 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_enhanced_step_hue_req_s -{ - /** Step mode, see @ref zb_zcl_color_control_step_mode_e */ - zb_uint8_t step_mode; - /** Step size */ - zb_uint16_t step_size; - /** Transition time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_enhanced_step_hue_req_t; - -/** @brief Enhanced Move to Hue payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_ENHANCED_STEP_HUE_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_enhanced_step_hue_req_t) - -/*! @brief Send Enhanced Step Hue command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - step mode value, see @ref zb_zcl_color_control_step_mode_e - @param step_size - step size value - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_enhanced_step_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Enhanced Step Hue command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_enhanced_step_hue_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - step mode value, see @ref zb_zcl_color_control_step_mode_e - @param step_size - step size value - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_enhanced_step_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_enhanced_step_hue_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_ENHANCED_STEP_HUE_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - step_mode, step_size, transition_time, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_enhanced_step_hue_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - step_mode, step_size, transition_time, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_enhanced_step_hue_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_ENHANCED_STEP_HUE_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, step_size, transition_time) \ -{ \ - zb_zcl_color_control_send_enhanced_step_hue_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, step_size, transition_time); \ -} - -/** @brief Macro for getting Enhanced Step Hue command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param enhanced_step_hue_req - variable of type @ref - * zb_zcl_color_control_enhanced_step_hue_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_STEP_HUE_REQ(buffer, enhanced_step_hue_req, status) \ -{ \ - zb_zcl_color_control_enhanced_step_hue_req_t *enhanced_step_hue_req_ptr; \ - (enhanced_step_hue_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_ENHANCED_STEP_HUE_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_enhanced_step_hue_req_t*)zb_buf_begin(buffer) : NULL; \ - if (enhanced_step_hue_req_ptr != NULL) \ - { \ - enhanced_step_hue_req.step_mode = enhanced_step_hue_req_ptr->step_mode; \ - ZB_HTOLE16(&(enhanced_step_hue_req).step_size, &(enhanced_step_hue_req_ptr->step_size)); \ - ZB_HTOLE16(&(enhanced_step_hue_req).transition_time, &(enhanced_step_hue_req_ptr->transition_time)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_ENHANCED_STEP_HUE_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* Enhanced Move to Hue and Saturation ******************************/ - -/*! @brief Structure representation of Move To Hue and Saturation command payload - @see ZCL spec, subclause 5.2.2.3.17 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_enhanced_move_to_hue_saturation_req_s -{ - /** Enhanced Hue */ - zb_uint16_t enhanced_hue; - /** Saturation */ - zb_uint8_t saturation; - /** Transition time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_color_control_enhanced_move_to_hue_saturation_req_t; - -/** @brief Enhanced Move to Hue payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_SATURATION_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_enhanced_move_to_hue_saturation_req_t) - -/*! @brief Send Enhanced Move to Hue and Saturation command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param enhanced_hue - enhanced hue - @param saturation - saturation - @param transition_time - Transition Time value - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t saturation, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Enhanced Move to Hue and Saturation command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param enhanced_hue - enhanced hue - @param saturation - saturation - @param transition_time - Transition Time value -*/ -void zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t saturation, - zb_uint16_t transition_time); - -/** Macro for calling @ref zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_ENHANCED_MOVE_TO_HUE_SATURATION_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, \ - cb, enhanced_hue, saturation, \ - transition_time, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, \ - cb, enhanced_hue, saturation, \ - transition_time, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_ENHANCED_MOVE_TO_HUE_SATURATION_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, enhanced_hue, saturation, transition_time) \ -{ \ - zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, enhanced_hue, saturation, transition_time); \ -} - -/** @brief Macro for getting Enhanced Move To Hue and Saturation command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param enhanced_move_to_hue_saturation_req - variable of type @ref - * zb_zcl_color_control_enhanced_move_to_hue_saturation_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_MOVE_TO_HUE_SATURATION_REQ(buffer, enhanced_move_to_hue_saturation_req, status) \ -{ \ - zb_zcl_color_control_enhanced_move_to_hue_saturation_req_t *enhanced_move_to_hue_saturation_req_ptr; \ - (enhanced_move_to_hue_saturation_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_SATURATION_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_enhanced_move_to_hue_saturation_req_t*)zb_buf_begin(buffer) : NULL; \ - if (enhanced_move_to_hue_saturation_req_ptr != NULL) \ - { \ - ZB_HTOLE16(&(enhanced_move_to_hue_saturation_req).enhanced_hue, &(enhanced_move_to_hue_saturation_req_ptr->enhanced_hue)); \ - enhanced_move_to_hue_saturation_req.saturation = enhanced_move_to_hue_saturation_req_ptr->saturation; \ - ZB_HTOLE16(&(enhanced_move_to_hue_saturation_req).transition_time, &(enhanced_move_to_hue_saturation_req_ptr->transition_time)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_SATURATION_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* Color Loop Set ******************************/ - -/*! @brief Structure representation of Color Loop Set command payload - @see ZCL8 spec, subclause 5.2.2.3.19 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_color_loop_set_req_s -{ - /** Update flags, see @ref zb_zcl_color_control_color_loop_update_e */ - zb_uint8_t update_flags; - /** Action, see @ref zb_zcl_color_control_color_loop_action_e */ - zb_uint8_t action; - /** Direction, see @ref zb_zcl_color_control_color_loop_direction_e */ - zb_uint8_t direction; - /** Time */ - zb_uint16_t time; - /** Start hue */ - zb_uint16_t start_hue; -} ZB_PACKED_STRUCT zb_zcl_color_control_color_loop_set_req_t; - -/** @brief Enhanced Color Loop Set payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_COLOR_LOOR_SET_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_color_loop_set_req_t) - -/** @brief Update flag for Color Loop Set command - * See ZCL specs 5.2.2.3.18.1 */ -enum zb_zcl_color_control_color_loop_update_e -{ - /** Update action */ - ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_ACTION = 1 << 0, - /** Update direction */ - ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_DIRECTION = 1 << 1, - /** Update time */ - ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_TIME = 1 << 2, - /** Update start hue */ - ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_START_HUE = 1 << 3, -}; - -/** @brief Action enumerate for Color Loop Set command - * See ZCL specs 5.2.2.3.18.2 */ -enum zb_zcl_color_control_color_loop_action_e -{ - /** De-activate the color loop */ - ZB_ZCL_CMD_COLOR_CONTROL_LOOP_ACTION_DEACTIVATE = 0, - /** Activate the color loop from the value in the Color Loop Start Enhanced Hue field*/ - ZB_ZCL_CMD_COLOR_CONTROL_LOOP_ACTION_START_HUE = 1, - /** Activate the color loop from the value of the Enhanced Current Hue attribute*/ - ZB_ZCL_CMD_COLOR_CONTROL_LOOP_ACTION_CURRENT_HUE = 2, -}; - -/** @brief Direction enumerate for Color Loop Set command - * See ZCL specs 5.2.2.3.18.3 */ -enum zb_zcl_color_control_color_loop_direction_e -{ - /** Decrement the hue in the color loop */ - ZB_ZCL_CMD_COLOR_CONTROL_LOOP_DIRECTION_DECREMENT = 0, - /** Increment the hue in the color loop */ - ZB_ZCL_CMD_COLOR_CONTROL_LOOP_DIRECTION_INCREMENT = 1, -}; - -/*! @internal - * @brief Structure for loop of Color Loop Set command */ -typedef struct zb_zcl_color_control_color_loop_set_s -{ - /** Command header */ - zb_zcl_parsed_hdr_t cmd_info; - - /** Last time - beacon interval */ - zb_time_t last_time; - -} zb_zcl_color_control_color_loop_set_t; - -#define ZB_ZCL_COLOR_CONTROL_FILL_COLOR_LOOP_SET_DATA(buf, cmd_info_) \ -{ \ - zb_zcl_color_control_color_loop_set_t *loop_data = \ - ZB_BUF_GET_PARAM((buf), zb_zcl_color_control_color_loop_set_t); \ - ZB_MEMMOVE(&(loop_data->cmd_info), (cmd_info_), sizeof(zb_zcl_parsed_hdr_t)); \ - loop_data->last_time = ZB_TIMER_GET(); \ -} - -/*! @brief Send Color Loop Set command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param update_flags - update flags, see @ref zb_zcl_color_control_color_loop_update_e - @param action - action, see @ref zb_zcl_color_control_color_loop_action_e - @param direction - direction, see @ref zb_zcl_color_control_color_loop_direction_e - @param time - time - @param start_hue - start hue - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_color_loop_set_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t update_flags, - zb_uint8_t action, - zb_uint8_t direction, - zb_uint16_t time, - zb_uint16_t start_hue, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Color Loop Set command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_color_loop_set_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param update_flags - update flags, see @ref zb_zcl_color_control_color_loop_update_e - @param action - action, see @ref zb_zcl_color_control_color_loop_action_e - @param direction - direction, see @ref zb_zcl_color_control_color_loop_direction_e - @param time - time - @param start_hue - start hue -*/ -void zb_zcl_color_control_send_color_loop_set_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t update_flags, - zb_uint8_t action, - zb_uint8_t direction, - zb_uint16_t time, - zb_uint16_t start_hue); - -/** Macro for calling @ref zb_zcl_color_control_send_color_loop_set_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_COLOR_LOOP_SET_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, update_flags,\ - action, direction, time, start_hue, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_color_loop_set_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, update_flags, \ - action, direction, time, start_hue, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_color_loop_set_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_COLOR_LOOP_SET_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, update_flags, action, direction, time, start_hue) \ -{ \ - zb_zcl_color_control_send_color_loop_set_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, update_flags, action, direction, time, start_hue);\ -} - -/** @brief Macro for getting Color Loop Set command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param color_loop_set_req - pointer to a variable of - * type @ref zb_zcl_color_control_color_loop_set_req_t - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_COLOR_LOOP_SET_REQ(buffer, color_loop_set_req, status) \ -{ \ - zb_zcl_color_control_color_loop_set_req_t *color_loop_set_req_ptr; \ - (color_loop_set_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_COLOR_LOOR_SET_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_color_loop_set_req_t*)zb_buf_begin(buffer) : NULL; \ - if (color_loop_set_req_ptr != NULL) \ - { \ - color_loop_set_req.update_flags = color_loop_set_req_ptr->update_flags; \ - color_loop_set_req.action = color_loop_set_req_ptr->action; \ - color_loop_set_req.direction = color_loop_set_req_ptr->direction; \ - ZB_HTOLE16(&(color_loop_set_req).time, &(color_loop_set_req_ptr->time)); \ - ZB_HTOLE16(&(color_loop_set_req).start_hue, &(color_loop_set_req_ptr->start_hue)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_COLOR_LOOR_SET_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* Stop move step ******************************/ - -/*! @brief Stop move step command, see ZCL8 spec 5.2.2.3.20 - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_stop_move_step_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Stop move step command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_stop_move_step_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -void zb_zcl_color_control_send_stop_move_step_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb); - -/** Macro for calling @ref zb_zcl_color_control_send_stop_move_step_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_STOP_MOVE_STEP_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_stop_move_step_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_stop_move_step_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_STOP_MOVE_STEP_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_zcl_color_control_send_stop_move_step_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb); \ -} - -/******************************* Move color temperature command ******************************/ - -/*! @brief Structure representation of Move color temperature command payload - @see ZCL8 spec, subclause 5.2.2.3.21 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_move_color_temp_req_s -{ - /** Move mode, see @ref zb_zcl_color_control_move_direction_e */ - zb_uint8_t move_mode; - /** Rate */ - zb_uint16_t rate; - /** Color temperature minimum */ - zb_uint16_t color_temp_min; - /** Color temperature maximum */ - zb_uint16_t color_temp_max; -} ZB_PACKED_STRUCT zb_zcl_color_control_move_color_temp_req_t; - -/** @brief Enhanced Move Color Temperature payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_MOVE_COLOR_TEMP_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_move_color_temp_req_t) - -/*! @brief Send Move color temperature command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - move mode, see @ref zb_zcl_color_control_move_direction_e - @param rate - rate - @param color_temp_min - color temperature minimum - @param color_temp_max - color temperature maximum - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_move_color_temp_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Move color temperature command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_move_color_temp_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - move mode, see @ref zb_zcl_color_control_move_direction_e - @param rate - rate - @param color_temp_min - color temperature minimum - @param color_temp_max - color temperature maximum -*/ -void zb_zcl_color_control_send_move_color_temp_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max); - -/** Macro for calling @ref zb_zcl_color_control_send_move_color_temp_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_COLOR_TEMP_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, \ - rate, color_temp_min, color_temp_max, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_move_color_temp_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, \ - rate, color_temp_min, color_temp_max, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_move_color_temp_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_MOVE_COLOR_TEMP_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate, color_temp_min, color_temp_max) \ -{ \ - zb_zcl_color_control_send_move_color_temp_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate, color_temp_min, color_temp_max); \ -} - -/** @brief Macro for getting Move color temperature command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param move_color_temp_req - variable of type @ref - * zb_zcl_color_control_move_color_temp_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_MOVE_COLOR_TEMP_REQ(buffer, move_color_temp_req, status) \ -{ \ - zb_zcl_color_control_move_color_temp_req_t *move_color_temp_req_ptr; \ - (move_color_temp_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_MOVE_COLOR_TEMP_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_move_color_temp_req_t*)zb_buf_begin(buffer) : NULL; \ - if (move_color_temp_req_ptr != NULL) \ - { \ - move_color_temp_req.move_mode = move_color_temp_req_ptr->move_mode; \ - ZB_HTOLE16(&(move_color_temp_req).rate, &(move_color_temp_req_ptr->rate)); \ - ZB_HTOLE16(&(move_color_temp_req).color_temp_min, &(move_color_temp_req_ptr->color_temp_min)); \ - ZB_HTOLE16(&(move_color_temp_req).color_temp_max, &(move_color_temp_req_ptr->color_temp_max)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_MOVE_COLOR_TEMP_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/******************************* Step color temperature command ******************************/ - -/*! @brief Structure representation of Step color temperature command command payload - @see ZCL8 spec, subclause 5.2.2.3.22 */ -typedef ZB_PACKED_PRE struct zb_zcl_color_control_step_color_temp_req_s -{ - /** Step mode, see @ref zb_zcl_color_control_step_mode_e */ - zb_uint8_t step_mode; - /** Step size */ - zb_uint16_t step_size; - /** Transition time field */ - zb_uint16_t transition_time; - /** Color temperature minimum */ - zb_uint16_t color_temp_min; - /** Color temperature maximum */ - zb_uint16_t color_temp_max; -} ZB_PACKED_STRUCT zb_zcl_color_control_step_color_temp_req_t; - -/** @brief Enhanced Move Color Temperature payload length macro */ -#define ZB_ZCL_COLOR_CONTROL_STEP_COLOR_TEMP_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_color_control_step_color_temp_req_t) - -/*! @brief Step color temperature command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - move mode, see @ref zb_zcl_color_control_step_mode_e - @param step_size - step size - @param transition_time - Transition Time value - @param color_temp_min - color temperature minimum - @param color_temp_max - color temperature maximum - @param options_mask - Options Mask - @param options_override - Options Override -*/ -void zb_zcl_color_control_send_step_color_temp_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Step color temperature command (pre-ZCL8) - Use @ref zb_zcl_color_control_send_step_color_temp_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - move mode, see @ref zb_zcl_color_control_step_mode_e - @param step_size - step size - @param transition_time - Transition Time value - @param color_temp_min - color temperature minimum - @param color_temp_max - color temperature maximum -*/ -void zb_zcl_color_control_send_step_color_temp_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max); - -/** Macro for calling @ref zb_zcl_color_control_send_step_color_temp_req_zcl8 function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_STEP_COLOR_TEMP_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, \ - step_size, transition_time, color_temp_min, \ - color_temp_max, \ - options_mask, options_override) \ -{ \ - zb_zcl_color_control_send_step_color_temp_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, \ - step_size, transition_time, color_temp_min, \ - color_temp_max, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_color_control_send_step_color_temp_req function - */ -#define ZB_ZCL_COLOR_CONTROL_SEND_STEP_COLOR_TEMP_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, step_size, transition_time, color_temp_min, color_temp_max) \ -{ \ - zb_zcl_color_control_send_step_color_temp_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, step_mode, step_size, transition_time, color_temp_min, color_temp_max); \ -} - -/** @brief Macro for getting Move color temperature command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param move_color_temp_req - variable of type @ref - * zb_zcl_color_control_move_color_temp_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_MOVE_COLOR_TEMP_REQ(buffer, move_color_temp_req, status) \ -{ \ - zb_zcl_color_control_move_color_temp_req_t *move_color_temp_req_ptr; \ - (move_color_temp_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_MOVE_COLOR_TEMP_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_move_color_temp_req_t*)zb_buf_begin(buffer) : NULL; \ - if (move_color_temp_req_ptr != NULL) \ - { \ - move_color_temp_req.move_mode = move_color_temp_req_ptr->move_mode; \ - ZB_HTOLE16(&(move_color_temp_req).rate, &(move_color_temp_req_ptr->rate)); \ - ZB_HTOLE16(&(move_color_temp_req).color_temp_min, &(move_color_temp_req_ptr->color_temp_min)); \ - ZB_HTOLE16(&(move_color_temp_req).color_temp_max, &(move_color_temp_req_ptr->color_temp_max)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_MOVE_COLOR_TEMP_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @brief Macro for getting Move color temperature command - * @attention Assumes that ZCL header already cut. - * @param buffer containing the packet (by pointer). - * @param step_color_temp_req - variable of type @ref - * zb_zcl_color_control_step_color_temp_req_s. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_COLOR_CONTROL_GET_STEP_COLOR_TEMP_REQ(buffer, step_color_temp_req, status) \ -{ \ - zb_zcl_color_control_step_color_temp_req_t *step_color_temp_req_ptr; \ - (step_color_temp_req_ptr) = zb_buf_len(buffer) >= \ - ZB_ZCL_COLOR_CONTROL_STEP_COLOR_TEMP_REQ_PAYLOAD_LEN ? \ - (zb_zcl_color_control_step_color_temp_req_t*)zb_buf_begin(buffer) : NULL; \ - if (step_color_temp_req_ptr != NULL) \ - { \ - step_color_temp_req.step_mode = step_color_temp_req_ptr->step_mode; \ - ZB_HTOLE16(&(step_color_temp_req).step_size, &(step_color_temp_req_ptr->step_size)); \ - ZB_HTOLE16(&(step_color_temp_req).transition_time, &(step_color_temp_req_ptr->transition_time)); \ - ZB_HTOLE16(&(step_color_temp_req).color_temp_min, &(step_color_temp_req_ptr->color_temp_min)); \ - ZB_HTOLE16(&(step_color_temp_req).color_temp_max, &(step_color_temp_req_ptr->color_temp_max)); \ - (void)zb_buf_cut_left(buffer, ZB_ZCL_COLOR_CONTROL_STEP_COLOR_TEMP_REQ_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/*! @} */ /* Color Control cluster commands */ - -/** @cond internals_doc - * - @name Added struct and define for specific Color Control cluster commands - @{ -*/ - -#define ZB_ZCL_COLOR_CONTROL_SEC_TO_MSEC 1000 - -/** Standard Color Control time uint = 1/10 sec */ -#define ZB_ZCL_COLOR_CONTROL_TIMER_INTERVAL 100 - -/** Standard Color Control time uint = 1/10 sec, beacon */ -#define ZB_ZCL_COLOR_CONTROL_TIMER_BEACON_INTERVAL \ - ZB_MILLISECONDS_TO_BEACON_INTERVAL(ZB_ZCL_COLOR_CONTROL_TIMER_INTERVAL) - -/** - * @brief Struct for process one iteration of move command for one attribute - */ -typedef struct zb_zcl_color_control_loop_element_s -{ - zb_uint8_t endpoint; /** Device endpoint */ - zb_uint8_t buffer_id; /** buffer for invoke User App */ - - zb_uint16_t attr_id; /** Attribute ID */ - zb_int16_t value; /** delta value */ - zb_bool_t is_continue; /** If ZB_TRUE attribute when is already limit value, command - contentious from another limit. If ZB_FALSE attribute when - is already limit value, command stop */ - zb_uint16_t limit; /** limit of attribute value */ - -} zb_zcl_color_control_loop_element_t; - -/** - * @brief Define for fill struct process step command for one attribute, - * see @ref zb_zcl_color_control_loop_element_s - * - * @param el_data - struct see @ref zb_zcl_color_control_loop_element_s 'zb_zcl_color_control_loop_element_t' - * @param endp - endpoint - * @param param - buffer for invoke User App - * @param attr - attribute ID - * @param value_ - value - * @param is_continue_ - continue if limit dest - * @param limit_ - limit of attribute value, min or max - depend of sing of rate field - */ -#define ZB_ZCL_COLOR_CONTROL_FILL_LOOP_ELEMENT(el_data, endp, \ - param, attr, value_, is_continue_, limit_) \ - (el_data).endpoint = (endp); \ - (el_data).buffer_id = (param); \ - (el_data).attr_id = (attr); \ - (el_data).value = (value_); \ - (el_data).is_continue = (is_continue_); \ - (el_data).limit = (limit_); - - -/** - * @brief Copy 16bit attribute value for Color Control cluster - * - * @param endpoint - device endpoint - * @param attr_id_to - destination attribute ID - * @param attr_id_from - source attribute ID - */ -#define ZB_ZCL_COLOR_CONTROL_COPY_ATTRIBUTE_16(endpoint, attr_id_to, attr_id_from) \ -{ \ - zb_uint16_t value; \ - zb_zcl_attr_t * attr_desc = zb_zcl_get_attr_desc_a((endpoint), \ - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, (attr_id_from)); \ - ZB_ASSERT(attr_desc); \ - value = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); \ - \ - attr_desc = zb_zcl_get_attr_desc_a((endpoint), \ - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, (attr_id_to)); \ - ZB_ASSERT(attr_desc); \ - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, value); \ -} - -/** - * @brief Struct invoke User App and set attribute value - */ -typedef struct zb_zcl_color_control_invoke_user_s -{ - zb_uint8_t endpoint; - zb_uint16_t attr_id; - zb_uint16_t new_value; /** New value attribute */ -} zb_zcl_color_control_invoke_user_t; - -/** @} - * - * @endcond */ /* internals_doc */ - - -/*! @} */ /* ZCL Color Control cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_color_control_init_server(void); -void zb_zcl_color_control_init_client(void); - -#define ZB_ZCL_CLUSTER_ID_COLOR_CONTROL_SERVER_ROLE_INIT zb_zcl_color_control_init_server -#define ZB_ZCL_CLUSTER_ID_COLOR_CONTROL_CLIENT_ROLE_INIT zb_zcl_color_control_init_client - -#endif /* ZB_ZCL_COLOR_CONTROL_H */ diff --git a/zboss/development/include/zcl/zb_zcl_commands.h b/zboss/development/include/zcl/zb_zcl_commands.h deleted file mode 100644 index f60c35fdaa..0000000000 --- a/zboss/development/include/zcl/zb_zcl_commands.h +++ /dev/null @@ -1,2383 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Zigbee cluster library commands common for all clusters -*/ -#ifndef ZB_ZCL_COMMANDS_H -#define ZB_ZCL_COMMANDS_H 1 - -#include "zcl/zb_zcl_common.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -struct zb_zcl_reporting_info_s; /* Forward declaration */ - -/* Debug functions */ -#if TRACE_ENABLED(TRACE_ZCL1) -#define ZB_ZCL_DEBUG_DUMP_COMMAND(buf) zb_zcl_dump_cmd(buf) -void zb_zcl_dump_cmd(zb_bufid_t buf); -#endif /* TRACE_ENABLED(TRACE_ZCL1) */ - -#if TRACE_ENABLED(TRACE_ZCL3) -#define ZB_ZCL_DEBUG_DUMP_HEADER(header) dump_zcl_header(header) -void dump_zcl_header(zb_zcl_parsed_hdr_t *header); -#endif /* TRACE_ENABLED(TRACE_ZCL3) */ - -#ifndef ZB_ZCL_DEBUG_DUMP_COMMAND -#define ZB_ZCL_DEBUG_DUMP_COMMAND(buf) ((void)buf) -#endif /* ZB_ZCL_DEBUG_DUMP_COMMAND */ - -#ifndef ZB_ZCL_DEBUG_DUMP_HEADER -#define ZB_ZCL_DEBUG_DUMP_HEADER(header) ((void)header) -#endif /* ZB_ZCL_DEBUG_DUMP_HEADER */ - -/** @addtogroup ZB_ZCL_COMMANDS - * @{ - * @details - * This section describes data structures representing command payloads shared by all clusters, - * and APIs for sending these commands and parsing their payloads. - */ - -/** - * @name ZCL common command IDs - * @anchor zcl_cmd - * @see ZCL spec, clause 2.4 - * @note These values do not contain commands not unused in ZB HA profile - */ -/** @{ */ -#define ZB_ZCL_CMD_READ_ATTRIB 0x00U /*!< Read attributes command */ -#define ZB_ZCL_CMD_READ_ATTRIB_RESP 0x01U /*!< Read attributes response command */ -#define ZB_ZCL_CMD_WRITE_ATTRIB 0x02U /*!< Write attributes foundation command */ -#define ZB_ZCL_CMD_WRITE_ATTRIB_UNDIV 0x03U /*!< Write attributes undivided command */ -#define ZB_ZCL_CMD_WRITE_ATTRIB_RESP 0x04U /*!< Write attributes response command */ -#define ZB_ZCL_CMD_WRITE_ATTRIB_NO_RESP 0x05U /*!< Write attributes no response command */ -#define ZB_ZCL_CMD_CONFIG_REPORT 0x06U /*!< Configure reporting command */ -#define ZB_ZCL_CMD_CONFIG_REPORT_RESP 0x07U /*!< Configure reporting response command */ -#define ZB_ZCL_CMD_READ_REPORT_CFG 0x08U /*!< Read reporting config command */ -#define ZB_ZCL_CMD_READ_REPORT_CFG_RESP 0x09U /*!< Read reporting config response command */ -#define ZB_ZCL_CMD_REPORT_ATTRIB 0x0aU /*!< Report attribute command */ -#define ZB_ZCL_CMD_DEFAULT_RESP 0x0bU /*!< Default response command */ -#define ZB_ZCL_CMD_DISC_ATTRIB 0x0cU /*!< Discover attributes command */ -#define ZB_ZCL_CMD_DISC_ATTRIB_RESP 0x0dU /*!< Discover attributes response command */ -/* Not release yet */ -#define ZB_ZCL_CMD_READ_ATTRIB_STRUCT 0x0eU /*!< Read attributes structured */ -#define ZB_ZCL_CMD_WRITE_ATTRIB_STRUCT 0x0fU /*!< Write attributes structured */ -#define ZB_ZCL_CMD_WRITE_ATTRIB_STRUCT_RESP 0x10U /*!< Write attributes structured response */ - -#define ZB_ZCL_CMD_DISCOVER_COMMANDS_RECEIVED 0x11U /*!< Discover Commands Received command */ -/** Discover Commands Received response command */ -#define ZB_ZCL_CMD_DISCOVER_COMMANDS_RECEIVED_RES 0x12U -#define ZB_ZCL_CMD_DISCOVER_COMMANDS_GENERATED 0x13U /*!< Discover Commands Generated command */ -/** Discover Commands Generated response command */ -#define ZB_ZCL_CMD_DISCOVER_COMMANDS_GENERATED_RES 0x14U - -/* Discover attr ext is HA1.2 specific, but as soon as this command handling is done together with - * ZCL Discover attr cmd, declare it unconditionally */ -#define ZB_ZCL_CMD_DISCOVER_ATTR_EXT 0x15U /*!< Discover attributes extended command */ -/** Discover attributes extended response command */ -#define ZB_ZCL_CMD_DISCOVER_ATTR_EXT_RES 0x16U -/** @} */ - -/** - * @brief Type for ZCL common command IDs. - * - * @deprecated holds one of @ref zcl_cmd. Kept only for backward compatibility as - * @ref zcl_cmd were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_zcl_cmd_t; - -/** @brief ZCL broadcast endpoint */ -#define ZB_ZCL_BROADCAST_ENDPOINT 0xFFU - -/** @brief Minimum time delay between responses to ZCL command sent to broadcast endpoint */ -#define ZB_ZCL_BROADCAST_ENDPOINT_CMD_RESP_JITTER (ZB_MILLISECONDS_TO_BEACON_INTERVAL(500)) - -/** @cond internals_doc */ - -/** @brief Start to declare cluster descriptors list */ -#define ZB_ZCL_START_DECLARE_CLUSTER_LIST(_cluster_list_name) \ - zb_zcl_cluster_desc_t _cluster_list_name[] = { - - -/** @brief Declare general cluster descriptor */ -#define ZB_ZCL_DECLARE_CLUSTER_DESC(_cluster_id, _attrib_list, _role) \ - { \ - (_cluster_id), \ - ZB_ZCL_ARRAY_SIZE((_attrib_list), zb_zcl_attr_t), \ - (_attrib_list), \ - (_role), \ - ZB_ZCL_MANUF_CODE_INVALID, \ - } - - -/** @brief Declare manufacturer specific cluster descriptor */ -#define ZB_ZCL_DECLARE_MANUF_CLUSTER_DESC(_cluster_id, _attrib_list, _role, _code) \ - { \ - (_cluster_id), \ - ZB_ZCL_ARRAY_SIZE((_attrib_list), zb_zcl_attr_t), \ - (_attrib_list), \ - (_role), \ - (_code) \ - } - - -/** @brief Finish cluster descriptors list */ -#define ZB_ZCL_FINISH_DECLARE_CLUSTER_LIST } - - -/** @internal @brief Send ZCL request command - - Sends ZCL request command (with direction @ref ZB_ZCL_FRAME_DIRECTION_TO_SRV) to the device - with 16-bit address. - @param buffer - ID zb_bufid_t of a buffer with payload - @param addr - short destination address - @param dst_addr_mode - address mode, only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and - @ref ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported - @param dst_ep - destination end point - @param ep - our end point - @param prof_id - profile identifier - @param cluster_id - cluster identifier - @param cmd_id - command identifier -*/ -#define ZB_ZCL_SEND_GENERAL_COMMAND_REQ_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, cmd_id) \ -{ \ - zb_uint8_t * ptr = NULL; \ - (void)zb_buf_alloc_left((buffer), sizeof(zb_zcl_frame_hdr_short_t), ptr); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL(ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, ZB_ZCL_GET_SEQ_NUM(), (cmd_id)); \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, NULL) \ -} - -/** @internal @brief Send ZCL response command - - Sends ZCL response command (with direction @ref ZB_ZCL_FRAME_DIRECTION_TO_CLI) to the device - with 16-bit address. - @param buffer - ID zb_bufid_t of a buffer with payload - @param addr - short destination address - @param dst_addr_mode - address mode, only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and - @ref ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported - @param dst_ep - destination end point - @param ep - our end point - @param prof_id - profile identifier - @param cluster_id - cluster identifier - @param seq_num - sequence number - @param cmd_id - command identifier -*/ -#define ZB_ZCL_SEND_GENERAL_COMMAND_RESP_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, seq_num, cmd_id) \ -{ \ - zb_uint8_t * ptr = NULL; \ - (void)zb_buf_alloc_left((buffer), sizeof(zb_zcl_frame_hdr_short_t), ptr); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL(ptr); \ - TRACE_MSG( \ - TRACE_APS1, \ - "fc: 0x%x, seq num: %i, cmd: 0x%hx", \ - (FMT__D_D_D, *(zb_uint8_t*)zb_buf_begin(buffer), seq_num, cmd_id)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, (seq_num), (cmd_id)); \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, NULL) \ -} - -#define ZB_ZCL_SCHEDULE_STATUS_ABORT(buffer, addr, dst_addr_mode, dst_ep, ep, cb) \ - zb_zcl_schedule_status_abort(buffer, addr, dst_addr_mode, dst_ep, ep, cb) - -#ifdef ZB_USEALIAS -void zb_zcl_send_command_short_alias(zb_bufid_t buffer, - zb_addr_u *addr, zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t ep, - zb_uint16_t prof_id, zb_uint16_t cluster_id, - zb_uint8_t radius, zb_callback_t cb, zb_uint8_t use_alias, - zb_uint16_t alias_addr, zb_uint8_t alias_seq); - -/** @internal @brief Send ZCL request command + Aliases - - Sends ZCL request command (with direction @ref ZB_ZCL_FRAME_DIRECTION_TO_SRV) to the device - with 16-bit address. - All parameters are the same as in ZB_ZCL_SEND_COMMAND_SHORT but with Aliases support - + - @param alias_addr - alias address - @param alias_seq - alias sequence number - */ -#define ZB_ZCL_SEND_COMMAND_SHORT_ALIAS( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, rd, cb, _use_alias, alias_addr, alias_seq) \ - zb_zcl_send_command_short_alias(buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, rd, cb, _use_alias, alias_addr, alias_seq) -#endif /* ZB_USEALIAS */ - -/** @internal @brief Send ZCL request command without ACK TX - - Sends ZCL request command (with direction @ref ZB_ZCL_FRAME_DIRECTION_TO_SRV) to the device - with 16-bit address. - @param buffer - ID zb_bufid_t of a buffer with payload - @param ptr - pointer to @ref zb_uint8_t start of ZCL command header - @param addr - short destination address - @param dst_addr_mode - address mode, only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and - @ref ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported - @param dst_ep - destination end point - @param ep - our end point - @param prof_id - profile identifier - @param cluster_id - cluster identifier - @param cb - callback for make next sequence number - @param random_delay - for a random delay before running the command - */ -#define ZB_ZCL_SEND_COMMAND_SHORT_WITHOUT_ACK( \ - buffer, ptr, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, cb, random_delay) \ - (void) zb_zcl_finish_and_send_packet_new((buffer), (ptr), (zb_addr_u *)(void *)(&(addr)), dst_addr_mode, dst_ep, ep, prof_id, cluster_id, cb, ZB_FALSE, ZB_TRUE, ZB_RANDOM_VALUE(random_delay)) - - -void zb_zcl_send_command_short_schedule(zb_bufid_t buffer, - zb_uint16_t addr, zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t ep, - zb_uint16_t prof_id, zb_uint16_t cluster_id, - zb_callback_t cb, zb_uint64_t delay); - -/** @internal @brief Send ZCL request command with delay (ms) - - Sends ZCL request command (with direction @ref ZB_ZCL_FRAME_DIRECTION_TO_SRV) to the device - with 16-bit address. - @param buffer - ID zb_bufid_t of a buffer with payload - @param addr - short destination address - @param dst_addr_mode - address mode, only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and - @ref ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported - @param dst_ep - destination end point - @param ep - our end point - @param prof_id - profile identifier - @param cluster_id - cluster identifier - @param cb - callback for make next sequence number - @param delay - Delay current send - */ -#define ZB_ZCL_SEND_COMMAND_SHORT_SCHEDULE( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, cb, delay) \ - zb_zcl_send_command_short_schedule(buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, cb, delay) - -/** @endcond */ /* internals_doc */ - -/** - * @defgroup zcl_def_resp Default response command sending and parsing. - * @{ - * @details - * Default response command is defined in ZCL spec, subclause 2.4.12. - * - * @par Example - * Command can be sent like in the following snippet: - * @snippet custom_cluster/custom_cluster_zr/custom_cluster_zr.c ZCL_SEND_DEFAULT_RESP - * Incoming default response can be parsed as following: - * @code - * zb_zcl_default_resp_payload_t* payload = ZB_ZCL_READ_DEFAULT_RESP(zcl_cmd_buf); - * @endcode - * @par - */ - -/** - * @brief Send default response command with custom Direction - * - * If you don't want to specify direction explicitly, use @ref ZB_ZCL_SEND_DEFAULT_RESP() - * - * @param buffer - ID zb_bufid_t of a buffer with payload - * @param addr - short destination address - * @param addr_mode - address mode, only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and @ref - * ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported - * @param dst_ep - destination end point - * @param ep - our end point - * @param prof_id - profile identifier - * @param cluster_id - cluster identifier - * @param seq_num - sequence number - * @param cmd - identifier of the command the response is dedicated to - * @param status_code - status field for received command - * @param direction - direction of the command (see @ref zcl_frame_direction) - */ -#define ZB_ZCL_SEND_DEFAULT_RESP_DIRECTION(buffer, addr, addr_mode, dst_ep, ep, prof_id, \ - cluster_id, seq_num, cmd, status_code, direction) \ - { \ - zb_uint8_t *ptr; \ - ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_A( \ - ptr, (direction), ZB_U2B(ZB_ZCL_NOT_MANUFACTURER_SPECIFIC)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, (seq_num), ZB_ZCL_CMD_DEFAULT_RESP); \ - *(ptr++) = (cmd); \ - *(ptr++) = (status_code); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT((buffer), (addr), (addr_mode), (dst_ep), (ep), (prof_id), \ - (cluster_id), NULL); \ - } - -/** - * @brief Send default response command and execute callback when it is acknowledged or expired - * - * If no callback is needed, use @ref ZB_ZCL_SEND_DEFAULT_RESP() - * - * @param buffer - ID zb_bufid_t of a buffer with payload - * @param addr - short destination address - * @param addr_mode - address mode, only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and @ref - * ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported - * @param dst_ep - destination end point - * @param ep - our end point - * @param prof_id - profile identifier - * @param cluster_id - cluster identifier - * @param seq_num - sequence number - * @param cmd - identifier of the command the response is dedicated to - * @param status_code - status field for received command - * @param callback - callback to be executed when command is acknowledged or expired (of type @ref zb_callback_t) - */ -#define ZB_ZCL_SEND_DEFAULT_RESP_WITH_CB(buffer, addr, addr_mode, dst_ep, ep, prof_id, cluster_id, \ - seq_num, cmd, status_code, callback) \ - { \ - zb_uint8_t *ptr; \ - ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, (seq_num), ZB_ZCL_CMD_DEFAULT_RESP); \ - *(ptr++) = (cmd); \ - *(ptr++) = (status_code); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT((buffer), (addr), (addr_mode), (dst_ep), (ep), (prof_id), \ - (cluster_id), (callback)); \ - } - -#define ZB_ZCL_SEND_DEFAULT_RESP_WITH_CB_NEW(buffer, addr, addr_mode, dst_ep, ep, prof_id, \ - cluster_id, seq_num, cmd, status_code, callback, \ - aps_secured) \ - { \ - zb_uint8_t *ptr; \ - ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, (seq_num), ZB_ZCL_CMD_DEFAULT_RESP); \ - *(ptr++) = (cmd); \ - *(ptr++) = (status_code); \ - ZB_ZCL_FINISH_N_SEND_PACKET_NEW((buffer), ptr, (addr), (addr_mode), (dst_ep), (ep), (prof_id), \ - (cluster_id), (callback), (aps_secured), ZB_FALSE, 0); \ - } - -/** - * @brief Send default response command and execute callback when it's acknowledged or expired - * - * If no callback is needed, use @ref ZB_ZCL_SEND_DEFAULT_RESP() - * - * @param buffer - ID zb_bufid_t of a buffer with payload - * @param addr - short destination address - * @param addr_mode - address mode, only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and @ref - * ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported - * @param dst_ep - destination end point - * @param ep - our end point - * @param prof_id - profile identifier - * @param cluster_id - cluster identifier - * @param seq_num - sequence number - * @param cmd - identifier of the command the response is dedicated to - * @param status_code - status field for received command - * @param manuf_code - manufacturer code - * @param direction - direction of the command (see @ref zcl_frame_direction) - * @param callback - callback to be executed when command is acknowledged or expired (of type @ref zb_callback_t) - */ -#define ZB_ZCL_SEND_DEFAULT_RESP_MANUF_WITH_CB(buffer, addr, addr_mode, dst_ep, ep, prof_id, \ - cluster_id, seq_num, cmd, status_code, manuf_code, direction, callback) \ -{ \ - zb_uint8_t * ptr = NULL; \ - ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_EXT(ptr, ZB_TRUE, direction); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, seq_num, ZB_TRUE, manuf_code, ZB_ZCL_CMD_DEFAULT_RESP); \ - *(ptr++) = cmd; \ - *(ptr++) = status_code; \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, addr_mode, dst_ep, ep, prof_id, cluster_id, (callback)); \ -} - -/** - * @brief check whether command requires default response to be sent - * - * Default response is sent if: - * - particular response is not sent yet - * - original command is NOT broadcast - * - disable_default_response is set to FALSE or command status is not Success - * - command itself is NOT default response - * - * This is a helper method, use @ref ZB_ZCL_CHECK_IF_SEND_DEFAULT_RESP instead - * - * @param _is_broadcast - broadcast bit from NWK header - * @param _delivery_mode - delivery mode from APS header - * @param _disable_def_resp - Disable Default Response bit from ZCL header - * @param _status - status of the handled command - * @param _is_def_resp_frame - check for command type - */ -#define ZB_ZCL_CHECK_IF_SEND_DEFAULT_RESP_EXT( \ - _is_broadcast, _delivery_mode, _disable_def_resp, _status, _is_def_resp_frame) \ - (!(_is_broadcast) && ((_delivery_mode) == ZB_APS_DELIVERY_UNICAST) && \ - (!(_disable_def_resp) || (_status) != ZB_ZCL_STATUS_SUCCESS) \ - && !(_is_def_resp_frame)) - - -/** - @brief API call that is used to check if it is needed to send - Default response for the command - @param _cmd_info - variable of zb_zcl_parsed_hdr_t type, containing - received command header data - @param _status - status of the handled command - */ -#define ZB_ZCL_CHECK_IF_SEND_DEFAULT_RESP(_cmd_info, _status) \ - (ZB_ZCL_CHECK_IF_SEND_DEFAULT_RESP_EXT( \ - ZB_NWK_IS_ADDRESS_BROADCAST((_cmd_info).addr_data.common_data.dst_addr), \ - ZB_APS_FC_GET_DELIVERY_MODE((_cmd_info).addr_data.common_data.fc), \ - (_cmd_info).disable_default_response, _status, \ - ((_cmd_info).is_common_command && (_cmd_info).cmd_id == ZB_ZCL_CMD_DEFAULT_RESP)) \ - && !ZB_ZCL_ADDR_TYPE_IS_GPD((_cmd_info).addr_data.common_data.source.addr_type)) - -/** - * @brief General API for sending Default response command - * - * @param _buffer - zb_bufid_t buffer - * @param _dst_addr - 16-bit destination address - * @param _dst_addr_mode - destination address mode. Possible values - * ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT, ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT, - * ZB_APS_ADDR_MODE_16_ENDP_PRESENT - * @param _dst_ep - destination Endpoint number - * @param _src_ep - source Endpoint number - * @param _prof_id - profile ID - * @param _cluster_id - cluster ID - * @param _seq_num - transaction sequence number - * @param _cmd - command ID - * @param _status_code - command status (see @ref zcl_status) - * @param _direction - direction of command (see @ref zcl_frame_direction) - * @param _is_manuf_specific - flag, equal to 1 if command is - * manufacturer specific - * @param _manuf_code - manufacturer specific code, is taken unto - * account only if _is_manuf_specific is equal to 1 - * @param _callback - pointer to the callback function that will be - * called when the command is sent - */ -#define ZB_ZCL_SEND_DEFAULT_RESP_EXT(_buffer, _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, \ - _prof_id, _cluster_id, _seq_num, _cmd, _status_code, \ - _direction, _is_manuf_specific, _manuf_code, _callback) \ - { \ - zb_uint8_t *_ptr; \ - _ptr = ZB_ZCL_START_PACKET(_buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_A(_ptr, (_direction), \ - (_is_manuf_specific)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(_ptr, (_seq_num), (_is_manuf_specific), (_manuf_code), \ - ZB_ZCL_CMD_DEFAULT_RESP); \ - *(_ptr++) = (_cmd); \ - *(_ptr++) = (_status_code); \ - ZB_ZCL_FINISH_PACKET((_buffer), _ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT((_buffer), (_dst_addr), (_dst_addr_mode), (_dst_ep), (_src_ep), \ - (_prof_id), (_cluster_id), (_callback)); \ - } - - -/** @brief Send default response command. - * @param buffer - ID zb_bufid_t of a buffer with payload - * @param addr - short destination address - * @param addr_mode - address mode, only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and @ref - * ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported - * @param dst_ep - destination end point - * @param ep - our end point - * @param prof_id - profile identifier - * @param cluster_id - cluster identifier - * @param seq_num - sequence number - * @param cmd - identifier of the command the response is dedicated to - * @param status_code - status field for received command - */ -#define ZB_ZCL_SEND_DEFAULT_RESP(buffer, addr, addr_mode, dst_ep, ep, prof_id, cluster_id, \ - seq_num, cmd, status_code) \ - ZB_ZCL_SEND_DEFAULT_RESP_WITH_CB(buffer, addr, addr_mode, dst_ep, ep, prof_id, cluster_id, \ - seq_num, cmd, status_code, NULL) - -#define ZB_ZCL_SEND_DEFAULT_RESP_NEW(buffer, addr, addr_mode, dst_ep, ep, prof_id, cluster_id, \ - seq_num, cmd, status_code, aps_secured) \ - ZB_ZCL_SEND_DEFAULT_RESP_WITH_CB_NEW(buffer, addr, addr_mode, dst_ep, ep, prof_id, cluster_id, \ - seq_num, cmd, status_code, NULL, aps_secured) - -/** - * @brief Send default response command. - * - * @param buffer - ID zb_bufid_t of a buffer with payload - * @param addr - short destination address - * @param addr_mode - address mode, only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and @ref - * ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported - * @param dst_ep - destination end point - * @param ep - our end point - * @param prof_id - profile identifier - * @param cluster_id - cluster identifier - * @param seq_num - sequence number - * @param cmd - identifier of the command the response is dedicated to - * @param status_code - status field for received command - * @param manuf_code - manufacturer code - * @param direction - direction of command (see @ref zcl_frame_direction) - */ -#define ZB_ZCL_SEND_DEFAULT_RESP_MANUF( \ - buffer, addr, addr_mode, dst_ep, ep, prof_id, cluster_id, seq_num, cmd, status_code, manuf_code, direction) \ - ZB_ZCL_SEND_DEFAULT_RESP_MANUF_WITH_CB(buffer, addr, addr_mode, dst_ep, ep, prof_id, cluster_id, \ - seq_num, cmd, status_code, manuf_code, direction, NULL) - - - -/** @brief Default response payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_default_resp_payload_s -{ - zb_uint8_t command_id; /*!< Command identifier */ - zb_uint8_t status; /*!< Command execution status */ -} ZB_PACKED_STRUCT zb_zcl_default_resp_payload_t; - -/** @brief Default response structured reading - @param buffer - pointer to the message buffer (of type zb_bufid_t) - containing payload - @return pointer to @ref zb_zcl_default_resp_payload_s structure - @attention returned pointer will point to the same data in the buffer thus - being valid until buffer data will be overwritten. -*/ -#define ZB_ZCL_READ_DEFAULT_RESP(buffer) \ - ( (zb_buf_len((buffer)) < sizeof(zb_zcl_default_resp_payload_t)) ? \ - NULL : \ - (zb_zcl_default_resp_payload_t*)zb_buf_begin((buffer))); \ - if (zb_buf_len((buffer)) >= sizeof(zb_zcl_default_resp_payload_t)) \ - { \ - zb_zcl_default_resp_payload_t *default_resp_payload = (zb_zcl_default_resp_payload_t*)zb_buf_begin((buffer)); \ - default_resp_payload->status = zb_zcl_zcl8_statuses_conversion(default_resp_payload->status); \ - } - -/** @} */ /* Default response command sending and parsing. */ - -/*************** Read attribute command definitions ************************/ - -/** - * @defgroup read_attr_command Read attributes request and response sending and parsing. - * @{ - * @details - * Read attributes command described in ZCL spec, subclauses 2.4.1 and 2.4.2. - * - * Read attributes request command can be formed and sent as in following snippet: - * @code - * ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ(zcl_cmd_buf, cmd_ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); - * ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID); - * ZB_ZCL_GENERAL_SEND_READ_ATTR_REQ(zcl_cmd_buf, cmd_ptr, DUT_ADDR, DUT_ADDR_MODE, DUT_ENDPOINT, - * TH_ENDPOINT, ZB_AF_HA_PROFILE_ID, - * ZB_ZCL_CLUSTER_ID_BINARY_INPUT, NULL); - * @endcode - * Read attributes response can be parsed as: - * @code - * ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES(buf, read_attr_resp); - * @endcode - * until allocated buffer space exceeds. - * - * Read attributes request parsing and response filling and sending is implemented in ZCL - * library internal functions. - */ - -/*! @brief ZCL Read Attribute Command frame - @see ZCL spec, zb_zcl_read_attr 2.4.1 Read Attributes Command - @note Command frame contains variable number of parameters -*/ -typedef ZB_PACKED_PRE struct zb_zcl_read_attr_req_s -{ - zb_uint16_t attr_id[1]; /*!< Attribute ID list */ -} ZB_PACKED_STRUCT -zb_zcl_read_attr_req_t; - -/** @cond internals_doc */ - -/** @brief Minimal size of Read attribute response, it should contain attribute id and status */ -#define ZB_ZCL_READ_ATTR_RESP_SIZE (sizeof(zb_uint16_t) + sizeof(zb_uint8_t)) - -/** @endcond */ /* internals_doc */ - -/*! @brief ZCL Read Attribute Response Command frame - @see ZCL spec, zb_zcl_read_attr 2.4.2 Read Attributes Response Command - @note Command frame contains variable number of parameters. Also, based on status value - attr_type and attr_value maybe absent. -*/ -typedef ZB_PACKED_PRE struct zb_zcl_read_attr_res_s -{ - zb_uint16_t attr_id; /*!< Attribute ID */ - zb_uint8_t status; /*!< Attribute status */ - zb_uint8_t attr_type; /*!< Attribute type */ - zb_uint8_t attr_value[1]; /*!< Attribute value */ -} ZB_PACKED_STRUCT zb_zcl_read_attr_res_t; - -/** @brief Parses Read attribute response and returns next Read attribute status record or NULL if - there is no more data. - - If response contains invalid data, NULL is returned. - @param data_buf - ID zb_bufid_t of a buffer containing read attribute response data - @param read_attr_resp - out pointer to zb_zcl_read_attr_res_t, containing Read attribute status - record - @note data_buf buffer should contain Read attribute response payload, without ZCL header. Each - parsed Read attribute status record is extracted from initial data_buf buffer - */ -#define ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES(data_buf, read_attr_resp) \ -{ \ - zb_uint8_t resp_size = 0xff; \ - (read_attr_resp) = zb_buf_len(data_buf) >= ZB_ZCL_READ_ATTR_RESP_SIZE ? \ - (zb_zcl_read_attr_res_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (read_attr_resp != NULL) \ - { \ - (read_attr_resp)->status = zb_zcl_zcl8_statuses_conversion((read_attr_resp)->status); \ - resp_size = ZB_ZCL_READ_ATTR_RESP_SIZE; \ - ZB_ZCL_HTOLE16_INPLACE(&(read_attr_resp)->attr_id); \ - if ((read_attr_resp)->status == ZB_ZCL_STATUS_SUCCESS) \ - { \ - resp_size += \ - sizeof(zb_uint8_t) + \ - zb_zcl_get_attribute_size((read_attr_resp)->attr_type, (read_attr_resp)->attr_value); \ - if (resp_size <= zb_buf_len(data_buf)) \ - { \ - ZB_ZCL_FIX_ENDIAN((read_attr_resp)->attr_value, (read_attr_resp)->attr_type); \ - } \ - } \ - \ - if (resp_size <= zb_buf_len(data_buf)) \ - { \ - (void)zb_buf_cut_left((data_buf), resp_size); \ - } \ - else \ - { \ - (read_attr_resp) = NULL; \ - } \ - } \ -} - -/** @brief Initialize Read attribute command - @param buffer to put packet to - @param cmd_ptr - command buffer pointer - @param def_resp - enable/disable default response -*/ -#define ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ(buffer, cmd_ptr, def_resp) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL(cmd_ptr, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_READ_ATTRIB); \ -} - -/** - * @brief Initialize Read Attribute Request command - * - * @param buffer - buffer to store command data - * @param cmd_ptr - pointer to a command data memory - * @param direction - direction of command (see @ref zcl_frame_direction) - * @param def_resp - enable/disable default response - */ -#define ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ_A(buffer, cmd_ptr, direction, def_resp) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_A(cmd_ptr, direction, ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_READ_ATTRIB); \ -} - -/** - * @brief Initialize Read Attribute Request command with manufacturer code - * - * @param buffer - buffer to store command data - * @param cmd_ptr - pointer to a command data memory - * @param direction - direction of command (see @ref zcl_frame_direction) - * @param def_resp - enable/disable default response - * @param manuf_code - manufacturer specific code - */ -#define ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ_MANUF(buffer, cmd_ptr, direction, def_resp, manuf_code) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_A(cmd_ptr, direction, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_TRUE, manuf_code, ZB_ZCL_CMD_READ_ATTRIB); \ -} - -/** @brief Add attribute id to command payload - @param cmd_ptr - command buffer pointer - @param attr_id - attribute ID -*/ -#define ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, attr_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (attr_id)); \ -} - -/** @brief Sends Read attribute command - @param buffer to place data to - @param cmd_ptr - pointer to the memory area after the command data end - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param profile_id - profile identifier - @param cluster_id - cluster identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_GENERAL_SEND_READ_ATTR_REQ(buffer, cmd_ptr, addr, dst_addr_mode, dst_ep, ep, profile_id, cluster_id, cb) \ - ZB_ZCL_FINISH_PACKET(buffer, cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, profile_id, cluster_id, cb); - -/** @brief Parses Read attribute request and returns next Read attribute record or NULL if there - * is no more data. - - If request contains invalid data, NULL is returned. - @param _data_buf - ID zb_bufid_t of a buffer containing write attribute request data - @param _read_attr_req - out pointer to zb_zcl_read_attr_req_t, containing Read attribute record - out value direct into data_buf. Do not change data_buf before finish work with read_attr_req - @note data_buf buffer should contain Read attribute request payload, without ZCL header. Each - parsed Read attribute record is extracted from initial data_buf buffer - - */ -#define ZB_ZCL_GENERAL_GET_READ_ATTR_REQ(_data_buf, _read_attr_req) \ -{ \ - (_read_attr_req) = zb_buf_len((_data_buf)) >= sizeof(zb_zcl_read_attr_req_t) ? \ - (zb_zcl_read_attr_req_t*)zb_buf_begin((_data_buf)) : NULL; \ - \ - if ((_read_attr_req)) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(_read_attr_req)->attr_id); \ - (void)zb_buf_cut_left((_data_buf), sizeof(zb_zcl_read_attr_req_t)); \ - } \ -} - -/** @brief Initialize Read Attribute Response command - @param _buffer - buffer to store command data - @param _cmd_ptr - pointer to a command data memory - @param _seq - command sequence -*/ -#define ZB_ZCL_GENERAL_INIT_READ_ATTR_RESP(_buffer, _cmd_ptr, _seq) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET((_buffer)); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL((_cmd_ptr)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER((_cmd_ptr), (_seq), ZB_ZCL_CMD_READ_ATTRIB_RESP); \ -} - -/** - * @brief Initialize Read Attribute Response command - * - * @param _buffer - buffer to store command data - * @param _cmd_ptr - pointer to a command data memory - * @param _direction - direction of command (see @ref zcl_frame_direction) - * @param _seq - command sequence - * @param _is_manuf - whether command is manufacturer specific - * @param _manuf_id - manufacturer ID (needed if _is_manuf is set) - */ -#define ZB_ZCL_GENERAL_INIT_READ_ATTR_RESP_EXT(_buffer, _cmd_ptr, _direction, _seq, _is_manuf, _manuf_id) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET((_buffer)); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_A((_cmd_ptr), (_direction), (_is_manuf)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT((_cmd_ptr), (_seq), (_is_manuf), (_manuf_id), ZB_ZCL_CMD_READ_ATTRIB_RESP); \ -} - - -/** @brief Send Read attribute response command - @param _buffer - buffer to store command data - @param _cmd_ptr - pointer to a command data memory - @param _addr - address to send packet to - @param _dst_addr_mode - addressing mode - @param _dst_ep - destination endpoint - @param _ep - sending endpoint - @param _profile_id - profile identifier - @param _cluster_id - cluster identifier - @param _cb - callback for getting command send status -*/ -#define ZB_ZCL_GENERAL_SEND_READ_ATTR_RESP( \ - _buffer, _cmd_ptr, _addr, _dst_addr_mode, _dst_ep, _ep, _profile_id, _cluster_id, _cb) \ -{ \ - ZB_ZCL_FINISH_PACKET((_buffer), (_cmd_ptr)) \ - ZB_ZCL_SEND_COMMAND_SHORT((_buffer), (_addr), (_dst_addr_mode), (_dst_ep), (_ep), \ - (_profile_id), (_cluster_id), (_cb)); \ -} - -/** @} */ /* Read attribute request and response sending and parsing. */ - -/********************** Write attribute command definitions ***************************/ - -/** - * @defgroup write_attr_cmd Write attributes command sending and parsing. - * @{ - * @details - * Both write attributes request and response commands have variable-length payload. - * - * Write attributes request can be filled as following: - * @code - * ZB_ZCL_GENERAL_INIT_WRITE_ATTR_REQ(data_buf, ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); - * ZB_ZCL_GENERAL_ADD_VALUE_WRITE_ATTR_REQ(ptr, attr_id, attr_type, attr_val); - * ZB_ZCL_GENERAL_SEND_WRITE_ATTR_REQ( - * data_buf, - * ptr, - * dst_addr, - * ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - * dst_ep, - * src_ep, - * ZB_AF_HA_PROFILE_ID, - * ZB_ZCL_CLUSTER_ID_ON_OFF, - * NULL); - * @endcode - * On the server side, this packet could be parsed in the following manner: - * @code - * zb_zcl_write_attr_req_t *write_attr_req; - * ... - * do - * { - * ZB_ZCL_GENERAL_GET_NEXT_WRITE_ATTR_REQ(data_buf, write_attr_req); - * if (write_attr_req) - * { - * process write attribute request record - * } - * } - * while(write_attr_req); - * @endcode - * - * Response sending and parsing could be done in the same manner. - */ - -/*! @brief ZCL Write Attribute Command frame - @see ZCL spec, 2.4.3 Write Attributes Command -*/ -typedef ZB_PACKED_PRE struct zb_zcl_write_attr_req_s -{ - zb_uint16_t attr_id; /*!< Attribute ID */ - zb_uint8_t attr_type; /*!< Attribute type */ - zb_uint8_t attr_value[1]; /*!< Attribute value */ -} ZB_PACKED_STRUCT -zb_zcl_write_attr_req_t; - -/** @cond internals_doc */ - -/** @brief Minimal size of Write attribute request, it will be more if attr_value size is more - * than 1 byte - */ -#define ZB_ZCL_WRITE_ATTR_REQ_SIZE sizeof(zb_zcl_write_attr_req_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Write attribute request and returns next Write attribute record or NULL if there - * is no more data. - - If request contains invalid data, NULL is returned. - @param data_ptr - pointer to the data of a zb_bufid_t buffer containing write attribute request data - @param data_len - variable containing length of a zb_bufid_t buffer - @param write_attr_req - out pointer to zb_zcl_write_attr_req_t, containing Write attribute record - @note buffer data by data_ptr should contain Write attribute request payload, without ZCL header. - */ -#define ZB_ZCL_GENERAL_GET_NEXT_WRITE_ATTR_REQ(data_ptr, data_len, write_attr_req) \ - { \ - zb_uint8_t req_size = ZB_UINT8_MAX; \ - (write_attr_req) = (data_len) >= ZB_ZCL_WRITE_ATTR_REQ_SIZE \ - ? (zb_zcl_write_attr_req_t *)(void *)(data_ptr) \ - : NULL; \ - \ - if ((write_attr_req) != NULL) \ - { \ - /* substruct sizeof(zb_uint8_t) because its size */ \ - /* is already included into ZB_ZCL_WRITE_ATTR_REQ_SIZE */ \ - ZB_ASSERT_COMPILE_TIME(ZB_ZCL_WRITE_ATTR_REQ_SIZE <= ZB_UINT8_MAX); \ - req_size = (zb_uint8_t)ZB_ZCL_WRITE_ATTR_REQ_SIZE - (zb_uint8_t)sizeof(zb_uint8_t) \ - + zb_zcl_get_attribute_size((write_attr_req)->attr_type, \ - (write_attr_req)->attr_value); \ - \ - if (req_size <= (data_len)) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(write_attr_req)->attr_id); \ - ZB_ZCL_FIX_ENDIAN((write_attr_req)->attr_value, (write_attr_req)->attr_type); \ - } \ - } \ - \ - if (req_size <= (data_len)) \ - { \ - (data_ptr) = (data_ptr) + req_size; \ - (data_len) = (data_len)-req_size; \ - } \ - else \ - { \ - (write_attr_req) = NULL; \ - } \ - } - -/*! @brief ZCL Write Attribute Command frame - @see ZCL spec, 2.4.3 Write Attributes Command -*/ -typedef ZB_PACKED_PRE struct zb_zcl_write_attr_res_s -{ - zb_uint8_t status; /*!< Write attribute status */ - zb_uint16_t attr_id; /*!< Attribute ID */ -} ZB_PACKED_STRUCT -zb_zcl_write_attr_res_t; - -/** @cond internals_doc */ - -/** Minimal size of write attribute response */ -#define ZB_ZCL_WRITE_ATTR_RES_SIZE sizeof(zb_uint8_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Write attribute response and returns next Write attribute status or NULL if there - is no more data. - - If response contains invalid data, NULL is returned. - @param data_buf - ID zb_bufid_t of a buffer containing write attribute response data - @param write_attr_resp - out pointer to zb_zcl_write_attr_res_t, containing Write attribute status - @note data_buf buffer should contain Write attribute response payload, without ZCL header. Each - parsed Write attribute response is extracted from initial data_buf buffer - */ -#define ZB_ZCL_GET_NEXT_WRITE_ATTR_RES(data_buf, write_attr_resp) \ -{ \ - zb_uint8_t res_size; \ - (write_attr_resp) = zb_buf_len(data_buf) >= ZB_ZCL_WRITE_ATTR_RES_SIZE ? \ - (zb_zcl_write_attr_res_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (write_attr_resp) \ - { \ - (write_attr_resp)->status = \ - zb_zcl_zcl8_statuses_conversion((write_attr_resp)->status); \ - if ((write_attr_resp)->status != ZB_ZCL_STATUS_SUCCESS) \ - { \ - /* In case of error, attribute id is reported */ \ - res_size = sizeof(zb_zcl_write_attr_res_t); \ - if (res_size <= zb_buf_len(data_buf)) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(write_attr_resp)->attr_id); \ - } \ - } \ - else \ - { \ - res_size = ZB_ZCL_WRITE_ATTR_RES_SIZE; \ - } \ - \ - if (res_size <= zb_buf_len(data_buf)) \ - { \ - (void)zb_buf_cut_left((data_buf), res_size); \ - } \ - else \ - { \ - (write_attr_resp) = NULL; \ - } \ - } \ -} - -/** @brief Initialize Write attribute command - @param buffer - buffer to store command data - @param cmd_ptr - pointer to a command data memory - @param def_resp - enable/disable default response - @param write_attr_type - type of 'Write Attribute' command: - default - @see ZB_ZCL_CMD_WRITE_ATTRIB; - no response - @see ZB_ZCL_CMD_WRITE_ATTRIB_NO_RESP; - undivided - @see ZB_ZCL_CMD_WRITE_ATTRIB_UNDIV; -*/ -#define ZB_ZCL_GENERAL_INIT_WRITE_ATTR_REQ_BY_TYPE(buffer, cmd_ptr, def_resp, write_attr_type) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL(cmd_ptr, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), write_attr_type); \ -} - -/** @brief Initialize Write attribute command - @param buffer - buffer to store command data - @param cmd_ptr - pointer to a command data memory - @param def_resp - enable/disable default response -*/ -#define ZB_ZCL_GENERAL_INIT_WRITE_ATTR_REQ(buffer, cmd_ptr, def_resp) \ - ZB_ZCL_GENERAL_INIT_WRITE_ATTR_REQ_BY_TYPE( \ - (buffer), (cmd_ptr), (def_resp), ZB_ZCL_CMD_WRITE_ATTRIB); - -/** @brief Initialize Write Attribute No Response command - @param buffer - buffer to store command data - @param cmd_ptr - pointer to a command data memory - @param def_resp - enable/disable default response -*/ -#define ZB_ZCL_GENERAL_INIT_WRITE_ATTR_REQ_NO_RESP(buffer, cmd_ptr, def_resp) \ - ZB_ZCL_GENERAL_INIT_WRITE_ATTR_REQ_BY_TYPE( \ - (buffer), (cmd_ptr), (def_resp), ZB_ZCL_CMD_WRITE_ATTRIB_NO_RESP); - -/** @brief Initialize Write Attribute Undivided command - @param buffer - buffer to store command data - @param cmd_ptr - pointer to a command data memory - @param def_resp - enable/disable default response -*/ -#define ZB_ZCL_GENERAL_INIT_WRITE_ATTR_REQ_UNDIV(buffer, cmd_ptr, def_resp) \ - ZB_ZCL_GENERAL_INIT_WRITE_ATTR_REQ_BY_TYPE( \ - (buffer), (cmd_ptr), (def_resp), ZB_ZCL_CMD_WRITE_ATTRIB_UNDIV); - -/** - * @brief Initialize Write attribute command - * - * @param buffer - buffer to store command data - * @param cmd_ptr - pointer to a command data memory - * @param direction - direction of command (see @ref zcl_frame_direction) - * @param def_resp - enable/disable default response - */ -#define ZB_ZCL_GENERAL_INIT_WRITE_ATTR_REQ_A(buffer, cmd_ptr, direction, def_resp) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_A(cmd_ptr, direction, ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_WRITE_ATTRIB); \ -} - -/** @brief Add attribute value to command payload - @param cmd_ptr - pointer to a command data memory - @param attr_id - attribute identifier - @param attr_type - attribute type - @param attr_val - pointer to attribute data value -*/ -#define ZB_ZCL_GENERAL_ADD_VALUE_WRITE_ATTR_REQ(cmd_ptr, attr_id, attr_type, attr_val) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (attr_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (attr_type)); \ - (cmd_ptr) = zb_zcl_put_value_to_packet(cmd_ptr, attr_type, attr_val); \ -} - -/** @brief Send Write attribute command - @param buffer - buffer to store command data - @param cmd_ptr - pointer to a command data memory - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param profile_id - profile identifier - @param cluster_id - cluster identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_GENERAL_SEND_WRITE_ATTR_REQ( \ - buffer, cmd_ptr, addr, dst_addr_mode, dst_ep, ep, profile_id, cluster_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, profile_id, cluster_id, cb); \ -} - - -/** @brief Send "write attributes" request. - * deprecate */ -#define ZB_ZCL_GENERAL_SEND_WRITE_ATTRS_REQ( \ - buffer, addr, addr_mode, dst_ep, ep, prof_id, cluster_id) \ - ZB_ZCL_SEND_GENERAL_COMMAND_REQ_SHORT( \ - buffer, addr, addr_mode, dst_ep, ep, prof_id, cluster_id, ZB_ZCL_CMD_WRITE_ATTRIB) - - -/** @brief Initialize Write attribute response command - @param _buffer - buffer to store command data - @param _cmd_ptr - pointer to a command data memory - @param _seq - command sequence -*/ -#define ZB_ZCL_GENERAL_INIT_WRITE_ATTR_RESP(_buffer, _cmd_ptr, _seq) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET((_buffer)); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL((_cmd_ptr)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER((_cmd_ptr), (_seq), ZB_ZCL_CMD_WRITE_ATTRIB_RESP); \ -} - -/** - * @brief Initialize Write attribute response command - * - * @param _buffer - buffer to store command data - * @param _cmd_ptr - pointer to a command data memory - * @param _direction - direction of command (see @ref zcl_frame_direction) - * @param _seq - command sequence - * @param _is_manuf - whether command is manufacturer specific - * @param _manuf_id - manufacturer ID (needed if _is_manuf is set) - */ -#define ZB_ZCL_GENERAL_INIT_WRITE_ATTR_RESP_EXT(_buffer, _cmd_ptr, _direction, _seq, _is_manuf, _manuf_id) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET((_buffer)); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_A((_cmd_ptr), (_direction), (_is_manuf)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT((_cmd_ptr), (_seq), (_is_manuf), (_manuf_id), ZB_ZCL_CMD_WRITE_ATTRIB_RESP); \ -} - -/** @brief Add Success status value to Write attribute response command payload - @param _cmd_ptr - pointer to a command data memory -*/ -#define ZB_ZCL_GENERAL_SUCCESS_WRITE_ATTR_RESP(_cmd_ptr) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA8((_cmd_ptr), ZB_ZCL_STATUS_SUCCESS); \ -} - - -/** @brief Send Write attribute response command - @param _buffer - buffer to store command data - @param _cmd_ptr - pointer to a command data memory - @param _addr - address to send packet to - @param _dst_addr_mode - addressing mode - @param _dst_ep - destination endpoint - @param _ep - sending endpoint - @param _profile_id - profile identifier - @param _cluster_id - cluster identifier - @param _cb - callback for getting command send status -*/ -#define ZB_ZCL_GENERAL_SEND_WRITE_ATTR_RESP( \ - _buffer, _cmd_ptr, _addr, _dst_addr_mode, _dst_ep, _ep, _profile_id, _cluster_id, _cb) \ -{ \ - ZB_ZCL_FINISH_PACKET((_buffer), (_cmd_ptr)) \ - ZB_ZCL_SEND_COMMAND_SHORT((_buffer), (_addr), (_dst_addr_mode), (_dst_ep), (_ep), \ - (_profile_id), (_cluster_id), (_cb)); \ -} - - -/** @} */ /* Write attributes command sending and parsing. */ - -/*************** Discover attribute command definitions ************************/ - -/** - * @defgroup disc_attr_command Discover attributes request and response sending and parsing. - * @{ - * @details - * Discover attributes command described in ZCL spec, subclauses 2.4.13 and 2.4.14. - * - * Read attributes request command can be formed and sent as in following snippet: - * @code - * ZB_ZCL_GENERAL_DISC_ATTR_REQ(zcl_cmd_buf, cmd_ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - * ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID, 5, - * DUT_ADDR, DUT_ADDR_MODE, DUT_ENDPOINT, - * TH_ENDPOINT, ZB_AF_HA_PROFILE_ID, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, NULL); - * @endcode - * Discover attributes response can be parsed as: - * @code - * ZB_ZCL_GENERAL_GET_COMPLETE_DISC_RES(buf, complete); - * ZB_ZCL_GENERAL_GET_NEXT_DISC_ATTR_RES(buf, disc_attr_info); - * @endcode - * until allocated buffer space exceeds. - * - * Discover attributes request parsing and response filling and sending is implemented in ZCL - * library internal functions. - */ - -/*! @brief ZCL Discover Attribute Command frame - @see ZCL spec, zb_zcl_disc_attr 2.4.13 Discover Attributes Command -*/ -typedef ZB_PACKED_PRE struct zb_zcl_disc_attr_req_s -{ - zb_uint16_t start_attr_id; /*!< Start attribute identifier */ - zb_uint8_t maximum; /*!< Maximum attribute identifiers */ -} ZB_PACKED_STRUCT -zb_zcl_disc_attr_req_t; - -/*! @brief ZCL Description for Discover Attribute Response frame - @see ZCL spec, zb_zcl_read_attr 2.4.14 Discover Attribute Response -*/ -typedef ZB_PACKED_PRE struct zb_zcl_disc_attr_info_s -{ - zb_uint16_t attr_id; /*!< Attribute identifier */ - zb_uint8_t data_type; /*!< Attribute data type */ -} ZB_PACKED_STRUCT -zb_zcl_disc_attr_info_t; - - -/*! @brief ZCL Discover Attribute Response frame - @see ZCL spec, zb_zcl_read_attr 2.4.15 Discover Attribute Response - @note Command frame contains variable number of parameters -*/ -typedef ZB_PACKED_PRE struct zb_zcl_disc_attr_res_s -{ - zb_uint8_t complete; /*!< Discovery complete */ - zb_zcl_disc_attr_info_t info[1]; /*!< Attribute desc list */ -} ZB_PACKED_STRUCT -zb_zcl_disc_attr_res_t; - -/** - * @name ZCL Discover Attribute Response - complete field - * @anchor zcl_disc_complete - * @see ZCL spec, clause 2.4.14 - */ -/** @{ */ -#define ZB_ZCL_DISC_NON_COMPLETE 0x00U /*!< more attributes to be discovered */ -#define ZB_ZCL_DISC_COMPLETE 0x01U /*!< no more attributes to be discovered */ -/** @} */ - -/** - * @brief Type for possible values of ZCL Discover Attribute Response. - * - * @deprecated holds one of @ref zcl_disc_complete. Kept only for backward - * compatibility as @ref zcl_disc_complete were declared previously as enum. Can be - * removed in future releases. - */ -typedef zb_uint8_t zb_zcl_disc_complete_t; - -/** @cond internals_doc */ - -#define ZB_ZCL_DISC_ATTR_RESP_SIZE sizeof(zb_zcl_disc_attr_info_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Discovery attribute response and returns next Read attribute status record or NULL if - there is no more data. - - If response contains invalid data, 0 is returned. - @param data_buf - ID zb_bufid_t of a buffer containing discover attribute response data - @param complete - variable to store Complete field - @note data_buf buffer should contain Discover attribute response payload, without ZCL header. - */ -#define ZB_ZCL_GENERAL_GET_COMPLETE_DISC_RES(data_buf, complete) \ -{ \ - if (zb_buf_len(data_buf) > 0) \ - { \ - complete = *(zb_uint8_t*)zb_buf_begin(data_buf); \ - (void)zb_buf_cut_left((data_buf), sizeof(zb_uint8_t)); \ - } \ - else \ - { \ - (complete) = 0; \ - } \ -} - -/** @brief Discovery attribute response and returns next Discovery attribute status record or NULL if - there is no more data. - - If response contains invalid data, NULL is returned. - @param data_buf - ID zb_bufid_t of a buffer containing part of Discover attribute response data - @param disc_attr_info - out pointer to zb_zcl_disc_attr_info_t, containing Discover attribute status - record - @note data_buf buffer should contain Discover attribute response payload, without ZCL header. Each - parsed Discover attribute status record is extracted from initial data_buf buffer - */ -#define ZB_ZCL_GENERAL_GET_NEXT_DISC_ATTR_RES(data_buf, disc_attr_info) \ -{ \ - (disc_attr_info) = zb_buf_len(data_buf) >= ZB_ZCL_DISC_ATTR_RESP_SIZE ? \ - (zb_zcl_disc_attr_info_t*)zb_buf_begin(data_buf) : (zb_zcl_disc_attr_info_t*)0; \ - \ - if (disc_attr_info) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(disc_attr_info)->attr_id); \ - \ - (void)zb_buf_cut_left((data_buf), ZB_ZCL_DISC_ATTR_RESP_SIZE); \ - } \ -} - -/** @brief Discover attribute command - @param buffer - reference to buffer to put packet into - @param def_resp - enable/disable default response - @param start_attr_id - start attribute ID - @param max_len - max count - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param profile_id - profile identifier - @param cluster_id - cluster identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_GENERAL_DISC_READ_ATTR_REQ(buffer, def_resp, start_attr_id, max_len, \ - addr, dst_addr_mode, dst_ep, ep, profile_id, cluster_id, cb) \ -{ \ - zb_uint8_t *cmd_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL(cmd_ptr, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_DISC_ATTRIB); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (start_attr_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (max_len)); \ - ZB_ZCL_FINISH_PACKET(buffer, cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, profile_id, cluster_id, cb); \ -} - -/** - * @brief Discover Attribute Request - * @param buffer - reference to buffer to put packet into - * @param cmd_ptr - pointer to command (not used) - * @param direction - direction of command (see @ref zcl_frame_direction) - * @param def_resp - enable/disable default response - * @param start_attr_id - start attribute ID - * @param max_len - max count - * @param addr - address to send packet to - * @param dst_addr_mode - addressing mode - * @param dst_ep - destination endpoint - * @param ep - sending endpoint - * @param profile_id - profile identifier - * @param cluster_id - cluster identifier - * @param cb - callback for getting command send status - */ -#define ZB_ZCL_GENERAL_DISC_ATTR_REQ_A(buffer, cmd_ptr, direction, def_resp, \ - start_attr_id, max_len, \ - addr, dst_addr_mode, dst_ep, ep, profile_id, cluster_id, cb) \ -{ \ - zb_uint8_t *cmd_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_A(cmd_ptr, direction, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_DISC_ATTRIB); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (start_attr_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (max_len)); \ - ZB_ZCL_FINISH_PACKET(buffer, cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, profile_id, cluster_id, cb); \ -} - -/** @} */ /* Discover attribute request and response sending and parsing. */ - - - -/********************** Configure reporting command definitions ***************************/ - -#if !(defined ZB_ZCL_DISABLE_REPORTING) || defined(DOXYGEN) - -/** - * @defgroup cfg_reporting_cmd Configure reporting command sending and parsing - * @{ - * @details - * Most of actions related to the attribute reporting configuration are implemented in ZCL - * internals. - * - * As described in ZCL spec, subclause 2.4.7, Configure Reporting command has two forms: - * @li client to server - instructs server to configure for attribute reporting. - * @li server to client - notifies client that server has configured for attribute reporting, - * and will report attribute values to the client. - * - * Request to configure server for attribute reporting can be filled like in the snippet below: - * @snippet simple_gw/simple_gw.c zcl_general_fill_configure_report - * Other variant of the command can be filled in a similar way with @ref - * ZB_ZCL_GENERAL_INIT_CONFIGURE_REPORTING_CLI_REQ() and @ref - * ZB_ZCL_GENERAL_ADD_RECV_REPORT_CONFIGURE_REPORTING_REQ() macros, and scheduled for sending - * with ZB_ZCL_GENERAL_SEND_CONFIGURE_REPORTING_REQ() macro. - * - * Configure reporting request record can be parsed as: - * @code - * zb_bufid_t buffer = pointer_to_the_packet_buffer; - * zb_zcl_configure_reporting_req_t* req_record; - * ... - * do - * { - * ZB_ZCL_GENERAL_GET_NEXT_CONFIGURE_REPORTING_REQ(buffer, req_record); - * if (! req_record) - * { - * break; - * } - * process_request_record(req_record); - * } while (1); - * @endcode - * - * Configure Reporting response command will be generated automatically by ZCL internals. - * Response record to the Configure Reporting command can be parsed as: - * @code - * ZB_ZCL_GENERAL_GET_NEXT_CONFIGURE_REPORTING_RES(buf, config_res); - * @endcode - * If there are several Configure Reporting response records, they could be processed cyclically - * in the same manner as Configure Reporting request ones. - * - */ - - /** u.clnt: as usual, cluster with client role sends this request - to a server to configure reporting: how attribute should be reported by a server */ -typedef ZB_PACKED_PRE struct zb_zcl_configure_reporting_req_clnt_s - { - zb_uint8_t attr_type; /*!< Attribute data type */ - zb_uint16_t min_interval; /*!< Minimum reporting interval */ - zb_uint16_t max_interval; /*!< Maximum reporting interval */ - zb_uint8_t delta[1]; /*!< Reportable change */ - } ZB_PACKED_STRUCT -zb_zcl_configure_reporting_req_clnt_t; - - /** u.srv: as usual, cluster with server role sends this request - to a client, to inform him how an attribute will be reported by a server */ -typedef ZB_PACKED_PRE struct zb_zcl_configure_reporting_req_srv_s - { - zb_uint16_t timeout; /*!< Timeout period */ - } ZB_PACKED_STRUCT -zb_zcl_configure_reporting_req_srv_t; - -/** - * @brief General type for Configure Reporting Request command. - - * see @ref zb_zcl_configure_reporting_req_srv_t - * see @ref zb_zcl_configure_reporting_req_clnt_t - */ -typedef ZB_PACKED_PRE union zb_zcl_configure_reporting_req_u_s -{ - zb_zcl_configure_reporting_req_clnt_t clnt; /*!< Parameters for client */ - zb_zcl_configure_reporting_req_srv_t srv; /*!< Parameters for server */ -} ZB_PACKED_STRUCT -zb_zcl_configure_reporting_req_u_t; - -/** @brief One chunk of Configure reporting command request - * - * Attribute reporting configuration record - */ -/* WARNING: Do not put directly packed_struct declaration inside another packet_struct - some - * compilers does not handle it correctly! */ -typedef ZB_PACKED_PRE struct zb_zcl_configure_reporting_req_s -{ - zb_uint8_t direction; /*!< Direction */ - zb_uint16_t attr_id; /*!< Attribute ID */ - zb_zcl_configure_reporting_req_u_t u; /*!< Request fields */ -} ZB_PACKED_STRUCT zb_zcl_configure_reporting_req_t; - -/*! Configure reporting command, direction field values */ -typedef enum zb_zcl_configure_reporting_direction_value_e -{ - ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT = 0x00, /**< Report should be send by a cluster. */ - ZB_ZCL_CONFIGURE_REPORTING_RECV_REPORT = 0x01 /**< Report should be received by a cluster. */ -} -zb_zcl_configure_reporting_direction_value_t; - -/** @cond internals_doc */ - -/* client configuration size is larger then srv version, can take - * sizeof(struct); reduce by sizeof(zb_uint8_t) because delta maybe omitted */ -#define ZB_ZCL_CONFIGURE_REPORTING_FOR_SEND_SIZE \ - (sizeof(zb_zcl_configure_reporting_req_t) - sizeof(zb_uint8_t)) - -/* calculate size for srv command version: direction, attr_id, timeout */ -#define ZB_ZCL_CONFIGURE_REPORTING_FOR_RECV_SIZE sizeof(zb_uint8_t) + sizeof(zb_uint16_t)*2 - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Configure reporting command request and returns next Attribute reporting - configuration record or NULL if there is no more data. - - If request contains invalid data, NULL is returned. - @param data_buf - ID zb_bufid_t of a buffer containing Parses Configure reporting command data - @param config_rep_req - out pointer to zb_zcl_configure_reporting_req_t, containing Attribute - reporting configuration record - @note data_buf buffer should contain Configure reporting command payload, without ZCL header. - Each parsed Attribute reporting configuration record is extracted from initial data_buf buffer - */ -#define ZB_ZCL_GENERAL_GET_NEXT_CONFIGURE_REPORTING_REQ(data_buf, config_rep_req) \ -{ \ - zb_uint8_t res_size = 0xff; \ - /* ZB_ZCL_CONFIGURE_REPORTING_FOR_SEND_SIZE - is minimum payload length */ \ - (config_rep_req) = zb_buf_len(data_buf) >= ZB_ZCL_CONFIGURE_REPORTING_FOR_RECV_SIZE ? \ - (zb_zcl_configure_reporting_req_t *)zb_buf_begin(data_buf) : NULL; \ - \ - if (config_rep_req) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(config_rep_req)->attr_id); \ - if ((config_rep_req)->direction == ZB_ZCL_CONFIGURE_REPORTING_RECV_REPORT) \ - { \ - res_size = ZB_ZCL_CONFIGURE_REPORTING_FOR_RECV_SIZE; \ - ZB_ZCL_HTOLE16_INPLACE(&(config_rep_req)->u.srv.timeout); \ - } \ - else /* ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT */ \ - { \ - res_size = ZB_ZCL_CONFIGURE_REPORTING_FOR_SEND_SIZE; \ - ZB_ZCL_HTOLE16_INPLACE(&(config_rep_req)->u.clnt.min_interval); \ - ZB_ZCL_HTOLE16_INPLACE(&(config_rep_req)->u.clnt.max_interval); \ - if (zb_zcl_is_analog_data_type((config_rep_req)->u.clnt.attr_type)) \ - { \ - res_size += zb_zcl_get_analog_attribute_size((config_rep_req)->u.clnt.attr_type); \ - if (res_size <= zb_buf_len(data_buf)) \ - { \ - ZB_ZCL_FIX_ENDIAN((config_rep_req)->u.clnt.delta, (config_rep_req)->u.clnt.attr_type); \ - } \ - } \ - } /* if ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT */ \ - } /* if config_rep_req */ \ - \ - if (res_size <= zb_buf_len(data_buf)) \ - { \ - (void)zb_buf_cut_left((data_buf), res_size); \ - } \ - else \ - { \ - (config_rep_req) = NULL; \ - } \ -} - -/** One chunk of Configure reporting response command - * - * Attribute status record - */ -typedef ZB_PACKED_PRE struct zb_zcl_configure_reporting_res_s -{ - zb_uint8_t status; /*!< Configure reporting status */ - zb_uint8_t direction; /*!< Direction */ - zb_uint16_t attr_id; /*!< Attribute ID */ -} ZB_PACKED_STRUCT -zb_zcl_configure_reporting_res_t; - -/** @cond internals_doc */ - -/*! Minimum size of zb_zcl_configure_reporting_res_t */ -#define ZB_ZCL_CONFIGURE_REPORTING_RES_SIZE sizeof(zb_uint8_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Configure reporting response and returns next - configure attribute status record or NULL if there is no more data. - - If response contains invalid data, NULL is returned. - @param data_buf - ID zb_bufid_t of a buffer containing Configure reporting response data - @param config_rep_res - out pointer to zb_zcl_configure_reporting_res_t, containing Configure - attribute status record - @note data_buf buffer should contain Configure reporting response payload, without ZCL header. - Each parsed Configure attribute status record is extracted from initial data_buf buffer - */ -#define ZB_ZCL_GENERAL_GET_NEXT_CONFIGURE_REPORTING_RES(data_buf, config_rep_res) \ -{ \ - zb_uint8_t res_size = 0; \ - (config_rep_res) = zb_buf_len(data_buf) >= ZB_ZCL_CONFIGURE_REPORTING_RES_SIZE ? \ - (zb_zcl_configure_reporting_res_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (config_rep_res) \ - { \ - (config_rep_res)->status = \ - zb_zcl_zcl8_statuses_conversion((config_rep_res)->status); \ - if ((config_rep_res)->status != ZB_ZCL_STATUS_SUCCESS \ - && (config_rep_res)->status != ZB_ZCL_STATUS_MALFORMED_CMD) \ - { \ - /* In case of error, direction and attribute id is reported */ \ - res_size = sizeof(zb_zcl_configure_reporting_res_t); \ - if (res_size <= zb_buf_len(data_buf)) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(config_rep_res)->attr_id); \ - } \ - } \ - else \ - { \ - res_size = ZB_ZCL_CONFIGURE_REPORTING_RES_SIZE; \ - } \ - \ - if (res_size <= zb_buf_len(data_buf)) \ - { \ - (void)zb_buf_cut_left((data_buf), res_size); \ - } \ - else \ - { \ - (config_rep_res) = NULL; \ - } \ - } \ -} - -/*! @brief Initialize Configure reporting command (report send case) - @param buffer to put packet to - @param ptr - command buffer pointer - @param def_resp - enable/disable default response -*/ -#define ZB_ZCL_GENERAL_INIT_CONFIGURE_REPORTING_SRV_REQ(buffer, ptr, def_resp) \ -{ \ - ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_A( \ - ptr, ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_CONFIG_REPORT); \ -} - -/*! @brief Initialize Configure reporting command (report receive case) - @param buffer to put packet to - @param ptr - command buffer pointer - @param def_resp - enable/disable default response -*/ -#define ZB_ZCL_GENERAL_INIT_CONFIGURE_REPORTING_CLI_REQ(buffer, ptr, def_resp) \ -{ \ - ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_A( \ - ptr, ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_CONFIG_REPORT); \ -} - -/*! @brief Add attribute reporting configuration record to command payload (report send case) - @param ptr - command buffer pointer - @param attr_id - attribute identifier - @param attr_type - type of the attribute - @param min_interval - reporting minimum interval - @param max_interval - reporting maximum interval - @param report_change - reportable value change -*/ -#define ZB_ZCL_GENERAL_ADD_SEND_REPORT_CONFIGURE_REPORTING_REQ( \ - ptr, attr_id, attr_type, min_interval, max_interval, report_change) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (attr_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (attr_type)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (min_interval)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (max_interval)); \ - if (zb_zcl_is_analog_data_type(attr_type)) \ - { \ - (ptr) = zb_zcl_put_value_to_packet((ptr), (attr_type), report_change); \ - } \ -} - -/*! @brief Add attribute reporting configuration record to command payload (report receive case) - @param ptr - command buffer pointer - @param attr_id - attribute identifier - @param timeout - reporting timeout -*/ -#define ZB_ZCL_GENERAL_ADD_RECV_REPORT_CONFIGURE_REPORTING_REQ(ptr, attr_id, timeout) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, ZB_ZCL_CONFIGURE_REPORTING_RECV_REPORT); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (attr_id)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (timeout)); \ -} - -/** @brief Sends Configure reporting command - @param buffer to put data to - @param ptr - pointer to the memory area to put data to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cluster_id - cluster identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_GENERAL_SEND_CONFIGURE_REPORTING_REQ( \ - buffer, ptr, addr, dst_addr_mode, dst_ep, ep, prfl_id, cluster_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cluster_id, cb); \ -} - -/** @} */ /* Configure reporting command sending and parsing. */ - -/************************** Report attribute command definitions **********************************/ - -/** - * @defgroup report_attr_cmd Report attribute command parsing - * @{ - * @details - * Report attributes command originates from ZCL internals as a packet constructed according to - * ZCL spec, subclause 2.4.11. This command can be parsed by cyclical application of @ref - * ZB_ZCL_GENERAL_GET_NEXT_REPORT_ATTR_REQ() macro. - * - */ - -/** @cond internals_doc */ - -/** @brief Minimal size of Read attribute response, it should contain attribute id and status */ -#define ZB_ZCL_REPORT_ATTR_CMD_SIZE sizeof(zb_zcl_report_attr_req_t) - -/** @endcond */ /* internals_doc */ - -/*! @brief ZCL Report Attribute Command frame - @see ZCL spec, 2.4.11.1 Report Attributes Command - @note Report attribute command contains variable number of attribute reports, - zb_zcl_report_attr_req_t defines one attribute report -*/ -typedef ZB_PACKED_PRE struct zb_zcl_report_attr_req_s -{ - zb_uint16_t attr_id; /*!< Attribute ID */ - zb_uint8_t attr_type; /*!< Attribute type */ - zb_uint8_t attr_value[1]; /*!< Attribute value */ -} ZB_PACKED_STRUCT -zb_zcl_report_attr_req_t; - -/** @cond internals_doc */ - -/** @brief Minimum size of report attribute command */ -#define ZB_ZCL_REPORT_ATTR_REQ_SIZE sizeof(zb_zcl_report_attr_req_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Report attribute command and returns next Attribute - report or NULL if there is no more data. - - If command contains invalid data, NULL is returned. - @param data_buf - ID zb_bufid_t of a buffer containing Report attribute command data - @param rep_attr_req - out pointer to zb_zcl_report_attr_req_t, containing Attribute report - @note data_buf buffer should contain Report attribute command payload, without ZCL header. - Each parsed Attribute report attribute is extracted from initial data_buf buffer - */ -#define ZB_ZCL_GENERAL_GET_NEXT_REPORT_ATTR_REQ(data_buf, rep_attr_req) \ -{ \ - zb_uint8_t req_size = 0xff; \ - (rep_attr_req) = zb_buf_len(data_buf) >= ZB_ZCL_REPORT_ATTR_REQ_SIZE ? \ - (zb_zcl_report_attr_req_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (rep_attr_req) \ - { \ - req_size = ZB_ZCL_REPORT_ATTR_REQ_SIZE; \ - ZB_ZCL_HTOLE16_INPLACE(&(rep_attr_req)->attr_id); \ - /* Reduce req_size value by sizeof(zb_uint8_t) because it is \ - * already included into zb_zcl_report_attr_req_t */ \ - req_size += \ - zb_zcl_get_attribute_size((rep_attr_req)->attr_type, (rep_attr_req)->attr_value) - \ - sizeof(zb_uint8_t); \ - if (req_size <= zb_buf_len(data_buf)) \ - { \ - ZB_ZCL_FIX_ENDIAN((rep_attr_req)->attr_value, (rep_attr_req)->attr_type); \ - } \ - \ - if (req_size <= zb_buf_len(data_buf)) \ - { \ - (void)zb_buf_cut_left((data_buf), req_size); \ - } \ - else \ - { \ - (rep_attr_req) = NULL; \ - } \ - } \ -} - -/** @} */ /* Report attribute command parsing. */ - -/************************** Read Reporting Configuration command definitions **********************************/ - -/** - * @defgroup read_reporting_cfg_cmd Read reporting configuration command sending and parsing - * @{ - * @details - * Most of actions related to the read attribute reporting configuration are implemented in ZCL - * internals. - * Read reporting configuration command is described in ZCL spec, subclause 2.4.9. - */ - - - -/**Format of the Attribute Status Record Field - *Figure 2.20 in ZCL spec. - *NOTE: it can be various number of attribute status record fields in Read - *reporting configuration request - */ -typedef ZB_PACKED_PRE struct zb_zcl_read_reporting_cfg_req_s -{ - zb_uint8_t direction; /*!< The direction field specifies whether - * values of the attribute are reported (0x00), or - *whether reports of the attribute are received (0x01). - */ - zb_uint16_t attr_id; /*!< The attribute identifier field shall - *contain the identifier of the attribute whose - *reporting configuration details are to be read. - */ -} ZB_PACKED_STRUCT - zb_zcl_read_reporting_cfg_req_t; - -/** @brief Minimal size of Write attribute request, it will be more if attr_value size is more - * than 1 byte - */ -#define ZB_ZCL_READ_REP_CFG_REQ_SIZE sizeof(zb_zcl_read_reporting_cfg_req_t) - -/** @brief Parses read reporting configuration request and returns - * next Read reporting configuration attribute record or NULL if there - * is no more data. - - If request contains invalid data, NULL is returned. - @param data_buf - ID zb_bufid_t of a buffer containing read reporting configuration request data - @param rep_cfg_req - out pointer to @ref zb_zcl_read_attr_req_t, containing read reporting configuration request - @param rslt - returns TRUE if record exist and FALSE if not - @note data_buf buffer should contain read reporting configuration request payload, without ZCL header. Each - parsed read reporting configuration request is extracted from initial data_buf buffer - */ -#define ZB_ZCL_GENERAL_GET_NEXT_READ_REP_CFG_REQ(data_buf, rep_cfg_req, rslt) \ - { \ -zb_zcl_read_reporting_cfg_req_t *cfg_req; \ - (cfg_req) = zb_buf_len(data_buf) >= ZB_ZCL_READ_REP_CFG_REQ_SIZE ? \ - (zb_zcl_read_reporting_cfg_req_t *) zb_buf_begin(data_buf) : NULL; \ - if (cfg_req) \ - { \ - rep_cfg_req.direction = cfg_req -> direction; \ - rep_cfg_req.attr_id = cfg_req -> attr_id; \ - ZB_ZCL_HTOLE16_INPLACE(&(read_rep_cfg_req).attr_id); \ - (void)zb_buf_cut_left((data_buf), ZB_ZCL_READ_REP_CFG_REQ_SIZE); \ - rslt = ZB_TRUE; \ - } \ - else \ - { \ - rslt = ZB_FALSE; \ - } \ -} - - -/**Format of the Attribute Reporting Configuration Record Field - *Figure 2.22 in ZCL spec. - *NOTE: it can be various number of attribute recording configuration - *record fields in Read reporting configuration response - */ -typedef ZB_PACKED_PRE struct zb_zcl_read_reporting_cfg_rsp_s -{ - zb_uint8_t status; /*!direction == ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT) \ - { \ - min_resp_size = zb_zcl_is_analog_data_type((read_rep_conf_res)->u.clnt.attr_type)? \ - ZB_ZCL_READ_REPORTING_CFG_RES_SIZE: \ - ZB_ZCL_READ_REPORTING_CFG_RES_SIZE - sizeof(zb_uint8_t); \ - } \ - else \ - { \ - min_resp_size += sizeof(zb_uint16_t); /* timeout value */ \ - } \ - \ - if (zb_buf_len(data_buf) < min_resp_size) \ - { \ - (read_rep_conf_res) = NULL; \ - } \ - } \ - \ - if (read_rep_conf_res) \ - { \ - (read_rep_conf_res)->status = \ - zb_zcl_zcl8_statuses_conversion((read_rep_conf_res)->status); \ - if ((read_rep_conf_res)->status != ZB_ZCL_STATUS_SUCCESS \ - && (read_rep_conf_res)->status != ZB_ZCL_STATUS_MALFORMED_CMD) \ - { \ - /* In case of error, direction and attribute id is reported */ \ - res_size = sizeof(zb_uint16_t) + 2*sizeof(zb_uint8_t); \ - if (res_size <= zb_buf_len(data_buf)) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(read_rep_conf_res)->attr_id); \ - } \ - } \ - else \ - { \ - res_size = min_resp_size; \ - } \ - } \ - \ - if (res_size <= zb_buf_len(data_buf)) \ - { \ - (void)zb_buf_cut_left((data_buf), res_size); \ - } \ - else \ - { \ - (read_rep_conf_res) = NULL; \ - } \ -} - - -/** @} */ /* Configure read reporting configuration command sending and parsing. */ - -/** @cond internals_doc */ - -#endif - - -/******************** HA extensions: discovery commands ***************************/ -/********************* HA extension: discovery commands *****************************/ - -#if defined ZB_ENABLE_HA || defined DOXYGEN - -/** - * @defgroup disc_cmd Discovery commands command sending and parsing. - * @{ - * @details - * Discovery commands request has fixed length payload. - * Discovery commands response has variable-length payload. - * - */ - -/********* request commands ************/ - -/*! @brief ZCL Discovery Commands Command frame - @see HA spec, 12.1.1 Discovery Commands Command - @see HA spec, 12.1.3 Discovery Commands Command -*/ -typedef ZB_PACKED_PRE struct zb_zcl_disc_cmd_req_s -{ - zb_uint8_t start_cmd_id; /*!< Start command identifier */ - zb_uint8_t maximum; /*!< Maximum command identifiers */ -} ZB_PACKED_STRUCT -zb_zcl_disc_cmd_req_t; - -/** @brief Discover commands Generated command - @param _buffer to put packet to - @param _direction - direction client-to-server or server-to-client - @param _def_resp - enable/disable default response - @param _addr - address to send packet to - @param _dst_addr_mode - addressing mode - @param _dst_ep - destination endpoint - @param _ep - sending endpoint - @param _profile_id - profile identifier - @param _cluster_id - cluster identifier - @param _cb - callback for getting command send status - @param _is_manuf - is discovery manufacturer attributes - @param _manuf_id - manufacturer ID - @param _start_cmd_id - start command ID - @param _max_len - max count -*/ -#define ZB_ZCL_GENERAL_DISC_COMMAND_GENERATED_REQ(_buffer, _direction, _def_resp, \ - _addr, _dst_addr_mode, _dst_ep, _ep, _profile_id, _cluster_id, _cb, \ - _is_manuf, _manuf_id, _start_cmd_id, _max_len) \ -{ \ - zb_uint8_t *cmd_ptr = ZB_ZCL_START_PACKET((_buffer)); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_EXT(cmd_ptr, \ - ((_is_manuf) ? ZB_ZCL_MANUFACTURER_SPECIFIC : ZB_ZCL_NOT_MANUFACTURER_SPECIFIC), \ - (_direction), (_def_resp)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), (_is_manuf), \ - (_manuf_id), ZB_ZCL_CMD_DISCOVER_COMMANDS_GENERATED); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (_start_cmd_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (_max_len)); \ - ZB_ZCL_FINISH_PACKET((_buffer), cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT((_buffer), (_addr), (_dst_addr_mode), (_dst_ep), (_ep), \ - (_profile_id), (_cluster_id), (_cb)); \ -} - -/** @brief Discover commands Received command - @param _buffer to put packet to - @param _direction - direction client-to-server or server-to-client - @param _def_resp - enable/disable default response - @param _addr - address to send packet to - @param _dst_addr_mode - addressing mode - @param _dst_ep - destination endpoint - @param _ep - sending endpoint - @param _profile_id - profile identifier - @param _cluster_id - cluster identifier - @param _cb - callback for getting command send status - @param _is_manuf - is discovery manufacturer attributes - @param _manuf_id - manufacturer ID - @param _start_cmd_id - start command ID - @param _max_len - max count -*/ -#define ZB_ZCL_GENERAL_DISC_COMMAND_RECEIVED_REQ(_buffer, _direction, _def_resp, \ - _addr, _dst_addr_mode, _dst_ep, _ep, _profile_id, _cluster_id, _cb, \ - _is_manuf, _manuf_id, _start_cmd_id, _max_len) \ -{ \ - zb_uint8_t *cmd_ptr = ZB_ZCL_START_PACKET((_buffer)); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_EXT(cmd_ptr, \ - ((_is_manuf) ? ZB_ZCL_MANUFACTURER_SPECIFIC : ZB_ZCL_NOT_MANUFACTURER_SPECIFIC), \ - (_direction), (_def_resp)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), (_is_manuf), \ - (_manuf_id), ZB_ZCL_CMD_DISCOVER_COMMANDS_RECEIVED); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (_start_cmd_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (_max_len)); \ - ZB_ZCL_FINISH_PACKET((_buffer), cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT((_buffer), (_addr), (_dst_addr_mode), (_dst_ep), (_ep), \ - (_profile_id), (_cluster_id), (_cb)); \ -} - -/** @brief Get parameter of Discovery command request. - - @param _buffer - buffer containing part of Discover command request data - @param _data_ptr - out pointer to zb_zcl_disc_cmd_req_t, containing Discover command data - @param _status - result parse, see @ref zb_zcl_parse_status_t - */ -#define ZB_ZCL_GENERAL_GET_DISC_COMMAND(_data_ptr, _buffer, _status) \ -{ \ - if (zb_buf_len((_buffer)) != sizeof(zb_zcl_disc_cmd_req_t)) \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_disc_cmd_req_t *src_ptr = \ - (zb_zcl_disc_cmd_req_t*)zb_buf_begin((_buffer)); \ - (_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (_data_ptr)->start_cmd_id = src_ptr->start_cmd_id; \ - (_data_ptr)->maximum = src_ptr->maximum; \ - } \ -} - -/********* response commands ************/ - -/*! @brief ZCL Discover command complete enum - @see HA spec, subclause 12.1.2.1.2. -*/ -typedef enum zb_zcl_disc_cmd_complete_e -{ - /*! Are more commands to be discovered */ - ZB_ZCL_DISC_CMD_NOT_COMPLETE = 0x00, - /*! No more commands to be discovered */ - ZB_ZCL_DISC_CMD_COMPLETE = 0x01, -} zb_zcl_disc_cmd_complete_t; - -/*! @brief ZCL Discovery Commands Command frame - @see HA spec, 12.1.2 Discovery Commands Command - @see HA spec, 12.1.4 Discovery Commands Command -*/ -typedef ZB_PACKED_PRE struct zb_zcl_disc_cmd_resp_s -{ - zb_uint8_t complete; /*!< Discovery complete */ -} ZB_PACKED_STRUCT -zb_zcl_disc_cmd_resp_t; - -/** @brief Init Discover commands response manufacture specific and not specific - @param _cmd_ptr - pointer of current part command - @param _buffer to put packet to - @param _direction - direction client-to-server or server-to-client - @param _seq - sequence of request - @param _cmd - command Id - @param _is_manuf - is manufacturer specific - @param _manuf_id - manufacturer ID - @param _complete - The discovery complete field is a boolean field -*/ -#define ZB_ZCL_GENERAL_INIT_DISC_COMMAND_RESP(_cmd_ptr, _buffer, \ - _direction, _seq, _cmd, _is_manuf, _manuf_id, _complete) \ -{ \ - (_cmd_ptr) = ZB_ZCL_START_PACKET((_buffer)); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_EXT((_cmd_ptr), \ - ((_is_manuf)!=ZB_FALSE ? \ - ZB_ZCL_MANUFACTURER_SPECIFIC : ZB_ZCL_NOT_MANUFACTURER_SPECIFIC), \ - (_direction)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT((_cmd_ptr), (_seq), (_is_manuf), \ - (_manuf_id), (_cmd)); \ - ZB_ZCL_PACKET_PUT_DATA8((_cmd_ptr), (_complete)); \ -} - -/** @brief Add command Id to Discover commands response - @param _cmd_ptr - pointer of current part command - @param _cmd_id - The discovery complete field is a boolean field -*/ -#define ZB_ZCL_GENERAL_ADD_DISC_COMMAND_RESP(_cmd_ptr, _cmd_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA8((_cmd_ptr), (_cmd_id)); \ -} - -/** @brief Finish command Id to Discover commands response - @param _buffer to put packet to - @param _cmd_ptr - pointer of current part command - @param _addr - address to send packet to - @param _dst_addr_mode - addressing mode - @param _dst_ep - destination endpoint - @param _ep - sending endpoint - @param _profile_id - profile identifier - @param _cluster_id - cluster identifier -*/ -#define ZB_ZCL_GENERAL_FINISH_DISC_COMMAND_RESP(_buffer, _cmd_ptr, \ - _addr, _dst_addr_mode, _dst_ep, _ep, _profile_id, _cluster_id) \ -{ \ - ZB_ZCL_FINISH_PACKET((_buffer), (_cmd_ptr)) \ - ZB_ZCL_SEND_COMMAND_SHORT((_buffer), (_addr), (_dst_addr_mode), (_dst_ep), \ - (_ep), (_profile_id), (_cluster_id), NULL); \ -} - - -/** @brief Get parameter of Discovery command response. - - @param _buffer - ID zb_bufid_t of a buffer containing part of Discover command response data - @param _data_ptr - out pointer to zb_zcl_disc_cmd_res_t, containing Discover command response - @param _status - result parse, see @ref zb_zcl_parse_status_t - */ -#define ZB_ZCL_GENERAL_GET_DISC_COMMAND_RESP(_data_ptr, _buffer, _status) \ -{ \ - if (zb_buf_len((_buffer)) < sizeof(zb_zcl_disc_cmd_resp_t)) \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_disc_cmd_resp_t *src_ptr = \ - (zb_zcl_disc_cmd_resp_t*)zb_buf_begin((_buffer)); \ - (_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (_data_ptr)->complete = src_ptr->complete; \ - (void)zb_buf_cut_left(()buffer), sizeof(zb_zcl_disc_cmd_resp_t)); \ - } \ -} - -/** @brief Get next command ID from Discovery command response. - - @param _buffer - ID zb_bufid_t of a buffer containing part of Discover command response data - @param _cmd_id - out next command ID - @param _status - result parse, see @ref zb_zcl_parse_status_t - */ -/* sizeof(cmd_id) == sizeof(zb_uint8_t), - command ID has not special struct */ -#define ZB_ZCL_GENERAL_GET_NEXT_CMD_ID_DISC_COMMAND_RESP(_cmd_id, _buffer, _status) \ -{ \ - if (zb_buf_len((_buffer)) < sizeof(zb_uint8_t)) \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_uint8_t *cmd_id_list = (zb_uint8_t*)zb_buf_begin((_buffer)); \ - (_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (_cmd_id) = cmd_id_list[0]; \ - (void)zb_buf_cut_left((_buffer), sizeof(zb_uint8_t)); \ - } \ -} - -/** @} */ /* Discovery commands command sending and parsing */ - -#endif /* defined ZB_ENABLE_HA || defined DOXYGEN */ - -/***** HA extension: discovery attribute extended ************************/ - -/*! @brief ZCL Discover Attribute Extended Command frame - @see HA1.2 spec, zb_zcl_disc_attr_ext 12.1.5 Discover Attributes Extended Command -*/ -/* command frames are identical for Discover attr and Discover attr ext */ -typedef zb_zcl_disc_attr_req_t zb_zcl_disc_attr_ext_req_t; - -/** @brief Discover Attributes Extended command - @param _buffer to put packet to - @param _direction - direction client-to-server or server-to-client - @param _def_resp - enable/disable default response - @param _addr - address to send packet to - @param _dst_addr_mode - addressing mode - @param _dst_ep - destination endpoint - @param _ep - sending endpoint - @param _profile_id - profile identifier - @param _cluster_id - cluster identifier - @param _cb - callback for getting command send status - @param _is_manuf - is discovery manufacturer attributes - @param _manuf_id - manufacturer ID - @param _start_attr_id - start attribute ID - @param _max_len - max count -*/ -#define ZB_ZCL_GENERAL_DISC_ATTRIBUTE_EXT_REQ(_buffer, _direction, _def_resp, \ - _addr, _dst_addr_mode, _dst_ep, _ep, _profile_id, _cluster_id, _cb, \ - _is_manuf, _manuf_id, _start_attr_id, _max_len) \ -{ \ - zb_uint8_t *cmd_ptr = ZB_ZCL_START_PACKET((_buffer)); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_EXT(cmd_ptr, \ - ((_is_manuf) ? ZB_ZCL_MANUFACTURER_SPECIFIC : ZB_ZCL_NOT_MANUFACTURER_SPECIFIC), \ - (_direction), (_def_resp)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), (_is_manuf), \ - (_manuf_id), ZB_ZCL_CMD_DISCOVER_ATTR_EXT); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (_start_attr_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (_max_len)); \ - ZB_ZCL_FINISH_PACKET((_buffer), cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT((_buffer), (_addr), (_dst_addr_mode), \ - (_dst_ep), (_ep), (_profile_id), (_cluster_id), (_cb)); \ -} - -/*! @brief HA1.2 Description for Discover Attribute Response frame - @see ZCL spec, zb_zcl_read_attr 2.4.14 Discover Attribute Response -*/ -typedef ZB_PACKED_PRE struct zb_zcl_disc_attr_ext_info_s -{ - zb_uint16_t attr_id; /*!< Attribute identifier */ - zb_uint8_t data_type; /*!< Attribute data type */ - zb_uint8_t attr_access; /*!< Attribute access control */ -} ZB_PACKED_STRUCT -zb_zcl_disc_attr_ext_info_t; - -#define ZB_ZCL_DISC_ATTR_EXT_RESP_SIZE sizeof(zb_zcl_disc_attr_ext_info_t) - -/*! @brief ZCL Discover Attribute Response frame - @see ZCL spec, zb_zcl_read_attr 2.4.15 Discover Attribute Response - @note Command frame contains variable number of parameters -*/ -typedef ZB_PACKED_PRE struct zb_zcl_disc_attr_ext_res_s -{ - zb_uint8_t complete; /*!< Discovery complete */ - zb_zcl_disc_attr_ext_info_t info[1]; /*!< Attribute desc list */ -} ZB_PACKED_STRUCT -zb_zcl_disc_attr_ext_res_t; - -/** @brief Get parameter of Discovery Attribute Extended response. - - @param _buffer - ID zb_bufid_t of a buffer containing part of Discover Attribute Extended response data - @param _complete - out variable to complete field Discover command response, see @ref zcl_disc_complete - @param _status - result parse, see @ref zb_zcl_parse_status_t - */ -#define ZB_ZCL_GENERAL_GET_COMPLETE_DISC_ATTR_RESP(_complete, _buffer, _status) \ -{ \ - if (zb_buf_len((_buffer)) < sizeof(zb_uint8_t)) \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - zb_uint8_t *complete_ptr = (zb_uint8_t*)zb_buf_begin((_buffer)); \ - (_complete) = *complete_ptr; \ - (void)zb_buf_cut_left((_buffer), sizeof(zb_uint8_t)); \ - } \ -} - -/** @brief Get next command ID from Discovery command response. - - @param _buffer - ID zb_bufid_t of a buffer containing part of Discover command response data - @param _data_ptr - out Description for Discover Attribute Response frame, see @ref zb_zcl_disc_attr_ext_info_t - @param _status - result parse, see @ref zb_zcl_parse_status_t - */ -#define ZB_ZCL_GENERAL_GET_NEXT_ATTR_DISC_COMMAND_RESP(_data_ptr, _buffer, _status) \ -{ \ - if (zb_buf_len((_buffer)) < sizeof(zb_zcl_disc_attr_ext_info_t)) \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_disc_attr_ext_info_t *src_ptr = \ - (zb_zcl_disc_attr_ext_info_t*)zb_buf_begin((_buffer)); \ - (_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&((_data_ptr)->attr_id), &(src_ptr->attr_id)); \ - (_data_ptr)->data_type = src_ptr->data_type; \ - (_data_ptr)->data_access = src_ptr->data_access; \ - (void)zb_buf_cut_left((_buffer), sizeof(zb_zcl_disc_attr_ext_info_t)); \ - } \ -} - - /*! Convert internal attribute access bitmask into ZCL/HA1.2 bitmask - * value (actually, support 0 and 1 bits) */ -#define ZB_ZCL_CONVERT_ATTR_ACCESS_BITMASK(_access) ((_access) & 0x3U) - -/******************** Command handlers ***************************/ - -/* ZCL handlers */ -void zb_zcl_read_attr_handler(zb_uint8_t param); -void zb_zcl_write_attr_handler(zb_uint8_t param); -#if defined ZB_ENABLE_HA -void zb_zcl_discover_commands_res(zb_uint8_t param, zb_bool_t recv_cmd_type); -#endif /* ZB_ENABLE_HA */ - -#if !(defined ZB_ZCL_DISABLE_REPORTING) || defined(DOXYGEN) - -void zb_zcl_configure_reporting_handler(zb_uint8_t param); - -/* ZCL commands */ -void zb_zcl_send_report_attr_command(struct zb_zcl_reporting_info_s *rep_info, zb_uint8_t param); - -#endif - -zb_bool_t zb_zcl_handle_general_commands(zb_uint8_t param); - -/** @endcond */ /* internals_doc */ - -/** @} */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#endif /* ZB_ZCL_COMMANDS_H */ diff --git a/zboss/development/include/zcl/zb_zcl_common.h b/zboss/development/include/zcl/zb_zcl_common.h deleted file mode 100644 index 7f5232dcb5..0000000000 --- a/zboss/development/include/zcl/zb_zcl_common.h +++ /dev/null @@ -1,2386 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Zigbee cluster library types and macros common for all clusters -*/ - -#ifndef ZB_ZCL_COMMON_H -#define ZB_ZCL_COMMON_H 1 - -#include /* int types, zb_bufid_t */ - -/** @cond DOXYGEN_ZCL_SECTION */ - -#ifdef DEBUG -/* If defined, samples included to zcl source files will be compiled - need for development only */ -#define ZB_COMPILE_ZCL_SAMPLE -#endif - - -/** @addtogroup ZB_ZCL_COMMON - * @{ - */ - -/** - * @defgroup zb_zcl_common_types ZCL common types - * @{ - * @details - * The section contains enumerations defining cluster identifiers and inter-device operation - * statuses, and a callback type used to notify application on attribute value change (see @ref - * write_attr_cmd "Write attributes" command description). - */ - -/*************************** ZCL cluster definitions ***********************************/ - -/*! ZCL payload maximum size; is used to calculate number of - * available bytes in variable-size commands */ -/* TODO: current max size is defined for the worst case (nwk security - * enabled, long address is specified). Possibly - recalculate this - * max size in run-time taking into account current parameters */ -/* TODO: check this value - calculate it correctly!!! */ -/* - Let's count: -- max PHY payload - 127 bytes -- MAC hdr (w/o Pan ID completion, short src/dest) - (FC 2, Seq 1, Pan ID 2, DST addr 2, SRC addr -2, FCS 2) = 11b MAC -- NWK HDR 8 + 8*2 (addresses). Note: not use source routing, else have more fields. -- NWK security 18b -- APS HDR (without security) 8b -Total 61 (45 without ieee addresses). -So, rest is 127-61 = 66b -So, rest is 127-45 = 82b - */ -/* #define ZB_ZCL_MAX_PAYLOAD_SIZE 55 */ -/*! Maximal payload size */ -#define ZB_ZCL_HI_MAX_PAYLOAD_SIZE 66U -/*! Maximal payload size without long address sending */ -#define ZB_ZCL_HI_WO_IEEE_MAX_PAYLOAD_SIZE 82U - -struct zb_zcl_attr_s; /* Forward declaration */ - -/** @brief ZCL Cluster Init Handler. This handler is called on registering device context (@ref - ZB_AF_REGISTER_DEVICE_CTX). Initialization of the cluster should include @ref - zb_zcl_add_cluster_handlers call, if any of the cluster handlers are implemented. - - Cluster Init handler is bound to the cluster declaration via ZB_ZCL_CLUSTER_DESC macro. Every - cluster should implement "__INIT" macro, for example: - @code - #define ZB_ZCL_CLUSTER_ID_ON_OFF_SERVER_ROLE_INIT zb_zcl_on_off_init_server - #define ZB_ZCL_CLUSTER_ID_ON_OFF_CLIENT_ROLE_INIT zb_zcl_on_off_init_client - @endcode - - If cluster does not have any initialization steps and does not need any cluster handlers, - Cluster Init handler may be NULL, for example: - @code - #define ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING_SERVER_ROLE_INIT (zb_zcl_cluster_init_t)NULL - #define ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING_CLIENT_ROLE_INIT (zb_zcl_cluster_init_t)NULL - @endcode -*/ -typedef void (*zb_zcl_cluster_init_t)(void); -/** @brief ZCL Cluster Command Handler. This handler is called on incoming ZCL command for - corresponding cluster. - @param param - pointer to buffer with ZCL command - - @return ZB_TRUE if command was handled (no additional actions are needed), - ZB_FALSE otherwise -*/ -typedef zb_bool_t (*zb_zcl_cluster_handler_t)(zb_uint8_t param); -/** @brief ZCL Cluster Check Value Handler. This handler is called before attribute change (for - corresponding cluster) and checks if new value is in correct range and can be applied. - @param attr_id - ZCL Attribute ID - @param endpoint - Device Endpoint - @param value - pointer to the new Attribute Value - - @return RET_OK if check is passed successfully (attribute can be changed), - RET_OUT_OF_RANGE if the value is out of range (TODO: describe), - RET_ERROR otherwise -*/ -typedef zb_ret_t (*zb_zcl_cluster_check_value_t)(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -/** @brief ZCL Cluster Write Attribute Hook Handler. This handler is called before attribute change - (if any cluster-specific action needs to be bound to attribute change, it can be placed in this - handler). - @param endpoint - Device Endpoint - @param attr_id - ZCL Attribute ID - @param new_value - pointer to the new Attribute Value -*/ -typedef void (*zb_zcl_cluster_write_attr_hook_t)(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -/** @brief ZCL cluster description. */ -typedef ZB_PACKED_PRE struct zb_zcl_cluster_desc_s -{ - zb_uint16_t cluster_id; /**< ZCL 16-bit cluster id. @see zcl_cluster_id */ - zb_uint16_t attr_count; /**< Attributes number supported by the cluster */ - struct zb_zcl_attr_s *attr_desc_list; /**< List of cluster attributes, - declared using ZB_ZCL_DECLARE__ATTRIB_LIST() macro */ - zb_uint8_t role_mask; /**< Cluster role, refer to zcl_cluster_role */ - zb_uint16_t manuf_code; /**< Manufacturer code for cluster and its attributes */ - zb_zcl_cluster_init_t cluster_init; -} ZB_PACKED_STRUCT -zb_zcl_cluster_desc_t; - -/** - * @brief Add ZCL cluster handlers for Cluster ID and Cluster Role. - * - * @param cluster_id - ZCL Cluster ID - * @param cluster_role - ZCL Cluster Role, see @ref zcl_cluster_role - * @param cluster_check_value - "Check Value" handler, see @ref zb_zcl_cluster_check_value_t; may - * be NULL if this handler is not needed - * @param cluster_write_attr_hook - "Write Attr Hook" handler, see @ref - * zb_zcl_cluster_write_attr_hook_t; may be NULL if this handler is not needed - * @param cluster_handler - "Cluster Commands" handler, see @ref zb_zcl_cluster_handler_t; may - * be NULL if this handler is not needed - * - * @return RET_OK if ZCL handlers were installed - * @return RET_ALREADY_EXISTS if ZCL handlers are already installed (for given Cluster ID and Role), - * new handlers will not be installed in that case - * @return RET_EMPTY if ZCL handlers were not installed - */ -zb_ret_t zb_zcl_add_cluster_handlers(zb_uint16_t cluster_id, zb_uint8_t cluster_role, - zb_zcl_cluster_check_value_t cluster_check_value, - zb_zcl_cluster_write_attr_hook_t cluster_write_attr_hook, - zb_zcl_cluster_handler_t cluster_handler); - -/** @cond internals_doc */ -zb_zcl_cluster_handler_t zb_zcl_get_cluster_handler(zb_uint16_t cluster_id, zb_uint8_t cluster_role); -zb_zcl_cluster_check_value_t zb_zcl_get_cluster_check_value(zb_uint16_t cluster_id, zb_uint8_t cluster_role); -zb_zcl_cluster_write_attr_hook_t zb_zcl_get_cluster_write_attr_hook(zb_uint16_t cluster_id, zb_uint8_t cluster_role); - -#ifdef ZB_CONTROL4_NETWORK_SUPPORT -/** Functions for adding and getting Control4 Network cluster specific handlers */ -zb_ret_t zb_zcl_add_control4_cluster_handlers(zb_uint16_t cluster_id, zb_uint8_t cluster_role, - zb_zcl_cluster_check_value_t cluster_check_value, - zb_zcl_cluster_write_attr_hook_t cluster_write_attr_hook, - zb_zcl_cluster_handler_t cluster_handler); - -zb_zcl_cluster_handler_t zb_zcl_get_control4_cluster_handler(zb_uint16_t cluster_id, zb_uint8_t cluster_role); -zb_zcl_cluster_check_value_t zb_zcl_get_control4_cluster_check_value(zb_uint16_t cluster_id, zb_uint8_t cluster_role); -zb_zcl_cluster_write_attr_hook_t zb_zcl_get_control4_cluster_write_attr_hook(zb_uint16_t cluster_id, zb_uint8_t cluster_role); -#endif /* ZB_CONTROL4_NETWORK_SUPPORT */ -/** @endcond */ /* internals_doc */ - -/** - * @name Cluster roles in message exchange - * @anchor zcl_cluster_role - * - * Note: These values were members of `enum zb_zcl_cluster_role_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -/** Server cluster role */ -#define ZB_ZCL_CLUSTER_SERVER_ROLE 0x01U -/** Client cluster role */ -#define ZB_ZCL_CLUSTER_CLIENT_ROLE 0x02U -/** Internal value - used for searching any role (on the moment when cluster role is not known yet). */ -#define ZB_ZCL_CLUSTER_ANY_ROLE 0x03U -/** Reverts cluster role */ -#define ZB_ZCL_REVERT_CLUSTER_ROLE(_d) \ - (((_d) != ZB_ZCL_CLUSTER_ANY_ROLE) ? (((_d) == ZB_ZCL_CLUSTER_SERVER_ROLE) ? ZB_ZCL_CLUSTER_CLIENT_ROLE : ZB_ZCL_CLUSTER_SERVER_ROLE) : \ - ZB_ZCL_CLUSTER_ANY_ROLE) -/** @} */ - -/** - * @name ZCL cluster identifiers - * @anchor zcl_cluster_id - * @see ZCL spec, subclause 2.2.2 - */ -/** @{ */ -#define ZB_ZCL_CLUSTER_ID_BASIC 0x0000U /*!< Basic cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_POWER_CONFIG 0x0001U /*!< Power configuration cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_DEVICE_TEMP_CONFIG 0x0002U /*!< Device temperature configuration cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_IDENTIFY 0x0003U /*!< Identify cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_GROUPS 0x0004U /*!< Groups cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_SCENES 0x0005U /*!< Scenes cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_ON_OFF 0x0006U /*!< On/Off cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_ON_OFF_SWITCH_CONFIG 0x0007U /*!< On/Off switch configuration cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL 0x0008U /*!< Level control cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_ALARMS 0x0009U /*!< Alarms cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_TIME 0x000aU /*!< Time cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_RSSI_LOCATION 0x000bU /*!< RSSI location cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_ANALOG_INPUT 0x000cU /*!< Analog input (basic) cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT 0x000dU /*!< Analog output (basic) cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_ANALOG_VALUE 0x000eU /*!< Analog value (basic) cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_BINARY_INPUT 0x000fU /*!< Binary input (basic) cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT 0x0010U /*!< Binary output (basic) cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_BINARY_VALUE 0x0011U /*!< Binary value (basic) cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_MULTI_INPUT 0x0012U /*!< Multistate input (basic) cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_MULTI_OUTPUT 0x0013U /*!< Multistate output (basic) cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_MULTI_VALUE 0x0014U /*!< Multistate value (basic) cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_COMMISSIONING 0x0015U /*!< Commissioning cluster identifier. */ - -#define ZB_ZCL_CLUSTER_ID_OTA_UPGRADE 0x0019U /*!< Over The Air cluster identifier. */ - -/* General clusters */ -#define ZB_ZCL_CLUSTER_ID_POLL_CONTROL 0x0020U /*!< Poll control cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_GREEN_POWER 0x0021U /*!< Green Power cluster identifier. */ - -#define ZB_ZCL_CLUSTER_ID_KEEP_ALIVE 0x0025U /*!< Keep Alive cluster identifier. */ - -/* Closures clusters */ -#define ZB_ZCL_CLUSTER_ID_SHADE_CONFIG 0x0100U /*!< Shade configuration cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_DOOR_LOCK 0x0101U /*!< Door lock cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_WINDOW_COVERING 0x0102U /*!< Window covering cluster identifier. */ -/* HVAC clusters */ -#define ZB_ZCL_CLUSTER_ID_PUMP_CONFIG_CONTROL 0x200U /*!< Pump configuration and control cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_THERMOSTAT 0x201U /*!< Thermostat cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_FAN_CONTROL 0x202U /*!< Fan control cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_DEHUMID_CONTROL 0x203U /*!< Dehumidification control cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_THERMOSTAT_UI_CONFIG 0x204U /*!< Thermostat user interface configuration cluster identifier. */ - -/* Lighting clusters */ -#define ZB_ZCL_CLUSTER_ID_COLOR_CONTROL 0x0300U /*!< Color control cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_BALLAST_CONFIG 0x0301U /*!< Ballast configuration cluster identifier. */ - -/* Measurement and Sensing */ -#define ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT 0x0400U /*!< Illuminance measurement */ -#define ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT 0x0402U /*!< Temperature measurement */ -#define ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT 0x0403U /*!< Pressure measurement */ -#define ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT 0x0405U /*!< Relative humidity measurement */ -#define ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING 0x0406U /*!< Occupancy sensing */ - -/* IAS clusters */ -#define ZB_ZCL_CLUSTER_ID_IAS_ZONE 0x0500U /*!< IAS Zone cluster identifier */ -#define ZB_ZCL_CLUSTER_ID_IAS_ACE 0x0501U /*!< IAS ACE cluster identifier */ -#define ZB_ZCL_CLUSTER_ID_IAS_WD 0x0502U /*!< IAS WD cluster identifier */ - -/* Smart Energy */ -#define ZB_ZCL_CLUSTER_ID_PRICE 0x0700U /*!< Price cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_DRLC 0x0701U /*!< Demand-Response cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_METERING 0x0702U /*!< Metering cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_MESSAGING 0x0703U /*!< Messaging cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_TUNNELING 0x0704U /*!< Tunneling cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_PREPAYMENT 0x0705U /*!< Prepayment cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_ENERGY_MANAGEMENT 0x0706U /*!< Energy Management cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_CALENDAR 0x0707U /*!< Calendar cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_DEVICE_MANAGEMENT 0x0708U /*!< Device Management cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_EVENTS 0x0709U /*!< Events cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_MDU_PAIRING 0x070AU /*!< MDU Pairing cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_SUB_GHZ 0x070BU /*!< Sub-GHz cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE 0x070DU /*!< Daily Schedule cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_KEY_ESTABLISHMENT 0x0800U /*!< Key Establishment cluster identifier. */ - - -/* Home Automation */ -#define ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS 0x0b02U /*!< Appliance events and alerts cluster identifier */ -/* HA specU rev. 29U ver. 1.2 - Electricity MeasurementU not sure that its Electrical Measurement */ -#define ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT 0x0b04U /*!< Electrical Measurement cluster identifier. */ -#define ZB_ZCL_CLUSTER_ID_DIAGNOSTICS 0x0b05U /*!< Home Automation Diagnostics */ - -#define ZB_ZCL_CLUSTER_ID_WWAH 0xFC57U /*!< Works with All Hubs cluster identifier */ -/** @cond touchlink */ -#define ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING 0x1000U /*!< Touchlink Commissioning cluster identifier */ -/** @endcond */ /* touchlink */ - -/************** Manufacturer specific clusters ****************/ - -#define ZB_ZCL_CLUSTER_ID_TUNNEL 0xfc00U /*!< Manufacturer specific Tunnel cluster */ -#define ZB_ZCL_CLUSTER_ID_IR_BLASTER 0xfc01U /*!< Manufacturer specific IR Blaster cluster */ - -#define ZB_ZCL_CLUSTER_ID_CUSTOM_ATTR 0xffeeU /*!< Custom Attributes */ - -#define ZB_ZCL_CLUSTER_ID_METER_IDENTIFICATION 0x0B01U /*!< Meter Identification cluster identifier */ - -/* TODO: define other clusters IDs */ -/* Measurements and sensing clusters */ -/* Security and safety clusters */ - -/** @} */ - -/** - * @brief Type for cluster roles in message exchange. - * - * Holds one of @ref zcl_cluster_id. Kept for backward compatibility as - * @ref zcl_cluster_id were declared previously as enum. - */ -typedef zb_uint16_t zb_zcl_cluster_id_t; - -#ifdef ZB_CONTROL4_NETWORK_SUPPORT -#define ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING ((zb_uint16_t)0x0001) -#endif - -/** @brief Check whether cluster is manufacturer specific. */ -#define ZB_ZCL_IS_CLUSTER_MANUF_SPEC(_cluster_id) ((_cluster_id) > 0xfbff) - -/** @brief Internal invalid manufacturer code value. */ -#define ZB_ZCL_MANUF_CODE_INVALID 0x0000 - - -/** @brief Parse frame operation status. */ -typedef enum zb_zcl_parse_status_e -{ - ZB_ZCL_PARSE_STATUS_SUCCESS, /**< Frame parsed successfully. */ - ZB_ZCL_PARSE_STATUS_FAILURE /**< Frame parse operation failed. */ -} zb_zcl_parse_status_t; - -/** @brief Attribute Reporting Status. */ -typedef enum zb_zcl_attribute_reporting_status_e -{ - ZB_ZCL_AR_STATUS_PENDING = 0x00, /**< Pending. */ - ZB_ZCL_AR_STATUS_COMPLETE = 0x01 /**< Attribute Reporting Complete. */ -} zb_zcl_attribute_reporting_status_t; - -/** - * @name ZCL status values - * @anchor zcl_status - * @see ZCL8 spec, subclause 2.6.3, Table 2-12 - * @note The enumeration does not contain statuses not used in ZB HA profile - */ -/** @{ */ -#define ZB_ZCL_STATUS_SUCCESS 0x00U /*!< ZCL Success */ -#define ZB_ZCL_STATUS_FAIL 0x01U /*!< ZCL Fail */ -#define ZB_ZCL_STATUS_NOT_AUTHORIZED 0x7EU /*!< The sender of the command does not have authorization to carry out this command. */ -#define ZB_ZCL_STATUS_RESERVED 0x7FU /*!< CCB 2318 a reserved field may be used in the future and then be non-zero. */ -#define ZB_ZCL_STATUS_MALFORMED_CMD 0x80U /*!< Malformed command */ -#define ZB_ZCL_STATUS_UNSUP_CMD 0x81U /*!< ZCL8: Unsupported command */ -#define ZB_ZCL_STATUS_UNSUP_CLUST_CMD 0x81U /*!< ZCL7: Unsupported cluster command, ZCL8: use UNSUP_COMMAND*/ -#define ZB_ZCL_STATUS_UNSUP_GEN_CMD 0x82U /*!< ZCL7: Unsupported general command, ZCL8: use UNSUP_COMMAND*/ -#define ZB_ZCL_STATUS_UNSUP_MANUF_CLUST_CMD 0x83U /*!< ZCL7: Unsupported manuf-specific clust command, ZCL8: use UNSUP_COMMAND*/ -#define ZB_ZCL_STATUS_UNSUP_MANUF_GEN_CMD 0x84U /*!< ZCL7: Unsupported manuf-specific general command, ZCL8: use UNSUP_COMMAND*/ -#define ZB_ZCL_STATUS_INVALID_FIELD 0x85U /*!< Invalid field */ -#define ZB_ZCL_STATUS_UNSUP_ATTRIB 0x86U /*!< Unsupported attribute */ -#define ZB_ZCL_STATUS_INVALID_VALUE 0x87U /*!< Invalid value */ -#define ZB_ZCL_STATUS_READ_ONLY 0x88U /*!< Read only */ -#define ZB_ZCL_STATUS_INSUFF_SPACE 0x89U /*!< Insufficient space */ -#define ZB_ZCL_STATUS_DUPE_EXISTS 0x8aU /*!< ZCL7: Duplicate exists, ZCL8: use SUCCESS*/ -#define ZB_ZCL_STATUS_NOT_FOUND 0x8bU /*!< Not found */ -#define ZB_ZCL_STATUS_UNREPORTABLE_ATTRIB 0x8cU /*!< Unreportable attribute */ -#define ZB_ZCL_STATUS_INVALID_TYPE 0x8dU /*!< Invalid type */ -#define ZB_ZCL_STATUS_WRITE_ONLY 0x8fU /*!< ZCL7: Write only, ZCL8: use NOT_AUTHORIZED*/ -#define ZB_ZCL_STATUS_INCONSISTENT_STARTUP_STATE 0x90U /*!< ZCL7: The value can put the device in an inconsistent state on startup, ZCL8: FAILURE, CCB 2477 Status Code Cleanup: never used */ -#define ZB_ZCL_STATUS_DEFINED_OUT_OF_BAND 0x91U /*!< ZCL7: Out-of-band method to write an attribute, ZCL8: FAILURE, CCB 2477 Status Code Cleanup: never used */ -#define ZB_ZCL_STATUS_INCONSISTENT 0x92U /*!< ZCL7: Supplied values are inconsistent, ZCL8: reserved, CCB 2477 Status Code Cleanup: never used */ -/** ZCL7: The credentials presented by the device sending the command are not sufficient to perform this - * action. - * ZCL8: use FAILURE*/ -#define ZB_ZCL_STATUS_ACTION_DENIED 0x93U -#define ZB_ZCL_STATUS_TIMEOUT 0x94U /*!< Timeout */ -#define ZB_ZCL_STATUS_ABORT 0x95U /*!< Abort */ -#define ZB_ZCL_STATUS_INVALID_IMAGE 0x96U /*!< Invalid OTA upgrade image */ -#define ZB_ZCL_STATUS_WAIT_FOR_DATA 0x97U /*!< Server does not have data block available yet */ -/**< No OTA upgrade image available for a particular client. */ -#define ZB_ZCL_STATUS_NO_IMAGE_AVAILABLE 0x98U -/** The client still requires more OTA upgrade image files in order to successfully upgrade. */ -#define ZB_ZCL_STATUS_REQUIRE_MORE_IMAGE 0x99U -/** The command has been received and is being processed.*/ -#define ZB_ZCL_STATUS_NOTIFICATION_PENDING 0x9AU -#define ZB_ZCL_STATUS_HW_FAIL 0xc0U /*!< ZCL7: Hardware failure, ZCL8: use FAILURE */ -#define ZB_ZCL_STATUS_SW_FAIL 0xc1U /*!< ZCL7: Software failure, ZCL8: use FAILURE */ -#define ZB_ZCL_STATUS_CALIB_ERR 0xc2U /*!< ZCL7: Calibration error, ZCL8: reserved, CCB 2477 Status Code Cleanup: never used */ -#define ZB_ZCL_STATUS_UNSUP_CLUST 0xc3U /*!< Cluster is not found on the target endpoint */ -#define ZB_ZCL_STATUS_LIMIT_REACHED 0xc4U /*!< ZCL7: Cluster is not found on the target endpoint, ZCL8: use SUCCESS */ -/** @} */ - -/** - * @brief Type for ZCL status values. - * - * Holds one of @ref zcl_status. Kept only for backward compatibility as - * @ref zcl_status were declared previously as enum. - */ -typedef zb_uint8_t zb_zcl_status_t; - -/** @brief ZCL global attribute: cluster revision returned by default. - Used if the GLOBAL_CLUSTER_REVISION attribute is undefined for the cluster/role. -*/ -#define ZB_ZCL_GLOBAL_CLUSTER_REVISION_DEFAULT 1 - -/** @brief ZCL pre-ZCL8 API default cluster revision (minimal Cluster revision) -*/ -#define ZB_ZCL_CLUSTER_REV_MIN ZB_ZCL_GLOBAL_CLUSTER_REVISION_DEFAULT - -/** @brief ZCL unknown peer Cluster revision value -*/ -#define ZB_ZCL_PEER_CLUSTER_REV_UNKNOWN 0xFFFFu - -/** - * @name ZCL backward compatibility modes - * @anchor zcl_backward_compatibility_modes - * @brief ZCL backward compatibility modes, introduced for ZCL8: - * ZB_ZCL_LEGACY_MODE (default mode) - pre-ZCL8 API sends packets in pre-ZCL8 format as is, no conversion applied - * ZCL8 API transforms packets into format according to the revision set in Cluster revision attribute value - * ZB_ZCL_AUTO_MODE - both pre-ZCL8 API and ZCL8 API transforms packets into format according to revision set in Cluster revision attribute value - * ZB_ZCL_COMPATIBILITY_MODE - both pre-ZCL8 API and ZCL8 API transforms packets into format according to peer Cluster revision provided by the application - * if the peer Cluster revision is greater than Cluster revision attribute value, then the Cluster revision will be used - * if there is no peer Cluster revision, the packet format is converted to the lowest possible Cluster revision - */ -/** @{ */ -#define ZB_ZCL_LEGACY_MODE 0x00U /*!< ZBOSS ZCL legacy mode */ -#define ZB_ZCL_AUTO_MODE 0x01U /*!< ZBOSS ZCL auto mode */ -#define ZB_ZCL_COMPATIBILITY_MODE 0x02U /*!< ZBOSS ZCL compatibility mode */ -/** @} */ - -/** - * @name ZCL backward compatibility status modes - * @anchor zcl_backward_compatibility_status_modes - * @brief ZCL backward compatibility status modes, introduced for ZCL8: - * ZCL8 spec merges some statuses defined in previous ZCL specs into one - * LIMIT_REACHED, DUPLICATE_EXISTS, SUCCESS ==> SUCCESS - * INCONSISTENT_STARTUP_STATE, DEFINED_OUT_OF_BAND, ACTION_DENIED, HARDWARE_FAILURE, SOFTWARE_FAILURE ==> FAILURE - * WRITE_ONLY, NOT_AUTHORIZED ==> NOT_AUTHORIZED - * MALFORMED_COMMAND, INVALID_FIELD ==> INVALID_FIELD - * UNSUP_CLUSTER_COMMAND, UNSUP_GENERAL_COMMAND, UNSUP_MANUF_CLUSTER_COMMAND, UNSUP_MANUF_GENERAL_COMMAND ==> UNSUP_COMMAND - * INCONSISTENT, CALIBRATION_ERROR, RESERVED ==> RESERVED - * There is no well-defined mechanism how to define which version of ZCL is used by the peer. It looks like the optimal solution is to - * send statuses according to ZCL6 and ZCL7 specifications. In that case there will be no miscommunication with legacy devices. - * Other ZCL8 devices should process obsolete statuses correctly because of backward compatibility required by ZCL8 spec. - * If application requires send statuses defined strictly according to ZCL8 spec, the device can be switch to this mode (and vice versa) - * in runtime to ZCL8 statuses mode via zb_zcl_set_backward_compatible_statuses_mode API function - * ZB_ZCL_STATUSES_PRE_ZCL8_MODE (default mode) - statuses will be send according to pre ZCL8 specifications - * ZB_ZCL_STATUSES_ZCL8_MODE - statuses will be send according to ZCL8 specification -*/ -/** @{ */ -#define ZB_ZCL_STATUSES_PRE_ZCL8_MODE 0x00U /*!< ZBOSS ZCL statuses Pre ZCL8 mode */ -#define ZB_ZCL_STATUSES_ZCL8_MODE 0x01U /*!< ZBOSS ZCL statuses ZCL8 mode */ -/** @} */ - -#if defined ZB_ENABLE_HA - -/** @brief Discovery manufacture specific command - @param direction - direction 0 (client to server) or 1 (server to client) - @param ep - endpoint number - @param cluster_id - cluster ID - @param manuf_id - manufacture ID - @param recv_cmd_type - need list of received (ZB_TRUE) or generated (ZB_FALSE) command - @param value - (out) pointer to list command ID - - @return number of value elements -*/ -typedef zb_uint8_t (*zb_zcl_disc_manuf_cmd_cb_t)( - zb_uint8_t direction, zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint16_t manuf_id, zb_bool_t recv_cmd_type, zb_uint8_t **value); - -#endif /* ZB_ENABLE_HA */ - -/********************************** ZCL attributes definitions ************************************/ - -/** @brief Informs application that some attribute value is being updated by Write attribute command - @param ep - endpoint number - @param cluster_id - cluster ID - @param attr_id - attribute ID of the attribute being updated - @param value - pointer to new data -*/ -typedef void (*zb_zcl_modify_attr_value_cb_t)( - zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint16_t attr_id, zb_uint8_t *value); - -/*! @defgroup zb_zcl_common_attrs General attributes' description - Types and macros shared among all attributes' definitions. - @{ - Use @ref ZB_ZCL_SET_ATTRIBUTE - @par -*/ - -/** @brief Sets correctly ZCL char string value */ -#define ZB_ZCL_SET_STRING_VAL(str, val, len) \ - (ZB_MEMCPY((zb_uint8_t*)(str) + 1, (val), (len)), *(zb_uint8_t*)(str) = (len)) - -/** @brief Get ZCL string length */ -#define ZB_ZCL_GET_STRING_LENGTH(str) ((str)[0]) - -#define ZB_ZCL_SET_STRING_LENGTH(str, _newlen) (((str))[0] = (_newlen)) - -/** @brief Returns size of a string constant */ -#define ZB_ZCL_STRING_CONST_SIZE(str) (zb_uint8_t)(sizeof(str) - 1) - -/** Get pointer to first char in the string. */ -#define ZB_ZCL_GET_STRING_BEGIN(_str) (&((_str)[1])) - -/** Get pointer to (begin + length) char in the string. */ -#define ZB_ZCL_GET_STRING_END(_str) (ZB_ZCL_GET_STRING_BEGIN(_str) + ZB_ZCL_GET_STRING_LENGTH(_str)) - -/** Get pointer to char in string at specified pos. */ -#define ZB_ZCL_GET_STRING_REF_AT(_str, _pos) (ZB_ZCL_GET_STRING_BEGIN(_str) + _pos) - -/** Get char by specified pos. */ -#define ZB_ZCL_GET_STRING_CHAR_AT(_str, _pos) *ZB_ZCL_GET_STRING_REF_AT(_str, _pos) - -/** Turn ZCL Octet string into string with null-term. */ -#define ZB_ZCL_STRING_TO_C_STRING(_str) \ -{ \ - zb_uint8_t _len = _str[0]; \ - ZB_MEMMOVE(_str, _str + 1, _len); \ - _str[_len] = 0; \ -} - -/** Set size of ZCL Octet String into 0 .*/ -#define ZB_ZCL_STRING_CLEAR(_str) (_str[0] = 0) - -/** Add some data to ZCL Octet String. */ -static ZB_INLINE zb_uint16_t zb_zcl_string_append_data(zb_uint8_t *zcl_str, - zb_uint8_t zcl_str_max_size, - const zb_uint8_t *c_str, - zb_uint8_t c_str_len) -{ - zb_uint16_t newlen = ZB_ZCL_GET_STRING_LENGTH(zcl_str) + (zb_uint16_t)c_str_len; - - if (newlen < (zb_uint16_t) zcl_str_max_size) - { - ZB_MEMCPY(ZB_ZCL_GET_STRING_END(zcl_str), c_str, c_str_len); - ZB_ZCL_SET_STRING_LENGTH(zcl_str, (zb_uint8_t)newlen); - } - else - { - newlen = 0; - } - - return newlen; -} - -/** Add single byte to ZCL Octet String. */ -static ZB_INLINE zb_uint16_t zb_zcl_string_append_byte(zb_uint8_t *zcl_str, - zb_uint8_t zcl_str_max_size, - zb_uint8_t value) -{ - zb_uint16_t newlen = (zb_uint16_t)ZB_ZCL_GET_STRING_LENGTH(zcl_str) + 1U; - - if (newlen < (zb_uint16_t) zcl_str_max_size) - { - *ZB_ZCL_GET_STRING_END(zcl_str) = value; - ZB_ASSERT(newlen <= ZB_UINT8_MAX); - ZB_ZCL_SET_STRING_LENGTH(zcl_str, (zb_uint8_t)newlen); - } - else - { - newlen = 0; - } - - return newlen; -} - -/** Append C-string to ZCL string. */ -#define ZB_ZCL_STRING_APPEND_C_STR(_zcl_str, _zcl_str_max_size, _c_str) \ - zb_zcl_string_append_data(_zcl_str, _zcl_str_max_size, (const zb_uint8_t *) _c_str, strlen(_c_str)) - -/** Append C-string to ZCL static string. */ -#define ZB_ZCL_STATIC_STRING_APPEND_C_STR(_zcl_s_str, _c_str) \ - ZB_ZCL_STRING_APPEND_C_STR((zb_uint8_t *) _zcl_s_str, sizeof(_zcl_s_str), _c_str) - -/** Append char to ZCL static string. */ -#define ZB_ZCL_STATIC_STRING_APPEND_CHAR(_zcl_s_str, _char) \ - zb_zcl_string_append_byte(_zcl_s_str, sizeof(_zcl_s_str), (zb_uint8_t) _char) - - -/** - * @name ZCL attribute data type values - * @anchor zcl_attr_type - * @note The enumeration is not full, and does not contain ZCL types not used in HA profile. - * @see ZCL spec., subclause 2.5.2, Table 2-10. Data Types - */ -/** @{ */ -#define ZB_ZCL_ATTR_TYPE_NULL 0x00U /*!< Null data type */ -#define ZB_ZCL_ATTR_TYPE_8BIT 0x08U /*!< 8-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_16BIT 0x09U /*!< 16-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_24BIT 0x0aU /*!< 24-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_32BIT 0x0bU /*!< 32-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_40BIT 0x0cU /*!< 40-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_48BIT 0x0dU /*!< 48-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_56BIT 0x0eU /*!< 56-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_64BIT 0x0fU /*!< 64-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_BOOL 0x10U /*!< Boolean data type */ -#define ZB_ZCL_ATTR_TYPE_8BITMAP 0x18U /*!< 8-bit bitmap data type */ -#define ZB_ZCL_ATTR_TYPE_16BITMAP 0x19U /*!< 16-bit bitmap data type */ -#define ZB_ZCL_ATTR_TYPE_24BITMAP 0x1aU /*!< 24-bit bitmap data type */ -#define ZB_ZCL_ATTR_TYPE_32BITMAP 0x1bU /*!< 32-bit bitmap data type */ -#define ZB_ZCL_ATTR_TYPE_40BITMAP 0x1cU /*!< 40-bit bitmap data type */ -#define ZB_ZCL_ATTR_TYPE_48BITMAP 0x1dU /*!< 48-bit bitmap data type */ -#define ZB_ZCL_ATTR_TYPE_56BITMAP 0x1eU /*!< 56-bit bitmap data type */ -#define ZB_ZCL_ATTR_TYPE_64BITMAP 0x1fU /*!< 64-bit bitmap data type */ -#define ZB_ZCL_ATTR_TYPE_U8 0x20U /*!< Unsigned 8-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_U16 0x21U /*!< Unsigned 16-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_U24 0x22U /*!< Unsigned 24-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_U32 0x23U /*!< Unsigned 32-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_U40 0x24U /*!< Unsigned 40-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_U48 0x25U /*!< Unsigned 48-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_U56 0x26U /*!< Unsigned 56-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_U64 0x27U /*!< Unsigned 64-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_S8 0x28U /*!< Signed 8-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_S16 0x29U /*!< Signed 16-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_S24 0x2aU /*!< Signed 24-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_S32 0x2bU /*!< Signed 32-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_S40 0x2cU /*!< Signed 40-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_S48 0x2dU /*!< Signed 48-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_S56 0x2eU /*!< Signed 56-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_S64 0x2fU /*!< Signed 64-bit value data type */ -#define ZB_ZCL_ATTR_TYPE_8BIT_ENUM 0x30U /*!< 8-bit enumeration (U8 discrete) data type */ -#define ZB_ZCL_ATTR_TYPE_16BIT_ENUM 0x31U /*!< 16-bit enumeration (U16 discrete) data type */ -#define ZB_ZCL_ATTR_TYPE_SEMI 0x38U /*!< 2 byte floating point */ -#define ZB_ZCL_ATTR_TYPE_SINGLE 0x39U /*!< 4 byte floating point */ -#define ZB_ZCL_ATTR_TYPE_DOUBLE 0x3aU /*!< 8 byte floating point */ -#define ZB_ZCL_ATTR_TYPE_OCTET_STRING 0x41U /*!< Octet string data type */ -#define ZB_ZCL_ATTR_TYPE_CHAR_STRING 0x42U /*!< Character string (array) data type */ -#define ZB_ZCL_ATTR_TYPE_LONG_OCTET_STRING 0x43U /*!< Long octet string */ -#define ZB_ZCL_ATTR_TYPE_LONG_CHAR_STRING 0x44U /*!< Long character string */ -#define ZB_ZCL_ATTR_TYPE_ARRAY 0x48U /*!< Array data type 2 + sum of content len */ -#define ZB_ZCL_ATTR_TYPE_STRUCTURE 0x4cU /*!< Structure data type 2 + sum of content len */ -#define ZB_ZCL_ATTR_TYPE_SET 0x50U /*!< Collection:set, size = sum of len of content */ -#define ZB_ZCL_ATTR_TYPE_BAG 0x51U /*!< Collection:bag, size = sum of len of content */ -#define ZB_ZCL_ATTR_TYPE_TIME_OF_DAY 0xe0U /*!< Time of day, 4 bytes */ -#define ZB_ZCL_ATTR_TYPE_DATE 0xe1U /*!< Date, 4 bytes */ -#define ZB_ZCL_ATTR_TYPE_UTC_TIME 0xe2U /*!< UTC Time, 4 bytes */ -#define ZB_ZCL_ATTR_TYPE_CLUSTER_ID 0xe8U /*!< Cluster ID, 2 bytes */ -#define ZB_ZCL_ATTR_TYPE_ATTRIBUTE_ID 0xe9U /*!< Attribute ID, 2 bytes */ -#define ZB_ZCL_ATTR_TYPE_BACNET_OID 0xeaU /*!< BACnet OID, 4 bytes */ -#define ZB_ZCL_ATTR_TYPE_IEEE_ADDR 0xf0U /*!< IEEE address (U64) type */ -#define ZB_ZCL_ATTR_TYPE_128_BIT_KEY 0xf1U /*!< 128-bit security key */ - -/** Custom array of 32 elems data type (now is equal to ZB_ZCL_ATTR_TYPE_ARRAY) */ -#define ZB_ZCL_ATTR_TYPE_CUSTOM_32ARRAY 0x4aU - -#define ZB_ZCL_ATTR_TYPE_INVALID 0xffU /*!< Invalid data type */ -/** @} */ - -/** - * @brief Type for ZCL attribute data type values. - * - * @deprecated holds one of @ref zcl_attr_type. Kept only for backward compatibility as - * @ref zcl_attr_type were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_zcl_attr_type_t; - -/** - * @name ZCL attribute access values - * @anchor zcl_attr_access - */ -/** @{ */ -#define ZB_ZCL_ATTR_ACCESS_READ_ONLY 0x01U -#define ZB_ZCL_ATTR_ACCESS_WRITE_ONLY 0x02U /*!< Attribute is write only */ -/** Attribute is read/write */ -#define ZB_ZCL_ATTR_ACCESS_READ_WRITE (ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_WRITE_ONLY) -#define ZB_ZCL_ATTR_ACCESS_REPORTING 0x04U /*!< Attribute is allowed for reporting */ -/** @cond internals_doc */ -/** Attribute is read only, but may be marked as writable due to ZCL specification (using - * ZB_ZCL_SET_ATTR_WRITABLE) */ -#define ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL (ZB_ZCL_ATTR_ACCESS_READ_ONLY) -/** @endcond */ /* internals_doc */ -#define ZB_ZCL_ATTR_ACCESS_SINGLETON 0x08U /*!< Attribute is singleton */ -#define ZB_ZCL_ATTR_ACCESS_SCENE 0x10U /*!< Attribute is accessed through scene */ - -/* Use free bit in access attribute field to save RAM */ -#define ZB_ZCL_ATTR_MANUF_SPEC 0x20U /*!< Attribute is manufacturer specific */ -#define ZB_ZCL_ATTR_ACCESS_INTERNAL 0x40U /*!< ZBOSS Internal access only Attribute */ -/** @} */ - -/** - * @brief Type for possible values of ZCL attribute access values. - * - * Holds one of @ref zcl_attr_access. Kept for backward compatibility as - * @ref zcl_attr_access were declared previously as enum. - */ -typedef zb_uint8_t zb_zcl_attr_access_t; - -#define ZB_ZCL_ATTR_SET_WITH_ATTR_ID(_set, _id) ((_set << 8) | (_id & 0xFF)) - -/** @cond internals_doc */ - -/** - * @brief Sets attribute access type to WRITABLE, if it is optionally permitted. - * @param attr_desc - pointer to attribute descriptor - * @hideinitializer - */ -#define ZB_ZCL_SET_ATTR_WRITABLE(attr_desc) \ -{ \ - if (attr_desc->access & ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL) \ - { \ - attr_desc->access |= ZB_ZCL_ATTR_ACCESS_WRITE_ONLY; \ - } \ -} - -/** @endcond */ /* internals_doc */ - -/*! @brief ZCL attribute definition structure */ -typedef ZB_PACKED_PRE struct zb_zcl_attr_s -{ - zb_uint16_t id; /*!< Attribute id */ - zb_uint8_t type; /*!< Attribute type see @ref zcl_attr_type */ - zb_uint8_t access; /*!< Attribute access options according to @ref zcl_attr_access */ - void* data_p; /*!< Pointer to data */ -} ZB_PACKED_STRUCT -zb_zcl_attr_t; - - -/** - * @name Global attributes that are included to each cluster - * @anchor zcl_attr_global - * @see ZCL spec - 6.0 - */ -/** @{ */ -#define ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID 0xfffdU /*!< Cluster revision */ -#define ZB_ZCL_ATTR_GLOBAL_ATTRIBUTE_REPORTING_STATUS_ID 0xfffeU /*!< Attribute reporting status */ -/** @} */ - -/** @brief ZCL 6.0: Default value for cluster revision global attribute, - * see @ref zcl_attr_global - */ -#define ZB_ZCL_CLUSTER_REVISION_DEFAULT 1 - -/** @cond internals_doc */ - -/*! @internal @brief Set attribute description. - @param attr_id - attribute identifier (defined individually for any particular cluster). - @param data_ptr - pointer to attribute's value storage. - - Creates attribute description value (@ref zb_zcl_attr_s) initialized with provided pointer to - attribute's data. -*/ -#define ZB_ZCL_SET_ATTR_DESC(attr_id, data_ptr) ZB_SET_ATTR_DESCR_WITH_##attr_id(data_ptr), - - -/*! @internal @brief Set manufacturer specific attribute description. - @param attr_id - attribute identifier (defined individually for any particular cluster). - @param attr_type - attribute data type @see @ref zcl_attr_type - @param attr_access - attribute access bitmask @see @ref zcl_attr_access - @param data_ptr - pointer to attribute's value storage. - - Creates attribute description value (@ref zb_zcl_attr_s) initialized with provided pointer to - attribute's data. -*/ -#define ZB_ZCL_SET_MANUF_SPEC_ATTR_DESC(attr_id, attr_type, attr_access, data_ptr) \ - { \ - attr_id, \ - attr_type, \ - attr_access | ZB_ZCL_ATTR_MANUF_SPEC, \ - (void*) data_ptr \ - }, - - -/*! @internal @brief Start declaration of attributes list */ -#define ZB_ZCL_START_DECLARE_ATTRIB_LIST(attrs_desc_name) \ - zb_uint16_t cluster_revision_##attrs_desc_name = ZB_ZCL_CLUSTER_REVISION_DEFAULT; \ - zb_zcl_attr_t attrs_desc_name [] = { \ - { \ - ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) &(cluster_revision_##attrs_desc_name) \ - }, - -/*! @internal @brief Start declaration of static attributes list */ -#define ZB_ZCL_START_DECLARE_ATTRIB_LIST_STATIC(attrs_desc_name) \ - static zb_uint16_t cluster_revision_##attrs_desc_name = ZB_ZCL_CLUSTER_REVISION_DEFAULT; \ - static zb_zcl_attr_t attrs_desc_name [] = { \ - { \ - ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) &(cluster_revision_##attrs_desc_name) \ - }, - -/** @endcond */ /* internals_doc */ - -/*! @brief Start declaration of attributes list with cluster revision */ -#define ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attrs_desc_name, cluster_name) \ - zb_uint16_t cluster_revision_##attrs_desc_name = cluster_name##_CLUSTER_REVISION_DEFAULT; \ - zb_zcl_attr_t attrs_desc_name [] = { \ - { \ - ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) &(cluster_revision_##attrs_desc_name) \ - }, - -/** @cond internals_doc */ - -/*! @internal @brief Start declaration of static attributes list with cluster revision */ -#define ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION_STATIC(attrs_desc_name, cluster_name) \ - static zb_uint16_t cluster_revision_##attrs_desc_name = cluster_name##_CLUSTER_REVISION_DEFAULT; \ - static zb_zcl_attr_t attrs_desc_name [] = { \ - { \ - ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) &(cluster_revision_##attrs_desc_name) \ - }, - -/*! @internal @brief End declaration of attributes list */ -#define ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST \ - { \ - ZB_ZCL_NULL_ID, \ - 0, \ - 0, \ - NULL \ - } \ -} - -#define ZB_ZCL_SET_ATTR_DESC_M(id, data_ptr, type, attr) \ - { \ - (id), (type), (attr), (data_ptr) \ - }, - -#if !(defined ZB_ZCL_DISABLE_REPORTING) || defined(DOXYGEN) - -/*! @internal @brief Check, if attribute is reportable */ -#define ZB_ZCL_IS_ATTR_REPORTABLE(attr_desc) ((attr_desc)->access & ZB_ZCL_ATTR_ACCESS_REPORTING) - -#endif - -/*! @internal @brief Check, if attribute is singleton */ -#define ZB_ZCL_IS_ATTR_SINGLETON(attr_desc) ZB_BIT_IS_SET((attr_desc)->access, ZB_ZCL_ATTR_ACCESS_SINGLETON) - -/*! @internal @brief Check, if attribute is accessed through scene */ -#define ZB_ZCL_IS_ATTR_SCENE_ACCESSED(attr_desc) ZB_BIT_IS_SET((attr_desc)->access, ZB_ZCL_ATTR_ACCESS_SCENE) - -/*! @internal @brief Check, if attribute is manufacturer specific */ -#define ZB_ZCL_IS_ATTR_MANUF_SPEC(attr_desc) ZB_BIT_IS_SET((attr_desc)->access, ZB_ZCL_ATTR_MANUF_SPEC) - -/*! Mark attribute ID to distinguish if it is common/manufacturer - specific/internal attribute: - - set bit 15 (the highest) for internal attributes - - set bit 14 for manufacturer specific attributes -*/ -/*! @internal @brief Mark attribute Id as custom/manufacture specific attribute */ -#define ZB_ZCL_ATTR_INTERNAL_ID(_attr_id) ((_attr_id) | (1U << 15)) - -/*! @internal @brief Check if attribute Id is custom/manufacture specific */ -#define ZB_ZCL_ATTR_CHECK_INTERNAL_ID(_attr_id) ((_attr_id) & (1U << 15)) - - -/*! @internal @brief Mark attribute Id as custom/manufacture specific attribute */ -#define ZB_ZCL_ATTR_CUSTOM_ID(_attr_id) ((_attr_id) | (1U << 14)) - -/*! @internal @brief Check if attribute Id is custom/manufacture specific */ -#define ZB_ZCL_ATTR_CHECK_CUSTOM_ID(_attr_id) ((_attr_id) & (1U << 14)) - - -/*! @internal @brief Start number for custom attributes */ -#define ZB_ZCL_ATTR_CUSTOM_START_NUMBER 0xfff0 - -/*! @internal @brief Check boolean type attribute value */ -#define ZB_ZCL_CHECK_BOOL_VALUE(x) ((x) == ZB_FALSE || (x) == ZB_TRUE) - - -/** @endcond */ /* internals_doc */ - -/** - * @brief Sets attribute value, perform all needed checks before and after setting new value, - * including read-only check and marking for reporting. - * @param ep - end point number. - * @param cluster_id - cluster identifier. - * @param cluster_role - role (see @ref zcl_cluster_role) - * @param attr_id - attribute identifier. - * @param value_ptr - pointer to new attribute value. - * @param check_access - boolean flag to specify if to perform access check or not. - * @hideinitializer - */ -#define ZB_ZCL_SET_ATTRIBUTE(ep, cluster_id, cluster_role, attr_id, value_ptr, check_access) \ - ZVUNUSED(zb_zcl_set_attr_val(ep, cluster_id, cluster_role, attr_id, value_ptr, check_access)) - - -/** - * @brief Set attribute 8-bit value without any check. Use this macro - * on your own risk, if and only if you are absolutely sure that no check for Access - * rights, Reporting and attribute type is needed. - * @param attr_desc - pointer to an attribute description structure @ref zb_zcl_attr_s. - * @param value - 8-bit value to be set. - * @hideinitializer - */ -#define ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, value) \ - (*(zb_uint8_t*)attr_desc->data_p = (zb_uint8_t)(value)) - -/** - * @brief Set attribute 16-bit value without any check. Use this macro - * on your own risk, if and only if you are absolutely sure that no check for Access - * rights, Reporting and attribute type is needed. - * @param attr_desc - pointer to an attribute description structure @ref zb_zcl_attr_s. - * @param value - 16-bit value to be set. - * @hideinitializer - */ -#define ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, value) \ - (*(zb_uint16_t*)attr_desc->data_p = (zb_uint16_t)(value)) - -/** - * @brief Set attribute 32-bit value without any check. Use this macro - * on your own risk, if and only if you are absolutely sure that no check for Access - * rights, Reporting and attribute type is needed. - * @param attr_desc - pointer to an attribute description structure @ref zb_zcl_attr_s. - * @param value - 32-bit value to be set. - * @hideinitializer - */ -#define ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, value) \ - (*(zb_uint32_t*)attr_desc->data_p = (zb_uint32_t)(value)) - - -/*! Get 8-bit unsigned attribute value (without any check) */ -#define ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) \ - (*(zb_uint8_t*)attr_desc->data_p) - -/*! Get 8-bit signed attribute value (without any check) */ -#define ZB_ZCL_GET_ATTRIBUTE_VAL_S8(attr_desc) \ - (*(zb_int8_t*)attr_desc->data_p) - -/*! Get 16-bit unsigned attribute value (without any check) */ -#define ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) \ - (*(zb_uint16_t*)attr_desc->data_p) - -/*! Get 16-bit signed attribute value (without any check) */ -#define ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) \ - (*(zb_int16_t*)attr_desc->data_p) - -/*! Get 32-bit unsigned attribute value (without any check) */ -#define ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc) \ - (*(zb_uint32_t*)attr_desc->data_p) - -/*! Get 32-bit unsigned attribute value (without any check) */ -#define ZB_ZCL_GET_ATTRIBUTE_VAL_S32(attr_desc) \ - (*(zb_int32_t*)attr_desc->data_p) - - -/*! @} */ /* General attributes' description */ - - -/************************************** ZCL frame definitions ************************************/ - -/*! @defgroup zb_zcl_common_frame General frame description - Types and macros required for ZCL frame manipulations - @{ - -*/ - -/** @cond internals_doc */ - -/*! @brief ZCL header size */ -#define ZB_ZCL_GET_HEADER_SIZE(frm_ctl) \ - ( (ZB_ZCL_IS_MANUF_SPECIFIC(frm_ctl)) \ - ? sizeof(zb_zcl_frame_hdr_full_t) \ - : sizeof(zb_zcl_frame_hdr_short_t)) - -/** @internal @brief Cuts ZCL header form a buffer. */ -#define ZB_ZCL_CUT_HEADER(buf) \ - (void)zb_buf_cut_left(buf, ZB_ZCL_GET_HEADER_SIZE(*(zb_uint8_t*)zb_buf_begin(buf))) - -/** @endcond */ /* internals_doc */ - -/** @name ZCL frame type - * @brief Defines Permitted values for Frame Type subfield of Frame Control field in ZCL frame. - * @anchor zcl_frame_type - */ -/** @{ */ -#define ZB_ZCL_FRAME_TYPE_COMMON 0x00U /*!< Command acts across the entire profile */ -#define ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC 0x01U /*!< Command is specific to a cluster */ -/** @} */ - -/** - * @brief Type for ZCL frame type. - * - * @deprecated holds one of @ref zcl_frame_type. Kept only for backward compatibility as - * @ref zcl_frame_type were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_zcl_frame_type_t; - -/** - * @name Values for Manufacturer-specific subfield of FCF in ZCL frame - * @anchor zcl_manufacturer_specific - * @see ZCL spec, subclause 2.3.1.1.2 - */ -/** @{ */ -/** Standard profile command. Manufacturer code field shall @b not be included into ZCL frame - * header. */ -#define ZB_ZCL_NOT_MANUFACTURER_SPECIFIC 0x00U -/** Command refers to manufacturer-specific profile extension. Manufacturer code field shall be - * included into ZCL frame header. */ -#define ZB_ZCL_MANUFACTURER_SPECIFIC 0x01U -/** @} */ - -/** - * @brief Type for return statuses of mathematical operations. - * - * @deprecated holds one of @ref zcl_manufacturer_specific. Kept only for backward compatibility as - * @ref zcl_manufacturer_specific were declared previously as enum. Can be removed in future - * releases. - */ -typedef zb_uint8_t zb_zcl_manufacturer_specific_t; - -#define ZB_ZCL_MANUFACTURER_WILDCARD_ID 0xffff - -/** - * @name Disable default response subfield of FCF in ZCL frame - * @anchor zcl_disable_default_response - * @see ZCL spec, subclause 2.3.1.1.3 - */ -/** @{ */ -/** Enable default response */ -#define ZB_ZCL_ENABLE_DEFAULT_RESPONSE 0x00U -/** Disable default response */ -#define ZB_ZCL_DISABLE_DEFAULT_RESPONSE 0x01U -/** @} */ - -/** - * @brief Type for possible values of Disable default response subfield of FCF in ZCL frame. - * - * Holds one of @ref zcl_disable_default_response. Kept for backward compatibility as - * @ref zcl_disable_default_response were declared previously as enum. - */ -typedef zb_uint8_t zb_zcl_disable_default_response_t; - - -/** - * @name ZCL frame direction - * @anchor zcl_frame_direction - * @see ZCL spec, subclause 2.3.1.1.3. - */ -/** @{ */ -/*! Command sent from client to a server */ -#define ZB_ZCL_FRAME_DIRECTION_TO_SRV 0x00U -/*! Command sent from server to a client */ -#define ZB_ZCL_FRAME_DIRECTION_TO_CLI 0x01U -/** @} */ - -/** - * @brief Type for ZCL frame direction. - * - * Holds one of @ref zcl_frame_direction. Kept only for backward compatibility as - * @ref zcl_frame_direction were declared previously as enum. - */ -typedef zb_uint8_t zb_zcl_frame_direction_t; - -/*! @brief Reverts ZCL direction value */ -#define ZB_ZCL_REVERT_DIRECTION(_d) \ - (((_d) == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? ZB_ZCL_FRAME_DIRECTION_TO_CLI : ZB_ZCL_FRAME_DIRECTION_TO_SRV) - -/*! @brief ZCL frame control field - @see ZCL spec, subclause 2.3.1.1 -*/ -typedef ZB_PACKED_PRE struct zb_zcl_frame_ctrl_s -{ - zb_bitfield_t frame_type:2; /*!< Frame type @ref zcl_frame_type */ - zb_bitfield_t manufacturer:1; /*!< Manufacturer specific frame @ref zcl_manufacturer_specific*/ - zb_bitfield_t direction:1; /*!< Direction @ref zcl_frame_direction */ - zb_bitfield_t disable_def_resp:1; /*!< Disable default response */ - zb_bitfield_t reserved:3; -} ZB_PACKED_STRUCT zb_zcl_frame_ctrl_t; - -/*! @brief ZCL frame header with manufacturer code - @see ZCL spec, subclause 2.3.1 -*/ -typedef ZB_PACKED_PRE struct zb_zcl_frame_hdr_full_s -{ - zb_zcl_frame_ctrl_t frame_ctrl; /*!< Frame control filed see @ref zb_zcl_frame_ctrl_s */ - zb_uint16_t manufacturer_code; /*!< Manufacturer Code */ - zb_uint8_t seq_number; /*!< Transaction Sequence Number */ - zb_uint8_t command_id; /*!< Command Identifier Field */ -} ZB_PACKED_STRUCT -zb_zcl_frame_hdr_full_t; - -/*! @brief ZCL frame header without manufacturer code - @see ZCL spec, subclause 2.3.1 -*/ -typedef ZB_PACKED_PRE struct zb_zcl_frame_hdr_short_s -{ - zb_zcl_frame_ctrl_t frame_ctrl; /*!< Frame control field see @ref zb_zcl_frame_ctrl_s */ - zb_uint8_t seq_number; /*!< Transaction Sequence Number */ - zb_uint8_t command_id; /*!< Command Identifier Field */ -} ZB_PACKED_STRUCT -zb_zcl_frame_hdr_short_t; - -/** - * @name ZCL address type - * @brief Possible address types of devices from which ZCL message is received. - * @anchor zcl_addr_type - */ -/** @{ */ -#define ZB_ZCL_ADDR_TYPE_SHORT 0U -#define ZB_ZCL_ADDR_TYPE_IEEE_GPD 1U -#define ZB_ZCL_ADDR_TYPE_SRC_ID_GPD 2U -#define ZB_ZCL_ADDR_TYPE_IEEE 3U -/** @} */ - -/** - * @name ZCL GPD address type - * @brief Macro helps to see whether addr_type belongs to GPD subgroup - */ -/** @{ */ -#define ZB_ZCL_ADDR_TYPE_IS_GPD(_addr_type) \ - ((_addr_type) == ZB_ZCL_ADDR_TYPE_IEEE_GPD || \ - (_addr_type) == ZB_ZCL_ADDR_TYPE_SRC_ID_GPD) -/** @} */ - -/** - * @brief Type to represent source address of ZCL message - * - * It is needed if ZGP sink is enabled and therefore messages can - * be received from ZGPD devices which are identified by 32-bit - * source Id. - */ -typedef ZB_PACKED_PRE struct zb_zcl_addr_s -{ - zb_uint8_t addr_type; /**< address type (see @ref zcl_addr_type) */ - ZB_PACKED_PRE union zb_zcl_addr_u - { - zb_uint16_t short_addr; /**< Zigbee short address */ - zb_uint32_t src_id; /**< Source ID of ZGPD */ - zb_ieee_addr_t ieee_addr; /**< Full IEEE-address of ZGPD */ - } u; -} ZB_PACKED_STRUCT -zb_zcl_addr_t; - -/*! Parsed ZCL header */ -typedef ZB_PACKED_PRE struct zb_zcl_parsed_hdr_s -{ - /* Values from APS data indication */ - ZB_PACKED_PRE union - { - ZB_PACKED_PRE struct - { - //zb_uint16_t src_addr; - zb_zcl_addr_t source; - zb_uint16_t dst_addr; - zb_uint8_t src_endpoint; - zb_uint8_t dst_endpoint; - zb_uint8_t fc; -#if (defined ZB_ENABLE_SE) || (defined ZB_ZCL_SUPPORT_CLUSTER_WWAH) - zb_uint8_t aps_key_source:1; - zb_uint8_t aps_key_attrs:2; - zb_uint8_t aps_key_from_tc:1; - zb_uint8_t reserved:4; -#endif - } ZB_PACKED_STRUCT common_data; - } addr_data; - zb_uint16_t cluster_id; - zb_uint16_t profile_id; - - /* ZCL specific fields */ - zb_uint8_t cmd_id; /**< Command identifier. */ - zb_uint8_t cmd_direction; /**< Command direction identifier. */ - zb_uint8_t seq_number; /**< ZCL transaction sequence number. */ - zb_bool_t is_common_command; /**< "Common command" flag. */ - zb_bool_t disable_default_response; /**< "Disable default response" flag. */ - zb_bool_t is_manuf_specific; /**< "Has manufacturer-specific data" flag. */ - zb_uint16_t manuf_specific; /**< Manufacturer-specific data. */ -} ZB_PACKED_STRUCT -zb_zcl_parsed_hdr_t; - - -/*! Attribute address info structure */ -typedef struct zb_zcl_attr_addr_info_s -{ - zb_uint8_t src_ep; /**< Source endpoint */ - zb_uint8_t dst_ep; /**< Destination endpoint */ - zb_uint16_t dst_short_addr; /**< Destination short address */ - - zb_uint16_t profile_id; /**< Profile id */ - zb_uint16_t cluster_id; /**< Cluster id */ - zb_uint8_t cluster_role; /**< Cluster role */ - zb_uint16_t attr_id; /**< Attribute id */ -} -zb_zcl_attr_addr_info_t; - - -/** @brief Extract common addressing data from parsed ZCL structure. - * @param header - pointer to the parsed ZCL header structure (see @ref zb_zcl_parsed_hdr_s). - */ -#define ZB_ZCL_PARSED_HDR_SHORT_DATA(header) ((header)->addr_data.common_data) - -/** - * @brief Get ZCL frame type @ref zcl_frame_type. - * @hideinitializer - */ -#define ZB_ZCL_GET_FRAME_TYPE(v) ((v) & 0x3U) - -/** - * @brief Check is ZCL frame manufacturer specific @ref zcl_manufacturer_specific. - * @hideinitializer - */ -#define ZB_ZCL_GET_MANUF_SPECIFIC(v) (((v) >> 2U) & 0x1U) - -#define ZB_ZCL_IS_MANUF_SPECIFIC(v) (ZB_ZCL_GET_MANUF_SPECIFIC(v) != 0U) - -/** - * @brief Get ZCL frame direction @ref zcl_frame_direction. - * @hideinitializer - */ -#define ZB_ZCL_GET_DIRECTION(v) (((v) >> 3U) & 0x1U) - -/** - * @brief Get ZCL disable default response field @ref zcl_disable_default_response. - * @hideinitializer - */ -#define ZB_ZCL_GET_DISABLE_DEFAULT_RESPONSE(v) (((v) >> 4U) & 0x1U) - -/** - * @brief Set ZCL frame type @ref zcl_frame_type. - * @hideinitializer - */ -#define ZB_ZCL_SET_FRAME_TYPE(v, val) ((v) |= (val)) - -/** - * @brief Set ZCL frame manufacturer specific @ref zcl_manufacturer_specific. - * @hideinitializer - */ -#define ZB_ZCL_SET_MANUF_SPECIFIC(v, val) ((v) |= ((val) << 2)) - -/** - * @brief Set ZCL frame direction @ref zcl_frame_direction. - * @hideinitializer - */ -#define ZB_ZCL_SET_DIRECTION(v, val) ((v) |= ((val) << 3)) - -/** - * @brief Set ZCL disable default response field @ref zcl_disable_default_response. - * @hideinitializer - */ -#define ZB_ZCL_SET_DISABLE_DEFAULT_RESPONSE(v, val) ((v) |= ((val) << 4)) - -/** - * @brief Construct ZCL command header in the buffer - * @param zbbuf buffer ID - * @param frame_ctl Frame Control field for ZCL packet - * @param manuf_code manufacturer code, not used manufacturer-specific flag is not set - * @param cmd_id ZCL command id - * @param tsn pointer to variable (may be NULL) for TSN value of ZCL packet (generated by the function) - * - * Returns pointer to the buffer data begin after ZCL header (where command payload can be placed if needed). - */ -void *zb_zcl_start_command_header(zb_bufid_t zbbuf, zb_uint8_t frame_ctl, zb_uint16_t manuf_code, zb_uint8_t cmd_id, zb_uint8_t* tsn); - -/** @cond internals_doc */ - -/** @internal @brief Construct ZCL header frame control value */ -#define ZB_ZCL_CONSTRUCT_FRAME_CONTROL( \ - frame_type, manuf_specific, direction, disable_default_resp) \ - (( (frame_type) \ - | ((manuf_specific) << 2) \ - | ((direction) << 3) \ - | ((disable_default_resp) << 4))) - -#define ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL( \ - frame_ctl, frame_type, manuf_specific, direction, disable_default_resp) \ - ((frame_ctl) = ZB_ZCL_CONSTRUCT_FRAME_CONTROL((frame_type), \ - (manuf_specific), \ - (direction), \ - (disable_default_resp))) - -/* NOTE: We suppose all general requests/responses currently are not manufacturer specific */ -/** @internal @brief Construct ZCL header frame control value for General command request */ -#define ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL(buf_ptr, def_resp) \ - (ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*buf_ptr, \ - ZB_ZCL_FRAME_TYPE_COMMON, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, \ - (def_resp)), \ - buf_ptr++) - -#define ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_A(buf_ptr, \ - direction, is_manufacturer_specific, def_resp) \ - (ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*buf_ptr, \ - ZB_ZCL_FRAME_TYPE_COMMON, \ - (is_manufacturer_specific), \ - (direction), \ - (def_resp)), \ - buf_ptr++) - -/*! @internal Construct ZCL header frame control value for General - * command request, specifying extra parameters */ -#define ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_EXT(buf_ptr, \ - _is_manuf_specific, direction, def_resp) \ - (ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*buf_ptr, \ - ZB_ZCL_FRAME_TYPE_COMMON, \ - (_is_manuf_specific), \ - (direction), \ - (def_resp)), \ - buf_ptr++) - - -/* To do not change existing code too much: 3 consequent macro create single function call. */ -#define ZB_ZCL_START_PACKET_REQ(zbbuf) zb_zcl_start_command_header((zbbuf), -#define ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(buf_ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_FRAME_CONTROL(ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, (def_resp)), \ - 0, /* No manuf_code */ -#define ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(data_ptr, tsn, cmd_id) (cmd_id), NULL) - -/* TODO: Implement via zb_zcl_start_command_header() */ -#define ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_O(buf_ptr, def_resp) \ - (ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*buf_ptr, \ - ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, \ - def_resp), \ - buf_ptr++) - -#define ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(buf_ptr, direction, \ - is_manufacturer_specific, def_resp) \ - (ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*(buf_ptr), \ - ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ((is_manufacturer_specific) ? ZB_ZCL_MANUFACTURER_SPECIFIC \ - : ZB_ZCL_NOT_MANUFACTURER_SPECIFIC), \ - (direction), \ - (def_resp)), \ - (buf_ptr)++) - -#define ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_A(buf_ptr, direction, \ - is_manufacturer_specific) \ - (ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*(buf_ptr), \ - ZB_ZCL_FRAME_TYPE_COMMON, \ - ((is_manufacturer_specific) \ - ? ZB_ZCL_MANUFACTURER_SPECIFIC \ - : ZB_ZCL_NOT_MANUFACTURER_SPECIFIC), \ - (direction), \ - ZB_ZCL_DISABLE_DEFAULT_RESPONSE), \ - (buf_ptr)++) - -#define ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(buf_ptr, direction, \ - is_manufacturer_specific) \ - (ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*(buf_ptr), \ - ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ((is_manufacturer_specific) \ - ? ZB_ZCL_MANUFACTURER_SPECIFIC \ - : ZB_ZCL_NOT_MANUFACTURER_SPECIFIC), \ - (direction), \ - ZB_ZCL_DISABLE_DEFAULT_RESPONSE), \ - (buf_ptr)++) - -/*! @internal Construct ZCL header frame control valueZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL for General command response */ -#define ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL(buf_ptr) \ - (ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*(buf_ptr), ZB_ZCL_FRAME_TYPE_COMMON, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, \ - ZB_ZCL_DISABLE_DEFAULT_RESPONSE), \ - (buf_ptr)++) - - -/*! @internal Construct ZCL header frame control value for General - * command response, specifying extra parameters */ -#define ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_EXT(_buf_ptr, _is_manuf_specific, \ - _direction) \ - (ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*(_buf_ptr), \ - ZB_ZCL_FRAME_TYPE_COMMON, \ - ((_is_manuf_specific) ? ZB_ZCL_MANUFACTURER_SPECIFIC \ - : ZB_ZCL_NOT_MANUFACTURER_SPECIFIC), \ - (_direction), \ - ZB_ZCL_DISABLE_DEFAULT_RESPONSE), \ - (_buf_ptr)++) - -/** @endcond */ /* internals_doc */ - -/*! @brief Construct ZCL header frame control value for cluster-specific command response - * - * @snippet wwah_door_lock/dl_device/dl_door_lock.c zcl_construct_specific_frame_header - * */ -#define ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(buf_ptr) \ - (ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*(buf_ptr), \ - ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, \ - ZB_ZCL_DISABLE_DEFAULT_RESPONSE), \ - (buf_ptr)++) - -/** - * @brief Construct ZCL header - * @note To add Manufacturer specific field, use ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(), macro. - * @hideinitializer - */ -#define ZB_ZCL_CONSTRUCT_COMMAND_HEADER(data_ptr, tsn, cmd_id) \ - (ZB_ZCL_PACKET_PUT_DATA8((data_ptr), (tsn)), ZB_ZCL_PACKET_PUT_DATA8((data_ptr), (cmd_id))) - -/*! @brief Construct ZCL header, Manufacturer specific value is conditionally supported */ -#define ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(_data_ptr, _tsn, _is_manuf_spec, _manuf_specific, _cmd_id) \ - { \ - if ((_is_manuf_spec)) \ - { \ - ZB_ZCL_PACKET_PUT_DATA16_VAL((_data_ptr), (_manuf_specific)); \ - } \ - ZB_ZCL_PACKET_PUT_DATA8((_data_ptr), (_tsn)); \ - ZB_ZCL_PACKET_PUT_DATA8((_data_ptr), (_cmd_id)); \ - } - -/** @cond internals_doc */ - -/*! @internal @brief Calculate ZCL frame header size */ -#define ZB_ZCL_FRAME_HDR_GET_SIZE(p) ( ZB_ZCL_GET_MANUF_SPECIFIC(p) ? \ - 2*sizeof(zb_uint8_t)+sizeof(zb_uint16_t) : \ - 2*sizeof(zb_uint8_t) ) - -/*! @internal @brief Get ZCL frame manufacturer code from the packet */ -#define ZB_ZCL_FRAME_HDR_GET_MANUFACTURER_CODE(p) \ - ( *(zb_uint16_t *)((zb_uint8_t *)p + sizeof(zb_zcl_frame_ctrl_t)) ) - -/*! @internal Get ZCL frame sequence number from the packet. */ -#define ZB_ZCL_FRAME_HDR_GET_SEQ_NUM(p) \ - ( *((zb_uint8_t *)p \ - + sizeof(zb_zcl_frame_ctrl_t) \ - + (ZB_ZCL_GET_MANUF_SPECIFIC(p) ? sizeof(zb_uint16_t) : 0)) ) - -/*! @internal Get ZCL frame command identifier from the packet. */ -#define ZB_ZCL_FRAME_HDR_GET_COMMAND_ID(p) \ - ( *((zb_uint8_t *)p \ - + sizeof(zb_zcl_frame_ctrl_t) \ - + (ZB_ZCL_GET_MANUF_SPECIFIC(p) ? sizeof(zb_uint16_t) : 0) + sizeof(zb_uint8_t)) ) - -/** @endcond */ /* internals_doc */ - -/** - * @brief Return next sequence number for ZCL frame. - * @hideinitializer - */ -#define ZB_ZCL_GET_SEQ_NUM() (ZCL_CTX().seq_number++) - -/*! @brief Copy parsed ZCL header from buffer - @param buf - ID zb_bufid_t of buffer containing parsed ZCL header as parameter - @param dst - pointer to the memory area to copy header to -*/ -#define ZB_ZCL_COPY_PARSED_HEADER(buf, dst) \ - (ZB_MEMCPY( \ - (dst), \ - ZB_BUF_GET_PARAM((buf), zb_zcl_parsed_hdr_t), \ - sizeof(zb_zcl_parsed_hdr_t))) - - -/*! @brief General macro for sending a command with empty payload - @param buffer to put command payload and headers to - @param addr address to send to - @param dst_addr_mode destination address mode - @param dst_ep destination endpoint - @param ep source endpoint - @param prof_id profile the command belongs to - @param dis_default_resp "Disable default response" flag - @param cluster_id cluster identifier - @param command_id command identifier - @param cb command send status callback - - @code - #define ZB_ZCL_DOOR_LOCK_SEND_LOCK_DOOR_REQ(buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - dis_default_resp, \ - cb) \ - ZB_ZCL_SEND_CMD( buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - ZB_AF_HA_PROFILE_ID, \ - dis_default_resp, \ - ZB_ZCL_CLUSTER_ID_DOOR_LOCK, \ - ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR, \ - cb) - @endcode -*/ -#define ZB_ZCL_SEND_CMD( \ - buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - cluster_id, \ - command_id, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), command_id); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, cb); \ -} - -/*! @} */ /* General frame description */ - - -/******************************* ZCL frame basic manipulations *******************************/ - -/*! @defgroup zb_zcl_common_pckt_fill Fill ZCL packet low-level API - Types and macros shared fill Fill ZCL packet. - @{ - @par Example - @snippet HA_samples/write_attr_test/sample_zed.c ZB_ZCL_PACKET - @par -*/ - -/** - * @brief Initializes zb_buf_t buffer and returns pointer to the beginning of array. - * @hideinitializer - */ -#define ZB_ZCL_START_PACKET(zbbuf) \ - zb_buf_reuse(zbbuf) - -/** - * @brief Return number of bytes written to the buffer. - * @hideinitializer - */ -#define ZB_ZCL_GET_BYTES_WRITTEN(zbbuf, ptr) \ - zb_buf_get_ptr_off((zbbuf), (ptr)) - -zb_bool_t zb_zcl_can_cluster_be_fragmented(zb_uint16_t profile_id, zb_uint16_t cluster_id); - -#define ZB_ZCL_GET_BYTES_AVAILABLE_WITH_FRAGMENTATION(zbbuf, ptr) \ - (ZB_ASDU_MAX_FRAG_LEN - ZB_ZCL_GET_BYTES_WRITTEN(zbbuf, ptr)) - -#define ZB_ZCL_GET_BYTES_AVAILABLE_WO_FRAGMENTATION(zbbuf, ptr) \ - (ZB_ZCL_HI_WO_IEEE_MAX_PAYLOAD_SIZE - ZB_ZCL_GET_BYTES_WRITTEN(zbbuf, ptr)) - -/** - * @brief Return number of bytes available in a packet. - * @hideinitializer - */ -#ifdef APS_FRAGMENTATION -#define ZB_ZCL_GET_BYTES_AVAILABLE(zbbuf, ptr, profile_id, cluster_id) \ - (zb_zcl_can_cluster_be_fragmented(profile_id, cluster_id) ? \ - ZB_ZCL_GET_BYTES_AVAILABLE_WITH_FRAGMENTATION(zbbuf, ptr) : \ - ZB_ZCL_GET_BYTES_AVAILABLE_WO_FRAGMENTATION(zbbuf, ptr)) -#else -#define ZB_ZCL_GET_BYTES_AVAILABLE(zbbuf, ptr, profile_id, cluster_id) \ - ZB_ZCL_GET_BYTES_AVAILABLE_WO_FRAGMENTATION(zbbuf, ptr) -#endif /* APS_FRAGMENTATION */ - -/** - * @brief Put 8-bit value to packet. - * @hideinitializer - */ -#define ZB_ZCL_PACKET_PUT_DATA8(ptr, val) (*(ptr) = (val), (ptr)++) - -/*! - Put 16-bit value to packet - @param ptr - pointer to the place to put value to - @param val - pointer to the value to put into packet -*/ -#define ZB_ZCL_PACKET_PUT_DATA16(ptr, val) \ -do \ -{ \ - ZB_HTOLE16((ptr), (val)); \ - (ptr) += 2; \ -} while (ZB_FALSE) - -/*! - Put 16-bit value to packet - @param ptr - pointer to the place to put value to - @param val - value to put into packet -*/ -//#define ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, val) ZB_PUT_NEXT_HTOLE16(ptr, val) -#define ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, val) (ptr) = zb_put_next_htole16((ptr), val) - -#define ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, val1, val2) (ptr) = zb_put_next_2_htole16((ptr),(val1),(val2)) - -#define ZB_ZCL_PACKET_PUT_2DATA32_VAL(ptr, val1, val2) (ptr) = zb_put_next_2_htole32((ptr),(val1),(val2)) - -/** - * @brief Put 32-bit value to packet. - * @param ptr - pointer to the place to put value to - * @param val - pointer to the value to put into packet - * @hideinitializer - */ -#define ZB_ZCL_PACKET_PUT_DATA32_VAL(ptr, val) ZB_PUT_NEXT_HTOLE32((ptr),(val)) - -/** - * @brief Put 32-bit value to packet. - * @param ptr - pointer to the place to put value to - * @param val - pointer to the value to put into packet - * @hideinitializer - */ -#define ZB_ZCL_PACKET_PUT_DATA32(ptr, val) \ - (ZB_HTOLE32(ptr, val), (ptr) += 4) - -/** - * @brief Put 48-bit value to packet. - * @param ptr - pointer to the place to put value to - * @param val - value to put into packet - * @hideinitializer - */ -#define ZB_ZCL_PACKET_PUT_DATA48_VAL(ptr, val) \ - (PUT_DATA48_VAL(ptr, val)) - -/** - * @brief Put 48-bit value to packet. - * @param ptr - pointer to the place to put value to - * @param val - pointer to the value to put into packet - * @hideinitializer - */ -#define ZB_ZCL_PACKET_PUT_DATA48(ptr, val) \ - (PUT_DATA48(ptr, val)) - -/** - * @brief Put 24-bit value to packet. - * @param ptr - pointer to the place to put value to - * @param val - value to put into packet - * @hideinitializer - */ -#define ZB_ZCL_PACKET_PUT_DATA24_VAL(ptr, val) \ - (PUT_DATA24_VAL(ptr, val)) - -/** - * @brief Put 24-bit value to packet. - * @param ptr - pointer to the place to put value to - * @param val - pointer to the value to put into packet - * @hideinitializer - */ -#define ZB_ZCL_PACKET_PUT_DATA24(ptr, val) \ - (PUT_DATA24(ptr, val)) - - - -/** - * @brief Put 64-bit value to packet. - * @param ptr - pointer to the place to put value to - * @param val - pointer to the value to put into packet - * @hideinitializer - */ -#define ZB_ZCL_PACKET_PUT_DATA64(ptr, val) (ZB_HTOLE64(ptr, val), (ptr) += 8) - -/** @brief Get 8-bit value from packet. - * @param dst_ptr - pointer to the memory to store value (pointer value preserved). - * @param src_ptr - pointer to the memory to get value from (will be incremented). - */ -#define ZB_ZCL_PACKET_GET_DATA8(dst_ptr, src_ptr) \ -{ \ - *(dst_ptr) = *((src_ptr)++); \ -} - -/** - * @brief Put N byte data to packet. - * @param ptr - pointer to the place to put value to. - * @param val - pointer to the value to put into packet. - * @param n - number of bytes to be copied. - * @hideinitializer - */ -#define ZB_ZCL_PACKET_PUT_DATA_N(ptr, val, n) \ - (ZB_MEMCPY(ptr, val, n), (ptr) += (n)) - -/** @brief Get 16-bit value from packet. - * @param dst_ptr - pointer to the memory to store value (pointer value preserved). - * @param src_ptr - pointer to the memory to get value from (will be incremented by value size). - */ -#define ZB_ZCL_PACKET_GET_DATA16(dst_ptr, src_ptr) \ -{ \ - ZB_LETOH16((dst_ptr), (src_ptr)); \ - (src_ptr) += sizeof(zb_uint16_t); \ -} - -/** @brief Get 24-bit value from packet. - * @param dst_ptr - pointer to the memory to store value (pointer value preserved). - * @param src_ptr - pointer to the memory to get value from (will be incremented by value size). - */ -#define ZB_ZCL_PACKET_GET_DATA24(dst_ptr, src_ptr) \ -{ \ - ZB_LETOH24(dst_ptr, src_ptr); \ - (src_ptr) += ZB_24BIT_SIZE; \ -} - - -/** @brief Get 48-bit value from packet. - * @param dst_ptr - pointer to the memory to store value (pointer value preserved). - * @param src_ptr - pointer to the memory to get value from (will be incremented by value size). - */ -#define ZB_ZCL_PACKET_GET_DATA48(dst_ptr, src_ptr) \ -{ \ - ZB_LETOH48(dst_ptr, src_ptr); \ - (src_ptr) += ZB_48BIT_SIZE; \ -} - - -/** @brief Get 32-bit value from packet. - * @param dst_ptr - pointer to the memory to store value (pointer value preserved). - * @param src_ptr - pointer to the memory to get value from (will be incremented by value size). - */ -#define ZB_ZCL_PACKET_GET_DATA32(dst_ptr, src_ptr) \ -{ \ - ZB_LETOH32((dst_ptr), (src_ptr)); \ - (src_ptr) += sizeof(zb_uint32_t); \ -} - -/** @brief Get 64-bit value from packet. - * @param dst_ptr - pointer to the memory to store value (pointer value preserved). - * @param src_ptr - pointer to the memory to get value from (will be incremented by value size). - */ -#define ZB_ZCL_PACKET_GET_DATA64(dst_ptr, src_ptr) \ -{ \ - ZB_LETOH64((dst_ptr), (src_ptr)); \ - (src_ptr) += 8; \ -} - -/** @brief Get IEEE address from packet. - * @param dst_ptr - pointer to the memory to store value (pointer value preserved). - * @param src_ptr - pointer to the memory to get value from (will be incremented by value size). - */ -#define ZB_ZCL_PACKET_GET_DATA_IEEE(dst_ptr, src_ptr) \ -{ \ - ZB_IEEE_ADDR_COPY((dst_ptr), (src_ptr)); \ - (src_ptr) += sizeof(zb_ieee_addr_t); \ -} - -/** @brief Put IEEE address into packet. - * @param dst_ptr - pointer to the memory to store value (will be incremented by value size). - * @param src_ptr - pointer to the memory to get value from (pointer value preserved). - */ -#define ZB_ZCL_PACKET_PUT_DATA_IEEE(dst_ptr, src_ptr) \ -{ \ - ZB_IEEE_ADDR_COPY((dst_ptr), (src_ptr)); \ - (dst_ptr) += sizeof(zb_ieee_addr_t); \ -} - -/** Put ZCL Octet String to packet */ -#define ZB_ZCL_PACKET_PUT_STRING(_ptr, _val) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA8 (_ptr, ZB_ZCL_GET_STRING_LENGTH(_val)); \ - ZB_ZCL_PACKET_PUT_DATA_N(_ptr, ZB_ZCL_GET_STRING_BEGIN(_val), \ - ZB_ZCL_GET_STRING_LENGTH(_val)); \ -} - -/** Get ZCL String from packet. - * @note If string is invalid (cannot be stored in buffer) - * this macro sets data to NULL. - * - * @param _zcl_str - Destination buffer. - * @param data - Pointer to incoming data. - * @param _zcl_str_max_size - Size of destination buffer. - */ -#define ZB_ZCL_PACKET_GET_STRING(_zcl_str, data, _zcl_str_max_size) \ -{ \ - ZB_ZCL_PACKET_GET_DATA8(&_zcl_str[0], data); \ - if (_zcl_str_max_size > ZB_ZCL_GET_STRING_LENGTH(_zcl_str)) \ - { \ - ZB_ZCL_PACKET_GET_DATA_N(ZB_ZCL_GET_STRING_BEGIN(_zcl_str), \ - data, \ - ZB_ZCL_GET_STRING_LENGTH(_zcl_str)); \ - } \ - else \ - { \ - data = NULL; \ - } \ -} - -/** Get ZCL String from packet and put it into array with fixed size. */ -#define ZB_ZCL_PACKET_GET_STATIC_STRING(_zcl_str, data) \ - ZB_ZCL_PACKET_GET_STRING(_zcl_str, data, sizeof(_zcl_str)) - - -/** @brief Get N-byte value from packet. - * @param dst_ptr - pointer to the memory to store value (will be incremented by value size). - * @param src_ptr - pointer to the memory to get value from (pointer value preserved). - * @param n - data length. - */ -#define ZB_ZCL_PACKET_GET_DATA_N(dst_ptr, src_ptr, n) \ -{ \ - ZB_MEMCPY((dst_ptr), (src_ptr), (n)); \ - (src_ptr) += (n); \ -} - -/*! @brief ZCL finish and send packet - @param buffer pointer to the buffer where ZCL cmd is stored - @param ptr pointer to the end of ZCL cmd in buffer - @param dst_addr destination address (see zb_addr_u) - @param dst_addr_mode destination address mode (only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and - @ref ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported) - @param dst_ep destination endpoint - @param ep source endpoint - @param prof_id profile the command belongs to - @param cluster_id cluster identifier - @param cb command send status callback - */ -zb_ret_t zb_zcl_finish_and_send_packet(zb_bufid_t buffer, zb_uint8_t *ptr, - const zb_addr_u *dst_addr, zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t ep, - zb_uint16_t prof_id, zb_uint16_t cluster_id, - zb_callback_t cb); - -zb_ret_t zb_zcl_finish_and_send_packet_new(zb_bufid_t buffer, zb_uint8_t *ptr, - const zb_addr_u *dst_addr, zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t ep, - zb_uint16_t prof_id, zb_uint16_t cluster_id, - zb_callback_t cb, zb_bool_t aps_secured, - zb_bool_t disable_aps_ack, zb_uint16_t delay); - - -/*! - Finish ZCL packet filling. Used bytes number are marked in a buffer. - @param zbbuf - pointer to zb_buf_t buffer. - @param ptr - pointer to the byte after the last written byte in the buffer. - @attention After ZB_ZCL_FINISH_PACKET() call, pointer ptr is set to the beginning of the buffer - data. - @note Please note that this macro does not return ret code, so if this macro is used without callback, - this may lead to buffer leaks (if function is failed to send the packet). - Please use @ref zb_zcl_finish_and_send_packet() function directly to be able to check ret code. - */ -/* Glue ZB_ZCL_FINISH_PACKET and ZB_ZCL_SEND_COMMAND_SHORT into one call */ -#define ZB_ZCL_FINISH_PACKET(zbbuf, ptr) (void) zb_zcl_finish_and_send_packet((zbbuf), (ptr), - -#define ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, \ - cb) \ - (const zb_addr_u *)(const void *)(&(addr)), (dst_addr_mode), (dst_ep), (ep), (prof_id), (cluster_id), (cb)) - - -#define ZB_ZCL_FINISH_N_SEND_PACKET(zbbuf, ptr, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, cb) \ - (void) zb_zcl_finish_and_send_packet((zbbuf), (ptr),(const zb_addr_u *)(const void *)(&(addr)), dst_addr_mode, dst_ep, ep, prof_id, cluster_id, cb) - -#define ZB_ZCL_FINISH_N_SEND_PACKET_NEW(zbbuf, ptr, addr, dst_addr_mode, dst_ep, ep, prof_id, cluster_id, cb, aps_secured, disable_aps_ack, delay) \ - (void) zb_zcl_finish_and_send_packet_new((zbbuf), (ptr),(zb_addr_u *)(void *)(&(addr)), dst_addr_mode, dst_ep, ep, prof_id, cluster_id, cb, aps_secured, disable_aps_ack, delay) - -/* TODO: Implement via zb_zcl_finish_and_send_packet() */ -#define ZB_ZCL_FINISH_PACKET_O(zbbuf, ptr) \ - (ptr) = zb_buf_alloc_left((zbbuf), ZB_ZCL_GET_BYTES_WRITTEN((zbbuf), (ptr))); - -/*! @}*/ /* Fill ZCL packet */ - -/* align func */ -#ifdef ZB_NEED_ALIGN - -zb_uint16_t zb_zcl_attr_get16(zb_uint8_t *value); -zb_int16_t zb_zcl_attr_gets16(zb_uint8_t *value); -zb_uint32_t zb_zcl_attr_get32(zb_uint8_t *value); -zb_int32_t zb_zcl_attr_gets32(zb_uint8_t *value); -#define ZB_ZCL_ATTR_GET16(value) zb_zcl_attr_get16(value) -#define ZB_ZCL_ATTR_GETS16(value) zb_zcl_attr_gets16(value) -#define ZB_ZCL_ATTR_GET32(value) zb_zcl_attr_get32(value) -#define ZB_ZCL_ATTR_GETS32(value) zb_zcl_attr_gets32(value) - -zb_int24_t zb_zcl_attr_get24(zb_uint8_t *value); -zb_uint48_t zb_zcl_attr_get48(zb_uint8_t *value); -#define ZB_ZCL_ATTR_GET24(value) zb_zcl_attr_get24(value) -#define ZB_ZCL_ATTR_GET48(value) zb_zcl_attr_get48(value) - -#else - -#define ZB_ZCL_ATTR_GET16(value) (*((zb_uint16_t *)value)) -#define ZB_ZCL_ATTR_GETS16(value) (*((zb_int16_t *)value)) -#define ZB_ZCL_ATTR_GET32(value) (*((zb_uint32_t *)value)) -#define ZB_ZCL_ATTR_GETS32(value) (*((zb_int32_t *)value)) - -#define ZB_ZCL_ATTR_GET24(value) (*((zb_int24_t *)value)) -#define ZB_ZCL_ATTR_GET48(value) (*((zb_uint48_t *)value)) - -#endif - -/***************************** ZCL general functionality definitions ******************************/ - -/** @cond internals_doc */ -/** @internal @brief Calculates array size */ -#define ZB_ZCL_ARRAY_SIZE(ar, type) (sizeof(ar)/sizeof(type)) - -/** @internal @brief Calculates byte array size (add 2 bytes for full length). */ -#define ZB_ZCL_ARRAY_GET_SIZE(ar, val) ZB_LETOH16(ar, val) -#define ZB_ZCL_ARRAY_SET_SIZE(ar, val) ZB_HTOLE16_VAL(ar, val) - -/** @internal @brief Calculates 32-byte array size (add 2 bytes for full length). */ -#define ZB_BYTE_32ARRAY_GET_SIZE(ar, val) { ZB_ZCL_ARRAY_GET_SIZE(ar, val); *(zb_uint16_t*)(ar) *= 4U; } -#define ZB_BYTE_32ARRAY_SET_SIZE(ar, val) { ZB_ZCL_ARRAY_SET_SIZE(ar, val); *(zb_uint16_t*)(ar) /= 4U; } - -#define ZB_ZCL_NULL_EP_ID (zb_uint8_t)(-1) -#define ZB_ZCL_NULL_ID (zb_uint16_t)(-1) -#define ZB_ZCL_NULL_STRING (zb_uint8_t)(0) - -/** @internal @brief Maximum size of Character String (with Length octet) */ -#define ZB_ZCL_MAX_STRING_SIZE 0xFFU -#define ZB_ZCL_INVALID_STRING_VALUE 0xFFU -#define ZB_ZCL_INVALID_ARRAY_VALUE 0xFFFFU - -/** @endcond */ - -/*! @} */ /* ZCL common types and definitions */ - -#ifdef DOXYGEN -/** @brief Fix data endian, if needed, and store it in the same buffer - @param data_ptr - pointer to data value - @param data_type - ZCL data type - */ -#define ZB_ZCL_FIX_ENDIAN(data_ptr, data_type) -#endif - -/** @cond internals_doc */ -#if ! defined ZB_LITTLE_ENDIAN - -/** @internal @brief Fix data endian, if needed, and store it in the same buffer - @param data_ptr - pointer to data value - @param data_type - ZCL data type - */ -#define ZB_ZCL_FIX_ENDIAN(data_ptr, data_type) zb_zcl_fix_endian(data_ptr, data_type) - -void zb_zcl_fix_endian(zb_uint8_t *data_ptr, zb_uint8_t data_type); - -#define ZB_ZCL_HTOLE16_INPLACE(data_ptr) \ - { \ - zb_uint16_t tmp_place; \ - ZB_HTOLE16(&tmp_place, (data_ptr)); \ - ZB_ASSIGN_UINT16((data_ptr), &tmp_place); \ - } - -#else - -#define ZB_ZCL_FIX_ENDIAN(data_ptr, data_type) (ZVUNUSED((data_ptr)), ZVUNUSED((data_type))) - -#define ZB_ZCL_HTOLE16_INPLACE(data_ptr) (ZVUNUSED((data_ptr))) - -#endif /* ZB_LITTLE_ENDIAN */ - -#define ZB_ZCL_TRAN_TABLE_HASH_PARAM(param) ZB_1INT_HASH_FUNC(param) % ZCL_TRAN_TABLE_SIZE - -/** @internal @brief ZCL hash entity, stores callback functions for commands specified by - * buffer index */ -typedef struct zcl_cb_hash_ent_s -{ - zb_callback_t func; /*!< callback pointer */ - zb_uint8_t buf; /*!< buffer index */ -} -zcl_cb_hash_ent_t; - -/** @endcond */ - -/** Command send status structure */ -typedef struct zb_zcl_command_send_status_s -{ - zb_ret_t status; /*!< command send status */ - zb_uint8_t dst_endpoint; /*!< Destination endpoint */ - zb_zcl_addr_t dst_addr; /*!< Destination address */ - zb_uint8_t src_endpoint; /*!< Source endpoint */ - /* add more fields here if needed */ -} -zb_zcl_command_send_status_t; - -/** @brief Set default value attribute callback - @param ep - endpoint number -*/ -typedef void (*zb_zcl_set_default_value_attr_cb_t)(zb_uint8_t ep); - -/** @brief Check attribute value callback - @param cluster_id - Cluster ID - @param cluster_role - cluster role (@ref zcl_cluster_role) - @param endpoint - endpoint number - @param attr_id - attribute ID - @param value - new attribute value - - @return RET_OK - if new value is valid, RET_ERROR - if new value is wrong or - RET_IGNORE - if use default Check attribute functions -*/ -typedef zb_ret_t (*zb_zcl_app_check_attr_value_cb_t) - (zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *value); - -/** @brief Get peer Cluster revision callback - @param ieee_addr - IEEE address - @param cluster_id - Cluster ID - @param cluster_role - cluster role (@ref zcl_cluster_role) - @param endpoint - endpoint number - - @return peer Cluster revision attribute value, 0xFFFF - if the revision is unknown -*/ -typedef zb_uint16_t (*zb_zcl_peer_revision_cb_t) - (zb_ieee_addr_t ieee_addr, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint8_t endpoint); - -/* ZCL common functions */ - -/*! @brief Get registered attribute description by cluster descriptor - @param cluster_desc - cluster descriptor - @param attr_id - attribute identifier - @returns Pointer to attribute description, or NULL if no attribute description found. -*/ -zb_zcl_attr_t* zb_zcl_get_attr_desc(zb_zcl_cluster_desc_t *cluster_desc, zb_uint16_t attr_id); - -/** @brief Check registered attribute is writable one - @param attr_desc - attribute descriptor - @param endpoint - endpoint - @param cluster_id - cluster identifier - @param cluster_role - cluster role (@ref zcl_cluster_role) - @param new_value - new value for an attribute - @param check_access - check READ_ONLY access or not - @returns ZB_ZCL_STATUS_SUCCESS on success, error status otherwise -*/ -zb_uint8_t zb_zcl_check_attribute_writable( - zb_zcl_attr_t* attr_desc, - zb_uint8_t endpoint, - zb_uint16_t cluster_id, - zb_uint8_t cluster_role, - zb_uint8_t *new_value, - zb_bool_t check_access); - -/*! - Hook on Write Attribute command - @param endpoint - endpoint - @param cluster_id - cluster ID - @param cluster_role - cluster role (@ref zcl_cluster_role) - @param attr_id - attribute ID - @param new_value - pointer to newly assigned value -*/ -void zb_zcl_write_attr_hook(zb_uint8_t endpoint, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id, zb_uint8_t *new_value); - -/*! - Set attribute value cluster specific postprocessing - @param cmd_info - cluster role (@ref zcl_cluster_role) - @param attr_id - attribute ID - @param value - new value of attribute -*/ -void zb_zcl_set_attr_val_post_process_cluster_specific(zb_zcl_parsed_hdr_t *cmd_info, - zb_uint16_t attr_id, - zb_uint8_t *value); -/** - * @brief Get size of value of given attribute type - * - * @param attr_type - attribute type in question (see @ref zcl_attr_type) - * @param attr_value - pointer to value in question (needed for variable sized types) - * - * @return size in bytes or 0xFF if type is invalid - */ -zb_uint8_t zb_zcl_get_attribute_size(zb_uint8_t attr_type, zb_uint8_t *attr_value); - -/** - * @brief Get size of analog data type - * @param attr_type - attribute type in question (see @ref zcl_attr_type) - * - * @return size in bytes of 0xFF in type is not analog or invalid - */ -zb_uint8_t zb_zcl_get_analog_attribute_size(zb_uint8_t attr_type); - -/** - * @brief Check whether type of ZCL attribute is analog - * @param attr_type - attribute type in question (see @ref zcl_attr_type) - * - * @return ZB_TRUE if type is analog, ZB_FALSE otherwise - */ -zb_bool_t zb_zcl_is_analog_data_type(zb_uint8_t attr_type); - -/** - * @brief Check if attribute value is valid or not - * - * @param cluster_id - cluster ID - * @param cluster_role - cluster role (@ref zcl_cluster_role) - * @param endpoint - endpoint - * @param attr_id - attribute ID - * @param value - pointer to attribute data - * - * @return RET_OK if data value is valid, some error code otherwise - */ -zb_ret_t zb_zcl_check_attr_value(zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *value); - -zb_bool_t zb_zcl_is_target_endpoint(zb_af_endpoint_desc_t *ep_desc, zb_uint16_t profile_id); - -zb_uint8_t zb_zcl_get_next_target_endpoint( - zb_uint8_t start_from_ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t profile_id); - -/** - * @brief Search endpoint for cluster with given id - * - * @param ep_desc - application endpoint description - * @param cluster_id - cluster ID (see @ref zcl_cluster_id) - * @param cluster_role - role (see @ref zcl_cluster_role) - * @return cluster descriptor or NULL if not present - */ -zb_zcl_cluster_desc_t* get_cluster_desc(const zb_af_endpoint_desc_t* ep_desc, zb_uint16_t cluster_id, zb_uint8_t cluster_role); - -/** - * @brief Find endpoint which has cluster with given ID - * - * @param cluster_id - cluster ID (see @ref zcl_cluster_id) - * @param cluster_role - role (see @ref zcl_cluster_role) - * @return endpoint number or 0 if not found - */ -zb_uint8_t get_endpoint_by_cluster(zb_uint16_t cluster_id, zb_uint8_t cluster_role); - -/** - * @brief Find if device has cluster with given ID - * - * @param cluster_id - cluster ID (see @ref zcl_cluster_id) - * @return ZB_TRUE if cluster found - */ -zb_bool_t is_cluster_present(zb_uint16_t cluster_id); - -zb_uint16_t get_profile_id_by_endpoint(zb_uint8_t endpoint_id); - -/** - * @brief Find endpoint which has cluster with given ID and role - * - * @param cluster_id - cluster ID (see @ref zcl_cluster_id) - * @param cluster_role - role (see @ref zcl_cluster_role) - * - * @return endpoint number or 0 if not found - */ -zb_af_endpoint_desc_t *get_endpoint_by_cluster_with_role( - zb_uint16_t cluster_id, - zb_uint8_t cluster_role); - -/** - * Find attribute descriptor by given endpoint number, cluster ID and attribute ID - * - * @param ep - endpoint number (must exist) - * @param cluster_id - cluster ID (must exist on given ep, see @ref zb_zcl_cluster_id_t) - * @param cluster_role - role (see @ref zcl_cluster_role) - * @param attr_id - attribute ID - * - * @return attribute descriptor - */ -zb_zcl_attr_t* zb_zcl_get_attr_desc_a(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id); - -/** - * Put attribute value to command packet, fix endian if needed. - * - * @param cmd_ptr - pointer to destination - * @param attr_type - type of attribute being written (see @ref zcl_attr_type) - * @param attr_value - pointer to value to be put into packet - * - * @return command pointer adjusted to point at the tail of written value -*/ -zb_uint8_t* zb_zcl_put_value_to_packet( - zb_uint8_t *cmd_ptr, zb_uint8_t attr_type, zb_uint8_t *attr_value); - - -/** - * @brief Sets attribute value, perform all needed checks before and after setting new value - * - * @param ep - endpoint number - * @param cluster_id - cluster ID (see @ref zb_zcl_cluster_id_t) - * @param cluster_role - role (see @ref zcl_cluster_role) - * @param attr_id - ID of the attribute being set - * @param value - pointer to new value - * @param check_access - whether read-only check should be performed - * - * @return ZB_ZCL_STATUS_SUCCESS if value was written \n - * ZB_ZCL_STATUS_READ_ONLY if attribute is read only and check_access is false - * ZB_ZCL_STATUS_UNSUP_ATTRIB if attribute is not supported by cluster - * ZB_ZCL_STATUS_INVALID_VALUE if current value of attribute is invalid - * @note given endpoint with given cluster ID should exist - */ -zb_zcl_status_t zb_zcl_set_attr_val(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, - zb_uint16_t attr_id, zb_uint8_t *value, zb_bool_t check_access); - -/** - * @brief Register callback that should be called when APS acknowledge is received for ZCL command - * - * @param param - pointer to buffer with ZCL command - * @param cb - pointer to callback function - */ -zb_ret_t zb_zcl_register_cb(zb_uint8_t param, zb_callback_t cb); - -/** - * @brief Call callback on receiving APS acknowledge for ZCL command - * - * @param param - buffer with ZCL command - * - * @return RET_OK if callback was found and called - * RET_NOT_FOUND if no callback was registered - */ -zb_ret_t zb_zcl_ack_callback(zb_uint8_t param); - -/** - * Check whether ZCL command should be handled by stack - * - * @param param - reference to buffer with parsed ZCL command - * - * @return ZB_ZCL_STATUS_SUCCESS if command should be handled - * ZB_ZCL_STATUS_UNSUP_MANUF_CLUST_CMD if manufacturer specific command is not supported - * ZB_ZCL_STATUS_UNSUP_CLUST_CMD if general command is not supported - * ZB_ZCL_STATUS_UNSUP_CLUST if cluster with role specified in ZCL header is not supported - */ -zb_uint8_t zb_zcl_check_accept_command(zb_uint8_t param); - -/** @cond DOXYGEN_INTERNAL_DOC */ -/*! Get endpoint ID that is under initialization at the moment - @return endpoint ID - */ -zb_uint8_t zb_get_current_endpoint_id(void); - -/** @brief Common continue command - - Usually use after invoke User App. If invoke User App finished with error (status!=RET_OK), - send error response, else if not disabled default response send it or free buffer - - @param buffer - buffer for send response - @param pcmd_info - pointer of cmd_info (see @ref zb_zcl_parsed_hdr_s) - @param status - status of operation (see @ref zb_zcl_status_t) -*/ -void zb_zcl_process_command_finish(zb_bufid_t buffer, zb_zcl_parsed_hdr_t *pcmd_info, zb_uint8_t status); -#define ZB_ZCL_PROCESS_COMMAND_FINISH(buffer, pcmd_info, status) \ - zb_zcl_process_command_finish(buffer, pcmd_info, status) - -void zb_zcl_process_command_finish_new(zb_bufid_t buffer, zb_zcl_parsed_hdr_t *pcmd_info, zb_uint8_t status); -#define ZB_ZCL_PROCESS_COMMAND_FINISH_NEW(buffer, pcmd_info, status) \ - zb_zcl_process_command_finish_new(buffer, pcmd_info, status) - -/** @brief Declare for change attribute for User Application - * - * @note Size of values must be twice as large as maximum size of a possible attribute -*/ -typedef struct zb_zcl_set_attr_value_param_s -{ - zb_uint16_t cluster_id; /**< Cluster ID*/ - zb_uint16_t attr_id; /**< Attribute ID*/ - /* - * Constant size of values - for correct alloc place in buffer tail, as - * "ZB_BUF_GET_PARAM(buffer, zb_zcl_device_callback_param_t)". - * Current size = maximum of fixed size of any attribute. - * If will need to translate attribute with variable size then need - * set value as size and pointer of attribute. - * */ - union - { - zb_uint8_t data8; /**< 8bit data */ - zb_uint16_t data16; /**< 16bit data */ - zb_uint24_t data24; /**< 24bit data */ - zb_uint32_t data32; /**< 32bit data */ - zb_uint48_t data48; /**< 48bit data */ - zb_ieee_addr_t data_ieee; /**< 64bit data or IEEE address */ - struct - { - zb_uint8_t size; /**< Size of data (byte) */ - zb_uint8_t *p_data; /**< Pointer of data */ - } data_variable; /**< Variable size data - string or byte array */ - } - values; -} zb_zcl_set_attr_value_param_t; - -/** @cond internals_doc */ -/** @internal @brief Inform User Application about change attribute - * @param buffer - buffer for transmit data - * @param clusterId - cluster ID - * @param attrDesc - attribute description - * @param p_value - pointer of new value attribute - * @param result - [out] result user callback -*/ -#define ZB_ZCL_INVOKE_USER_APP_SET_ATTR_WITH_RESULT( \ - buffer, ep, clusterId, attrDesc, p_value, result) \ -{ \ - (result) = RET_OK; \ - \ - if (ZCL_CTX().device_cb != NULL) \ - { \ - zb_zcl_device_callback_param_t *data = \ - ZB_BUF_GET_PARAM((buffer), zb_zcl_device_callback_param_t); \ - zb_uint8_t size = \ - zb_zcl_get_attribute_size((attrDesc)->type, (attrDesc)->data_p); \ - \ - switch ((attrDesc)->type) \ - { \ - case ZB_ZCL_ATTR_TYPE_CHAR_STRING: \ - case ZB_ZCL_ATTR_TYPE_OCTET_STRING: \ - case ZB_ZCL_ATTR_TYPE_LONG_OCTET_STRING: \ - case ZB_ZCL_ATTR_TYPE_ARRAY: \ - case ZB_ZCL_ATTR_TYPE_CUSTOM_32ARRAY: \ - case ZB_ZCL_ATTR_TYPE_128_BIT_KEY: \ - { \ - zb_uint8_t *ptr = (zb_uint8_t*)zb_buf_initial_alloc((buffer), size); \ - data = ZB_BUF_GET_PARAM((buffer), zb_zcl_device_callback_param_t); \ - \ - ZB_MEMCPY(ptr, (p_value), size); \ - data->cb_param.set_attr_value_param.values.data_variable.size = size; \ - data->cb_param.set_attr_value_param.values.data_variable.p_data = ptr; \ - break; \ - } \ - \ - default: \ - ZB_MEMCPY(&(data->cb_param.set_attr_value_param.values), \ - (p_value), \ - size); \ - break; \ - } \ - \ - if (data != NULL) \ - { \ - data->device_cb_id = ZB_ZCL_SET_ATTR_VALUE_CB_ID; \ - data->endpoint = (ep); \ - data->attr_type = (attrDesc)->type; \ - data->cb_param.set_attr_value_param.cluster_id = (clusterId); \ - data->cb_param.set_attr_value_param.attr_id = (attrDesc)->id; \ - (ZCL_CTX().device_cb)((buffer)); \ - (result) = data->status; \ - } \ - } \ -} - -/** @endcond */ - -/** - * @brief Set ZCL backward compatibility modes - * - * @ref ZB_ZCL_LEGACY_MODE is default mode - * - * @param mode - see @ref zcl_backward_compatibility_modes - * - * @return RET_OK if ZCL backward compatibility modes were set - * @return RET_OUT_OF_RANGE if parameter is out of range - */ -zb_ret_t zb_zcl_set_backward_comp_mode(zb_uint8_t mode); - -/** - * @brief Get ZCL backward compatibility modes - * - * @return current backward compatibility mode - see @ref zcl_backward_compatibility_modes - */ -zb_uint8_t zb_zcl_get_backward_comp_mode(void); - -/** - * @brief Get cluster revision depending on current ZCL backward compatibility mode, see @ref zcl_backward_compatibility_modes - * - * @param api_revision - - * @param dst_addr destination address pointer (see zb_addr_u) - * @param dst_addr_mode destination address mode (only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and - * @ref ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported) - * @param dst_ep destination endpoint - * @param cluster_id cluster identifier - * @param cluster_role cluster role - * @param src_ep source endpoint - * - * @return cluster revision for the specific cluster - */ -zb_uint16_t zb_zcl_get_cluster_rev_by_mode(zb_uint16_t api_revision, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint16_t cluster_id, zb_uint8_t cluster_role, - zb_uint8_t src_ep); - -/** - * @brief Set peer revision callback, see @ref zb_zcl_peer_revision_cb_t - * If the callback is set, ZB_ZCL_COMPATIBILITY_MODE will be enabled automatically - * - * @param cb - peer revision callback, NULL if the callback should be removed - * - * @return RET_OK if callback was set, otherwise an error - */ -zb_ret_t zb_zcl_set_peer_revision_callback(zb_zcl_peer_revision_cb_t cb); - -/** - * @brief Returns Backward compatible status values mode - * When enabled it diversifies some common statuses as it was in ZCL6 and ZCL7 - * - * @return @ref zcl_backward_compatibility_status_modes - */ -zb_uint8_t zb_zcl_get_backward_compatible_statuses_mode(void); - -/** - * @brief Set Backward compatible status values mode - * - * @param statuses_mode - see @ref zcl_backward_compatibility_status_modes - * - * @return RET_OK if the mode was set, RET_OUT_OF_RANGE if value is invalid - */ -zb_ret_t zb_zcl_set_backward_compatible_statuses_mode(zb_uint8_t statuses_mode); - -/** - * @} - */ - -void zb_zcl_schedule_status_abort(zb_bufid_t buffer, zb_addr_u *addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_callback_t cb); - -zb_bool_t zb_zcl_handle_specific_commands(zb_uint8_t param); -zb_bool_t cluster_needs_aps_encryption(zb_uint8_t endpoint_id, zb_uint16_t cluster_id); -zb_zcl_status_t zb_zcl_get_zcl_status_from_ret(zb_ret_t result); - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ -#endif /* ZB_ZCL_COMMON_H */ diff --git a/zboss/development/include/zcl/zb_zcl_config.h b/zboss/development/include/zcl/zb_zcl_config.h deleted file mode 100644 index 5f79e38f87..0000000000 --- a/zboss/development/include/zcl/zb_zcl_config.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Configuration for Zigbee cluster library -*/ - -#ifndef ZB_ZCL_CONFIG_H -#define ZB_ZCL_CONFIG_H 1 - -/** @cond DOXYGEN_ZCL_SECTION */ - -/************ ZCL specific configuration ******************/ - -/** - ZCL: transactions table size -*/ -#define ZCL_TRAN_TABLE_SIZE 16U - -/* DA: range check error */ -/* #define ZB_DISABLE_TEMP_MEASUREMENT_TOLERANCE_ID */ - -/* #define ZB_ZCL_OTA_INCREMENTAL_QUERY_INTERVAL */ - -/* Enable CVC feature */ -#define ZB_ZCL_ENABLE_CVC - -/* Disable Poll Control Check-Ins during OTA upgrade (to reduce the load) */ -#define xZB_ZCL_NO_CHECKINS_DURING_OTA - - -/*********************** Cluster to command configuration **********************/ - -/* General commands default processing */ -#define ZB_ZCL_ENABLE_DEFAULT_REPORT_ATTR_PROCESSING - -/* Control per-cluster default command processing */ - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_GROUPS) -#define ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING -#endif /* ZB_ZCL_SUPPORT_CLUSTER_GROUPS */ - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_GROUPS_CLIENT) -#define ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING_CLIENT -#endif /* ZB_ZCL_SUPPORT_CLUSTER_GROUPS_CLIENT */ - -/* Control per-cluster default scene extension processing */ -#if defined ZB_ZCL_SUPPORT_CLUSTER_SCENES - -#if defined ZB_ZCL_SUPPORT_CLUSTER_THERMOSTAT -#define ZB_ZCL_SUPPORT_THERMOSTAT_SCENE_EXTENSIONS -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_THERMOSTAT */ - -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_SCENES */ - -#if defined ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL -#define ZB_HA_ENABLE_POLL_CONTROL_SERVER -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL */ - -/* TODO: Divide Server and Client processing and turn on server part only when it is really needed - - * OTA cluster is rather big in terms of ROM size! */ -#if defined ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE -#define ZB_ZCL_ENABLE_DEFAULT_OTA_UPGRADE_PROCESSING -#define ZB_HA_ENABLE_OTA_UPGRADE_SERVER 1 -#define ZB_HA_ENABLE_OTA_UPGRADE_CLIENT 1 -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE */ - -#if defined ZB_ZCL_SUPPORT_CLUSTER_TUNNEL -#define ZB_ZCL_ENABLE_DEFAULT_TUNNEL_PROCESSING -#endif /* defined ZB_ENABLE_TUNNEL_CLUSTER */ - - -#if defined ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS -#define ZB_MAC_DIAGNOSTICS -#define ZDO_DIAGNOSTICS -#endif /* ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#endif /* ZB_ZCL_CONFIG_H */ diff --git a/zboss/development/include/zcl/zb_zcl_control4_networking.h b/zboss/development/include/zcl/zb_zcl_control4_networking.h deleted file mode 100644 index e31a874de4..0000000000 --- a/zboss/development/include/zcl/zb_zcl_control4_networking.h +++ /dev/null @@ -1,483 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Poll Control cluster definitions -*/ - -#ifndef ZB_ZCL_CONTROL4_NETWORKING_H -#define ZB_ZCL_CONTROL4_NETWORKING_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_CONTROL4 - * @{ - * @details - * @warning Using this cluster makes an application not conforming to the Zigbee PRO specification - * - * This cluster provides an application level interface between Zigbee devices and a Control4 - * Controller. - * - * This is implemented using Control4 specific profile ZB_AF_CONTROL4_PROFILE_ID. - * - * Control4 Network cluster also uses Many-To-One routing requests. - * - */ - -/** @name Control4 Network cluster attributes - * @{ - */ - -enum zb_zcl_control4_networking_attr_e -{ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_DEVICE_TYPE_ID = 0x0000, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_ID = 0x0001, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_MTORR_PERIOD_ID = 0x0002, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_FIRMWARE_VERSION_ID = 0x0004, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_REFLASH_VERSION_ID = 0x0005, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_BOOT_COUNT_ID = 0x0006, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_PRODUCT_STRING_ID = 0x0007, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_ID = 0x0008, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_ID = 0x0009, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_COST_ID = 0x000a, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_MESH_CHANNEL_ID = 0x000c, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_AVG_RSSI_ID = 0x0013, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_AVG_LQI_ID = 0x0014, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_BATTERY_LEVEL_ID = 0x0015, - - ZB_ZCL_ATTR_CONTROL4_NETWORKING_RADIO_4_BARS_ID = 0x0016 -}; - -enum zb_zcl_control4_networking_device_type_e -{ - /*! "Non-sleepy end device" value */ - ZB_ZCL_CONTROL4_NETWORKING_DEVICE_TYPE_END_DEVICE = 0x03, - /*! "Sleepy end device" value */ - ZB_ZCL_CONTROL4_NETWORKING_DEVICE_TYPE_SLEEPY_END_DEVICE = 0x04 -}; - -/** @brief Default value for Control4 networking cluster revision global attribute */ -#define ZB_ZCL_CONTROL4_NETWORKING_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -#define ZB_ZCL_CONTROL4_NETWORKING_REFLASH_VERSION_VENDOR_SPECIFIC 0xff - -#define ZB_ZCL_CONTROL4_NETWORKING_BOOT_COUNT_DEF_VALUE 0 - -#define ZB_ZCL_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_MIN_VALUE ((zb_uint16_t)0x000f) - -#define ZB_ZCL_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_DEF_VALUE ((zb_uint16_t)0x012c) - -#define ZB_ZCL_CONTROL4_NETWORKING_MTORR_PERIOD_MIN_VALUE ((zb_uint16_t)0x000f) - -#define ZB_ZCL_CONTROL4_NETWORKING_MTORR_PERIOD_DEF_VALUE ((zb_uint16_t)0x012c) - -#define ZB_ZCL_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_DEF_VALUE ((zb_uint16_t)0xffff) - -#define ZB_ZCL_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_DEF_VALUE {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - -#define ZB_ZCL_CONTROL4_NETWORKING_ACCESS_POINT_COST_DEF_VALUE 0xff - -#define ZB_ZCL_CONTROL4_NETWORKING_MESH_CHANNEL_MIN_VALUE 0x0b - -#define ZB_ZCL_CONTROL4_NETWORKING_MESH_CHANNEL_MAX_VALUE 0x19 - -#define ZB_ZCL_CONTROL4_NETWORKING_AVG_RSSI_MIN_VALUE -128 - -#define ZB_ZCL_CONTROL4_NETWORKING_AVG_RSSI_MAX_VALUE 0 - -#define ZB_ZCL_CONTROL4_NETWORKING_BATTERY_LEVEL_MIN_VALUE 0 - -#define ZB_ZCL_CONTROL4_NETWORKING_BATTERY_LEVEL_MAX_VALUE 100 - -#define ZB_ZCL_CONTROL4_NETWORKING_RADIO_4_BARS_MAX_VALUE 4 - -/* Number of searching ZAP attempts */ -#define ZB_ZCL_CONTROL4_NETWORK_SEARCHING_ZAP_ATTEMPTS 2 - -/** @brief Declare attribute list for C4 Network cluster - @param attr_list - attribute list name - @param device_type - pointer to variable to store Device Type attribute value - @param firmware_version - pointer to variable to store Firmware Version attribute value - @param reflash_version - pointer to variable to store Reflash Version attribute value - @param boot_count - pointer to variable to store Boot Count attribute value - @param product_string - pointer to variable to store Product String attribute value - @param access_point_node_ID - pointer to variable to store Access Point Node ID attribute value - @param access_point_long_ID - pointer to variable to store Access Point Long ID attribute value - @param access_point_cost - pointer to variable to store Access Point Cost ID attribute value - @param mesh_channel - pointer to variable to store Mesh Channel attribute value -*/ -#define ZB_ZCL_DECLARE_CONTROL4_NETWORKING_ATTRIB_LIST_SRV(attr_list, device_type, firmware_version, \ - reflash_version, boot_count, product_string, access_point_node_ID, access_point_long_ID, \ - access_point_cost, mesh_channel) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_CONTROL4_NETWORKING) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_DEVICE_TYPE_ID, (device_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_FIRMWARE_VERSION_ID, (firmware_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_REFLASH_VERSION_ID, (reflash_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_BOOT_COUNT_ID, (boot_count)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_PRODUCT_STRING_ID, (product_string)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_ID, (access_point_node_ID)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_ID, (access_point_long_ID)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_COST_ID, (access_point_cost)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_MESH_CHANNEL_ID, (mesh_channel)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @brief Declare extended attribute list for C4 Network cluster - @param attr_list - attribute list name - @param device_type - pointer to variable to store Device Type attribute value - @param firmware_version - pointer to variable to store Firmware Version attribute value - @param announce_window - pointer to variable to store Announce Window attribute value - @param MTORR_period - pointer to variable to store MTORR Period attribute value - @param reflash_version - pointer to variable to store Reflash Version attribute value - @param boot_count - pointer to variable to store Boot Count attribute value - @param product_string - pointer to variable to store Product String attribute value - @param access_point_node_ID - pointer to variable to store Access Point Node ID attribute value - @param access_point_long_ID - pointer to variable to store Access Point Long ID attribute value - @param access_point_cost - pointer to variable to store Access Point Cost ID attribute value - @param mesh_channel - pointer to variable to store Mesh Channel attribute value - @param avg_RSSI - pointer to variable to store Avg RSSI attribute value - @param avg_LQI - pointer to variable to store Avg LQI attribute value - @param battery_level - pointer to variable to store Battery Level attribute value - @param radio_4_bars - pointer to variable to store Radio 4-Bar attribute value -*/ -#define ZB_ZCL_DECLARE_CONTROL4_NETWORKING_ATTRIB_LIST_SRV_EXT(attr_list, device_type, firmware_version, \ - announce_window, MTORR_period, \ - reflash_version, boot_count, product_string, access_point_node_ID, access_point_long_ID, \ - access_point_cost, mesh_channel, \ - avg_RSSI, avg_LQI, battery_level, radio_4_bars) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_CONTROL4_NETWORKING) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_DEVICE_TYPE_ID, (device_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_ID, (announce_window)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_MTORR_PERIOD_ID, (MTORR_period)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_FIRMWARE_VERSION_ID, (firmware_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_REFLASH_VERSION_ID, (reflash_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_BOOT_COUNT_ID, (boot_count)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_PRODUCT_STRING_ID, (product_string)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_ID, (access_point_node_ID)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_ID, (access_point_long_ID)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_COST_ID, (access_point_cost)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_MESH_CHANNEL_ID, (mesh_channel)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_AVG_RSSI_ID, (avg_RSSI)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_AVG_LQI_ID, (avg_LQI)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_BATTERY_LEVEL_ID, (battery_level)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CONTROL4_NETWORKING_RADIO_4_BARS_ID, (radio_4_bars)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ /*Control4 Network cluster attributes */ - -/** @name Control4 Network cluster commands - * @{ - */ -enum zb_zcl_control4_networking_cmd_e -{ - ZB_ZCL_CMD_CONTROL4_NETWORKING_IMMEDIATE_ANNOUNCE_ID = 0x00 /**< "Immediate announce command" command. */ -}; - -#define ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_CONTROL4_NETWORKING_IMMEDIATE_ANNOUNCE_ID \ - -#define ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING_CLIENT_ROLE_GENERATED_CMD_LIST - -/** @cond internals_doc */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_DEVICE_TYPE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_DEVICE_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_MTORR_PERIOD_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_MTORR_PERIOD_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_FIRMWARE_VERSION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_FIRMWARE_VERSION_ID, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_REFLASH_VERSION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_REFLASH_VERSION_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_BOOT_COUNT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_BOOT_COUNT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_PRODUCT_STRING_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_PRODUCT_STRING_ID, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_ID, \ - ZB_ZCL_ATTR_TYPE_IEEE_ADDR, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_COST_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_COST_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_MESH_CHANNEL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_MESH_CHANNEL_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_AVG_RSSI_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_AVG_RSSI_ID, \ - ZB_ZCL_ATTR_TYPE_S8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_AVG_LQI_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_AVG_LQI_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_BATTERY_LEVEL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_BATTERY_LEVEL_ID, \ - ZB_ZCL_ATTR_TYPE_S8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CONTROL4_NETWORKING_RADIO_4_BARS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_RADIO_4_BARS_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} -/** @endcond */ /*internals_doc*/ - - -/** - * Control4 Network Cluster Endpoint. - * - * @attention This endpoint number is reserved for internal usage in the stack (for Control4 feature). - */ -#define ZB_CONTROL4_NETWORK_ENDPOINT 0xc4 - -#define ZB_ZCL_CONTROL4_NETWORK_DECLARE_CLUSTER_LIST( \ - cluster_list_name, \ - c4_network_attr_list) \ - zb_zcl_cluster_desc_t cluster_list_name[] = \ - { \ - ZB_ZCL_CLUSTER_DESC( \ - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, \ - ZB_ZCL_ARRAY_SIZE(c4_network_attr_list, zb_zcl_attr_t), \ - (c4_network_attr_list), \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - ZB_ZCL_MANUF_CODE_INVALID \ - ), \ - ZB_ZCL_CLUSTER_DESC( \ - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, \ - 0, \ - NULL, \ - ZB_ZCL_CLUSTER_CLIENT_ROLE, \ - ZB_ZCL_MANUF_CODE_INVALID \ - ) \ - } - -/*! - @brief Declare simple descriptor for C4 Network Cluster endpoint - @param ep_name - endpoint variable name -*/ -#define ZB_ZCL_CONTROL4_NETWORK_DECLARE_SIMPLE_DESC(ep_name) \ - /* ZB_DECLARE_SIMPLE_DESC(1, 1); it is already defined */ \ - ZB_AF_SIMPLE_DESC_TYPE(1, 1) simple_desc_##ep_name = \ - { \ - ZB_CONTROL4_NETWORK_ENDPOINT, \ - ZB_AF_CONTROL4_PROFILE_ID, \ - 0, 1, 0, 1, 1, \ - { \ - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, \ - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING \ - } \ - } - -/*! - @brief Declare endpoint for C4 Network Cluster - @param ep_name - endpoint variable name - @param cluster_list - endpoint cluster list - */ -#define ZB_ZCL_CONTROL4_NETWORK_DECLARE_EP(ep_name, cluster_list) \ - ZB_ZCL_CONTROL4_NETWORK_DECLARE_SIMPLE_DESC(ep_name); \ - ZB_AF_DECLARE_ENDPOINT_DESC(ep_name, \ - ZB_CONTROL4_NETWORK_ENDPOINT, ZB_AF_CONTROL4_PROFILE_ID, \ - 0, \ - NULL, \ - ZB_ZCL_ARRAY_SIZE(cluster_list, zb_zcl_cluster_desc_t), \ - cluster_list, \ - (zb_af_simple_desc_1_1_t*)&simple_desc_##ep_name, \ - 0, NULL, 0, NULL) - -/** - Control4 Network Cluster states -*/ -typedef enum zb_zcl_control4_network_state_e -{ - ZB_ZCL_CONTROL4_NETWORK_STATE_IDLE, - ZB_ZCL_CONTROL4_NETWORK_STATE_SEARCHING_ZAP, - ZB_ZCL_CONTROL4_NETWORK_STATE_RUNNING, - ZB_ZCL_CONTROL4_NETWORK_STATE_STOPPED, -} zb_zcl_control4_network_state_t; - -/** - Control4 Zigbee Access Point (ZAP) discovery events -*/ -typedef enum zb_zcl_control4_zap_discover_event_e -{ - /** Information from ZAP (NODE ID and/or LONG_NODE_ID) received and is different from the - * current and default value. Bindings and/or reporting in the user application may require to be updated - */ - ZB_ZCL_CONTROL4_NETWORK_ZAP_UPDATED, - /** ZAP discovered failed after retrying ZB_ZCL_CONTROL4_NETWORK_SEARCHING_ZAP_ATTEMPTS times. - * User application may retry restart the Control4 network cluster or leave the network. - */ - ZB_ZCL_CONTROL4_NETWORK_ZAP_DISCOVER_FAILED, -} zb_zcl_control4_zap_discover_event_t; - -/** Control4 ZAP discover user app notification payload */ -typedef struct zb_zcl_control4_zap_info_notify_s -{ - /** Event for user application to handle*/ - zb_zcl_control4_zap_discover_event_t event; -} zb_zcl_control4_zap_info_notify_t; - -/** - Start Control4 Network Cluster -*/ -zb_ret_t zb_zcl_control4_network_cluster_start(void); - -/** - Stop Control4 Network Cluster -*/ -void zb_zcl_control4_network_cluster_stop(void); - -/** - Get Control4 Network Cluster state -*/ -zb_zcl_control4_network_state_t zb_zcl_control4_network_cluster_get_state(void); - -/** - Handle Read Attribute Response from Control4 Network Cluster -*/ -void zb_zcl_control4_network_cluster_read_attr_resp_handler(zb_bufid_t param); -/** @} */ /*Control4 Network cluster commands */ - -/*! @} */ /* ZCL Control4 Network cluster */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -/** - Control4 Network Cluster Initialization -*/ -void zb_zcl_control4_networking_init_server(void); -void zb_zcl_control4_networking_init_client(void); - -#define ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING_SERVER_ROLE_INIT zb_zcl_control4_networking_init_server -#define ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING_CLIENT_ROLE_INIT zb_zcl_control4_networking_init_client - -#endif /* ZB_ZCL_CONTROL4_NETWORKING_H */ diff --git a/zboss/development/include/zcl/zb_zcl_custom_cluster.h b/zboss/development/include/zcl/zb_zcl_custom_cluster.h deleted file mode 100644 index 38e33fab1b..0000000000 --- a/zboss/development/include/zcl/zb_zcl_custom_cluster.h +++ /dev/null @@ -1,501 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Time cluster definitions -*/ - -#ifndef ZB_ZCL_CUSTOM_ATTR_H -#define ZB_ZCL_CUSTOM_ATTR_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond (DOXYGEN_HA_SECTION && internals_doc) */ - -/** @addtogroup zcl_api - * @{ - */ - -#define ZB_ZCL_CLUSTER_ID_CUSTOM 0x1A0A -#define ZB_CUSTOM_DEVICE_ID 0x29A -#define ZB_CUSTOM_DEVICE_VERSION 6 - -/*! @name Custom Attributes cluster attributes - @{ -*/ - -/*! @brief Custom Attributes attribute identifiers - @see ZCL spec, subclause 3.12.2.2 -*/ -enum zb_zcl_custom_cluster_attr_e -{ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_U8_ID = 0x0001, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_S16_ID = 0x0002, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_24BIT_ID = 0x0003, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_32BITMAP_ID = 0x0004, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_IEEE_ID = 0x0005, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_CHAR_STRING_ID = 0x0006, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_UTC_TIME_ID = 0x0007, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_OCTET_STRING_ID = 0x0008, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_BOOL_ID = 0x0009, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_128_BIT_KEY_ID = 0x000a, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_U16_ID = 0x000b, - ZB_ZCL_CUSTOM_CLUSTER_ATTR_U32_ID = 0x000c -}; - -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_U8_DEFAULT_VALUE 0 -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_S16_DEFAULT_VALUE 0 -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_24BIT_DEFAULT_VALUE { 0 } -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_32BITMAP_DEFAULT_VALUE 0 -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_IEEE_DEFAULT_VALUE { 0 } -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_CHAR_STRING_DEFAULT_VALUE { 0 } -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_UTC_TIME_DEFAULT_VALUE 0 -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_BYTE_ARRAY_DEFAULT_VALUE { 0 } -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_BOOL_DEFAULT_VALUE ZB_FALSE -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_128_BIT_KEY_DEFAULT_VALUE { 0 } - -/** @brief Default value for Custom cluster revision global attribute */ -#define ZB_ZCL_CUSTOM_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/*! @brief Max size of char string attribute (with length byte) */ -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_CHAR_STRING_MAX_SIZE 11 - -/*! @brief Max size of byte array attribute (with length bytes) */ -#define ZB_ZCL_CUSTOM_CLUSTER_ATTR_BYTE_ARRAY_MAX_SIZE 66 - -/*! @} */ /* Custom Attributes cluster attributes */ - -/*! @name Custom Attributes commands - @{ -*/ - -/*! @brief Custom cluster commands identifiers */ -enum zb_zcl_custom_cluster_cmd_e -{ - ZB_ZCL_CUSTOM_CLUSTER_CMD1_ID = 0x21, - ZB_ZCL_CUSTOM_CLUSTER_CMD2_ID = 0x22, - ZB_ZCL_CUSTOM_CLUSTER_CMD3_ID = 0x23 -}; - -/*! @brief Custom cluster responses identifiers */ -enum zb_zcl_custom_cluster_resp_e -{ - ZB_ZCL_CUSTOM_CLUSTER_CMD1_RESP_ID = 0xF1, - ZB_ZCL_CUSTOM_CLUSTER_CMD2_RESP_ID = 0xF2 -}; - -/******** Custom cluster command 1 ********/ - -enum zb_zcl_custom_cluster_cmd1_mode_e -{ - ZB_ZCL_CUSTOM_CLUSTER_CMD1_MODE1 = 0x01, - ZB_ZCL_CUSTOM_CLUSTER_CMD1_MODE2 = 0x02 -}; - -typedef ZB_PACKED_PRE struct zb_zcl_custom_cluster_cmd1_req_s -{ - zb_uint8_t mode; - zb_uint8_t value; -} -ZB_PACKED_STRUCT zb_zcl_custom_cluster_cmd1_req_t; - -#define ZB_ZCL_CUSTOM_CLUSTER_GET_CMD1_REQ(buf, req, parse_status) \ -{ \ - zb_zcl_custom_cluster_cmd1_req_t *req_ptr = \ - zb_buf_len(buf) >= sizeof(zb_zcl_custom_cluster_cmd1_req_t) ? \ - (zb_zcl_custom_cluster_cmd1_req_t*)zb_buf_begin(buf) : NULL; \ - parse_status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, sizeof(zb_zcl_custom_cluster_cmd1_req_t)); \ - parse_status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/*! @brief Send Custom cluster command 1 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param mode - mode value (@see zb_zcl_custom_cluster_cmd1_mode_t) - @param value - some value -*/ -#define ZB_ZCL_CUSTOM_CLUSTER_SEND_CMD1_REQ( \ - buffer, dst_addr, dst_addr_mode, dst_ep, \ - src_ep, def_resp, cb, mode, value) \ -{ \ - zb_uint8_t *ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CUSTOM_CLUSTER_CMD1_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (mode)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (value)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (buffer), (dst_addr), (dst_addr_mode), (dst_ep), (src_ep), \ - ZB_AF_HA_PROFILE_ID, ZB_ZCL_CLUSTER_ID_CUSTOM, (cb)); \ -} - -/******** Custom cluster Response to command 1 ********/ - -typedef ZB_PACKED_PRE struct zb_zcl_custom_cluster_cmd1_resp_s -{ - zb_uint8_t status; -} -ZB_PACKED_STRUCT zb_zcl_custom_cluster_cmd1_resp_t; - -#define ZB_ZCL_CUSTOM_CLUSTER_GET_CMD1_RESP(buf, resp, parse_status) \ -{ \ - zb_zcl_custom_cluster_cmd1_resp_t *resp_ptr = \ - zb_buf_len(buf) >= sizeof(zb_zcl_custom_cluster_cmd1_resp_t) ? \ - (zb_zcl_custom_cluster_cmd1_resp_t*)zb_buf_begin(buf) : NULL; \ - parse_status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - if (resp_ptr) \ - { \ - ZB_MEMCPY(&(resp), resp_ptr, sizeof(zb_zcl_custom_cluster_cmd1_resp_t)); \ - parse_status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/*! @brief Send Custom cluster response to command 1 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param status - status value - */ -#define ZB_ZCL_CUSTOM_CLUSTER_SEND_CMD1_RESP( \ - buffer, seq, dst_addr, dst_addr_mode, \ - dst_ep, src_ep, cb, status) \ -{ \ - zb_uint8_t *cmd_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(cmd_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - cmd_ptr, (seq), ZB_ZCL_CUSTOM_CLUSTER_CMD1_RESP_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (status)); \ - ZB_ZCL_FINISH_PACKET((buffer), cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (buffer), (dst_addr), (dst_addr_mode), (dst_ep), (src_ep), \ - ZB_AF_HA_PROFILE_ID, ZB_ZCL_CLUSTER_ID_CUSTOM, (cb)); \ -} - -/******** Custom cluster command 2 ********/ - -enum zb_zcl_custom_cluster_cmd2_param_e -{ - ZB_ZCL_CUSTOM_CLUSTER_CMD2_PARAM1 = 0x01, - ZB_ZCL_CUSTOM_CLUSTER_CMD2_PARAM2 = 0x02, - ZB_ZCL_CUSTOM_CLUSTER_CMD2_PARAM3 = 0x03, - ZB_ZCL_CUSTOM_CLUSTER_CMD2_PARAM4 = 0x04 -}; - -typedef ZB_PACKED_PRE struct zb_zcl_custom_cluster_cmd2_req_s -{ - zb_uint8_t param; - zb_uint16_t value; -} -ZB_PACKED_STRUCT zb_zcl_custom_cluster_cmd2_req_t; - -#define ZB_ZCL_CUSTOM_CLUSTER_GET_CMD2_REQ(buf, req, parse_status) \ -{ \ - zb_zcl_custom_cluster_cmd2_req_t *req_ptr = \ - zb_buf_len(buf) >= sizeof(zb_zcl_custom_cluster_cmd2_req_t) ? \ - (zb_zcl_custom_cluster_cmd2_req_t*)zb_buf_begin(buf) : NULL; \ - parse_status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, sizeof(zb_zcl_custom_cluster_cmd2_req_t)); \ - if (req_ptr->value < 0xFFFF) \ - { \ - parse_status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - } \ -} - -/*! @brief Send Custom cluster command 2 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param param - some parameter - @param value - some value - */ -#define ZB_ZCL_CUSTOM_CLUSTER_SEND_CMD2_REQ( \ - buffer, dst_addr, dst_addr_mode, dst_ep, \ - src_ep, def_resp, cb, param, value) \ -{ \ - zb_uint8_t *ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CUSTOM_CLUSTER_CMD2_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (param)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (value)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (buffer), (dst_addr), (dst_addr_mode), (dst_ep), (src_ep), \ - ZB_AF_HA_PROFILE_ID, ZB_ZCL_CLUSTER_ID_CUSTOM, (cb)); \ -} - -/******** Custom cluster Response to command 2 ********/ - -typedef ZB_PACKED_PRE struct zb_zcl_custom_cluster_cmd2_resp_s -{ - zb_uint8_t status; -} -ZB_PACKED_STRUCT zb_zcl_custom_cluster_cmd2_resp_t; - -#define ZB_ZCL_CUSTOM_CLUSTER_GET_CMD2_RESP(buf, resp, status) \ -{ \ - zb_zcl_custom_cluster_cmd2_resp_t *resp_ptr = \ - zb_buf_len(buf) >= sizeof(zb_zcl_custom_cluster_cmd2_resp_t) ? \ - (zb_zcl_custom_cluster_cmd2_resp_t*)zb_buf_begin(buf) : NULL; \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - if (resp_ptr) \ - { \ - ZB_MEMCPY(&(resp), resp_ptr, sizeof(zb_zcl_custom_cluster_cmd2_resp_t)); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/*! @brief Send Custom cluster response to command 2 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param status - status value - */ -#define ZB_ZCL_CUSTOM_CLUSTER_SEND_CMD2_RESP( \ - buffer, seq, dst_addr, dst_addr_mode, \ - dst_ep, src_ep, cb, status) \ -{ \ - zb_uint8_t *cmd_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(cmd_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - cmd_ptr, seq, ZB_ZCL_CUSTOM_CLUSTER_CMD2_RESP_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (status)); \ - ZB_ZCL_FINISH_PACKET((buffer), cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (buffer), (dst_addr), (dst_addr_mode), (dst_ep), (src_ep), \ - ZB_AF_HA_PROFILE_ID, ZB_ZCL_CLUSTER_ID_CUSTOM, (cb)); \ -} - -/******** Custom cluster command 3 ********/ - -typedef ZB_PACKED_PRE struct zb_zcl_custom_cluster_cmd3_req_s -{ - zb_char_t zcl_str[ZB_ZCL_CUSTOM_CLUSTER_ATTR_CHAR_STRING_MAX_SIZE]; -} -ZB_PACKED_STRUCT zb_zcl_custom_cluster_cmd3_req_t; - -#define ZB_ZCL_CUSTOM_CLUSTER_GET_CMD3_REQ(buf, req, parse_status) \ -{ \ - zb_uint8_t zcl_str_len = *((zb_uint8_t*)zb_buf_begin(buf)); \ - parse_status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - if (((zb_uint_t)(zcl_str_len + 1)) == zb_buf_len(buf)) \ - { \ - ZB_MEMCPY(&(req), zb_buf_begin(buf), zcl_str_len + 1); \ - parse_status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/*! @brief Send Custom cluster command 3 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param zcl_str_ptr - pointer to ZCL string -*/ -#define ZB_ZCL_CUSTOM_CLUSTER_SEND_CMD3_REQ( \ - buffer, dst_addr, dst_addr_mode, dst_ep, \ - src_ep, def_resp, cb, zcl_str_ptr) \ -{ \ - zb_uint8_t *ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CUSTOM_CLUSTER_CMD3_ID); \ - ZB_ZCL_PACKET_PUT_STRING(ptr, (zcl_str_ptr)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (buffer), (dst_addr), (dst_addr_mode), (dst_ep), (src_ep), \ - ZB_AF_HA_PROFILE_ID, ZB_ZCL_CLUSTER_ID_CUSTOM, (cb)); \ -} - -/*! @} */ /* Custom Attributes commands */ - -/*! @internal @name Custom Attributes internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_CUSTOM_CLUSTER_ATTR_U8_ID(data_ptr) \ -{ \ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_U8_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_CUSTOM_CLUSTER_ATTR_S16_ID(data_ptr) \ -{ \ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_S16_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_WRITE_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_CUSTOM_CLUSTER_ATTR_24BIT_ID(data_ptr) \ -{ \ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_24BIT_ID, \ - ZB_ZCL_ATTR_TYPE_24BIT, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_CUSTOM_CLUSTER_ATTR_32BITMAP_ID(data_ptr) \ -{ \ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_32BITMAP_ID, \ - ZB_ZCL_ATTR_TYPE_32BITMAP, \ - ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_CUSTOM_CLUSTER_ATTR_IEEE_ID(data_ptr) \ -{ \ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_IEEE_ID, \ - ZB_ZCL_ATTR_TYPE_IEEE_ADDR, \ - ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL | ZB_ZCL_ATTR_ACCESS_WRITE_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_CUSTOM_CLUSTER_ATTR_CHAR_STRING_ID(data_ptr) \ -{ \ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_CHAR_STRING_ID, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_CUSTOM_CLUSTER_ATTR_UTC_TIME_ID(data_ptr) \ -{ \ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_UTC_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_CUSTOM_CLUSTER_ATTR_OCTET_STRING_ID(data_ptr) \ -{ \ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_OCTET_STRING_ID, \ - ZB_ZCL_ATTR_TYPE_OCTET_STRING, \ - ZB_ZCL_ATTR_ACCESS_WRITE_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_CUSTOM_CLUSTER_ATTR_BOOL_ID(data_ptr) \ -{ \ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_BOOL_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_CUSTOM_CLUSTER_ATTR_128_BIT_KEY_ID(data_ptr) \ -{ \ - ZB_ZCL_CUSTOM_CLUSTER_ATTR_128_BIT_KEY_ID, \ - ZB_ZCL_ATTR_TYPE_128_BIT_KEY, \ - ZB_ZCL_ATTR_MANUF_SPEC, \ - (void*) data_ptr \ -} - -/** @internal @brief Declare attribute list for Custom Attributes cluster -*/ - -#define ZB_ZCL_DECLARE_CUSTOM_ATTR_CLUSTER_ATTRIB_LIST( \ - attr_list, u8_attr, s16_attr, _24bit_attr, _32bitmap_attr, ieee_attr, \ - char_string_attr, utc_time_attr, octet_string_attr, bool_attr, _128_bit_key_attr) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_CUSTOM) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_CUSTOM_CLUSTER_ATTR_U8_ID, (u8_attr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_CUSTOM_CLUSTER_ATTR_S16_ID, (s16_attr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_CUSTOM_CLUSTER_ATTR_24BIT_ID, (_24bit_attr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_CUSTOM_CLUSTER_ATTR_32BITMAP_ID, (_32bitmap_attr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_CUSTOM_CLUSTER_ATTR_IEEE_ID, (ieee_attr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_CUSTOM_CLUSTER_ATTR_CHAR_STRING_ID, (char_string_attr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_CUSTOM_CLUSTER_ATTR_UTC_TIME_ID, (utc_time_attr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_CUSTOM_CLUSTER_ATTR_OCTET_STRING_ID, (octet_string_attr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_CUSTOM_CLUSTER_ATTR_BOOL_ID, (bool_attr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_CUSTOM_CLUSTER_ATTR_128_BIT_KEY_ID, (_128_bit_key_attr)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @internal Number of attributes mandatory for reporting in Custom Attributes cluster */ -#define ZB_ZCL_CUSTOM_ATTR_REPORT_ATTR_COUNT 8 - -/*! @} */ /* Custom Attributes cluster internals */ - -/*! @} */ /* ZCL Custom Attributes cluster definitions */ - -/** @endcond */ /* (DOXYGEN_ZCL_SECTION && internals_doc) */ - -void zb_zcl_custom_attr_init_server(void); -void zb_zcl_custom_attr_init_client(void); -#define ZB_ZCL_CLUSTER_ID_CUSTOM_SERVER_ROLE_INIT zb_zcl_custom_attr_init_server -#define ZB_ZCL_CLUSTER_ID_CUSTOM_CLIENT_ROLE_INIT zb_zcl_custom_attr_init_client - -#endif /* ZB_ZCL_CUSTOM_ATTR_H */ diff --git a/zboss/development/include/zcl/zb_zcl_cvc_commands.h b/zboss/development/include/zcl/zb_zcl_cvc_commands.h deleted file mode 100644 index 73bb00144d..0000000000 --- a/zboss/development/include/zcl/zb_zcl_cvc_commands.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Continuous Value Change feature commands declarations -*/ - -#ifndef ZCL_CVC_COMMANDS_H -#define ZCL_CVC_COMMANDS_H 1 - -#if defined ZB_CVC_FEATURE_SUPPORT - -/** @cond DOXYGEN_ZCL_SECTION */ - -/* Documentation - doc/HA/continuous_value_change-detailed_design.doc */ - -/* Internal variables, - see 1.7.4 */ - -/** @brief CVC Transition Time As Fast As Able */ -#define ZB_ZCL_CVC_TRANSITION_TIME_AS_FAST_AS_ABLE 0xffff -/** @brief CVC Transition Time minimal */ -#define ZB_ZCL_CVC_TRANSITION_TIME_MINIMAL 0x0001 -/** @brief CVC Transition Time error (in time units) */ -#define ZB_ZCL_CVC_TRANSITION_TIME_ERROR_TU 1 -/** @brief CVC Transition Time Unit (in msec) */ -#define ZB_ZCL_CVC_TRANSITION_TIME_UNIT_MS 100 -/** @brief CVC Transition Time Unit (in beacon intervals) */ -#define ZB_ZCL_CVC_TRANSITION_TIME_UNIT_BE ZB_TIME_ONE_SECOND / 10 -/** @brief CVC Invalid Remaining Time */ -#define ZB_ZCL_CVC_INVALID_REMAINING_TIME 0xffff -/** @brief CVC Invalid Alarm Id */ -#define ZB_ZCL_CVC_INVALID_ALARM_ID (zb_uint8_t)-1 -/** @brief CVC Transition Timer Quant (in msec) */ -#define ZB_ZCL_CVC_TRANSITION_TIMER_QUANT_MS 16 -/** @brief CVC Transition Timer Quant */ -#define ZB_ZCL_CVC_TRANSITION_TIMER_QUANT_TO_BE(quant) \ - ZB_MILLISECONDS_TO_BEACON_INTERVAL((quant) * ZB_ZCL_CVC_TRANSITION_TIMER_QUANT_MS) -/** @brief CVC alarm quants in a single CVC Transition Time Unit */ -#define ZB_ZCL_CVC_TRANSITION_TIME_UNIT_IN_QUANTS \ - (ZB_ZCL_CVC_TRANSITION_TIME_UNIT_MS / ZB_ZCL_CVC_TRANSITION_TIMER_QUANT_MS) - -#define ZB_ZCL_UNDEFINED_CVC_SLOT 0xff -#define ZB_ZCL_MAX_CVC_SLOTS_BY_EP (ZB_ZCL_UNDEFINED_CVC_SLOT / ZB_ZCL_MAX_EP_NUMBER) - -/** @brief Value set function that will be used for setting value on device */ -typedef zb_ret_t (ZB_CODE * zb_zcl_cvc_value_set_func_t)(zb_uint8_t endpoint, zb_uint16_t* new_value, zb_uint16_t remaining_time); - - -/** @internal Structure of Input variables - */ -typedef struct zb_zcl_cvc_input_variables_s -{ -/** @brief Current Value */ - zb_uint16_t current_value16; -/** @brief End Value */ - zb_uint16_t end_value16; -/** @brief Min Value */ - zb_uint16_t min_value16; -/** @brief Max Value */ - zb_uint16_t max_value16; -/** @brief Overlapping flag */ - zb_uint8_t overlap; -/** @brief Transition Time */ - zb_uint16_t transition_time; -/** @brief Value set function */ - zb_zcl_cvc_value_set_func_t value_set_func; -/** @brief Buffer id for after_processing_cb */ - zb_uint8_t buf_id; -/** @brief After Processing callback */ - zb_callback_t after_processing_cb; -} zb_zcl_cvc_input_variables_t; - -/** @internal Structure of Continuous Value Change variables - */ -typedef struct zb_zcl_cvc_variables_s -{ -/** @brief Input variables */ - zb_zcl_cvc_input_variables_t input_var; -/** @brief Time to next scheduled operation (delta time) */ - zb_uint16_t delta_time_q; -/** @brief Delta value for one step */ - zb_int16_t delta_value16; -/** @brief Number of remaining steps for transition */ - zb_uint16_t steps_number; -/** @brief Transition Time remainder */ - zb_uint16_t transition_time_q; -/** @brief End time of transition */ - zb_time_t end_time_tu; -} zb_zcl_cvc_variables_t; - -/** @internal Structure of Alarm variables - */ -typedef struct zb_zcl_cvc_alarm_variables_s -{ -/** @brief Endpoint id */ - zb_uint8_t endpoint_id; -/** @brief Cluster id */ - zb_uint16_t cluster_id; -/** @brief Attribute id */ - zb_uint16_t attribute_id; -/** @brief Alarm buffer id */ - zb_uint8_t alarm_buf_id; -/** @brief Is Used flag */ - zb_bool_t is_used; -} ZB_PACKED_STRUCT -zb_zcl_cvc_alarm_variables_t; - -/*! - @brief Calculate transition values and put it into buffer. - @param input_var - pointer to zb_zcl_cvc_input_variables_s containing input data - @return buffer ID with zb_zcl_cvc_variables_s -*/ -zb_uint8_t zb_zcl_cvc_calculate_transition_values(zb_zcl_cvc_input_variables_t* input_var); - - -/*! - @brief Initialize and start transition. - @param endpoint_id - ep id - @param cluster_id - cluster id - @param attribute_id - attribute id (from cluster) - @param alarm_buf_id - buffer_id with zb_zcl_cvc_variables_s - @return alarm ID -*/ -zb_uint8_t zb_zcl_cvc_start_alarm(zb_uint8_t endpoint_id, - zb_uint16_t cluster_id, - zb_uint16_t attribute_id, - zb_uint8_t alarm_buf_id); - - -/*! - @brief Initialize and start transition. - @param alarm_id - alarm id - @return old transition's buffer (input_var.buf_id) -*/ -zb_uint8_t zb_zcl_cvc_stop_transition(zb_uint8_t alarm_id); - - -/*! - @brief Check transition running. - @param endpoint_id - ep id - @param cluster_id - cluster id - @param attribute_id - attribute id (from cluster) - @return alarm ID (ZB_ZCL_CVC_INVALID_ALARM_ID if it is not running) -*/ -zb_uint8_t zb_zcl_cvc_check_transition_running( - zb_uint8_t endpoint_id, - zb_uint16_t cluster_id, - zb_uint16_t attribute_id); - - -/*! @brief Initialize alarm list (stored in device context). */ -void zb_zcl_init_cvc_alarm_info(void); - - -/*! - @brief Get remaining time of transition. - @param alarm_id - alarm id - @return remaining time -*/ -zb_uint16_t zb_zcl_cvc_get_remaining_time(zb_uint8_t alarm_id); - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#endif /* ZB_CVC_FEATURE_SUPPORT */ - -#endif /* ZCL_LEVEL_CVC_COMMANDS_H */ diff --git a/zboss/development/include/zcl/zb_zcl_daily_schedule.h b/zboss/development/include/zcl/zb_zcl_daily_schedule.h deleted file mode 100644 index e8f20382a1..0000000000 --- a/zboss/development/include/zcl/zb_zcl_daily_schedule.h +++ /dev/null @@ -1,761 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Daily Schedule cluster definitions -*/ - -#ifndef ZB_ZCL_DAILY_SCHEDULE_H_ -#define ZB_ZCL_DAILY_SCHEDULE_H_ -/******************************************************************************/ -/******************************************************************************/ -#include "zboss_api_core.h" -#include "zboss_api_aps.h" -#include "zb_zcl_common.h" - -/** @cond (DOXYGEN_ZCL_SECTION && DOXYGEN_DAILY_SCHEDULE_CLUSTER) */ - -/** @addtogroup ZB_ZCL_DAILY_SCHEDULE - * @{ - * @details - * The Daily Schedule cluster allows information that can be scheduled for an entire day - * to be transferred within the premises. The information is distributed by an ESI - * or similar server device. - */ - -/* Cluster ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE */ - -/** @defgroup ZB_ZCL_DAILY_SCHEDULE_ATTRS Daily Schedule cluster attributes - * @{ - */ - - -/** The attributes defined in this cluster are arranged into sets of related attributes; - * each set can contain up to 256 attributes. Attribute identifiers are encoded - * such that the most significant Octet specifies the attribute set and the least - * significant Octet specifies the attribute within the set. - * @see Zigbee-17-05035-004 Table D-3 - */ -typedef enum zb_zcl_daily_schedule_srv_attr_sets_e -{ - ZB_ZCL_DAILY_SCHEDULE_AUXILIARY_SWITCH_LABEL_SET = 0x00, /**< Auxiliary Switch Label - Attribute Set */ - - ZB_ZCL_DAILY_SCHEDULE_SCHEDULE_ATTRIBUTES_SET = 0x01, /**< Schedule Attribute Set */ - - /* 0x02-0xFF – reserved */ -} zb_zcl_daily_schedule_srv_attr_sets_t; - - -/** @see Zigbee-17-05035-004 Table D-4 – Auxiliary Switch Label Attribute Set */ -typedef enum zb_zcl_daily_schedule_srv_auxiliary_switch_attr_set_e -{ - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_AUX_SWITCH_1_LABEL = 0x0000, /**< The @e AuxSwitchNLabel attributes provide - a method for assigning a label to - * an Auxiliary Switch. - */ - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_AUX_SWITCH_2_LABEL, - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_AUX_SWITCH_3_LABEL, - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_AUX_SWITCH_4_LABEL, - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_AUX_SWITCH_5_LABEL, - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_AUX_SWITCH_6_LABEL, - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_AUX_SWITCH_7_LABEL, - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_AUX_SWITCH_8_LABEL -} zb_zcl_daily_schedule_srv_auxiliary_switch_attr_set_t; - - -/** @see Zigbee-17-05035-004 Table D-5 – Schedule Attribute Set */ -typedef enum zb_zcl_daily_schedule_srv_schedule_attr_set_e -{ - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_CURR_AUX_LOAD_SWITCH_STATE = 0x0100, /**< The @e - CurrentAuxiliaryLoadSwitchState - attribute */ - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_CURR_DELIVERED_TIER = 0x0101, /**< The @e CurrentDeliveredTier - attribute */ - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_CURR_TIER_LABEL = 0x0102, /**< The @e CurrentTierLabel attribute*/ - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_LINKY_PEAK_PERIOD_STATUS = 0x0103, /**< The @e LinkyPeakPeriodStatus - attribute */ - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_PEAK_START_TIME = 0x0104, /**< The @e PeakStartTime attribute */ - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_PEAK_END_TIME = 0x0105, /**< The @e PeakEndTime attribute */ - /* (O) */ - ZB_ZCL_ATTR_DAILY_SCHEDULE_CURR_TARIFF_LABEL = 0x0106, /**< The @e CurrentTariffLabel attribute */ -} zb_zcl_daily_schedule_srv_schedule_attr_set_t; - - -/** The @e LinkyPeakPeriodStatus attribute subfields */ -typedef ZB_PACKED_PRE struct zb_zcl_daily_schedule_attr_linky_peak_period_status_s -{ - zb_bitfield_t on_peak:2; - zb_bitfield_t peak_period_prior_notice:2; - zb_bitfield_t next_day_color:2; - zb_bitfield_t current_day_color:2; -} zb_zcl_daily_schedule_attr_linky_peak_period_status_t; - -/** @brief Default value for Daily Schedule cluster revision global attribute (not defined anywhere) */ -#define ZB_ZCL_DAILY_SCHEDULE_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/*! - @brief Declare attribute list for Daily Schedule cluster (only cluster revision attribute) - @param attr_list - attribute list name -*/ -#define ZB_ZCL_DECLARE_DAILY_SCHEDULE_ATTR_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_DAILY_SCHEDULE) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/* Constants for Current Day Color and Next Day Color subfields */ -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_COLOR_UNUSED 0b00 -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_COLOR_LOW_BLUE 0b01 -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_COLOR_MEDIUM_WHITE 0b10 -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_COLOR_HIGH_RED 0b11 - -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_PRIOR_NOTICE_NONE 0b00 -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_PRIOR_NOTICE_PP1 0b01 -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_PRIOR_NOTICE_PP2 0b10 -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_PRIOR_NOTICE_PP3 0b11 - -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_ON_PEAK_NONE 0b00 -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_ON_PEAK_PERIOD_1 0b01 -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_ON_PEAK_PERIOD_2 0b10 -#define ZB_ZCL_ATTR_LINKY_PEAK_PERIOD_STATUS_ON_PEAK_PERIOD_3 0b11 - -/** @} */ /* ZB_ZCL_DAILY_SCHEDULE_ATTRS */ - - -/** @defgroup ZB_ZCL_DAILY_SCHEDULE_COMMANDS Daily Schedule cluster commands - * @{ - */ - -/** Daily Schedule cluster client command identifiers. - * @see Zigbee-17-05035-004 Table D-14 Commands Received by the Daily Schedule Cluster Server - */ -typedef enum zb_zcl_daily_schedule_cli_cmd_e -{ - /* (O) */ - ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE = 0x00, /**< This command initiates - PublishSchedule command(s) for - specified Schedule updates. */ - /* (O) */ - ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_DAY_PROFILE = 0x01, /**< This command initiates one or more - PublishDayProfile commands for the - referenced Schedule. */ - /* (O) */ - ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE_CANCELLATION = 0x05, /**< This command initiates - the return of the last - CancelSchedule command held - on the associated server. */ -} zb_zcl_daily_schedule_cli_cmd_t; - - -/** @see Zigbee-17-05035-004 Table D-3 Daily Schedule Cluster Attribute Sets */ -typedef enum zb_zcl_daily_schedule_srv_cmd_e -{ - /* (O) */ - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_SCHEDULE = 0x00, /**< The PublishSchedule command is - published in response to a GetSchedule - command or if new schedule information - is available. */ - /* (O) */ - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_DAY_PROFILE = 0x01, /**< The PublishDayProfile command is - published in response to - a GetDayProfile command. */ - /* (O) */ - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_SCHEDULE = 0x05, /**< The CancelSchedule command indicates - that all data associated with - a particular schedule instance - should be discarded. */ - /* (O) */ - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_ALL_SCHEDULES = 0x06, /**< The CancelAllSchedules command indicates - that all data associated with - all schedules should be discarded. */ -} zb_zcl_daily_schedule_srv_cmd_t; - -/* Daily schedule cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_SCHEDULE, \ - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_DAY_PROFILE, \ - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_SCHEDULE, \ - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_ALL_SCHEDULES - -#define ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE, \ - ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_DAY_PROFILE, \ - ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE_CANCELLATION - -#define ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_CLIENT_ROLE_GENERATED_CMD_LIST - - -/** Schedule type enumeration. - * @see Zigbee-17-05035-004 Table D-12 Schedule Type Enumeration - */ -typedef enum zb_zcl_daily_schedule_type_e -{ - ZB_ZCL_DAILY_SCHEDULE_TYPE_LINKY_SCHEDULE = 0x00, /**< Linky Schedule */ - /* reserved 0x01 - 0xFF */ -} zb_zcl_daily_schedule_type_t; - - -/** Check if schedule type is valid - * @param _t - @ref zb_zcl_daily_schedule_get_schedule_payload_t::schedule_type field - * @see @ref zb_zcl_daily_schedule_get_schedule_payload_t - */ -#define ZB_ZCL_DAILY_SCHEDULE_TYPE_IS_VALID(_t) \ - (_t <= ZB_ZCL_DAILY_SCHEDULE_TYPE_LINKY_SCHEDULE) - - -/** @ref ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE "GetSchedule" command payload - * @see Zigbee-17-05035-004, D.9.2.4.1.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_daily_schedule_get_schedule_payload_s -{ - /** An unsigned 32-bit field containing a unique identifier for the commodity provider. - * This field allows differentiation in deregulated markets where multiple commodity - * providers may be available. - */ - zb_uint32_t provider_id; - - /** UTC Timestamp indicating the earliest start time of schedules to be - * returned by the corresponding PublishSchedule command. - */ - zb_uint32_t earliest_start_time; - - /** A 32-bit integer representing the minimum Issuer Event ID of schedules - * to be returned by the corresponding PublishSchedule command - */ - zb_uint32_t min_issuer_event_id; - - /** An 8-bit integer which represents the maximum number of PublishSchedule commands - * that the client is willing to receive in response to this command. - */ - zb_uint8_t number_of_schedules; - - /** An 8-bit enumeration identifying the type of the requested schedule. - * @see zb_zcl_daily_schedule_type_t - */ - zb_uint8_t schedule_type; -} ZB_PACKED_STRUCT zb_zcl_daily_schedule_get_schedule_payload_t; - - -/** Macro for initialization @ref ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE "GetSchedule" command payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_GET_SCHEDULE_PL_INIT \ - (zb_zcl_daily_schedule_get_schedule_payload_t) {0} - - -/** Macro for initialization @ref ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_DAY_PROFILE "GetDayProfile" command payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_GET_DAY_PROFILE_PL_INIT \ - (zb_zcl_daily_schedule_get_day_profile_payload_t) {0} - - -/** Check if @ref ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE "GetSchedule" command payload size is valid - * @param size - size of received data payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_GET_SCHEDULE_PL_SIZE_IS_VALID(size) \ - ((size >= sizeof(zb_zcl_daily_schedule_get_schedule_payload_t) ? ZB_TRUE : ZB_FALSE)) - - -/** Check if @ref ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_DAY_PROFILE "GetDayProfile" command payload size is valid - * @param size - size of received data payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_GET_DAY_PROFILE_PL_SIZE_IS_VALID(size) \ - ((size >= sizeof(zb_zcl_daily_schedule_get_day_profile_payload_t) ? ZB_TRUE : ZB_FALSE)) - - -/** This enumeration presents possible values of Schedule Time Reference field - * @see Zigbee-17-05035-004, Table D-13 – Schedule Time Reference Enumeration - */ -typedef enum zb_zcl_daily_schedule_time_reference_e -{ - ZB_ZCL_DAILY_SCHEDULE_TIME_REFERENCE_UTC_TIME = 0x00, /**< UTC time */ - ZB_ZCL_DAILY_SCHEDULE_TIME_REFERENCE_STANDARD_TIME, /**< Standard time */ - ZB_ZCL_DAILY_SCHEDULE_TIME_REFERENCE_LOCAL_TIME /**< Local time */ - /* 0x03 - 0xFF is reserved */ -} zb_zcl_daily_schedule_time_reference_t; - - -/** @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_SCHEDULE "PublishSchedule" command - * @see Zigbee-17-05035-004, subclause D.9.2.3.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_daily_schedule_publish_schedule_payload_s -{ - - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this - * field allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** Unique identifier generated by the commodity Supplier to identify a particular schedule. - */ - zb_uint32_t schedule_id; /* (M) */ - - /** Unique identifier generated by the commodity supplier. - */ - zb_uint16_t day_id; /* (M) */ - - /** A UTC Time field to denote the time at which the published schedule becomes - * valid. A start date/time of 0x00000000 shall indicate that the command - * should be executed immediately. - */ - zb_uint32_t start_time; /* (M) */ - - /** An 8-bit enumeration identifying the type of schedule published in this - * command. - * @see zb_zcl_daily_schedule_type_t - */ - zb_uint8_t schedule_type; /* (M) */ - - /** This field indicates how the Start Times contained in the schedule are to be interpreted. - * @see zb_zcl_daily_schedule_time_reference_t - */ - zb_uint8_t schedule_time_reference; /* (M) */ - - /** The ScheduleName provides a method for utilities to assign a name to a schedule. - */ - zb_uint8_t schedule_name[1 + 12]; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_daily_schedule_publish_schedule_payload_t; - - -/** Macro for initialization @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_SCHEDULE "PublishSchedule" command payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_PUBLISH_SCHEDULE_PL_INIT \ - (zb_zcl_daily_schedule_publish_schedule_payload_t) {0} - - -/** Macro for initialization @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_DAY_PROFILE "PublishDayProfile" command payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_PUBLISH_DAY_PROFILE_PL_INIT \ - (zb_zcl_daily_schedule_publish_day_profile_payload_t) {0} - - -/** Macro for initialization @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_SCHEDULE "CancelSchedule" command payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_CANCEL_SCHEDULE_PL_INIT \ - (zb_zcl_daily_schedule_cancel_schedule_payload_t) {0} - - -/** Compute expected size of received @ref zb_zcl_daily_schedule_publish_schedule_payload_t - * data payload - * @param pl - pointer to @ref zb_zcl_daily_schedule_publish_schedule_payload_t payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_PUBLISH_SCHEDULE_PL_EXPECTED_SIZE(pl) \ - (sizeof(zb_zcl_daily_schedule_publish_schedule_payload_t)-sizeof((pl)->schedule_name)+1+ZB_ZCL_GET_STRING_LENGTH((pl)->schedule_name)) - - -/** Check if @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_SCHEDULE "PublishSchedule" command payload size is valid - * @param pl - pointer to @ref zb_zcl_daily_schedule_publish_schedule_payload_t payload (pointer - * to buffer beginning that contains @ref zb_zcl_daily_schedule_publish_schedule_payload_t data payload) - * @param size - size of received data payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_PUBLISH_SCHEDULE_PL_SIZE_IS_VALID(pl, size) \ - ((size >= ZB_ZCL_DAILY_SCHEDULE_PUBLISH_SCHEDULE_PL_EXPECTED_SIZE((zb_zcl_daily_schedule_publish_schedule_payload_t *)pl)) ? ZB_TRUE : ZB_FALSE) - - -/** Check if @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_DAY_PROFILE "PublishDayProfile" command payload size is valid - * @param size - size of received data payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_PUBLISH_DAY_PROFILE_PL_SIZE_IS_VALID(size) \ - ((size >= (sizeof(zb_zcl_daily_schedule_publish_day_profile_payload_t)-sizeof(void *)-sizeof(zb_uint8_t)) ? ZB_TRUE : ZB_FALSE)) - - -/** Check if @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_SCHEDULE "CancelSchedule" command payload size is valid - * @param size - size of received data payload - */ -#define ZB_ZCL_DAILY_SCHEDULE_CANCEL_SCHEDULE_PL_SIZE_IS_VALID(size) \ - ((size >= sizeof(zb_zcl_daily_schedule_cancel_schedule_payload_t) ? ZB_TRUE : ZB_FALSE)) - - -/** Linky Schedules Command Sub-Payload structure - * See Zigbee-17-05035-004, D.9.2.3.2.3.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_daily_schedule_linky_schedule_entry_s -{ - /** The Start Time is represented in minutes from midnight. - */ - zb_uint16_t start_time; /* (M) */ - - /** This is the current price tier that is valid until - * the start time of the next Schedule Entry. - */ - zb_uint8_t price_tier; /* (M) */ - - /** The required status of the auxiliary switches is indicated by the state of the bits. - * Bit0 correspond to Auxiliary Switch 1 and bit7 corresponds to Auxiliary Switch 8. - */ - zb_uint8_t auxiliary_load_switch_state; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_daily_schedule_linky_schedule_entry_t; - - -/** The format of schedule entry is dependent on schedule type. - */ -typedef ZB_PACKED_PRE union zb_zcl_daily_schedule_entry_u -{ - zb_zcl_daily_schedule_linky_schedule_entry_t linky_schedule_entry; -} ZB_PACKED_STRUCT zb_zcl_daily_schedule_entry_t; - - -/** @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_DAY_PROFILE "PublishDayProfile" command payload. - * @see Zigbee-17-05035-004, subclause D.9.2.3.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_daily_schedule_publish_day_profile_payload_s -{ - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this - * field allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** Unique identifier generated by the commodity supplier. The Day ID is used as a reference to assign a Day Profile to a Daily Schedule - */ - zb_uint16_t day_id; /* (M) */ - - /** Unique identifier generated by the commodity Supplier to identify a particular schedule. - */ - zb_uint32_t schedule_id; /* (M) */ - - /** An 8-bit integer representing the total number of ScheduleEntries in this Day Profile. - */ - zb_uint8_t total_number_of_schedule_entries; /* (M) */ - - /** The CommandIndex is used to count the payload fragments in the case where the entire payload - * does not fit into one message. The CommandIndex starts at 0 and is incremented for each fragment - * belonging to the same command - */ - zb_uint8_t command_index; /* (M) */ - - /** In the case where the entire payload does not fit into one message, the - * Total Number of Commands field indicates the total number of sub-commands - * in the message. - */ - zb_uint8_t total_number_of_commands; /* (M) */ - - /** An 8-bit enumeration identifying the type of schedule published in this - * command. - * @see zb_zcl_daily_schedule_type_t - */ - zb_uint8_t schedule_type; /* (M) */ - - /** - * day_schedule_entries pointer is considered as a beginning of array (of day schedule entries), - * number_of_entries_in_this_command - as a number of entries. Please also take into account - * overall ZCL payload size. - * @see zb_zcl_daily_schedule_entry_t - */ - zb_zcl_daily_schedule_entry_t *day_schedule_entries; /* (M) */ - - /** An 8-bit integer representing the number of Day Schedule entries in - * this command - */ - zb_uint8_t number_of_entries_in_this_command; /* (ZBOSS) */ -} ZB_PACKED_STRUCT zb_zcl_daily_schedule_publish_day_profile_payload_t; - - -/** @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_SCHEDULE "CancelSchedule" command payload. - * @see Zigbee-17-05035-004, D.9.2.3.3 - */ -typedef ZB_PACKED_PRE struct zb_zcl_daily_schedule_cancel_schedule_payload_s -{ - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity Supplier to identify a particular schedule. - */ - zb_uint32_t schedule_id; /* (M) */ - - /** An 8-bit enumeration identifying the type of schedule published in this - * command. - * @see zb_zcl_daily_schedule_type_t - */ - zb_uint8_t schedule_type; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_daily_schedule_cancel_schedule_payload_t; - - -/** @ref ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_DAY_PROFILE "GetDayProfile" command payload - * @see Zigbee-17-05035-004, D.9.2.4.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_daily_schedule_get_day_profile_payload_s -{ - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** - * ScheduleID of the schedule to which the requested Day Profile belongs. - */ - zb_uint16_t day_id; -} ZB_PACKED_STRUCT zb_zcl_daily_schedule_get_day_profile_payload_t; - - -/** Function for sending @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_SCHEDULE "PublishSchedule" command. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param pl - Packet payload (ref to @ref zb_zcl_daily_schedule_publish_schedule_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives - * APS ack. - */ -void zb_zcl_daily_schedule_send_cmd_publish_schedule(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_daily_schedule_publish_schedule_payload_t *pl, - zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_DAY_PROFILE "PublishDayProfile" command. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param pl - Packet payload (ref to @ref zb_zcl_daily_schedule_publish_day_profile_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives - * APS ack. - */ -void zb_zcl_daily_schedule_send_cmd_publish_day_profile(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_daily_schedule_publish_day_profile_payload_t *pl, - zb_callback_t cb -); - - -/** Function for sending @ref ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE "GetSchedule" command. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param pl - Packet payload (ref to @ref zb_zcl_daily_schedule_get_schedule_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives - * APS ack. - */ -void zb_zcl_daily_schedule_send_cmd_get_schedule(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_daily_schedule_get_schedule_payload_t *pl, - zb_callback_t cb -); - - -/** Function for sending @ref ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_DAY_PROFILE "GetDayProfile" command. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param pl - Packet payload (ref to @ref zb_zcl_daily_schedule_get_day_profile_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives - * APS ack. - */ -void zb_zcl_daily_schedule_send_cmd_get_day_profile(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_daily_schedule_get_day_profile_payload_t *pl, - zb_callback_t cb -); - -/** Function for send @ref ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE_CANCELLATION - * "GetScheduleCancellation" command. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param cb - Callback which should be called when the ZCL stack receives - * APS ack. - */ -void zb_zcl_daily_schedule_send_cmd_get_schedule_cancellation(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - zb_callback_t cb -); - - -/** Function for send @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_SCHEDULE "CancelSchedule" command. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param pl - Packet payload (ref to @ref zb_zcl_daily_schedule_cancel_schedule_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives - * APS ack. - */ -void zb_zcl_daily_schedule_send_cmd_cancel_schedule(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_daily_schedule_cancel_schedule_payload_t *pl, - zb_callback_t cb -); - -/** Function for send @ref ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_ALL_SCHEDULES "CancelAllSchedules" command. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param cb - Callback which should be called when the ZCL stack receives - * APS ack. - */ -void zb_zcl_daily_schedule_send_cmd_cancel_all_schedules(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - zb_callback_t cb -); - -/** Macro for calling @ref zb_zcl_daily_schedule_send_cmd_publish_schedule function - */ -#define ZB_ZCL_DAILY_SCHEDULE_SEND_CMD_PUBLISH_SCHEDULE(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload) \ - zb_zcl_daily_schedule_send_cmd_publish_schedule(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, NULL) - - -/** Macro for calling @ref zb_zcl_daily_schedule_send_cmd_publish_day_profile function - */ -#define ZB_ZCL_DAILY_SCHEDULE_SEND_CMD_PUBLISH_DAY_PROFILE(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload) \ - zb_zcl_daily_schedule_send_cmd_publish_day_profile(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, NULL) - - -/** Macro for call @ref zb_zcl_daily_schedule_send_cmd_cancel_schedule function - */ -#define ZB_ZCL_DAILY_SCHEDULE_SEND_CMD_CANCEL_SCHEDULE(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload) \ - zb_zcl_daily_schedule_send_cmd_cancel_schedule(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, NULL) - -/** Macro for call @ref zb_zcl_daily_schedule_send_cmd_cancel_all_schedules function - */ -#define ZB_ZCL_DAILY_SCHEDULE_SEND_CMD_CANCEL_ALL_SCHEDULES(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep) \ - zb_zcl_daily_schedule_send_cmd_cancel_all_schedules(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, NULL) - -/** Macro for call @ref zb_zcl_daily_schedule_send_cmd_get_schedule function - */ -#define ZB_ZCL_DAILY_SCHEDULE_SEND_CMD_GET_SCHEDULE(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload) \ - zb_zcl_daily_schedule_send_cmd_get_schedule(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, NULL) - - -/** Macro for call @ref zb_zcl_daily_schedule_send_cmd_get_day_profile function - */ -#define ZB_ZCL_DAILY_SCHEDULE_SEND_CMD_GET_DAY_PROFILE(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload) \ - zb_zcl_daily_schedule_send_cmd_get_day_profile(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, NULL) - - -/** Macro for call @ref zb_zcl_daily_schedule_send_cmd_get_schedule_cancellation function - */ -#define ZB_ZCL_DAILY_SCHEDULE_SEND_CMD_GET_SCHEDULE_CANCELLATION(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep) \ - zb_zcl_daily_schedule_send_cmd_get_schedule_cancellation(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, NULL) - -/** @} */ /* ZB_ZCL_DAILY_SCHEDULE_COMMANDS */ - -/** @brief Default value for CurrentAuxiliaryLoadSwitchState attribute */ -#define ZB_ZCL_DAILY_SCHEDULE_CURRENT_AUXILLARY_LOAD_SWITCH_STATE_DEFAULT_VALUE 0x00 - -/** @brief Default value for LinkyPeakPeriodStatus attribute */ -#define ZB_ZCL_DAILY_SCHEDULE_LINKY_PEAK_PERIOD_STATUS_DEFAULT_VALUE 0x00 - -/** @brief Default value for PeakStartTime attribute */ -#define ZB_ZCL_DAILY_SCHEDULE_PEAK_START_TIME_DEFAULT_VALUE ((zb_uint32_t)0xFFFFFFFF) - -/** @brief Default value for PeakEndTime attribute */ -#define ZB_ZCL_DAILY_SCHEDULE_PEAK_END_TIME_DEFAULT_VALUE ((zb_uint32_t)0xFFFFFFFF) - -/** @brief Default value for CurrentTariffLabel attribute */ -#define ZB_ZCL_DAILY_SCHEDULE_CURRENT_TARIFF_LABEL_DEFAULT_VALUE {0} -/** @} */ /* ZCL Daily Schedule cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -/******************************************************************************/ -/* Server */ -/******************************************************************************/ -/* Client */ -/******************************************************************************/ -/* Common */ - -/******************************************************************************/ - -void zb_zcl_daily_schedule_init_server(); -void zb_zcl_daily_schedule_init_client(); -#define ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_SERVER_ROLE_INIT zb_zcl_daily_schedule_init_server -#define ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_CLIENT_ROLE_INIT zb_zcl_daily_schedule_init_client - -/******************************************************************************/ -#endif /* ZB_ZCL_DAILY_SCHEDULE_H_ */ diff --git a/zboss/development/include/zcl/zb_zcl_dehumidification_control.h b/zboss/development/include/zcl/zb_zcl_dehumidification_control.h deleted file mode 100644 index 7335acdc90..0000000000 --- a/zboss/development/include/zcl/zb_zcl_dehumidification_control.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Dehumidification Control cluster definitions -*/ - -#ifndef ZB_ZCL_DEHUMIDIFICATION_CONTROL_H -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_DEHUMIDIFICATION - * @{ - */ - - -/* Cluster ZB_ZCL_CLUSTER_ID_DEHUMIDIFICATION_CONTROL */ - -/*! @name Dehumidification Control cluster attributes - @{ -*/ - -/*! @brief Dehumidification Control cluster attribute identifiers - @see ZCL spec, subclause 6.4.2.2 -*/ -enum zb_zcl_dehumidification_control_attr_e -{ - /** The RelativeHumidity attribute is an 8-bit value that represents the current - * relative humidity (in %) measured by a local or remote sensor. */ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_RELATIVE_HUMIDITY_ID = 0x0000, - /** @brief Dehumidification Cooling attribute */ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_COOLING_ID = 0x0001, - /** @brief RHDehumidification Setpoint attribute */ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_RHDEHUMIDIFICATION_SETPOINT_ID = 0x0010, - /** The RelativeHumidityMode attribute is an 8-bit value that specifies how - * the RelativeHumidity value is being updated. */ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_RELATIVE_HUMIDITY_MODE_ID = 0x0011, - /** The DehumidificationLockout attribute is an 8-bit value that specifies - * whether dehumidification is allowed or not. */ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_LOCKOUT_ID = 0x0012, - /** @brief Dehumidification Hysteresis attribute */ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_HYSTERESIS_ID = 0x0013, - /** @brief Dehumidification Max Cool attribute */ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_ID = 0x0014, - /** The RelativeHumidityDisplay attribute is an 8-bit value that specifies - * whether the RelativeHumidity value is displayed to the user or not. */ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_RELATIVE_HUMIDITY_DISPLAY_ID = 0x0015, -}; - -/** @brief Default value for Dehumidification Control cluster revision global attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/** @brief Min value for RHDehumidification Setpoint attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_RHDEHUMIDIFICATION_SETPOINT_MIN_VALUE 0x1e - -/** @brief Max value for RHDehumidification Setpoint attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_RHDEHUMIDIFICATION_SETPOINT_MAX_VALUE 0x64 - -/** @brief Default value for RHDehumidification Setpoint attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_RHDEHUMIDIFICATION_SETPOINT_DEFAULT_VALUE 0x32 - -/** @brief Default value for RelativeHumidityMode attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_RELATIVE_HUMIDITY_MODE_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for DehumidificationLockout attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_LOCKOUT_DEFAULT_VALUE ((zb_uint8_t)0x01) - -/** @brief Min value for Dehumidification Hysteresis attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_HYSTERESIS_MIN_VALUE 0x02 - -/** @brief Max value for Dehumidification Hysteresis attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_HYSTERESIS_MAX_VALUE 0x14 - -/** @brief Default value for Dehumidification Hysteresis attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_HYSTERESIS_DEFAULT_VALUE 0x02 - -/** @brief Min value for Dehumidification Max Cool attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_MIN_VALUE 0x14 - -/** @brief Max value for Dehumidification Max Cool attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_MAX_VALUE 0x64 - -/** @brief Default value for Dehumidification Max Cool attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_DEFAULT_VALUE 0x14 - -/** @brief Default value for RelativeHumidityDisplay attribute */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_RELATIVE_HUMIDITY_DISPLAY_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Declare attribute list for Dehumidification Control cluster - @param attr_list - attribute list name - @param dehumid_cooling - pointer to variable to store Dehumidification Cooling attribute value - @param dehumid_setpoint - pointer to variable to store Dehumidification Setpoint attribute value - @param dehumid_hysteresis - pointer to variable to store Dehumidification Hysteresis attribute value - @param dehumid_max_cool - pointer to variable to store Dehumidification Max Cool attribute value -*/ -#define ZB_ZCL_DECLARE_DEHUMIDIFICATION_CONTROL_ATTRIB_LIST(attr_list, dehumid_cooling, dehumid_setpoint, \ - dehumid_hysteresis, dehumid_max_cool) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_DEHUMIDIFICATION_CONTROL) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_COOLING_ID, (dehumid_cooling)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_RHDEHUMIDIFICATION_SETPOINT_ID, (dehumid_setpoint)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_HYSTERESIS_ID, (dehumid_hysteresis)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_ID, (dehumid_max_cool)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Dehumidification Control cluster attributes */ - -/*! @name Dehumidification Control cluster commands - @{ -*/ - -/*! @} */ /* Dehumidification Control cluster commands */ - -/** @cond internals_doc */ -/*! @internal @name Dehumidification Control cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_COOLING_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_COOLING_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_RHDEHUMIDIFICATION_SETPOINT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_RHDEHUMIDIFICATION_SETPOINT_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_HYSTERESIS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_HYSTERESIS_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in Dehumidification Control cluster */ -#define ZB_ZCL_DEHUMIDIFICATION_CONTROL_REPORT_ATTR_COUNT 1 - -/*! @} */ /* Dehumidification Control cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/*! @} */ /* ZCL HA Dehumidification Control cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_dehumidification_control_init_server(void); -void zb_zcl_dehumidification_control_init_client(void); -#define ZB_ZCL_CLUSTER_ID_DEHUMID_CONTROL_SERVER_ROLE_INIT zb_zcl_dehumidification_control_init_server -#define ZB_ZCL_CLUSTER_ID_DEHUMID_CONTROL_CLIENT_ROLE_INIT zb_zcl_dehumidification_control_init_client - -#endif /* ZB_ZCL_DEHUMID_CONTROL_H */ diff --git a/zboss/development/include/zcl/zb_zcl_diagnostics.h b/zboss/development/include/zcl/zb_zcl_diagnostics.h deleted file mode 100644 index b4dde97278..0000000000 --- a/zboss/development/include/zcl/zb_zcl_diagnostics.h +++ /dev/null @@ -1,668 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Diagnostics cluster definitions -*/ - -#ifndef ZB_ZCL_DIAGNOSTICS_H -#define ZB_ZCL_DIAGNOSTICS_H 1 - - -#if defined(ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS) || defined(DOXYGEN) - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_DIAGNOSTICS - * @{ - * @details - * ZCL Diagnostics cluster definitions - */ - -/* Cluster ZB_ZCL_CLUSTER_ID_DIAGNOSTICS */ - -/*! @name Diagnostics cluster attributes - @{ -*/ - -typedef ZB_PACKED_PRE struct zb_zcl_diagnostics_ctx_s -{ - zb_mac_diagnostic_info_t mac_data; - zdo_diagnostics_info_t zdo_data; - zb_callback_t sync_data_cb; - zb_uint8_t cb_param; -} -ZB_PACKED_STRUCT zb_zcl_diagnostics_ctx_t; - -extern zb_zcl_diagnostics_ctx_t diagnostics_ctx_zcl; - -/*! @brief Diagnostics cluster attribute identifiers - @see HA spec, Diagnostics Cluster 9.3.2.2.2 -*/ -enum zb_zcl_diagnostics_attr_e -{ - /** @brief number_of_resets, Zigbee Diagnostic Cluster spec 1.2.2.1.1 */ - ZB_ZCL_ATTR_DIAGNOSTICS_NUMBER_OF_RESETS_ID = 0x0000, - /** This attribute keeps track of the number of writes to persistent memory. - * HA spec 9.2.2.2.1.2 */ - ZB_ZCL_ATTR_DIAGNOSTICS_PERSISTENT_MEMORY_WRITES_ID = 0x0001, - /** @brief MacRxBcast, HA spec 9.2.2.2.2.1 */ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_RX_BCAST_ID = 0x0100, - /** @brief MacTxBcast, HA spec 9.2.2.2.2.2 */ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_BCAST_ID = 0x0101, - /** MacRxUcast Attribute A counter that is incremented each time the MAC - * layer receives a unicast. */ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_RX_UCAST_ID = 0x0102, - /** @brief MacTxUcast, HA spec 9.2.2.2.2.4 */ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_ID = 0x0103, - /** MacTxUcastRetry Attribute A counter that is incremented each time - * the MAC layer retries a unicast. */ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_RETRY_ID = 0x0104, - /** MacTxUcastFail Attribute A counter that is incremented each time - * the MAC layer fails to send a unicast. */ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_FAIL_ID = 0x0105, - /** APSRxBcast Attribute A counter that is incremented each time - * the APS layer receives a broadcast. */ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_RX_BCAST_ID = 0x0106, - /** @brief aps_tx_bcast, HA spec 9.3.2.2.2 (??) */ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_BCAST_ID = 0x0107, - /** APSRxUcast Attribute A counter that is incremented each time - * the APS layer receives a unicast. */ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_RX_UCAST_ID = 0x0108, - /** @brief aps_tx_ucast_success, HA spec 9.3.2.2.2 (??) */ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_SUCCESS_ID = 0x0109, - /** APSTxUcastRetry Attribute A counter that is incremented each time - * the APS layer retries the sending of a unicast. */ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_RETRY_ID = 0x010A, - /** @brief aps_tx_ucast_fail, HA spec 9.3.2.2.2 (??) */ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_FAIL_ID = 0x010b, - /** RouteDiscInitiated Attribute A counter that is incremented each time - * a route request is initiated . */ - ZB_ZCL_ATTR_DIAGNOSTICS_ROUTE_DISC_INITIATED_ID = 0x010C, - /** NeighborAdded Attribute A counter that is incremented each time - * an entry is added to the neighbor table. */ - ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_ADDED_ID = 0x010D, - /** NeighborRemoved Attribute A counter that is incremented each time - * an entry is removed from the neighbor table. */ - ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_REMOVED_ID = 0x010E, - /** A counter that is incremented each time a neighbor table entry becomes stale - * because the neighbor has not been heard from. */ - ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_STALE_ID = 0x010F, - /** @brief join_indication, HA spec 1.2.2.2.17 */ - ZB_ZCL_ATTR_DIAGNOSTICS_JOIN_INDICATION_ID = 0x0110, - /** A counter that is incremented each time an entry is removed from the child table. */ - ZB_ZCL_ATTR_DIAGNOSTICS_CHILD_MOVED_ID = 0x0111, - /** A counter that is incremented each time a message is dropped at the network - * layer because the APS frame counter was not higher than the last message seen - * from that source. */ - ZB_ZCL_ATTR_DIAGNOSTICS_NWKFC_FAILURE_ID = 0x0112, - /** A counter that is incremented each time a message is dropped at the APS layer - * because the APS frame counter was not higher than the last message seen from - * that source. */ - ZB_ZCL_ATTR_DIAGNOSTICS_APSFC_FAILURE_ID = 0x0113, - /** A counter that is incremented each time a message is dropped at the APS layer - * because it had APS encryption but the key associated with the sender has - * not been authenticated, and thus the key is not authorized for use - * in APS data messages. */ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_UNAUTHORIZED_KEY_ID = 0x0114, - /** A counter that is incremented each time a NWK encrypted message was received - * but dropped because decryption failed. */ - ZB_ZCL_ATTR_DIAGNOSTICS_NWK_DECRYPT_FAILURES_ID = 0x0115, - /** A counter that is incremented each time an APS encrypted message was received - * but dropped because decryption failed. */ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_DECRYPT_FAILURES_ID = 0x0116, - /** A counter that is incremented each time the stack failed to allocate a packet - * buffers. This doesn't necessarily mean that the packet buffer count was 0 at - * the time, but that the number requested was greater than the number free. */ - ZB_ZCL_ATTR_DIAGNOSTICS_PACKET_BUFFER_ALLOCATE_FAILURES_ID = 0x0117, - /** A counter that is incremented each time a unicast packet is relayed. */ - ZB_ZCL_ATTR_DIAGNOSTICS_RELAYED_UCAST_ID = 0x0118, - /** A counter that is incremented each time a packet is dropped because the PHY to - * MAC queue was exhausted */ - ZB_ZCL_ATTR_DIAGNOSTICS_PHYTOMACQUEUELIMITREACHED_ID = 0x0119, - /** A counter that is incremented each time a packet was dropped due to a packet - * validation error. This could be due to length or other formatting problems - * in the packet. */ - ZB_ZCL_ATTR_DIAGNOSTICS_PACKET_VALIDATEDROPCOUNT_ID = 0x011A, - /** A counter that is equal to the average number of MAC retries needed to send - * an APS message, HA spec 9.2.2.2.2.27 */ - ZB_ZCL_ATTR_DIAGNOSTICS_AVERAGE_MAC_RETRY_PER_APS_ID = 0x011b, - /** This is the Link Quality Indicator for the last message received. There is no - * current agreed upon standard for calculating the LQI. For some implementations - * LQI is related directly to RSSI for others it is a function of the number of - * errors received over a fixed number of bytes in a given message. The one thing - * that has been agreed is that the Link Quality Indicator is a value between 0 - * and 255 where 0 indicates the worst possible link and 255 indicates the best - * possible link. Note that for a device reading the Last Message LQI the returned - * value SHALL be the LQI for the read attribute message used to read the attribute - * itself. */ - ZB_ZCL_ATTR_DIAGNOSTICS_LAST_LQI_ID = 0x011c, - /** This is the receive signal strength indication for the last message received. - * As with Last Message LQI, a device reading the Last Message RSSI, the returned - * value SHALL be the RSSI of the read attribute message used to read the attribute - * itself. */ - ZB_ZCL_ATTR_DIAGNOSTICS_LAST_RSSI_ID = 0x011d, - /*! @brief A counter that is incremented on the NWK layer - * each time tries number of a packet resending are gone. - * - * @note It's a non-standard counter that depends on ZB_ENABLE_NWK_RETRANSMIT and - * will be zero always when the macro isn't set. */ - ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_NWK_RETRY_OVERFLOW_ID = 0xff00, - /** A non-standard counter that is incremented each time an the PHY layer was unable - * to transmit due to a failed CCA */ - ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_PHY_CCA_FAILURES_ID = 0xff01, - /** A non-standard counter of the number of times the NWK broadcast was dropped - * because the broadcast table was full. */ - ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_BCAST_TABLE_FULL_ID = 0xff02 -}; - -/** @brief Default value for Diagnostics cluster revision global attribute */ -#define ZB_ZCL_DIAGNOSTICS_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/** @brief Default value for number_of_resets attribute */ -#define ZB_ZCL_DIAGNOSTICS_NUMBER_OF_RESETS_DEFAULT_VALUE ((zb_uint16_t)0x00000000) - -/** @brief Default value for PersistentMemoryWrites attribute */ -#define ZB_ZCL_DIAGNOSTICS_PERSISTENT_MEMORY_WRITES_DEFAULT_VALUE ((zb_uint16_t)0x00000000) - -/** @brief Default value for MacRxBcast attribute */ -#define ZB_ZCL_DIAGNOSTICS_MAC_RX_BCAST_DEFAULT_VALUE ((zb_uint32_t)0) - -/** @brief Default value for MacTxBcast attribute */ -#define ZB_ZCL_DIAGNOSTICS_MAC_TX_BCAST_DEFAULT_VALUE ((zb_uint32_t)0) - -/** @brief Default value for MacRxUcast attribute */ -#define ZB_ZCL_DIAGNOSTICS_MAC_RX_UCAST_DEFAULT_VALUE ((zb_uint32_t)0) - -/** @brief Default value for MacTxUcast attribute */ -#define ZB_ZCL_DIAGNOSTICS_MAC_TX_UCAST_DEFAULT_VALUE ((zb_uint32_t)0) - -/** @brief Default value for MacTxUcastRetry attribute */ -#define ZB_ZCL_DIAGNOSTICS_MAC_TX_UCAST_RETRY_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for MacTxUcastFail attribute */ -#define ZB_ZCL_DIAGNOSTICS_MAC_TX_UCAST_FAIL_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for APSRxBcast attribute */ -#define ZB_ZCL_DIAGNOSTICS_APS_RX_BCAST_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for aps_tx_bcast attribute */ -#define ZB_ZCL_DIAGNOSTICS_APS_TX_BCAST_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for APSRxUcast attribute */ -#define ZB_ZCL_DIAGNOSTICS_APS_RX_UCAST_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for aps_tx_ucast_success attribute */ -#define ZB_ZCL_DIAGNOSTICS_APS_TX_UCAST_SUCCESS_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for APSTxUcastRetry attribute */ -#define ZB_ZCL_DIAGNOSTICS_APS_TX_UCAST_RETRY_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for aps_tx_ucast_fail attribute */ -#define ZB_ZCL_DIAGNOSTICS_APS_TX_UCAST_FAIL_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for RouteDiscInitiated attribute */ -#define ZB_ZCL_DIAGNOSTICS_ROUTE_DISC_INITIATED_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for NeighborAdded attribute */ -#define ZB_ZCL_DIAGNOSTICS_NEIGHBOR_ADDED_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for NeighborRemoved attribute */ -#define ZB_ZCL_DIAGNOSTICS_NEIGHBOR_REMOVED_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for NeighborStale attribute */ -#define ZB_ZCL_DIAGNOSTICS_NEIGHBOR_STALE_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for join_indication attribute */ -#define ZB_ZCL_DIAGNOSTICS_JOIN_INDICATION_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for ChildMoved attribute */ -#define ZB_ZCL_DIAGNOSTICS_CHILD_MOVED_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for nwk_fc_failure attribute */ -#define ZB_ZCL_DIAGNOSTICS_NWKFC_FAILURE_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for aps_fc_failure attribute */ -#define ZB_ZCL_DIAGNOSTICS_APSFC_FAILURE_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for APSUnauthorizedKey attribute */ -#define ZB_ZCL_DIAGNOSTICS_APS_UNAUTHORIZED_KEY_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for NWKDecryptFailures attribute */ -#define ZB_ZCL_DIAGNOSTICS_NWK_DECRYPT_FAILURES_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for APSDecryptFailures attribute */ -#define ZB_ZCL_DIAGNOSTICS_APS_DECRYPT_FAILURES_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for packet_buffer_allocate_failures attribute */ -#define ZB_ZCL_DIAGNOSTICS_PACKET_BUFFER_ALLOCATE_FAILURES_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for RelayedUcast attribute */ -#define ZB_ZCL_DIAGNOSTICS_RELAYED_UCAST_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for PhytoMACqueuelimitreached attribute */ -#define ZB_ZCL_DIAGNOSTICS_PHYTO_MA_CQUEUELIMITREACHED_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for PacketValidatedropcount attribute */ -#define ZB_ZCL_DIAGNOSTICS_PACKET_VALIDATEDROPCOUNT_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for AverageMACRetryPerAPS attribute */ -#define ZB_ZCL_DIAGNOSTICS_AVERAGE_MAC_RETRY_PER_APS_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for LastLQI attribute */ -#define ZB_ZCL_DIAGNOSTICS_LAST_LQI_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for LastRSSI attribute */ -#define ZB_ZCL_DIAGNOSTICS_LAST_RSSI_DEFAULT_VALUE ((zb_int8_t)0) - -#define ZB_ZCL_DIAGNOSTICS_CUSTOM_ATTR_NWK_RETRY_OVERFLOW_DEFAULT_VALUE ((zb_uint16_t)0) - -#define ZB_ZCL_DIAGNOSTICS_CUSTOM_ATTR_PHY_CCA_FAILURES_DEFAULT_VALUE ((zb_uint16_t)0) - -#define ZB_ZCL_DIAGNOSTICS_CUSTOM_ATTR_BCAST_TABLE_FULL_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @cond internals_doc */ -/*! @internal @name Diagnostics cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_NUMBER_OF_RESETS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_NUMBER_OF_RESETS_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_PACKET_BUFFER_ALLOCATE_FAILURES_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_PACKET_BUFFER_ALLOCATE_FAILURES_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_JOIN_INDICATION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_JOIN_INDICATION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_MAC_RX_BCAST_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_RX_BCAST_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_BCAST_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_BCAST_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_MAC_RX_UCAST_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_RX_UCAST_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_RETRY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_RETRY_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_FAIL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_FAIL_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_BCAST_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_BCAST_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_SUCCESS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_SUCCESS_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_RETRY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_RETRY_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_FAIL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_FAIL_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_ROUTE_DISC_INITIATED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_ROUTE_DISC_INITIATED_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_AVERAGE_MAC_RETRY_PER_APS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_AVERAGE_MAC_RETRY_PER_APS_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_LAST_LQI_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_LAST_LQI_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_LAST_RSSI_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_LAST_RSSI_ID, \ - ZB_ZCL_ATTR_TYPE_S8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_CHILD_MOVED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_CHILD_MOVED_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_NWKFC_FAILURE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_NWKFC_FAILURE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_APSFC_FAILURE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_APSFC_FAILURE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_APS_UNAUTHORIZED_KEY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_UNAUTHORIZED_KEY_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_NWK_DECRYPT_FAILURES_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_NWK_DECRYPT_FAILURES_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_APS_DECRYPT_FAILURES_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_APS_DECRYPT_FAILURES_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_PHYTOMACQUEUELIMITREACHED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_PHYTOMACQUEUELIMITREACHED_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_PACKET_VALIDATEDROPCOUNT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_PACKET_VALIDATEDROPCOUNT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_ADDED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_ADDED_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_REMOVED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_REMOVED_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_STALE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_STALE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_NWK_RETRY_OVERFLOW_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_NWK_RETRY_OVERFLOW_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_PHY_CCA_FAILURES_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_PHY_CCA_FAILURES_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_BCAST_TABLE_FULL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_BCAST_TABLE_FULL_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/** @brief Declare attribute list for Diagnostics cluster - server side - @param attr_list - attribute list name -*/ -#define ZB_ZCL_DECLARE_DIAGNOSTICS_ATTRIB_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_DIAGNOSTICS) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_MAC_RX_BCAST_ID, &diagnostics_ctx_zcl.mac_data.mac_rx_bcast) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_BCAST_ID, &diagnostics_ctx_zcl.mac_data.mac_tx_bcast) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_MAC_RX_UCAST_ID, &diagnostics_ctx_zcl.mac_data.mac_rx_ucast) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_ID, &diagnostics_ctx_zcl.mac_data.mac_tx_ucast_total_zcl) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_RETRY_ID, &diagnostics_ctx_zcl.mac_data.mac_tx_ucast_retries_zcl) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_MAC_TX_UCAST_FAIL_ID, &diagnostics_ctx_zcl.mac_data.mac_tx_ucast_failures_zcl) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_LAST_LQI_ID, &diagnostics_ctx_zcl.mac_data.last_msg_lqi) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_LAST_RSSI_ID, &diagnostics_ctx_zcl.mac_data.last_msg_rssi) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_PHYTOMACQUEUELIMITREACHED_ID, &diagnostics_ctx_zcl.mac_data.phy_to_mac_que_lim_reached) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_PACKET_VALIDATEDROPCOUNT_ID, &diagnostics_ctx_zcl.mac_data.mac_validate_drop_cnt) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_PHY_CCA_FAILURES_ID, &diagnostics_ctx_zcl.mac_data.phy_cca_fail_count) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_NUMBER_OF_RESETS_ID, &diagnostics_ctx_zcl.zdo_data.number_of_resets) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_BCAST_ID, &diagnostics_ctx_zcl.zdo_data.aps_tx_bcast) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_SUCCESS_ID, &diagnostics_ctx_zcl.zdo_data.aps_tx_ucast_success) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_RETRY_ID, &diagnostics_ctx_zcl.zdo_data.aps_tx_ucast_retry) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_APS_TX_UCAST_FAIL_ID, &diagnostics_ctx_zcl.zdo_data.aps_tx_ucast_fail) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_ROUTE_DISC_INITIATED_ID, &diagnostics_ctx_zcl.zdo_data.route_disc_initiated) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_ADDED_ID, &diagnostics_ctx_zcl.zdo_data.nwk_neighbor_added) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_REMOVED_ID, &diagnostics_ctx_zcl.zdo_data.nwk_neighbor_removed) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_NEIGHBOR_STALE_ID, &diagnostics_ctx_zcl.zdo_data.nwk_neighbor_stale) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_JOIN_INDICATION_ID, &diagnostics_ctx_zcl.zdo_data.join_indication) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_AVERAGE_MAC_RETRY_PER_APS_ID, &diagnostics_ctx_zcl.zdo_data.average_mac_retry_per_aps_message_sent) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_PACKET_BUFFER_ALLOCATE_FAILURES_ID, &diagnostics_ctx_zcl.zdo_data.packet_buffer_allocate_failures) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_CHILD_MOVED_ID, &diagnostics_ctx_zcl.zdo_data.childs_removed) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_NWKFC_FAILURE_ID, &diagnostics_ctx_zcl.zdo_data.nwk_fc_failure) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_APSFC_FAILURE_ID, &diagnostics_ctx_zcl.zdo_data.aps_fc_failure) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_APS_UNAUTHORIZED_KEY_ID, &diagnostics_ctx_zcl.zdo_data.aps_unauthorized_key) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_NWK_DECRYPT_FAILURES_ID, &diagnostics_ctx_zcl.zdo_data.nwk_decrypt_failure) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_APS_DECRYPT_FAILURES_ID, &diagnostics_ctx_zcl.zdo_data.aps_decrypt_failure) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_NWK_RETRY_OVERFLOW_ID, &diagnostics_ctx_zcl.zdo_data.nwk_retry_overflow) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DIAGNOSTICS_CUSTOM_ATTR_BCAST_TABLE_FULL_ID, &diagnostics_ctx_zcl.zdo_data.nwk_bcast_table_full) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Diagnostics cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/* ACHTUNG! ATTENTION! - * If you need to add a counter, do the following steps: - * 1) add a macro to declare an attribute like it's done above: - * ZB_SET_ATTR_DESCR_WITH_*attr_id*(data_ptr) - * 2) declare the attribute in the attributes list: - * ZB_ZCL_DECLARE_DIAGNOSTICS_ATTRIB_LIST - * 3) implement your counter at: - * 3.1) ZDO - * - zb_zdo_globals.h -> zdo_diagnostics_info_t - * - zdo_diagnostics.h -> zdo_diagnostics_counter_id_t - * - zdo_diagnostics.c -> zdo_diagnostics_inc() - * - increment your counter in code using the ZDO_DIAGNOSTICS_INC() macro; - * OR - * 3.2) MAC - * - zb_mac.h -> zb_mac_diagnostic_info_t - * - mac_zcl_diagnostic.c -> implement a function to increment the counter; - * - mac_internal.h -> add macros to use the incrementing function; - * - increment your counter in code using the macro; - * 4) add copying the counter value to - * zcl_diagnostics_commands.c -> zb_zcl_diagnostics_get_attr_value_by_id() - * - * Important note: - * We have asynchronous reading the Diagnostics attributes: - * in the zb_zcl_read_attr_handler() we call zdo_diagnostics_get_stats() - * that will copy all counters to the same buffer from the first byte. - * What the problem? We have the following buffer structure: - * a) buffer begin (from zero byte! not from zb_buf_begin()) - will contain all counters; - * b) buffer middle (from zb_buf_begin()) - contains one or more zb_zcl_read_attr_req_t; - * c) buffer end (can be get with ZB_BUF_GET_PARAM()) - contains zb_zcl_parsed_hdr_t. - * As you see, we can place all counters only from buffer begin (a). - * It's possible to get a situation when we don't have enough space, - * and you will catch assert in the zdo_diagnostics_get_mac_stats_cb() function. - * In this case it's necessary to move data from buffer middle to the right a bit. - */ - -/*! @} */ /* Diagnostics cluster attributes */ - -/*! @} */ /* ZCL Diagnostics cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_diagnostics_init_server(void); -void zb_zcl_diagnostics_init_client(void); - -/** - * @brief Synchronize MAC and ZDO counters with ZCL attributes. - * - * Call this function each time when you want to get an attribute value - * and process statistic using @zb_zcl_get_attr_desc_a - * - * When synchronization will be finished, users callback - * with a specified parameter will be called. - * - * @param cb_param - a parameter of users callback - * @param cb - users callback - */ -zb_ret_t zb_zcl_diagnostics_sync_counters(zb_uint8_t cb_param, zb_callback_t cb); - -#define ZB_ZCL_CLUSTER_ID_DIAGNOSTICS_SERVER_ROLE_INIT zb_zcl_diagnostics_init_server -#define ZB_ZCL_CLUSTER_ID_DIAGNOSTICS_CLIENT_ROLE_INIT zb_zcl_diagnostics_init_client - -#else /* defined(ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS) */ - -#define ZB_ZCL_CLUSTER_ID_DIAGNOSTICS_SERVER_ROLE_INIT -#define ZB_ZCL_CLUSTER_ID_DIAGNOSTICS_CLIENT_ROLE_INIT - -#endif /* defined(ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS) */ - -#endif /* ZB_ZCL_DIAGNOSTICS_H */ diff --git a/zboss/development/include/zcl/zb_zcl_door_lock.h b/zboss/development/include/zcl/zb_zcl_door_lock.h deleted file mode 100644 index da232838a6..0000000000 --- a/zboss/development/include/zcl/zb_zcl_door_lock.h +++ /dev/null @@ -1,798 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: DOOR_LOCK cluster definitions -*/ - -#ifndef ZB_ZCL_DOOR_LOCK_H -#define ZB_ZCL_DOOR_LOCK_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_DOOR_LOCK - * @{ - * @details - * Door Lock cluster defined in ZCL spec, clause 7.3. - * - * The cluster contains 2 command sets: - * @li Lock Door request and response; - * @li Unlock Door request and response. - * - * Both requests have no payload and could be scheduled for sending with corresponding macros. - * Both responses have simple payload, and their sending and parsing with corresponding macros - * is almost trivial. - * - * @par Examples: - * - * Send Door Lock command: - * @snippet HA_samples/door_lock/sample_zed.c send_door_lock_req - * - * Send Door Unlock command: - * @snippet HA_samples/door_lock/sample_zed.c send_door_lock_unlock_req - * - */ - -/*! @name Door Lock cluster attributes - @{ -*/ - -/*! @brief Door Lock cluster attribute identifiers - @see ZCL spec, subclause 7.3.2.2 -*/ -enum zb_zcl_door_lock_attr_e -{ - /** @brief LockState attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_ID = 0x0000, - /** @brief LockType attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_ID = 0x0001, - /** @brief ActuatorEnabled attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_ID = 0x0002, - /** @brief DoorState attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_DOOR_STATE_ID = 0x0003, - /** @brief DoorOpenEvents attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_NUM_OF_DOOR_OPEN_EVENTS_ID = 0x0004, - /** @brief DoorClosedEvents attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_NUM_OF_DOOR_CLOSED_EVENTS_ID = 0x0005, - /** @brief OpenPeriod attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_OPEN_PERIOD_ID = 0x0006, - /** The number of available log records. */ - ZB_ZCL_ATTR_DOOR_LOCK_NUMBER_OF_LOG_RECORDS_SUPPORTED_ID = 0x0010, - /** @brief NumberOfTotalUsersSupported attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_NUM_TOTAL_USERS_ID = 0x0011, - /** @brief NumberOfPINUsersSupported attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_NUM_PIN_USERS_ID = 0x0012, - /** The number of RFID users supported. */ - ZB_ZCL_ATTR_DOOR_LOCK_NUMBER_OF_RFID_USERS_SUPPORTED_ID = 0x0013, - /** @brief NumberOfWeekDaySchedulesSupportedPerUser attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_NUM_WEEK_DAY_SCHEDULE_PER_USER_ID = 0x0014, - /** @brief NumberOfYearDaySchedulesSupportedPerUser attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_NUM_YEAR_DAY_SCHEDULE_PER_USER_ID = 0x0015, - /** @brief NumberOfHolidaySchedulesSupported attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_NUM_HOLIDAY_SCHEDULE_ID = 0x0016, - /** @brief Max PIN code length attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_MAX_PIN_LEN_ID = 0x0017, - /** @brief Min PIN code length attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_MIN_PIN_LEN_ID = 0x0018, - /** An 8-bit value indicates the maximum length in bytes of a RFID Code - * on this device. */ - ZB_ZCL_ATTR_DOOR_LOCK_MAX_RFID_CODE_LENGTH_ID = 0x0019, - /** An 8-bit value indicates the minimum length in bytes of a RFID Code - * on this device. */ - ZB_ZCL_ATTR_DOOR_LOCK_MIN_RFID_CODE_LENGTH_ID = 0x001A, - /** Enable/disable event logging. */ - ZB_ZCL_ATTR_DOOR_LOCK_ENABLE_LOGGING_ID = 0x0020, - /** Modifies the language for the on-screen or audible user interface using - * three bytes from ISO-639-1. */ - ZB_ZCL_ATTR_DOOR_LOCK_LANGUAGE_ID = 0x0021, - /** The settings for the LED support three different modes. */ - ZB_ZCL_ATTR_DOOR_LOCK_LED_SETTINGS_ID = 0x0022, - /** The number of seconds to wait after unlocking a lock before it automatically - * locks again. */ - ZB_ZCL_ATTR_DOOR_LOCK_AUTO_RELOCK_TIME_ID = 0x0023, - /** The sound volume on a door lock has three possible settings: silent, low - * and high volumes. */ - ZB_ZCL_ATTR_DOOR_LOCK_SOUND_VOLUME_ID = 0x0024, - /** @brief OperatingMode attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_OPERATING_MODE_ID = 0x0025, - /** @brief SupportedOperatingModes attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_OPERATION_MODES_SUPPORTED_ID = 0x0026, - /** This attribute represents the default configurations as they are physically - * set on the device (example: hardware dip switch setting, etc) and represents - * the default setting for some of the attributes within this Operational Setting - * Attribute Set (for example: LED, Auto Lock, Sound Volume, and Operating Mode - * attributes). */ - ZB_ZCL_ATTR_DOOR_LOCK_DEFAULT_CONFIGURATION_REGISTER_ID = 0x0027, - /** @brief EnableLocalProgramming attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_ENABLE_LOCAL_PROGRAMMING_ID = 0x0028, - /** Enable/disable the ability to lock the door lock with a single touch on - * the door lock. */ - ZB_ZCL_ATTR_DOOR_LOCK_ENABLE_ONE_TOUCH_LOCKING_ID = 0x0029, - /** Enable/disable an inside LED that allows the user to see at a glance - * if the door is locked. */ - ZB_ZCL_ATTR_DOOR_LOCK_ENABLE_INSIDE_STATUS_LED_ID = 0x002A, - /** Enable/disable a button inside the door that is used to put the lock - * into privacy mode. */ - ZB_ZCL_ATTR_DOOR_LOCK_ENABLE_PRIVACY_MODE_BUTTON_ID = 0x002B, - /** The number of incorrect codes or RFID presentment attempts a user - * is allowed to enter before the door will enter a lockout state. */ - ZB_ZCL_ATTR_DOOR_LOCK_WRONG_CODE_ENTRY_LIMIT_ID = 0x0030, - /** The number of seconds that the lock shuts down following wrong code entry. */ - ZB_ZCL_ATTR_DOOR_LOCK_USER_CODE_TEMPORARY_DISABLE_TIME_ID = 0x0031, - /** Boolean set to True if it is ok for the door lock server to send PINs - * over the air. */ - ZB_ZCL_ATTR_DOOR_LOCK_SEND_PIN_OVER_THE_AIR_ID = 0x0032, - /** @brief Require PIN for RF operation attribute */ - ZB_ZCL_ATTR_DOOR_LOCK_REQUIRE_PIN_RF_ID = 0x0033, - /** The Security Level attribute allows the door lock manufacturer to indicate - * what level of security the door lock requires. */ - ZB_ZCL_ATTR_DOOR_LOCK_SECURITY_LEVEL_ID = 0x0034, - /** The alarm mask is used to turn on/off alarms for particular functions */ - ZB_ZCL_ATTR_DOOR_LOCK_ALARM_MASK_ID = 0x0040, - /** Event mask used to turn on and off the transmission of keypad operation events. */ - ZB_ZCL_ATTR_DOOR_LOCK_KEYPAD_OPERATION_EVENT_MASK_ID = 0x0041, - /** Event mask used to turn on and off the transmission of RF operation events. */ - ZB_ZCL_ATTR_DOOR_LOCK_RF_OPERATION_EVENT_MASK_ID = 0x0042, - /** Event mask used to turn on and off manual operation events. */ - ZB_ZCL_ATTR_DOOR_LOCK_MANUAL_OPERATION_EVENT_MASK_ID = 0x0043, - /** Event mask used to turn on and off RFID operation events. */ - ZB_ZCL_ATTR_DOOR_LOCK_RFID_OPERATION_EVENT_MASK_ID = 0x0044, - /** Event mask used to turn on and off keypad programming events. */ - ZB_ZCL_ATTR_DOOR_LOCK_KEYPAD_PROGRAMMING_EVENT_MASK_ID = 0x0045, - /** Event mask used to turn on and off RF programming events. */ - ZB_ZCL_ATTR_DOOR_LOCK_RF_PROGRAMMING_EVENT_MASK_ID = 0x0046, - /** Event mask used to turn on and off RFID programming events. */ - ZB_ZCL_ATTR_DOOR_LOCK_RFID_PROGRAMMING_EVENT_MASK_ID = 0x0047, -}; - - -/** @brief Values for LockState attribute - * @see ZCL spec, subclause 7.3.2.2.1 - */ -enum zb_zcl_door_lock_lock_state_e -{ - /*! "Not fully locked" value */ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_NOT_FULLY_LOCKED = 0x00, - /*! "Locked" value */ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_LOCKED = 0x01, - /*! "Unlocked" value */ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_UNLOCKED = 0x02, - /*! "Not Defined" value */ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_UNDEFINED = 0xff -}; - -/** @brief Default value for Door Lock cluster revision global attribute */ -#define ZB_ZCL_DOOR_LOCK_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/** @brief Default value for Lock State attribute. */ -#define ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_DEFAULT_VALUE ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_UNDEFINED - -/** @brief Values for LockType attribute - * @see ZCL spec, subclause 7.3.2.2.2 - */ -enum zb_zcl_door_lock_lock_type_e -{ - /*! "Deadbolt" value */ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_DEADBOLT = 0x00, - /*! "Magnetic" value */ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_MAGNETIC = 0x01, - /*! "Other" value */ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_OTHER = 0x02, - /*! "Not Defined" value */ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_UNDEFINED = 0xff -}; - -/** @brief Default value for Lock Type attribute. */ -#define ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_DEFAULT_VALUE ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_UNDEFINED - -/** @brief Values for ActuatorEnabled attribute - * @see ZCL spec, subclause 7.3.2.2.3 - */ -enum zb_zcl_door_lock_actuator_enabled_e -{ - /*! "Disabled" value */ - ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_DISABLED = 0x0b0, - /*! "Enabled" value */ - ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_ENABLED = 0x0b1 -}; - -/** @brief Default value for Actuator Enabled attribute. */ -#define ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_DEFAULT_VALUE \ - ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_ENABLED - -/** @brief Values for DoorState attribute - * @see ZCL spec, subclause 7.3.2.2.4 - */ -enum zb_zcl_door_lock_door_state_e -{ - /*! "Open" value */ - ZB_ZCL_ATTR_DOOR_LOCK_DOOR_STATE_OPEN = 0x00, - /*! "Closed" value */ - ZB_ZCL_ATTR_DOOR_LOCK_DOOR_STATE_CLOSED = 0x01, - /*! "Error (jammed)" value */ - ZB_ZCL_ATTR_DOOR_LOCK_DOOR_STATE_ERROR_JAMMED = 0x02, - /*! "Error (forced open)" value */ - ZB_ZCL_ATTR_DOOR_LOCK_DOOR_STATE_ERROR_FORCED_OPEN = 0x03, - /*! "Error (unspecified)" value */ - ZB_ZCL_ATTR_DOOR_LOCK_DOOR_STATE_ERROR_UNSPECIFIED = 0x04 -}; - -/** @brief Declare attribute list for Door Lock cluster - @param attr_list - attribute list name - @param lock_state - @param lock_type - @param actuator_enabled -*/ -#define ZB_ZCL_DECLARE_DOOR_LOCK_ATTRIB_LIST(attr_list, \ - lock_state, \ - lock_type, \ - actuator_enabled) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_DOOR_LOCK) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_ID, (lock_state)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_ID, (lock_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_ID, (actuator_enabled)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Door Lock cluster attributes */ - -/*! @name Door Lock cluster commands - @{ -*/ - -/*! @brief Door Lock cluster commands - @see ZCL spec, subclause 7.3.2.3 Commands Received -*/ -enum zb_zcl_door_lock_cmd_e -{ - /** This command causes the lock device to lock the door. */ - ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR = 0x00, - /** This command causes the lock device to unlock the door. */ - ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_DOOR = 0x01, - /** Request the status of the lock. */ - ZB_ZCL_CMD_DOOR_LOCK_TOGGLE = 0x02, - /** This command causes the lock device to unlock the door with a timeout parameter. */ - ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_WITH_TIMEOUT = 0x03, - /** Request a log record. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_LOG_RECORD = 0x04, - /** Set a PIN into the lock. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_PIN_CODE = 0x05, - /** Retrieve a PIN Code. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_PIN_CODE = 0x06, - /** Delete a PIN. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_PIN_CODE = 0x07, - /** Clear out all PINs on the lock. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_ALL_PIN_CODES = 0x08, - /** Set the status of a user ID. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_USER_STATUS = 0x09, - /** Get the status of a user. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_USER_STATUS = 0x0A, - /** Set a weekly repeating schedule for a specified user. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_WEEKDAY_SCHEDULE = 0x0B, - /** Retrieve the specific weekly schedule for the specific user. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_WEEKDAY_SCHEDULE = 0x0C, - /** Clear the specific weekly schedule for the specific user. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_WEEKDAY_SCHEDULE = 0x0D, - /** Set a time-specific schedule ID for a specified user. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_YEAR_DAY_SCHEDULE = 0x0E, - /** Retrieve the specific year day schedule for the specific user. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_YEAR_DAY_SCHEDULE = 0x0F, - /** Clears the specific year day schedule for the specific user. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_YEAR_DAY_SCHEDULE = 0x10, - /** Set the holiday Schedule by specifying local start time and local end time - * with respect to any Lock Operating Mode. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_HOLIDAY_SCHEDULE = 0x11, - /** Get the holiday Schedule by specifying Holiday ID. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_HOLIDAY_SCHEDULE = 0x12, - /** Clear the holiday Schedule by specifying Holiday ID. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_HOLIDAY_SCHEDULE = 0x13, - /** Set the type byte for a specified user. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_USER_TYPE = 0x14, - /** Retrieve the type byte for a specific user. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_USER_TYPE = 0x15, - /** Set an ID for RFID access into the lock. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_RFID_CODE = 0x16, - /** Retrieve an ID. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_RFID_CODE = 0x17, - /** Delete an ID. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_RFID_CODE = 0x18, - /** Clear out all RFIDs on the lock. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_ALL_RFID_CODES = 0x19, -}; - -/*! @brief Door Lock cluster commands response - @see ZCL spec, subclause 7.3.2.4 Commands Generated -*/ -enum zb_zcl_door_lock_cmd_resp_e -{ - /** This command is sent in response to a Lock command with one status byte payload. */ - ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR_RES = 0x00, - /** This command is sent in response to a Unlock command with one status byte payload. */ - ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_DOOR_RES = 0x01, - /** This command is sent in response to a Toggle command with one status byte payload. */ - ZB_ZCL_CMD_DOOR_LOCK_TOGGLE_RESPONSE = 0x02, - /** This command is sent in response to an Unlock with Timeout command - * with one status byte payload. */ - ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_WITH_TIMEOUT_RESPONSE = 0x03, - /** Returns the specified log record. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_LOG_RECORD_RESPONSE = 0x04, - /** Returns status of the PIN set command. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_PIN_CODE_RESPONSE = 0x05, - /** Returns the PIN for the specified user ID. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_PIN_CODE_RESPONSE = 0x06, - /** Returns pass/fail of the command. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_PIN_CODE_RESPONSE = 0x07, - /** Returns pass/fail of the command. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_ALL_PIN_CODES_RESPONSE = 0x08, - /** Returns the pass or fail value for the setting of the user status. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_USER_STATUS_RESPONSE = 0x09, - /** Returns the user status for the specified user ID. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_USER_STATUS_RESPONSE = 0x0A, - /** Returns pass/fail of the command. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_WEEKDAY_SCHEDULE_RESPONSE = 0x0B, - /** Returns the weekly repeating schedule data for the specified schedule ID. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_WEEKDAY_SCHEDULE_RESPONSE = 0x0C, - /** Returns pass/fail of the command. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_WEEKDAY_SCHEDULE_RESPONSE = 0x0D, - /** Returns pass/fail of the command. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_YEAR_DAY_SCHEDULE_RESPONSE = 0x0E, - /** Returns the weekly repeating schedule data for the specified schedule ID. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_YEAR_DAY_SCHEDULE_RESPONSE = 0x0F, - /** Returns pass/fail of the command. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_YEAR_DAY_SCHEDULE_RESPONSE = 0x10, - /** Returns pass/fail of the command. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_HOLIDAY_SCHEDULE_RESPONSE = 0x11, - /** Returns the Holiday Schedule Entry for the specified Holiday ID. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_HOLIDAY_SCHEDULE_RESPONSE = 0x12, - /** Returns pass/fail of the command. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_HOLIDAY_SCHEDULE_RESPONSE = 0x13, - /** Returns the pass or fail value for the setting of the user type. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_USER_TYPE_RESPONSE = 0x14, - /** Returns the user type for the specified user ID. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_USER_TYPE_RESPONSE = 0x15, - /** Returns status of the Set RFID Code command. */ - ZB_ZCL_CMD_DOOR_LOCK_SET_RFID_CODE_RESPONSE = 0x16, - /** Returns the RFID code for the specified user ID. */ - ZB_ZCL_CMD_DOOR_LOCK_GET_RFID_CODE_RESPONSE = 0x17, - /** Returns pass/fail of the command. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_RFID_CODE_RESPONSE = 0x18, - /** Returns pass/fail of the command. */ - ZB_ZCL_CMD_DOOR_LOCK_CLEAR_ALL_RFID_CODES_RESPONSE = 0x19, - /** The door lock server sends out operation event notification when the - * event is triggered by the various event sources. */ - ZB_ZCL_CMD_DOOR_LOCK_OPERATION_EVENT_NOTIFICATION_ID = 0x20, - /** The door lock server sends out a programming event notification - * whenever a programming event takes place on the door lock. */ - ZB_ZCL_CMD_DOOR_LOCK_PROGRAMMING_EVENT_NOTIFICATION = 0x21, -}; - -enum zb_zcl_door_lock_operation_event_source_e -{ - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_SOURCE_KEYPAD = 0x00, - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_SOURCE_RF = 0x01, - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_SOURCE_MANUAL = 0x02, - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_SOURCE_RFID = 0x03, - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_SOURCE_INDETERMINATE = 0xFF, -}; - -/** @cond internals_doc */ -/* Door lock cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_DOOR_LOCK_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR_RES, \ - ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_DOOR_RES - -#define ZB_ZCL_CLUSTER_ID_DOOR_LOCK_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_DOOR_LOCK_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_DOOR_LOCK_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR, \ - ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_DOOR - -#define ZB_ZCL_CLUSTER_ID_DOOR_LOCK_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_DOOR_LOCK_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Default value for NumberOfLogRecordsSupported attribute */ -#define ZB_ZCL_DOOR_LOCK_NUMBER_OF_LOG_RECORDS_SUPPORTED_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for NumTotalUsers attribute */ -#define ZB_ZCL_DOOR_LOCK_NUM_TOTAL_USERS_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for NumPINUsers attribute */ -#define ZB_ZCL_DOOR_LOCK_NUM_PIN_USERS_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for NumberOfRFIDUsersSupported attribute */ -#define ZB_ZCL_DOOR_LOCK_NUMBER_OF_RFID_USERS_SUPPORTED_DEFAULT_VALUE ((zb_uint16_t)0) - -/** @brief Default value for NumWeekDaySchedulePerUser attribute */ -#define ZB_ZCL_DOOR_LOCK_NUM_WEEK_DAY_SCHEDULE_PER_USER_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for NumYearDaySchedulePerUser attribute */ -#define ZB_ZCL_DOOR_LOCK_NUM_YEAR_DAY_SCHEDULE_PER_USER_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for NumHolidaySchedule attribute */ -#define ZB_ZCL_DOOR_LOCK_NUM_HOLIDAY_SCHEDULE_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for MaxPINLen attribute */ -#define ZB_ZCL_DOOR_LOCK_MAX_PIN_LEN_DEFAULT_VALUE ((zb_uint8_t)0x08) - -/** @brief Default value for MinPINLen attribute */ -#define ZB_ZCL_DOOR_LOCK_MIN_PIN_LEN_DEFAULT_VALUE ((zb_uint8_t)0x04) - -/** @brief Default value for MaxRFIDCodeLength attribute */ -#define ZB_ZCL_DOOR_LOCK_MAX_RFID_CODE_LENGTH_DEFAULT_VALUE ((zb_uint8_t)0x14) - -/** @brief Default value for MinRFIDCodeLength attribute */ -#define ZB_ZCL_DOOR_LOCK_MIN_RFID_CODE_LENGTH_DEFAULT_VALUE ((zb_uint8_t)0x08) - -/** @brief Default value for EnableLogging attribute */ -#define ZB_ZCL_DOOR_LOCK_ENABLE_LOGGING_DEFAULT_VALUE ((zb_bool_t)0) - -/** @brief Default value for Language attribute */ -#define ZB_ZCL_DOOR_LOCK_LANGUAGE_DEFAULT_VALUE {0} - -/** @brief Default value for LEDSettings attribute */ -#define ZB_ZCL_DOOR_LOCK_LED_SETTINGS_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for AutoRelockTime attribute */ -#define ZB_ZCL_DOOR_LOCK_AUTO_RELOCK_TIME_DEFAULT_VALUE ((zb_uint32_t)0) - -/** @brief Default value for SoundVolume attribute */ -#define ZB_ZCL_DOOR_LOCK_SOUND_VOLUME_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for OperatingMode attribute */ -#define ZB_ZCL_DOOR_LOCK_OPERATING_MODE_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for OperationModesSupported attribute */ -#define ZB_ZCL_DOOR_LOCK_OPERATION_MODES_SUPPORTED_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for DefaultConfigurationRegister attribute */ -#define ZB_ZCL_DOOR_LOCK_DEFAULT_CONFIGURATION_REGISTER_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for EnableLocalProgramming attribute */ -#define ZB_ZCL_DOOR_LOCK_ENABLE_LOCAL_PROGRAMMING_DEFAULT_VALUE ((zb_bool_t)0x01) - -/** @brief Default value for EnableOneTouchLocking attribute */ -#define ZB_ZCL_DOOR_LOCK_ENABLE_ONE_TOUCH_LOCKING_DEFAULT_VALUE ((zb_bool_t)0) - -/** @brief Default value for EnableInsideStatusLED attribute */ -#define ZB_ZCL_DOOR_LOCK_ENABLE_INSIDE_STATUS_LED_DEFAULT_VALUE ((zb_bool_t)0) - -/** @brief Default value for EnablePrivacyModeButton attribute */ -#define ZB_ZCL_DOOR_LOCK_ENABLE_PRIVACY_MODE_BUTTON_DEFAULT_VALUE ((zb_bool_t)0) - -/** @brief Default value for WrongCodeEntryLimit attribute */ -#define ZB_ZCL_DOOR_LOCK_WRONG_CODE_ENTRY_LIMIT_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for UserCodeTemporaryDisableTime attribute */ -#define ZB_ZCL_DOOR_LOCK_USER_CODE_TEMPORARY_DISABLE_TIME_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for SendPINOverTheAir attribute */ -#define ZB_ZCL_DOOR_LOCK_SEND_PIN_OVER_THE_AIR_DEFAULT_VALUE ((zb_bool_t)0) - -/** @brief Default value for RequirePIN_RF_ID attribute */ -#define ZB_ZCL_DOOR_LOCK_REQUIRE_PIN_RF_ID_DEFAULT_VALUE ((zb_bool_t)0) - -/** @brief Default value for SecurityLevel attribute */ -#define ZB_ZCL_DOOR_LOCK_SECURITY_LEVEL_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for AlarmMask attribute */ -#define ZB_ZCL_DOOR_LOCK_ALARM_MASK_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for KeypadOperationEventMask attribute */ -#define ZB_ZCL_DOOR_LOCK_KEYPAD_OPERATION_EVENT_MASK_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RFOperationEventMask attribute */ -#define ZB_ZCL_DOOR_LOCK_RF_OPERATION_EVENT_MASK_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for ManualOperationEventMask attribute */ -#define ZB_ZCL_DOOR_LOCK_MANUAL_OPERATION_EVENT_MASK_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RFIDOperationEventMask attribute */ -#define ZB_ZCL_DOOR_LOCK_RFID_OPERATION_EVENT_MASK_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for KeypadProgrammingEventMask attribute */ -#define ZB_ZCL_DOOR_LOCK_KEYPAD_PROGRAMMING_EVENT_MASK_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RFProgrammingEventMask attribute */ -#define ZB_ZCL_DOOR_LOCK_RF_PROGRAMMING_EVENT_MASK_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RFIDProgrammingEventMask attribute */ -#define ZB_ZCL_DOOR_LOCK_RFID_PROGRAMMING_EVENT_MASK_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -enum zb_zcl_door_lock_operation_event_code_e -{ - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_CODE_UNKNOWN = 0x00, - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_CODE_LOCK = 0x01, - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_CODE_UNLOCK = 0x02, - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_CODE_KEY_LOCK = 0x08, - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_CODE_KEY_UNLOCK = 0x09, - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_CODE_MANUAL_LOCK = 0x0D, - ZB_ZCL_DOOR_LOCK_OPERATION_EVENT_CODE_MANUAL_UNLOCK = 0x0E, -}; - -enum zb_zcl_door_lock_keypad_operation_event_mask_e -{ - ZB_ZCL_DOOR_LOCK_KEYPAD_OPERATION_EVENT_MASK_UNKNOWN = (1l << 0), - ZB_ZCL_DOOR_LOCK_KEYPAD_OPERATION_EVENT_MASK_LOCK = (1l << 1), - ZB_ZCL_DOOR_LOCK_KEYPAD_OPERATION_EVENT_MASK_UNLOCK = (1l << 2), -}; - -enum zb_zcl_door_lock_rf_operation_event_mask_e -{ - ZB_ZCL_DOOR_LOCK_RF_OPERATION_EVENT_MASK_UNKNOWN = (1l << 0), - ZB_ZCL_DOOR_LOCK_RF_OPERATION_EVENT_MASK_LOCK = (1l << 1), - ZB_ZCL_DOOR_LOCK_RF_OPERATION_EVENT_MASK_UNLOCK = (1l << 2), -}; - -enum zb_zcl_door_lock_manual_operation_event_mask_e -{ - ZB_ZCL_DOOR_LOCK_MANUAL_OPERATION_EVENT_MASK_UNKNOWN = (1l << 0), - ZB_ZCL_DOOR_LOCK_MANUAL_OPERATION_EVENT_MASK_THUMBTURN_LOCK = (1l << 1), - ZB_ZCL_DOOR_LOCK_MANUAL_OPERATION_EVENT_MASK_THUMBTURN_UNLOCK = (1l << 2), - ZB_ZCL_DOOR_LOCK_MANUAL_OPERATION_EVENT_MASK_KEY_LOCK = (1l << 4), - ZB_ZCL_DOOR_LOCK_MANUAL_OPERATION_EVENT_MASK_KEY_UNLOCK = (1l << 5), - ZB_ZCL_DOOR_LOCK_MANUAL_OPERATION_EVENT_MASK_MANUAL_LOCK = (1l << 9), - ZB_ZCL_DOOR_LOCK_MANUAL_OPERATION_EVENT_MASK_MANUAL_UNLOCK = (1l << 10), -}; - - -/*! @brief General macro for sending a "Door Lock" cluster command - @param buffer to put command payload and headers to - @param dst_addr address to send to - @param dst_addr_mode destination address mode - @param dst_ep destination endpoint - @param ep source endpoint - @param dis_default_resp "Disable default response" flag - @param cb command send status callback -*/ -#define ZB_ZCL_DOOR_LOCK_SEND_LOCK_DOOR_REQ(buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - dis_default_resp, \ - cb) \ - ZB_ZCL_SEND_CMD( buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - ZB_AF_HA_PROFILE_ID, \ - dis_default_resp, \ - ZB_ZCL_CLUSTER_ID_DOOR_LOCK, \ - ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR, \ - cb) - -/*! @brief General macro for sending a "Door Unlock" cluster command - @param buffer to put command payload and headers to - @param dst_addr address to send to - @param dst_addr_mode destination address mode - @param dst_ep destination endpoint - @param ep source endpoint - @param dis_default_resp "Disable default response" flag - @param cb command send status callback -*/ -#define ZB_ZCL_DOOR_LOCK_SEND_UNLOCK_DOOR_REQ(buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - dis_default_resp, \ - cb) \ - ZB_ZCL_SEND_CMD(buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - ZB_AF_HA_PROFILE_ID, \ - dis_default_resp, \ - ZB_ZCL_CLUSTER_ID_DOOR_LOCK, \ - ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_DOOR, cb) - -/*! @brief Door Lock command send response macro - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq_num - sequence number - @param status - result of command execute - @param aps_secured - APS security mode -*/ -#define ZB_ZCL_DOOR_LOCK_SEND_LOCK_DOOR_RES(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - seq_num, \ - status, \ - aps_secured) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq_num, ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR_RES); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, status); \ - ZB_ZCL_FINISH_N_SEND_PACKET_NEW(buffer, \ - ptr, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - ZB_ZCL_CLUSTER_ID_DOOR_LOCK, \ - NULL, \ - aps_secured, \ - ZB_FALSE, \ - 0); \ -} - -/*! @brief Door Unlock command send response macro - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq_num - sequence number - @param status - result of command execute - @param aps_secured - APS security mode -*/ -#define ZB_ZCL_DOOR_LOCK_SEND_UNLOCK_DOOR_RES(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - seq_num, \ - status, \ - aps_secured) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq_num, ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_DOOR_RES); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, status); \ - ZB_ZCL_FINISH_N_SEND_PACKET_NEW(buffer, \ - ptr, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - ZB_ZCL_CLUSTER_ID_DOOR_LOCK, \ - NULL, \ - aps_secured, \ - ZB_FALSE, \ - 0); \ -} - -/*! Door lock commands response payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_door_lock_read_lock_door_res_payload_s -{ - zb_uint8_t status; /*!< Command execution status */ -} ZB_PACKED_STRUCT zb_zcl_door_lock_read_lock_door_res_payload_t; - -/*! @brief Door Lock response structured reading - @param buffer - ID of the message buffer (of type zb_bufid_t) containing payload - @return pointer to @ref zb_zcl_door_lock_read_lock_door_res_payload_s structure - @attention returned pointer will point to the same data in the buffer thus being valid until - buffer data will be overwritten. -*/ -#define ZB_ZCL_DOOR_LOCK_READ_LOCK_DOOR_RES(buffer) \ - ( (zb_buf_len((buffer)) < sizeof(zb_zcl_door_lock_read_lock_door_res_payload_t)) \ - ? NULL \ - : (zb_zcl_door_lock_read_lock_door_res_payload_t*)zb_buf_begin((buffer))) - -/*! Door unlock commands response payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_door_lock_read_unlock_door_res_payload_s -{ - zb_uint8_t status; /*!< Command execution status */ -} ZB_PACKED_STRUCT zb_zcl_door_lock_read_unlock_door_res_payload_t; - -/*! @brief Door unLock response structured reading - @param buffer - ID of the message buffer (of type zb_buf_t) - containing payload - @return pointer to @ref zb_zcl_door_lock_read_unlock_door_res_payload_s structure - @attention returned pointer will point to the same data in the buffer thus - being valid until buffer data will be overwritten. -*/ -#define ZB_ZCL_DOOR_LOCK_READ_UNLOCK_DOOR_RES(buffer) \ - ( (zb_buf_len((buffer)) < sizeof(zb_zcl_door_lock_read_unlock_door_res_payload_t)) \ - ? NULL \ - : (zb_zcl_door_lock_read_unlock_door_res_payload_t*)zb_buf_begin((buffer))) - -/*! @} */ /* Door Lock cluster commands */ - -/*! @cond internals_doc - @internal @name Door Lock cluster internals - Internal structures for Door Lock cluster - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_ID(data_ptr) \ - { \ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ - } - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_ID(data_ptr) \ - { \ - ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ - } - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_ID(data_ptr) \ - { \ - ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ - } - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_DOOR_LOCK_RF_OPERATION_EVENT_MASK_ID(data_ptr) \ - { \ - ZB_ZCL_ATTR_DOOR_LOCK_RF_OPERATION_EVENT_MASK_ID, \ - ZB_ZCL_ATTR_TYPE_16BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ - } - -/*! @internal @brief Number of attributes mandatory for reporting in Door Lock cluster */ -#define ZB_ZCL_DOOR_LOCK_REPORT_ATTR_COUNT 1 - -/*! @} - @endcond */ /* Door Lock cluster internals */ - -/*! @} */ /* ZCL Door Lock cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_door_lock_init_server(void); -void zb_zcl_door_lock_init_client(void); -#define ZB_ZCL_CLUSTER_ID_DOOR_LOCK_SERVER_ROLE_INIT zb_zcl_door_lock_init_server -#define ZB_ZCL_CLUSTER_ID_DOOR_LOCK_CLIENT_ROLE_INIT zb_zcl_door_lock_init_client - -#endif /* ZB_ZCL_DOOR_LOCK_H */ diff --git a/zboss/development/include/zcl/zb_zcl_drlc.h b/zboss/development/include/zcl/zb_zcl_drlc.h deleted file mode 100644 index 0e2aaef512..0000000000 --- a/zboss/development/include/zcl/zb_zcl_drlc.h +++ /dev/null @@ -1,724 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Demand Response and Load Control cluster definitions -*/ - -#ifndef ZB_ZCL_DRLC_H_ -#define ZB_ZCL_DRLC_H_ - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_DRLC - * @{ - * @details This cluster provides an interface to the functionality of Smart - * Energy Demand Response and Load Control. - */ - - -/* Cluster ZB_ZCL_CLUSTER_ID_DRLC */ - -/** @defgroup ZB_ZCL_DRLC_ATTRS_AND_ENUMS DRLC attributes and enumerations - * @{ - * @details - * This section describes DRLC client attributes and common cluster enumerations. - */ - -/** @brief Default value for DRLC cluster revision global attribute */ -#define ZB_ZCL_DRLC_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief Maximal value for implemented DRLC cluster revision global attribute */ -#define ZB_ZCL_DRLC_CLUSTER_REVISION_MAX ZB_ZCL_DRLC_CLUSTER_REVISION_DEFAULT - -/** DRLC Client attributes. @see SE spec, subclause D.2.3.2 */ -typedef enum zb_zcl_drlc_cli_attr_e -{ - ZB_ZCL_ATTR_DRLC_UTILITY_ENROLLMENT_GROUP = 0x0000, /**< UtilityEnrollmentGroup attribute. - * Provides for utilities to assign devices to groups. - */ - - ZB_ZCL_ATTR_DRLC_START_RANDOMIZATION_MINUTES = 0x0001, /**< StartRandomizationMinutes attribute. - * Represents the maximum number of minutes to be used - * when randomizing the start of an event. - */ - - ZB_ZCL_ATTR_DRLC_DURATION_RANDOMIZATION_MINUTES = 0x0002, /**< DurationRandomizationMinutes attribute. - * Represents the maximum number of minutes to be used - * when randomizing the duration of an event. - */ - - ZB_ZCL_ATTR_DRLC_DEVICE_CLASS_VALUE = 0x0003, /**< DeviceClassValue attribute. - * Identifies which bits the device will match in the - * Device Class fields. - */ -} zb_zcl_drlc_cli_attr_t; - - -/** Criticality Level value applied by the device. - * @see SE spec, Table D-3 - */ -typedef enum zb_zcl_drlc_criticality_levels_e -{ - ZB_ZCL_DRLC_CRITICALITY_LEVEL_0 = 0x00, /**< Reserved */ - ZB_ZCL_DRLC_CRITICALITY_LEVEL_1, /**< Green */ - ZB_ZCL_DRLC_CRITICALITY_LEVEL_2, /**< Level 1 */ - ZB_ZCL_DRLC_CRITICALITY_LEVEL_3, /**< Level 2 */ - ZB_ZCL_DRLC_CRITICALITY_LEVEL_4, /**< Level 3 */ - ZB_ZCL_DRLC_CRITICALITY_LEVEL_5, /**< Level 4 */ - ZB_ZCL_DRLC_CRITICALITY_LEVEL_6, /**< Level 5 */ - ZB_ZCL_DRLC_CRITICALITY_LEVEL_7, /**< Emergency */ - ZB_ZCL_DRLC_CRITICALITY_LEVEL_8, /**< Planned Outage */ - ZB_ZCL_DRLC_CRITICALITY_LEVEL_9 /**< Service Disconnect */ -} zb_zcl_drlc_criticality_levels_t; - -/** DRLC device classes enumeration. - * @see SE spec, Table D-2. - */ -typedef enum zb_zcl_drlc_device_class_e -{ - ZB_ZCL_DRLC_DEVICE_CLASS_HVAC = 1 << 0, /**< HVAC Compressor or Furnace */ - ZB_ZCL_DRLC_DEVICE_CLASS_STRIP_HEATER = 1 << 1, /**< Strip Heaters/Baseboard Heaters */ - ZB_ZCL_DRLC_DEVICE_CLASS_WATER_HEATER = 1 << 2, /**< Water Heater */ - ZB_ZCL_DRLC_DEVICE_CLASS_POOL_PUMP = 1 << 3, /**< Pool Pump/Spa/Jacuzzi */ - ZB_ZCL_DRLC_DEVICE_CLASS_SMART_APPLIANCE = 1 << 4, /**< Smart Appliances */ - ZB_ZCL_DRLC_DEVICE_CLASS_IRRIGATION_PUMP = 1 << 5, /**< Irrigation Pump */ - ZB_ZCL_DRLC_DEVICE_CLASS_MCI_LOADS = 1 << 6, /**< Managed Commercial & Industrial (C&I) loads */ - ZB_ZCL_DRLC_DEVICE_CLASS_SIMPLE_LOADS = 1 << 7, /**< Simple misc. (Residential On/Off) loads */ - ZB_ZCL_DRLC_DEVICE_CLASS_EXTERIOR_LIGHTNING = 1 << 8, /**< Exterior Lighting */ - ZB_ZCL_DRLC_DEVICE_CLASS_INTERIOR_LIGHTNING = 1 << 9, /**< Interior Lighting */ - ZB_ZCL_DRLC_DEVICE_CLASS_ELECTRIC_VEHICLE = 1 << 10, /**< Electric Vehicle */ - ZB_ZCL_DRLC_DEVICE_CLASS_GENERATION_SYSTEMS = 1 << 11 /**< Generation Systems */ -} zb_zcl_drlc_device_class_t; - -/** DRLC Event Status enum - * @see SE spec, Table D-9 - */ -typedef enum zb_zcl_drlc_event_status_e -{ - ZB_ZCL_DRLC_EVENT_RESERVED_00 = 0x00, /**< Reserved for future use. */ - ZB_ZCL_DRLC_EVENT_LCE_RECEIVED, /**< Load Control Event command received */ - ZB_ZCL_DRLC_EVENT_EVENT_STARTED, /**< Event started */ - ZB_ZCL_DRLC_EVENT_EVENT_COMPLETED, /**< Event completed */ - ZB_ZCL_DRLC_EVENT_OPT_OUT, /**< User has chosen to “Opt-Out”, user will not participate in this event */ - ZB_ZCL_DRLC_EVENT_OPT_IN, /**< User has chosen to “Opt-In”, user will participate in this event */ - ZB_ZCL_DRLC_EVENT_EVENT_CANCELLED, /**< The event has been cancelled */ - ZB_ZCL_DRLC_EVENT_EVENT_SUPERSEDED, /**< The event has been superseded */ - ZB_ZCL_DRLC_EVENT_EVENT_PARTIALLY_OPT_OUT, /**< Event partially completed with User “Opt-Out”. */ - ZB_ZCL_DRLC_EVENT_EVENT_PARTIALLY_OPT_IN, /**< Event partially completed due to User “Opt-In”. */ - ZB_ZCL_DRLC_EVENT_EVENT_COMPLETED_NO_USER, /**< Event completed, no User participation (Previous “Opt-Out”). */ - ZB_ZCL_DRLC_EVENT_RESERVED_0B, /**< Reserved for future use. */ - ZB_ZCL_DRLC_EVENT_RESERVED_F7 = 0xF7, /**< Reserved for future use. */ - ZB_ZCL_DRLC_EVENT_REJECTED_INVALID_CANCEL_CMD, /**< Rejected - Invalid Cancel Command (Default) */ - ZB_ZCL_DRLC_EVENT_REJECTED_INVALID_EFFECTIVE_TIME, /**< Rejected - Invalid Cancel Command (Invalid Effective Time) */ - ZB_ZCL_DRLC_EVENT_RESERVED_FA, /**< Reserved */ - ZB_ZCL_DRLC_EVENT_REJECTED_EXPIRED, /**< Rejected - Event was received after it had expired@n (Current Time > Start Time + Duration) */ - ZB_ZCL_DRLC_EVENT_RESERVED_FC, /**< Reserved for future use. */ - ZB_ZCL_DRLC_EVENT_REJECTED_UNDEFINED_EVENT, /**< Rejected - Invalid Cancel Command (Undefined Event) */ - ZB_ZCL_DRLC_EVENT_REJECTED, /**< Load Control Event command Rejected */ - ZB_ZCL_DRLC_EVENT_RESERVED_FF /**< Reserved for future use. */ -} zb_zcl_drlc_event_status_t; - -/** DRLC signature type enum */ -typedef enum zb_zcl_drlc_signature_type_e -{ - ZB_ZCL_DRLC_LCE_NO_SIGNATURE = 0x00, /**< No Signature */ - ZB_ZCL_DRLC_LCE_SIGNATURE_ECDSA, /**< ECDSA */ - ZB_ZCL_DRLC_LCE_SIGNATURE_RESERVED /**< Reserved */ -} zb_zcl_drlc_signature_type_t; - -/** @} */ /* ZB_ZCL_DRLC_ATTRS_AND_ENUMS */ - - -/** @defgroup ZB_ZCL_DRLC_COMMANDS_STRUCTURES_AND_DEFINITIONS DRLC commands - * @{ - * @details - * This section describes all commands structures and data payloads. - */ - - -/** Commands are generated by DRLC Server. - * @see SE spec, Table D-1 - */ -typedef enum zb_zcl_drlc_srv_cmd_e -{ - ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT = 0x00, /**< LoadControlEvent is generated when the ESI wants to control one or more - * load control devices usually as the result of an energy curtailment - * command from the Smart Energy Network. - * @see zb_zcl_drlc_lce_payload_s - */ - - ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT = 0x01, /**< CancelLoadControlEvent is generated when the ESI wants to cancel - * previously scheduled control of one or more load control devices, usually - * as the result of an energy curtailment command from the Smart Energy - * Network - * @see zb_zcl_drlc_cancel_lce_payload_s - */ - - ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS = 0x02, /**< CancellAllLoadControlEvents is generated when the ESI wants to cancel all - * events for control device(s) - */ -} zb_zcl_drlc_srv_cmd_t; - - -/** Commands are generated by DRLC Client. - * @see SE spec, Table D-8 - */ -typedef enum zb_zcl_drlc_cli_cmd_e -{ - ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS = 0x00, /**< ReportEventStatus is generated when the client device detects a change of - * state for an active LoadControl event. - * @see zb_zcl_drlc_report_event_status_payload_s - */ - - ZB_ZCL_DRLC_CLI_CMD_GET_SCHEDULED_EVENTS = 0x01, /**< GetScheduledEvents is generated when the client device wishes to verify - * the available LoadControl events. - * @see zb_zcl_drlc_get_scheduled_events_payload_s - */ -} zb_zcl_drlc_cli_cmd_t; - -/** @cond internals_doc */ -/* DRLC cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_DRLC_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT, \ - ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT, \ - ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS - -#define ZB_ZCL_CLUSTER_ID_DRLC_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_DRLC_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_DRLC_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS, \ - ZB_ZCL_DRLC_CLI_CMD_GET_SCHEDULED_EVENTS - -#define ZB_ZCL_CLUSTER_ID_DRLC_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_DRLC_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/* Payload description */ - -/** @ref ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT "LoadControlEvent" command payload. - * @see SE spec, Figure D-2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_drlc_lce_payload_s { - - /** Unique identifier generated by the Energy provider. - * The value of this field allows matching of Event reports - * with a specific Demand Response and Load Control event. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** Bit encoded field representing the Device Class to apply the - * current Load Control Event. Each bit, if set individually or - * in combination, indicates the class device(s) needing to - * participate in the event. - */ - zb_uint16_t device_class; /* (M) */ - - /** This field can be used in conjunction with the Device Class bits - * for providing a mechanism to direct Load Control Events - * to groups of Devices. - */ - zb_uint8_t utility_enrollment_group; /* (M) */ - - /** UTC Timestamp representing when the event is scheduled to start. - * A start time of 0x00000000 is a special time denoting “now.” - */ - zb_uint32_t start_time; /* (M) */ - - /** Duration of this event in number of minutes. - * Maximum value is 1440 (one day). - */ - zb_uint16_t duration_in_minutes; /* (M) */ - - /** This field defines the level of criticality of event. The - * action for an event can be solely based on this value, - * or combination with other Load Control Event fields. - */ - zb_uint8_t criticality_level; /* (M) */ - - /** Requested offset to apply to the normal cooling setpoint - * at the time of the start of the event in + 0.1 Celsius. - */ - zb_uint8_t cooling_temperature_offset; /* (O) - use 0xff if optional */ - - /** Requested offset to apply to the normal heating setpoint - * at the time of the start of the event in + 0.1 Celsius. - */ - zb_uint8_t heating_temperature_offset; /* (O) - use 0xff if optional */ - - /** Requested cooling set point in 0.01 degrees Celsius. */ - zb_int16_t cooling_temperature_set_point; /* (O) - use 0x8000 if optional */ - - /** Requested heating set point in 0.01 degrees Celsius. */ - zb_int16_t heating_temperature_set_point; /* (O) - use 0x8000 if optional */ - - /** Defines a maximum energy usage limit as a percentage of - * the client implementations specific average energy usage. - */ - zb_int8_t average_load_adjustment_percentage; /* (O) */ - - /** Defines the maximum on state duty cycle as a percentage of time. */ - zb_uint8_t duty_cycle; /* (O) */ - - /** Identifies additional control options for the event. */ - zb_uint8_t event_control; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_drlc_lce_payload_t; - -/** @def ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT_IS_VALID - */ -#define ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT_IS_VALID(size) \ - ((size) >= sizeof(zb_zcl_drlc_lce_payload_t)) - -/** @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT "CancelLoadControlEvent" command payload - * @see SE spec, Figure D-3 - */ -typedef ZB_PACKED_PRE struct zb_zcl_drlc_cancel_lce_payload_s { - /* Mandatory fields. */ - - /** Unique identifier generated by the Energy provider. The value of - * this field allows matching of Event reports with a specific Demand Response - * and Load Control event. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** Bit encoded field representing the Device Class to apply the - * current Load Control Event. Each bit, if set individually or in combination, - * indicates the class device(s) needing to participate in the event. - */ - zb_uint16_t device_class; /* (M) */ - - /** This field can be used in conjunction with the Device Class bits - * for providing a mechanism to direct Load Control Events - * to groups of Devices. - */ - zb_uint8_t utility_enrollment_group; /* (M) */ - - /** This field is used to indicate that the Event is currently in process and - * a cancel command is received.*/ - zb_uint8_t cancel_control; /* (M) */ - - /** UTC Timestamp representing when the canceling of the event is - * scheduled to start. An effective time of 0x00000000 is a special - * time denoting “now.” - */ - zb_uint32_t effective_time; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_drlc_cancel_lce_payload_t; - -/** @def ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT_IS_VALID - */ -#define ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT_IS_VALID(size) \ - ((size) >= sizeof(zb_zcl_drlc_cancel_lce_payload_t)) - - -/** @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS "CancelAllLoadControlEvents" command payload - * @see SE spec, Figure D-3 - */ -typedef ZB_PACKED_PRE struct zb_zcl_drlc_cancel_alce_payload_s { - /* Mandatory fields. */ - - /** Where the Cancel Control field indicates that randomization is to be used, the receiving device should first - * check whether Duration Time was to be randomized and, if so, termination of the event should be adjusted - * according to the value of the DurationRandomizationMinutes attribute. - */ - zb_uint8_t cancel_control; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_drlc_cancel_alce_payload_t; - -/** @def ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS_IS_VALID - */ -#define ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS_IS_VALID(size) \ - ((size) >= sizeof(zb_zcl_drlc_cancel_alce_payload_t)) - -/** @ref ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS "ReportEventStatus" command payload - * @see SE spec, Figure D-5 - */ -typedef ZB_PACKED_PRE struct zb_zcl_drlc_report_event_status_payload_s { - /* Mandatory fields. */ - - /** Unique identifier generated by the Energy provider. The value of - * this field allows matching of Event reports with a specific Demand Response - * and Load Control event. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** This field stores value from set of event statuses*/ - zb_uint8_t event_status; /* (M) */ - - /** UTC Timestamp representing when the event status - * occurred. This field shall not use the value of 0x00000000. - */ - zb_uint32_t event_status_time; /* (M) */ - - /** Criticality Level value applied by the device */ - zb_uint8_t criticality_level_applied; /* (M) */ - - /** Defines Cooling Temperature Set Point value applied by the device. - * The value 0x8000 means that this field has not been used by the end device. - */ - zb_uint16_t cooling_temperature_set_point_applied; /* (O) */ - - /** Defines Heating Temperature Set Point value applied by the device. - * The value 0x8000 means that this field has not been used by - * the end device. - */ - zb_uint16_t heating_temperature_set_point_applied; /* (O) */ - - /** Defines Average Load Adjustment Percentage value applied by the device. - * The value 0x80 means that this field has not been used by the end device. - */ - zb_int8_t average_load_adjustment_percentage_applied; /* (O) */ - - /** Defines the maximum on state duty cycle applied by the device. - * The value 0xFF means that this field has not been used by the end device. - */ - zb_uint8_t duty_cycle_applied; /* (O) */ - - /** Identifies additional control options for the event. */ - zb_uint8_t event_control; /* (M) */ - - /** This field is used to enumerate the type of algorithm use to create the signature.*/ - zb_uint8_t signature_type; /* (M) */ - - /** A non-repudiation signature created by using the Matyas-Meyer-Oseas - * hash function used in conjunction with ECDSA. - */ - zb_uint8_t signature[42]; /* (O) */ -} ZB_PACKED_STRUCT zb_zcl_drlc_report_event_status_payload_t; - -/** @def ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS_IS_VALID - */ -#define ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS_IS_VALID(size) \ - ((size) >= sizeof(zb_zcl_drlc_report_event_status_payload_t)) - -/** @ref ZB_ZCL_DRLC_CLI_CMD_GET_SCHEDULED_EVENTS "GetScheduledEvents" command payload - * @see SE spec, Figure D-6 - */ -typedef ZB_PACKED_PRE struct zb_zcl_drlc_get_scheduled_events_payload_s { - /* Mandatory fields. */ - - /** UTC Timestamp representing the minimum Start Time of events that shall be - * matched and sent by the Server. A Start Time of 0x00000000 has no special - * meaning. - */ - zb_uint32_t start_time; /* (M) */ - - /** Represents the maximum number of events to be sent. A value of 0 indicates - * no maximum limit. - */ - zb_uint8_t number_of_events; /* (M) */ - - /** Represents the minimum Issuer Event ID of events to be matched and sent - * by the server with the same Start Time as the Get Scheduled Events command. - * A value of 0xFFFFFFFF indicates this field will not be used. - */ - zb_uint32_t issuer_event_id; /* (O) */ -} ZB_PACKED_STRUCT zb_zcl_drlc_get_scheduled_events_payload_t; - -/** Initialize @ref ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT "LoadControlEvent" command @ref zb_zcl_drlc_lce_payload_t payload*/ -#define ZB_ZCL_DRLC_LCE_PAYLOAD_INIT \ - (zb_zcl_drlc_lce_payload_t) \ -{ \ - .cooling_temperature_offset = 0xFF, \ - .heating_temperature_offset = 0xFF, \ - .cooling_temperature_set_point = (zb_int16_t) 0x8000, \ - .heating_temperature_set_point = (zb_int16_t) 0x8000, \ - .average_load_adjustment_percentage = (zb_int8_t) 0x80, \ - .duty_cycle = 0xFF, \ -} - -/** Initialize @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT "CancelLoadControlEvent" command @ref zb_zcl_drlc_cancel_lce_payload_t payload */ -#define ZB_ZCL_DRLC_CANCEL_LCE_PAYLOAD_INIT \ - (zb_zcl_drlc_cancel_lce_payload_t) {0} - -/** Initialize @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS "CancelAllLoadControlEvents" command @ref zb_zcl_drlc_cancel_alce_payload_t payload */ -#define ZB_ZCL_DRLC_CANCEL_ALCE_PAYLOAD_INIT \ - (zb_zcl_drlc_cancel_alce_payload_t) {0} - -/** Initialize @ref ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS "ReportEventStatus" command @ref zb_zcl_drlc_report_event_status_payload_t payload */ -#define ZB_ZCL_DRLC_REPORT_EVENT_STATUS_PAYLOAD_INIT \ - (zb_zcl_drlc_report_event_status_payload_t) \ -{ \ - .cooling_temperature_set_point_applied = (zb_uint16_t) 0x8000, \ - .heating_temperature_set_point_applied = (zb_uint16_t) 0x8000, \ - .average_load_adjustment_percentage_applied = (zb_int8_t) 0x80, \ - .duty_cycle_applied = (zb_uint8_t) 0xFF, \ - .signature = \ - { \ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ - }, \ -} - -/** Check if some size in range of variable size of specified payload. - */ -#define ZB_ZCL_DRLC_GET_SCHEDULED_EVENTS_PAYLOAD_SIZE_IS_VALID(size) \ -((size) >= ((zb_int16_t)sizeof(zb_zcl_drlc_get_scheduled_events_payload_t) - \ -(zb_int16_t)ZB_SIZEOF_FIELD(zb_zcl_drlc_get_scheduled_events_payload_t, issuer_event_id))) - -/** Initialize @ref ZB_ZCL_DRLC_CLI_CMD_GET_SCHEDULED_EVENTS "GetScheduledEvents" command @ref zb_zcl_drlc_get_scheduled_events_payload_t payload */ -#define ZB_ZCL_DRLC_CMD_GET_SCHEDULED_EVENTS_PAYLOAD_INIT \ - (zb_zcl_drlc_get_scheduled_events_payload_t) \ -{ \ - .issuer_event_id = 0xFFFFFFFF, \ -} - - -/** Function for send @ref ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT "LoadControlEvent" command. - * On sender's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with @ref ZB_ZCL_DRLC_GET_SCHEDULED_EVENTS_CB_ID - * callback id on reception of @ref ZB_ZCL_DRLC_CLI_CMD_GET_SCHEDULED_EVENTS "GetScheduledEvents" command. - * @n On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_DRLC_LOAD_CONTROL_EVENT_CB_ID callback id. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (@ref zb_zcl_drlc_lce_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - * @par Usage - * @n Handle @ref ZB_ZCL_DRLC_GET_SCHEDULED_EVENTS_CB_ID - * @snippet se/energy_service_interface/se_esi_zc.c handle_get_scheduled_events - * @n Example of sending @ref ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT "LoadControlEvent" command - * @snippet se/energy_service_interface/se_esi_zc.c esi_dev_cmd_send_lce_event1 - */ -void zb_drlc_server_send_load_control_event(zb_uint8_t param, - zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_zcl_drlc_lce_payload_t *payload, zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT "CancelLoadControlEvent" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_DRLC_CANCEL_LOAD_CONTROL_EVENT_CB_ID - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (@ref zb_zcl_drlc_cancel_lce_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - * @par Usage - * @n Example of sending @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT "CancelLoadControlEvent" command - * @snippet se/energy_service_interface/se_esi_zc.c esi_dev_cmd_send_lce_event2 - */ -void zb_drlc_server_send_cancel_load_control_event(zb_uint8_t param, - zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_zcl_drlc_cancel_lce_payload_t *payload, zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS "CancellAllLoadControlEvents" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_DRLC_CANCEL_ALL_LOAD_CONTROL_EVENTS_CB_ID - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload: pointer to zb_uint8_t, where - * "Cancel Control" field value is placed (see SE spec, D.2.2.3.3.1). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - * @par Usage - * @n Example of sending @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS "CancellAllLoadControlEvents" command - * @snippet se/energy_service_interface/se_esi_zc.c esi_dev_cmd_send_lce_event3 - */ -void zb_drlc_server_send_cancel_all_load_control_events(zb_uint8_t param, - zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_uint8_t *payload, zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS "ReportEventStatus" command. - * On sender's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with one of @ref ZB_ZCL_DRLC_LOAD_CONTROL_EVENT_CB_ID, - * @ref ZB_ZCL_DRLC_CANCEL_LOAD_CONTROL_EVENT_CB_ID, @ref ZB_ZCL_DRLC_CANCEL_ALL_LOAD_CONTROL_EVENTS_CB_ID - * callback ids on reception of @ref ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT "LoadControlEvent", - * @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT "CancelLoadControlEvent", - * @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS "CancellAllLoadControlEvents" commands respectively. - * @n On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_DRLC_REPORT_EVENT_STATUS_CB_ID callback id. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (@ref zb_zcl_drlc_report_event_status_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - * @par Usage - * @n Handle @ref ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS "CancellAllLoadControlEvents" command - * @snippet se/in_home_display/se_ihd_zr.c ihd_handle_cancel_all_load_control_events - * @n Example of sending @ref ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS "ReportEventStatus" command - * @snippet se/in_home_display/se_ihd_zr.c ihd_send_report_event_status - */ -void zb_drlc_client_send_report_event_status(zb_uint8_t param, - zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_zcl_drlc_report_event_status_payload_t *payload, zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_DRLC_CLI_CMD_GET_SCHEDULED_EVENTS "GetScheduledEvents" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_DRLC_GET_SCHEDULED_EVENTS_CB_ID callback id. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (@ref zb_zcl_drlc_get_scheduled_events_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - * @par Usage - * @n Example of sending @ref ZB_ZCL_DRLC_CLI_CMD_GET_SCHEDULED_EVENTS "GetScheduledEvents" - * @snippet se/in_home_display/se_ihd_zr.c ihd_dev_cmd_get_scheduled_events - */ -void zb_drlc_client_send_get_scheduled_events(zb_uint8_t param, - zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_zcl_drlc_get_scheduled_events_payload_t *payload, zb_callback_t cb); - -/** Macro for call @ref zb_drlc_server_send_load_control_event function - */ -#define ZB_ZCL_DRLC_SEND_CMD_LOAD_CONTROL_EVENT(_param, \ - _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload ) \ - zb_drlc_server_send_load_control_event(_param, \ - _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload, NULL) - -/** Macro for call @ref zb_drlc_server_send_cancel_load_control_event function - */ -#define ZB_ZCL_DRLC_SEND_CMD_CANCEL_LCE(_param, \ - _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload ) \ - zb_drlc_server_send_cancel_load_control_event(_param, \ - _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload, NULL) - -/** Macro for call @ref zb_drlc_server_send_cancel_all_load_control_events function - */ -#define ZB_ZCL_DRLC_SEND_CMD_CANCEL_ALL_LCE(_param, \ - _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload ) \ - zb_drlc_server_send_cancel_all_load_control_events(_param, \ - _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload, NULL) - -/** Macro for call @ref zb_drlc_client_send_get_scheduled_events function - */ -#define ZB_ZCL_DRLC_SEND_CMD_GET_SCHEDULED_EVENTS(_param, \ - _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload ) \ - zb_drlc_client_send_get_scheduled_events(_param, \ - _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload, NULL) - -/** Macro for call @ref zb_drlc_client_send_report_event_status function - */ -#define ZB_ZCL_DRLC_SEND_CMD_REPORT_EVENT_STATUS( _param, \ - _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload ) \ - zb_drlc_client_send_report_event_status(_param, \ - _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload, NULL) - - -/** @} */ /* ZB_ZCL_DRLC_COMMANDS_STRUCTURES_AND_DEFINITIONS */ - -/** @brief Declare attribute list for DRLC cluster - * @param[in] attr_list - attribute list variable name - * @param[in] utility_enrollment_group - pointer to variable to store @ref ZB_ZCL_ATTR_DRLC_UTILITY_ENROLLMENT_GROUP value - * @param[in] start_randomization_munutes - pointer to variable to store @ref ZB_ZCL_ATTR_DRLC_START_RANDOMIZATION_MINUTES value - * @param[in] duration_randomization_minutes - pointer to variable to store @ref ZB_ZCL_ATTR_DRLC_DURATION_RANDOMIZATION_MINUTES value - * @param[in] device_class - pointer to variable to store @ref ZB_ZCL_ATTR_DRLC_DEVICE_CLASS_VALUE value - */ - #define ZB_ZCL_DECLARE_DRLC_ATTRIB_LIST(attr_list, utility_enrollment_group, \ - start_randomization_munutes, duration_randomization_minutes, device_class) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_DRLC) \ - ZB_ZCL_SET_ATTR_DESC_M(ZB_ZCL_ATTR_DRLC_UTILITY_ENROLLMENT_GROUP, (utility_enrollment_group), ZB_ZCL_ATTR_TYPE_8BIT, ZB_ZCL_ATTR_ACCESS_READ_WRITE) \ - ZB_ZCL_SET_ATTR_DESC_M(ZB_ZCL_ATTR_DRLC_START_RANDOMIZATION_MINUTES, (start_randomization_munutes), ZB_ZCL_ATTR_TYPE_8BIT, ZB_ZCL_ATTR_ACCESS_READ_WRITE) \ - ZB_ZCL_SET_ATTR_DESC_M(ZB_ZCL_ATTR_DRLC_DURATION_RANDOMIZATION_MINUTES, (duration_randomization_minutes), ZB_ZCL_ATTR_TYPE_8BIT, ZB_ZCL_ATTR_ACCESS_READ_WRITE) \ - ZB_ZCL_SET_ATTR_DESC_M(ZB_ZCL_ATTR_DRLC_DEVICE_CLASS_VALUE, (device_class), ZB_ZCL_ATTR_TYPE_16BIT, ZB_ZCL_ATTR_ACCESS_READ_WRITE) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - - -/** Initialize @ref zb_zcl_drlc_client_attrs_s DRLC cluster's attributes */ -#define ZB_ZCL_DECLARE_DRLC_ATTR_LIST_INIT \ - (zb_zcl_drlc_client_attrs_t) \ - { .utility_enrollment_group = 0, \ - .start_randomization_munutes = 0x1e, \ - .duration_randomization_minutes = 0, } - - -/** - * @brief DRLC client cluster attributes - */ -typedef struct zb_zcl_drlc_client_attrs_s -{ - /** @copydoc ZB_ZCL_ATTR_DRLC_UTILITY_ENROLLMENT_GROUP - * @see ZB_ZCL_ATTR_DRLC_UTILITY_ENROLLMENT_GROUP - */ - zb_uint8_t utility_enrollment_group; - - /** @copydoc ZB_ZCL_ATTR_DRLC_START_RANDOMIZATION_MINUTES - * @see ZB_ZCL_ATTR_DRLC_START_RANDOMIZATION_MINUTES - */ - zb_uint8_t start_randomization_munutes; - - /** @copydoc ZB_ZCL_ATTR_DRLC_DURATION_RANDOMIZATION_MINUTES - * @see ZB_ZCL_ATTR_DRLC_DURATION_RANDOMIZATION_MINUTES - */ - zb_uint8_t duration_randomization_minutes; - - /** @copydoc ZB_ZCL_ATTR_DRLC_DEVICE_CLASS_VALUE - * @see ZB_ZCL_ATTR_DRLC_DEVICE_CLASS_VALUE - */ - zb_uint16_t device_class_value; -} zb_zcl_drlc_client_attrs_t; - - -/** @brief Declare attribute list for DRLC cluster - * @param[in] attr_list - attribute list variable name - * @param[in] attrs - variable of @ref zb_zcl_drlc_client_attrs_t type (containing DRLC cluster attributes) - */ -#define ZB_ZCL_DECLARE_DRLC_ATTR_LIST(attr_list, attrs) \ - ZB_ZCL_DECLARE_DRLC_ATTRIB_LIST(attr_list, &attrs.utility_enrollment_group, \ - &attrs.start_randomization_munutes, &attrs.duration_randomization_minutes, \ - &attrs.device_class_value) - -/** @} */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ -/** Internal handler for DRLC Cluster commands */ - -void zb_zcl_drlc_init_server(void); -void zb_zcl_drlc_init_client(void); -#define ZB_ZCL_CLUSTER_ID_DRLC_SERVER_ROLE_INIT zb_zcl_drlc_init_server -#define ZB_ZCL_CLUSTER_ID_DRLC_CLIENT_ROLE_INIT zb_zcl_drlc_init_client - -#endif /* ZB_ZCL_DRLC_H_ */ diff --git a/zboss/development/include/zcl/zb_zcl_el_measurement.h b/zboss/development/include/zcl/zb_zcl_el_measurement.h deleted file mode 100644 index 6a7f92ab7a..0000000000 --- a/zboss/development/include/zcl/zb_zcl_el_measurement.h +++ /dev/null @@ -1,939 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Electrical Measurement cluster definitions -*/ - -#ifndef ZB_ZCL_ELECTRICAL_MEASUREMENT_H -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond DOXYGEN_ZCL_SECTION */ - -/* Cluster ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT */ - -/*! @addtogroup ZB_ZCL_ELECTRICAL_MEASUREMENT - @{ - @name Electrical Measurement cluster attributes - @{ -*/ - -/** @brief Default value for Electrical Measurement cluster revision global attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/*! @brief Electrical Measurement cluster attribute identifiers - @see HA spec, subclause 9.2.2.2 -*/ -enum zb_zcl_electrical_measurement_attr_e -{ - /** This attribute indicates a device s measurement capabilities. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASUREMENT_TYPE_ID = 0x0000, - /** The DCVoltage attribute represents the most recent DC voltage reading in Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_ID = 0x0100, - /** The DCVoltageMin attribute represents the lowest DC voltage value measured in Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MIN_ID = 0x0101, - /** The DCVoltageMax attribute represents the highest DC voltage value measured in Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MAX_ID = 0x0102, - /** The DCCurrent attribute represents the most recent DC current reading in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_ID = 0x0103, - /** The DCCurrentMin attribute represents the lowest DC current value measured in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MIN_ID = 0x0104, - /** The DCCurrentMax attribute represents the highest DC current value measured in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MAX_ID = 0x0105, - /** The @e DCPower attribute represents the most recent DC power reading in @e Watts (W) */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DCPOWER_ID = 0x0106, - /** The DCPowerMin attribute represents the lowest DC power value measured in Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MIN_ID = 0x0107, - /** The DCPowerMax attribute represents the highest DC power value measured in Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MAX_ID = 0x0108, - /** The DCVoltageMultiplier provides a value to be multiplied against the DCVoltage, - * DCVoltageMin, and DCVoltageMax attributes. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MULTIPLIER_ID = 0x0200, - /** The DCVoltageDivisor provides a value to be divided against the DCVoltage, - * DCVoltageMin, and DCVoltageMax attributes. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_DIVISOR_ID = 0x0201, - /** The DCCurrentMultiplier provides a value to be multiplied against the DCCurrent, - * DCCurrentMin, and DCCurrentMax attributes. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_MULTIPLIER_ID = 0x0202, - /** The DCCurrentDivisor provides a value to be divided against the DCCurrent, - * DCCurrentMin, and DCCurrentMax attributes. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_DIVISOR_ID = 0x0203, - /** The DCPowerMultiplier provides a value to be multiplied against the DCPower, - * DCPowerMin, and DCPowerMax attributes. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_MULTIPLIER_ID = 0x0204, - /** The DCPowerDivisor provides a value to be divided against the DCPower, - * DCPowerMin, and DCPowerMax attributes. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_POWER_DIVISOR_ID = 0x0205, - /** The ACFrequency attribute represents the most recent AC Frequency reading in Hertz (Hz). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_ID = 0x0300, - /** The ACFrequencyMin attribute represents the lowest AC Frequency value measured in Hertz (Hz). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MIN_ID = 0x0301, - /** The ACFrequencyMax attribute represents the highest AC Frequency value measured in Hertz (Hz). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MAX_ID = 0x0302, - /** The NeutralCurrent attribute represents the AC neutral (Line-Out) current value - * at the moment in time the attribute is read, in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_NEUTRAL_CURRENT_ID = 0x0303, - /** Active power represents the current demand of active power delivered or - * received at the premises, in @e kW */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_TOTAL_ACTIVE_POWER_ID = 0x0304, - /** Reactive power represents the current demand of reactive power delivered or - * received at the premises, in kVAr. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_TOTAL_REACTIVE_POWER_ID = 0x0305, - /** Represents the current demand of apparent power, in @e kVA */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_TOTAL_APPARENT_POWER_ID = 0x0306, - /** Attribute represent the most recent 1st harmonic current reading in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED1ST_HARMONIC_CURRENT_ID = 0x0307, - /** Attribute represent the most recent 3rd harmonic current reading in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED3RD_HARMONIC_CURRENT_ID = 0x0308, - /** Attribute represent the most recent 5th harmonic current reading in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED5TH_HARMONIC_CURRENT_ID = 0x0309, - /** Attribute represent the most recent 7th harmonic current reading in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED7TH_HARMONIC_CURRENT_ID = 0x030a, - /** Attribute represent the most recent 9th harmonic current reading in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED9TH_HARMONIC_CURRENT_ID = 0x030b, - /** Attribute represent the most recent 11th harmonic current reading in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED11TH_HARMONIC_CURRENT_ID = 0x030c, - /** Attribute represent the most recent phase of the 1st harmonic current reading - * in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED_PHASE1ST_HARMONIC_CURRENT_ID = 0x030d, - /** Attribute represent the most recent phase of the 3rd harmonic current reading - * in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED_PHASE3RD_HARMONIC_CURRENT_ID = 0x030e, - /** Attribute represent the most recent phase of the 5th harmonic current reading - * in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED_PHASE5TH_HARMONIC_CURRENT_ID = 0x030f, - /** Attribute represent the most recent phase of the 7th harmonic current reading - * in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED_PHASE7TH_HARMONIC_CURRENT_ID = 0x0310, - /** Attribute represent the most recent phase of the 9th harmonic current reading - * in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED_PHASE9TH_HARMONIC_CURRENT_ID = 0x0311, - /** Attribute represent the most recent phase of the 11th harmonic current reading - * in an AC frequency. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASURED_PHASE11TH_HARMONIC_CURRENT_ID = 0x0312, - /** Provides a value to be multiplied against the ACFrequency attribute. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MULTIPLIER_ID = 0x0400, - /** Provides a value to be divided against the ACFrequency attribute. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_DIVISOR_ID = 0x0401, - /** Provides a value to be multiplied against a raw or uncompensated - * sensor count of power being measured by the metering device. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_MULTIPLIER_ID = 0x0402, - /** Provides a value to divide against the results of applying the - * @e Multiplier attribute against a raw or uncompensated sensor - * count of power being measured by the metering device. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_DIVISOR_ID = 0x0403, - /** Represents the unit value for the MeasuredNthHarmonicCurrent attribute in the - * format MeasuredNthHarmonicCurrent * 10 ^ HarmonicCurrentMultiplier amperes. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_HARMONIC_CURRENT_MULTIPLIER_ID = 0x0404, - /** Represents the unit value for the MeasuredPhaseNthHarmonicCurrent attribute in - * the format MeasuredPhaseNthHarmonicCurrent * 10 ^ PhaseHarmonicCurrentMultiplier - * degrees. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_PHASE_HARMONIC_CURRENT_MULTIPLIER_ID = 0x0405, - /** Represents the single phase or Phase A, AC line current (Square root of active and - * reactive current) value at the moment in time the attribute is read, in @e Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_LINE_CURRENT_ID = 0x0501, - /** Represents the single phase or Phase A, AC active/resistive current value at the - * moment in time the attribute is read, in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_CURRENT_ID = 0x0502, - /** Represents the single phase or Phase A, AC reactive current value at the moment - * in time the attribute is read, in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_REACTIVE_CURRENT_ID = 0x0503, - /** Represents the most recent RMS voltage reading in @e Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID = 0x0505, - /** Represents the lowest RMS voltage value measured in Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_ID = 0x0506, - /** Represents the highest RMS voltage value measured in Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_ID = 0x0507, - /** Represents the most recent RMS current reading in @e Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID = 0x0508, - /** Represents the lowest RMS current value measured in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_ID = 0x0509, - /** Represents the highest RMS current value measured in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_ID = 0x050a, - /** Represents the single phase or Phase A, current demand of active power delivered or - * received at the premises, in @e Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID = 0x050B, - /** Represents the lowest AC power value measured in Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_ID = 0x050c, - /** Represents the highest AC power value measured in Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_ID = 0x050d, - /** Represents the single phase or Phase A, current demand of reactive power delivered - * or received at the premises, in VAr. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_REACTIVE_POWER_ID = 0x050e, - /** Represents the single phase or Phase A, current demand of apparent (Square root - * of active and reactive power) power, in @e VA. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_APPARENT_POWER_ID = 0x050F, - /** Contains the single phase or PhaseA, Power Factor ratio in 1/100th. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID = 0x0510, - /** The Period in seconds that the RMS voltage is averaged over. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMSVOLTAGE_MEASUREMENT_PERIOD_ID = 0x0511, - /** The number of times the average RMS voltage, has been above the AverageRMS - * OverVoltage threshold since last reset. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_OVER_VOLTAGE_COUNTER_ID = 0x0512, - /** The number of times the average RMS voltage, has been below the AverageRMS - * underVoltage threshold since last reset. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_UNDER_VOLTAGE_COUNTER_ID = 0x0513, - /** The duration in seconds used to measure an extreme over voltage condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_EXTREME_OVER_VOLTAGE_PERIOD_ID = 0x0514, - /** The duration in seconds used to measure an extreme under voltage condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_EXTREME_UNDER_VOLTAGE_PERIOD_ID = 0x0515, - /** The duration in seconds used to measure a voltage sag condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SAG_PERIOD_ID = 0x0516, - /** The duration in seconds used to measure a voltage swell condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SWELL_PERIOD_ID = 0x0517, - /** Provides a value to be multiplied against the @e InstantaneousVoltage and @e - * RMSVoltage attributes. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_MULTIPLIER_ID = 0x0600, - /** Provides a value to be divided against the @e InstantaneousVoltage and - * @e RMSVoltage attributes. This attribute must be used in conjunction with the @e - * ACVoltageMultiplier attribute. 0x0000 is an invalid value for this attribute. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_DIVISOR_ID = 0x0601, - /** Provides a value to be multiplied against the @e InstantaneousCurrent and @e - * RMSCurrent attributes */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_MULTIPLIER_ID = 0x0602, - /** Provides a value to be divided against the @e ACCurrent, @e InstantaneousCurrent - * and @e RMSCurrent attributes. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_DIVISOR_ID = 0x0603, - /** Provides a value to be multiplied against the @e InstantaneousPower and @e - * ActivePower attributes */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_MULTIPLIER_ID = 0x0604, - /** Provides a value to be divided against the @e InstantaneousPower and @e - * ActivePower attributes. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_DIVISOR_ID = 0x0605, - /** Specifies which configurable alarms may be generated. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_OVERLOAD_ALARMS_MASK_ID = 0x0700, - /** Specifies the alarm threshold, set by the manufacturer, for the maximum output - * voltage supported by device. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_OVERLOAD_ID = 0x0701, - /** Specifies the alarm threshold, set by the manufacturer, for the maximum output - * current supported by device. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DC_CURRENT_OVERLOAD_ID = 0x0702, - /** Specifies which configurable alarms may be generated. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_ALARMS_MASK_ID = 0x0800, - /** Specifies the alarm threshold, set by the manufacturer, for the maximum output - * voltage supported by device. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_VOLTAGE_OVERLOAD_ID = 0x0801, - /** Specifies the alarm threshold, set by the manufacturer, for the maximum output - * current supported by device. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_CURRENT_OVERLOAD_ID = 0x0802, - /** Specifies the alarm threshold, set by the manufacturer, for the maximum output - * active power supported by device. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_ACTIVE_POWER_OVERLOAD_ID = 0x0803, - /** Specifies the alarm threshold, set by the manufacturer, for the maximum output - * reactive power supported by device. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AC_REACTIVE_POWER_OVERLOAD_ID = 0x0804, - /** The average RMS voltage above which an over voltage condition is reported. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_OVER_VOLTAGE_ID = 0x0805, - /** The average RMS voltage below which an under voltage condition is reported. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_UNDER_VOLTAGE_ID = 0x0806, - /** The RMS voltage above which an extreme under voltage condition is reported. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_EXTREME_OVER_VOLTAGE_ID = 0x0807, - /** The RMS voltage below which an extreme under voltage condition is reported. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_EXTREME_UNDER_VOLTAGE_ID = 0x0808, - /** The RMS voltage below which a sag condition is reported. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SAG_ID = 0x0809, - /** The RMS voltage above which a swell condition is reported. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SWELL_ID = 0x080a, - /** Represents the Phase B, AC line current (Square root sum of active and reactive - * currents) value at the moment in time the attribute is read, in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_LINE_CURRENT_PH_B_ID = 0x0901, - /** Represents the Phase B, AC active/resistive current value at the moment in time - * the attribute is read, in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_CURRENT_PH_B_ID = 0x0902, - /** Represents the Phase B, AC reactive current value at the moment in time the - * attribute is read, in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_REACTIVE_CURRENT_PH_B_ID = 0x0903, - /** Represents the most recent RMS voltage reading in @e Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_ID = 0x0905, - /** Represents the lowest RMS voltage value measured in Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_PH_B_ID = 0x0906, - /** Represents the highest RMS voltage value measured in Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_PH_B_ID = 0x0907, - /** Represents the most recent RMS current reading in @e Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_ID = 0x0908, - /** Represents the lowest RMS current value measured in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_PH_B_ID = 0x0909, - /** Represents the highest RMS current value measured in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_PH_B_ID = 0x090a, - /** Represents the Phase B, current demand of active power delivered or received at - * the premises, in @e Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_ID = 0x090B, - /** Represents the lowest AC power value measured in Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_PH_B_ID = 0x090c, - /** Represents the highest AC power value measured in Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_PH_B_ID = 0x090d, - /** Represents the Phase B, current demand of reactive power delivered or received - * at the premises, in VAr. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_REACTIVE_POWER_PH_B_ID = 0x090e, - /** Represents the Phase B, current demand of apparent (Square root of active and - * reactive power) power, in @e VA. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_APPARENT_POWER_PHB_ID = 0x090F, - /** Contains the PhaseB, Power Factor ratio in 1/100th. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_ID = 0x0910, - /** The number of times the average RMS voltage, has been above the - * @e AverageRMS @e OverVoltage threshold since last reset. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMSVOLTAGE_MEASUREMENT_PERIOD_PHB_ID = 0x0911, - /** The number of times the average RMS voltage, has been above the AverageRMS - * OverVoltage threshold since last reset. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_OVER_VOLTAGE_COUNTER_PH_B_ID = 0x0912, - /** The number of times the average RMS voltage, has been below the AverageRMS - * underVoltage threshold since last reset. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_UNDER_VOLTAGE_COUNTER_PH_B_ID = 0x0913, - /** The duration in seconds used to measure an extreme over voltage condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_EXTREME_OVER_VOLTAGE_PERIOD_PH_B_ID = 0x0914, - /** The duration in seconds used to measure an extreme under voltage condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_EXTREME_UNDER_VOLTAGE_PERIOD_PH_B_ID = 0x0915, - /** The duration in seconds used to measure a voltage sag condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SAG_PERIOD_PH_B_ID = 0x0916, - /** The duration in seconds used to measure a voltage swell condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SWELL_PERIOD_PH_B_ID = 0x0917, - /** Represents the Phase C, AC line current (Square root of active and reactive - * current) value at the moment in time the attribute is read, in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_LINE_CURRENT_PH_C_ID = 0x0a01, - /** Represents the Phase C, AC active/resistive current value at the moment in time - * the attribute is read, in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_CURRENT_PH_C_ID = 0x0a02, - /** Represents the Phase C, AC reactive current value at the moment in time the - * attribute is read, in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_REACTIVE_CURRENT_PH_C_ID = 0x0a03, - /** Represents the most recent RMS voltage reading in @e Volts (V).*/ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_ID = 0x0A05, - /** Represents the lowest RMS voltage value measured in Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_PH_C_ID = 0x0a06, - /** Represents the highest RMS voltage value measured in Volts (V). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_PH_C_ID = 0x0a07, - /** Represents the most recent RMS current reading in @e Amps (A).*/ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_ID = 0x0A08, - /** Represents the lowest RMS current value measured in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_PH_C_ID = 0x0a09, - /** Represents the highest RMS current value measured in Amps (A). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_PH_C_ID = 0x0a0a, - /** Represents the Phase C, current demand of active power delivered - * or received at the premises, in @e Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_ID = 0x0A0B, - /** Represents the lowest AC power value measured in Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_PH_C_ID = 0x0a0c, - /** Represents the highest AC power value measured in Watts (W). */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_PH_C_ID = 0x0a0d, - /** Represents the Phase C, current demand of reactive power delivered or received - * at the premises, in VAr. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_REACTIVE_POWER_PH_C_ID = 0x0a0e, - /** Represents the Phase C, current demand of apparent (Square root of active and - * reactive power) power, in @e VA. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_APPARENT_POWER_PHC_ID = 0x0A0F, - /** Contains the Phase C, Power Factor ratio in 1/100th. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_ID = 0x0a10, - /** The Period in seconds that the RMS voltage is averaged over*/ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMSVOLTAGE_MEASUREMENT_PERIOD_PHC_ID = 0x0A11, - /** The number of times the average RMS voltage, has been above the AverageRMS - * OverVoltage threshold since last reset. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_OVER_VOLTAGE_COUNTER_PH_C_ID = 0x0a12, - /** The number of times the average RMS voltage, has been below the AverageRMS - * underVoltage threshold since last reset. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_UNDER_VOLTAGE_COUNTER_PH_C_ID = 0x0a13, - /** The duration in seconds used to measure an extreme over voltage condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_EXTREME_OVER_VOLTAGE_PERIOD_PH_C_ID = 0x0a14, - /** The duration in seconds used to measure an extreme under voltage condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_EXTREME_UNDER_VOLTAGE_PERIOD_PH_C_ID = 0x0a15, - /** The duration in seconds used to measure a voltage sag condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SAG_PERIOD_PH_C_ID = 0x0a16, - /** The duration in seconds used to measure a voltage swell condition. */ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SWELL_PERIOD_PH_C_ID = 0x0a17, -}; - -/*! @brief Bit mapping for Measurement Type attribute, - @see HA spec, subclause 9.2.2.2.1.1 */ -enum zb_zcl_electrical_measurement_measurement_type_e -{ - /*! Active Measurement bit */ - ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_MEASUREMENT = 0x00000001, - /*! Reactive Measurement bit */ - ZB_ZCL_ELECTRICAL_MEASUREMENT_REACTIVE_MEASUREMENT = 0x00000002, - /*! Apparent Measurement bit */ - ZB_ZCL_ELECTRICAL_MEASUREMENT_APPARENT_MEASUREMENT = 0x00000004, - /*! Phase A Measurement bit */ - ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_A_MEASUREMENT = 0x00000008, - /*! Phase B Measurement bit */ - ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_B_MEASUREMENT = 0x00000010, - /*! Phase C Measurement bit */ - ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_C_MEASUREMENT = 0x00000020, - /*! DC Measurement bit */ - ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_MEASUREMENT = 0x00000040, - /*! Harmonic Measurement bit */ - ZB_ZCL_ELECTRICAL_MEASUREMENT_HARMONIC_MEASUREMENT = 0x00000080, - /*! Power Quality Measurement bit */ - ZB_ZCL_ELECTRICAL_MEASUREMENT_POWER_QUALITY_MEASUREMENT = 0x00000100, - - ZB_ZCL_ELECTRICAL_MEASUREMENT_RESERVED = 0x00000200 -}; - -/** @brief Default value for Measurement Type attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASUREMENT_TYPE_DEFAULT_VALUE 0x00000000 - -/** @brief Default value for DCVoltage attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for DCVoltageMin attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MIN_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for DCVoltageMax attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MAX_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for DCCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for DCCurrentMin attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_CURRENT_MIN_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for DCCurrentMax attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_CURRENT_MAX_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for DCPowerMin attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_POWER_MIN_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for DCPowerMax attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_POWER_MAX_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for DCVoltageMultiplier attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_MULTIPLIER_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for DCVoltageDivisor attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_DIVISOR_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for DCCurrentMultiplier attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_CURRENT_MULTIPLIER_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for DCCurrentDivisor attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_CURRENT_DIVISOR_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for DCPowerMultiplier attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_POWER_MULTIPLIER_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for DCPowerDivisor attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_POWER_DIVISOR_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for ACFrequency attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for ACFrequencyMin attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MIN_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for ACFrequencyMax attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MAX_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for NeutralCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_NEUTRAL_CURRENT_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for DCPower attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DCPOWER_DEFAULT_VALUE 0x8000 - -/** @brief Default value for Measured1stHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED1ST_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for Measured3rdHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED3RD_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for Measured5thHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED5TH_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for Measured7thHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED7TH_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for Measured9thHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED9TH_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for Measured11thHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED11TH_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for MeasuredPhase1stHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED_PHASE1ST_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for MeasuredPhase3rdHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED_PHASE3RD_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for MeasuredPhase5thHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED_PHASE5TH_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for MeasuredPhase7thHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED_PHASE7TH_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for MeasuredPhase9thHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED_PHASE9TH_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for MeasuredPhase11thHarmonicCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_MEASURED_PHASE11TH_HARMONIC_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ACFrequencyMultiplier attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_MULTIPLIER_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for ACFrequencyDivisor attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AC_FREQUENCY_DIVISOR_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for PowerMultiplier attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_POWER_MULTIPLIER_DEFAULT_VALUE ((zb_uint32_t)0x000001) - -/** @brief Default value for PowerDivisor attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_POWER_DIVISOR_DEFAULT_VALUE ((zb_uint32_t)0x000001) - -/** @brief Default value for HarmonicCurrentMultiplier attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_HARMONIC_CURRENT_MULTIPLIER_DEFAULT_VALUE ((zb_int8_t)0x00) - -/** @brief Default value for PhaseHarmonicCurrentMultiplier attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_PHASE_HARMONIC_CURRENT_MULTIPLIER_DEFAULT_VALUE ((zb_int8_t)0x00) - -/** @brief Default value for LineCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_LINE_CURRENT_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for ActiveCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ReactiveCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_REACTIVE_CURRENT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for RMSVoltageMin attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for RMSVoltageMax attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for RMSCurrentMin attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for RMSCurrentMax attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for ActivePowerMin attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ActivePowerMax attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ReactivePower attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_REACTIVE_POWER_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ApparentPower attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_APPARENT_POWER_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for AverageRmsvoltageMeasurementPeriod attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AVERAGE_RMSVOLTAGE_MEASUREMENT_PERIOD_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for AverageRMSOverVoltageCounter attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_OVER_VOLTAGE_COUNTER_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for AverageRMSUnderVoltageCounter attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_UNDER_VOLTAGE_COUNTER_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSExtremeOverVoltagePeriod attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_EXTREME_OVER_VOLTAGE_PERIOD_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSExtremeUnderVoltagePeriod attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_EXTREME_UNDER_VOLTAGE_PERIOD_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSVoltageSagPeriod attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SAG_PERIOD_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSVoltageSwellPeriod attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SWELL_PERIOD_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for AcvoltageMultiplier attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACVOLTAGE_MULTIPLIER_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for AcvoltageDivisor attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACVOLTAGE_DIVISOR_DEFAULT_VALUE ((zb_uint16_t)0x0001) - -/** @brief Default value for DCOverloadAlarmsMask attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_OVERLOAD_ALARMS_MASK_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for DCVoltageOverload attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_VOLTAGE_OVERLOAD_DEFAULT_VALUE ((zb_int16_t)0xFFFF) - -/** @brief Default value for DCCurrentOverload attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_DC_CURRENT_OVERLOAD_DEFAULT_VALUE ((zb_int16_t)0xFFFF) - -/** @brief Default value for ACAlarmsMask attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AC_ALARMS_MASK_DEFAULT_VALUE ((zb_uint16_t)0x00) - -/** @brief Default value for ACVoltageOverload attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AC_VOLTAGE_OVERLOAD_DEFAULT_VALUE ((zb_int16_t)0xFFFF) - -/** @brief Default value for ACCurrentOverload attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AC_CURRENT_OVERLOAD_DEFAULT_VALUE ((zb_int16_t)0xFFFF) - -/** @brief Default value for ACActivePowerOverload attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AC_ACTIVE_POWER_OVERLOAD_DEFAULT_VALUE ((zb_int16_t)0xFFFF) - -/** @brief Default value for ACReactivePowerOverload attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AC_REACTIVE_POWER_OVERLOAD_DEFAULT_VALUE ((zb_int16_t)0xFFFF) - -/** @brief Default value for RMSVoltage attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_DEFAULT_VALUE 0xffff - -/** @brief Default value for RMSCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMSCURRENT_DEFAULT_VALUE 0xffff - -/** @brief Default value for ActivePower attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_DEFAULT_VALUE 0xffff - -/** @brief Default value for RMSCurrent attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_POWER_FACTOR_DEFAULT_VALUE 0x0 - -/** @brief Default value for PowerMultiplier attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACPOWER_MULTIPLIER_DEFAULT_VALUE 0x0001 - -/** @brief Default value for PowerDivisor attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACPOWER_DIVISOR_DEFAULT_VALUE 0x0001 - -/** @brief Default value for ACCurrentMultiplier attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACCURRENT_MULTIPLIER_DEFAULT_VALUE 0x0001 - -/** @brief Default value for ACCurrentDivisor attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACCURRENT_DIVISOR_DEFAULT_VALUE 0x0001 - -/** @brief Default value for LineCurrentPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_LINE_CURRENT_PH_B_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for ActiveCurrentPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_CURRENT_PH_B_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ReactiveCurrentPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_REACTIVE_CURRENT_PH_B_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for RmsvoltagePHB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHB_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for RMSVoltageMinPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_PH_B_DEFAULT_VALUE ((zb_uint16_t)0x8000) - -/** @brief Default value for RMSVoltageMaxPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_PH_B_DEFAULT_VALUE ((zb_uint16_t)0x8000) - -/** @brief Default value for RmscurrentPHB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHB_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for RMSCurrentMinPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_PH_B_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for RMSCurrentMaxPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_PH_B_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for ActivePowerPHB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHB_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ActivePowerMinPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_PH_B_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ActivePowerMaxPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_PH_B_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ReactivePowerPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_REACTIVE_POWER_PH_B_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ApparentPowerPHB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_APPARENT_POWER_PHB_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for PowerFactorPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_B_DEFAULT_VALUE ((zb_int8_t)0x00) - -/** @brief Default value for AverageRmsvoltageMeasurementPeriodPHB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AVERAGE_RMSVOLTAGE_MEASUREMENT_PERIOD_PHB_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for AverageRMSOverVoltageCounterPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_OVER_VOLTAGE_COUNTER_PH_B_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for AverageRMSUnderVoltageCounterPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_UNDER_VOLTAGE_COUNTER_PH_B_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSExtremeOverVoltagePeriodPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_EXTREME_OVER_VOLTAGE_PERIOD_PH_B_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSExtremeUnderVoltagePeriodPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_EXTREME_UNDER_VOLTAGE_PERIOD_PH_B_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSVoltageSagPeriodPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SAG_PERIOD_PH_B_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSVoltageSwellPeriodPhB attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SWELL_PERIOD_PH_B_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for LineCurrentPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_LINE_CURRENT_PH_C_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for ActiveCurrentPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_CURRENT_PH_C_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ReactiveCurrentPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_REACTIVE_CURRENT_PH_C_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for rmsvoltagePHC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_PHC_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for RMSVoltageMinPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MIN_PH_C_DEFAULT_VALUE ((zb_uint16_t)0x8000) - -/** @brief Default value for RMSVoltageMaxPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_MAX_PH_C_DEFAULT_VALUE ((zb_uint16_t)0x8000) - -/** @brief Default value for rmscurrentPHC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMSCURRENT_PHC_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for RMSCurrentMinPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MIN_PH_C_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for RMSCurrentMaxPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_CURRENT_MAX_PH_C_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for ActivePowerPHC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_PHC_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ActivePowerMinPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MIN_PH_C_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ActivePowerMaxPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_MAX_PH_C_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ReactivePowerPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_REACTIVE_POWER_PH_C_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for ApparentPowerPHC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_APPARENT_POWER_PHC_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for PowerFactorPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_POWER_FACTOR_PH_C_DEFAULT_VALUE ((zb_int8_t)0x00) - -/** @brief Default value for AverageRmsvoltageMeasurementPeriodPHC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AVERAGE_RMSVOLTAGE_MEASUREMENT_PERIOD_PHC_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for AverageRMSOverVoltageCounterPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_OVER_VOLTAGE_COUNTER_PH_C_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for AverageRMSUnderVoltageCounterPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_AVERAGE_RMS_UNDER_VOLTAGE_COUNTER_PH_C_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSExtremeOverVoltagePeriodPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_EXTREME_OVER_VOLTAGE_PERIOD_PH_C_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSExtremeUnderVoltagePeriodPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_EXTREME_UNDER_VOLTAGE_PERIOD_PH_C_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSVoltageSagPeriodPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SAG_PERIOD_PH_C_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for RMSVoltageSwellPeriodPhC attribute */ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_RMS_VOLTAGE_SWELL_PERIOD_PH_C_DEFAULT_VALUE ((zb_uint16_t)0x0000) - - -/*! @} */ /* Electrical Measurement cluster attributes */ - -/*! @brief Electrical Measurement cluster server command identifiers - @see ZCL spec, subclause 4.9.2.3.1 -*/ -enum zb_zcl_electrical_measurement_srv_cmd_e -{ - /** This command is generated when the Client command GetProfileInfo is received. */ - ZB_ZCL_CMD_ELECTRICAL_MEASUREMENT_GET_PROFILE_INFO_RESPONSE_COMMAND = 0x00, - /** This command is generated when the Client command GetMeasurementProfile is received. */ - ZB_ZCL_CMD_ELECTRICAL_MEASUREMENT_GET_MEASUREMENT_PROFILE_RESPONSE_COMMAND = 0x01, -}; - -/*! @brief Electrical Measurement cluster client command identifiers - @see ZCL spec, subclause 4.9.2.4.1 -*/ -enum zb_zcl_electrical_measurement_cli_cmd_e -{ - /** Get Profile Info Command */ - ZB_ZCL_CMD_ELECTRICAL_MEASUREMENT_GET_PROFILE_INFO_COMMAND = 0x00, - /** Get Measurement Profile Command */ - ZB_ZCL_CMD_ELECTRICAL_MEASUREMENT_GET_MEASUREMENT_PROFILE_COMMAND = 0x01, -}; - -/*! @cond internals_doc - @internal @name Electrical Measurement cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASUREMENT_TYPE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASUREMENT_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_32BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DCPOWER_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DCPOWER_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ID, \ - ZB_ZCL_ATTR_TYPE_S8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_MULTIPLIER_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_MULTIPLIER_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_DIVISOR_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_DIVISOR_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/*! -* @} -* @endcond -*/ -/** @brief Declare attribute list for Electrical Measurement cluster - @param attr_list - attribute list name - @param measurement_type - pointer to variable to store Measurement Type attribute value - @param dcpower - pointer to variable to store DCPower attribute value -*/ -#define ZB_ZCL_DECLARE_ELECTRICAL_MEASUREMENT_ATTRIB_LIST(attr_list, measurement_type, dcpower) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_ELECTRICAL_MEASUREMENT) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_MEASUREMENT_TYPE_ID, (measurement_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_DCPOWER_ID, (dcpower)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! - @cond internals_doc - @{ - @internal Number of attributes mandatory for reporting in Electrical Measurement cluster -*/ -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_REPORT_ATTR_COUNT 2 - -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_SEND_GET_PROFILE_INFO_RESP( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - profile_count, profile_interval_period, max_number_of_intervals, \ - list_of_attributes, list_of_attributes_size) \ -{ \ - zb_uint8_t ind; \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_ELECTRICAL_MEASUREMENT_GET_PROFILE_INFO_RESPONSE_COMMAND); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (profile_count)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (profile_interval_period)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (max_number_of_intervals)); \ - for (ind=0; ind < list_of_attributes_size; ind++) \ - { \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (list_of_attributes[ind])); \ - } \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, \ - prfl_id, ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, cb); \ -} - -#define ZB_ZCL_ELECTRICAL_MEASUREMENT_SEND_GET_MEASUREMENT_PROFILE_INFO_RESP( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - start_time, status, profile_interval_period, number_of_intervals_delivered, attr_id, \ - list_of_intervals) \ -{ \ - zb_uint8_t ind; \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_ELECTRICAL_MEASUREMENT_GET_MEASUREMENT_PROFILE_RESPONSE_COMMAND); \ - ZB_ZCL_PACKET_PUT_DATA32_VAL(ptr, (start_time)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (status)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (profile_interval_period)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (number_of_intervals_delivered)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (attr_id)); \ - for (ind=0; ind < number_of_intervals_delivered; ind++) \ - { \ - \ - } \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, \ - prfl_id, ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, cb); \ -} -/*! @} - @endcond */ /* Electrical Measurement cluster internals */ - -/*! @} */ /* ZCL HA Electrical Measurement cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_el_measurement_init_server(void); -void zb_zcl_el_measurement_init_client(void); - -#define ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT_SERVER_ROLE_INIT zb_zcl_el_measurement_init_server -#define ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT_CLIENT_ROLE_INIT zb_zcl_el_measurement_init_client - -#endif /* ZB_ZCL_ELECTRICAL_MEASUREMENT_H */ diff --git a/zboss/development/include/zcl/zb_zcl_en50523_appliance_events_and_alerts.h b/zboss/development/include/zcl/zb_zcl_en50523_appliance_events_and_alerts.h deleted file mode 100644 index 991584fe8f..0000000000 --- a/zboss/development/include/zcl/zb_zcl_en50523_appliance_events_and_alerts.h +++ /dev/null @@ -1,457 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: EN50523 Appliance events and alerts cluster definitions -*/ - -#ifndef ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_H -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_H 1 - -/** @cond DOXYGEN_ZCL_SECTION */ - -/*! @addtogroup ZB_ZCL_EN50523_APP_EVENTS_ALERTS - @{ -*/ -/*! @name EN50523 Appliance events and alerts cluster commands - @{ -*/ -/*! @brief EN50523 Appliance events and alerts cluster - command received identifiers - @see ZCL 6.0 spec, subclause 15.4.2.3 -*/ -enum zb_zcl_en50523_appl_ev_and_alerts_recv_cmd_e -{ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_ID = 0x00, /**< "Get alerts" command. */ -}; - -/*! @brief EN50523 Appliance events and alerts cluster - commands generated identifiers - @see ZCL 6.0 spec, subclause 15.4.2.4 -*/ -enum zb_zcl_en50523_appl_ev_and_alerts_send_cmd_e -{ - /*! "Get alerts response" command. */ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_RESP_ID = 0x00, - /*! "Alerts notification" command. */ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_ALERTS_NOTIFICATION_ID = 0x01, - /*! "Event notification" command. */ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_EVENT_NOTIFICATION_ID = 0x02, -}; - -/** @brief Default value for EN50523 Appliance events and alerts cluster revision global attribute */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/*! - @brief Declare attribute list for EN50523 Appliance events and alerts cluster (only cluster revision attribute) - @param attr_list - attribute list name -*/ -#define ZB_ZCL_DECLARE_EN50523_APPL_EV_AND_ALERTS_ATTR_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_EN50523_APPL_EV_AND_ALERTS) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @cond internals_doc */ -/* en50523 cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_APPL_EV_AND_ALERTS_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_ID - -#define ZB_ZCL_CLUSTER_ID_APPL_EV_AND_ALERTS_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_RESP_ID, \ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_ALERTS_NOTIFICATION_ID, \ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_EVENT_NOTIFICATION_ID - -#define ZB_ZCL_CLUSTER_ID_APPL_EV_AND_ALERTS_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_APPL_EV_AND_ALERTS_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_APPL_EV_AND_ALERTS_CLIENT_ROLE_GENERATED_CMD_LIST ZB_ZCL_CLUSTER_ID_APPL_EV_AND_ALERTS_SERVER_ROLE_RECEIVED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/******************************* Get Alerts Command ******************************/ - -/*! @brief Get Alerts command, ZCL spec 15.4.2.2.1 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_GET_ALERTS_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_ID); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS, cb); \ -} - -/******************************* Get Alerts Response Command ******************************/ - -/*! @brief Maximum number of Alerts */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_MAX_ALERTS_NUM 15 - -/*! @brief Type of alert */ -enum zb_zcl_en50523_appl_ev_and_alerts_alerts_type_e -{ - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_TYPE_UNSTRUCTURED = 0x00, -}; - -/*! @brief Alert category */ -enum zb_zcl_en50523_appl_ev_and_alerts_alert_category_e -{ - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_CATEGORY_WARNING = 0x01, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_CATEGORY_DANGER = 0x02, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_CATEGORY_FAILURE = 0x03, -}; - -/*! @brief Alert presence recovery */ -enum zb_zcl_en50523_appl_ev_and_alerts_alert_presence_e -{ - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_RECOVERY = 0x00, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_PRESENCE = 0x01, -}; - -/*! @brief Get Number of Alerts */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_COUNT_GET_NUM(_alerts_count) ((_alerts_count) & 0x0F) - -/*! @brief Set Number of Alerts */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_COUNT_SET_NUM(_alerts_count, num) ((_alerts_count) |= (num & 0x0F)) - -/*! @brief Get Type of alert */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_COUNT_GET_TYPE(_alerts_count) (((_alerts_count) & 0xF0) >> 4) - -/*! @brief Set Type of alert */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_COUNT_SET_TYPE(_alerts_count, type) ((_alerts_count) |= ((type & 0x0F) << 4)) - -/*! @brief Get Alert ID */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_STRUCT_GET_ID(_alert_struct) ((_alert_struct).alert[2] & 0xFF) - -/*! @brief Set Alert ID */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_STRUCT_SET_ID(_alert_struct, id) ((_alert_struct).alert[2] = (id & 0xFF)) - -/*! @brief Get Alert Category */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_STRUCT_GET_CATEGORY(_alert_struct) ((_alert_struct).alert[1] & 0x0F) - -/*! @brief Set Alert Category */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_STRUCT_SET_CATEGORY(_alert_struct, cat) ((_alert_struct).alert[1] |= (cat & 0x0F)) - -/*! @brief Get Alert Presence recovery */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_STRUCT_GET_PRESENCE(_alert_struct) (((_alert_struct).alert[1] & 0xF0) >> 4) - -/*! @brief Set Alert Presence recovery */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_STRUCT_SET_PRESENCE(_alert_struct, pres) ((_alert_struct).alert[1] |= (pres & 0x0F) << 4) - -/*! @brief Get Alert Manufacturer specific bits */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_STRUCT_GET_MANUF_SPEC(_alert_struct) ((_alert_struct).alert[0] & 0xFF) - -/*! @brief Set Alert Manufacturer specific bits */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERT_STRUCT_SET_MANUF_SPEC(_alert_struct, val) ((_alert_struct).alert[0] = (val & 0xFF)) - -/*! @brief Alert structure */ -typedef ZB_PACKED_PRE struct zb_zcl_en50523_appl_ev_and_alerts_alert_struct_s -{ - /** Alert field - Alert ID, Category, Presence recovery, Manufacturer specific bits */ - zb_uint8_t alert[3]; -} ZB_PACKED_STRUCT zb_zcl_en50523_appl_ev_and_alerts_alert_struct_t; - -/*! @brief Structure representation of Get Alerts Response command */ -typedef ZB_PACKED_PRE struct zb_zcl_en50523_appl_ev_and_alerts_get_alerts_resp_s -{ - /** Alerts count fields - Number of Alerts, Type of alert */ - zb_uint8_t alerts_count; - /** Alert structure fields, see zb_zcl_en50523_appl_ev_and_alerts_alert_struct_t */ - zb_zcl_en50523_appl_ev_and_alerts_alert_struct_t alert_struct[ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_MAX_ALERTS_NUM]; - -} ZB_PACKED_STRUCT zb_zcl_en50523_appl_ev_and_alerts_get_alerts_resp_t; - -/*! Get Alerts Response command payload size */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_RESP_PAYLOAD_SIZE(ptr) (sizeof(((zb_zcl_en50523_appl_ev_and_alerts_get_alerts_resp_t *)(ptr))->alerts_count) + \ - (ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_COUNT_GET_NUM(((zb_zcl_en50523_appl_ev_and_alerts_get_alerts_resp_t *)(ptr))->alerts_count)* \ - sizeof(zb_zcl_en50523_appl_ev_and_alerts_alert_struct_t))) - -/*! @brief Start Get Alerts Response command, ZCL spec 15.4.2.3.1 - @param buffer - to put packet to - @param seq - sequence - @param alerts_count - Alerts count field - @param ptr - [out] (zb_uint8_t*) current position for @ref ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_GET_ALERTS_RESP_ADD - and @ref ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_GET_ALERTS_RESP_END -*/ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_GET_ALERTS_RESP_START( \ - buffer, seq, alerts_count, ptr) \ -{ \ - (ptr) = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_RESP_ID); \ - ZB_ZCL_PACKET_PUT_DATA8((ptr), (alerts_count)); \ -} - -/*! @brief Add Alert Structure to Get Alerts Response command, ZCL spec 15.4.2.3.1 - @param ptr - [in/out] (zb_uint8_t*) current position - @param alert_struct - pointer to the Alert structure to put into packet -*/ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_GET_ALERTS_RESP_ADD(ptr, alert_struct) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA24(ptr, (alert_struct)); \ -} - -/*! @brief End form Get Alerts Response command and send it, ZCL spec 15.4.2.3.1 - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier -*/ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_GET_ALERTS_RESP_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id) \ -{ \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS, NULL); \ -} - -/** @brief Macro for getting Get Alerts Response command, ZCL spec 15.4.2.3.1 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_en50523_appl_ev_and_alerts_get_alerts_resp_t - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_GET_ALERTS_RESP(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < \ - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_RESP_PAYLOAD_SIZE(data)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->alerts_count, data); \ - ZB_ZCL_PACKET_GET_DATA_N((data_ptr)->alert_struct, data, \ - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_COUNT_GET_NUM((data_ptr)->alerts_count)*sizeof(zb_zcl_en50523_appl_ev_and_alerts_alert_struct_t)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/******************************* Alerts Notification Command ******************************/ - -/*! @brief Structure representation of Alerts Notification command */ -typedef ZB_PACKED_PRE struct zb_zcl_en50523_appl_ev_and_alerts_alerts_notif_s -{ - /** Alerts count fields - Number of Alerts, Type of alert */ - zb_uint8_t alerts_count; - /** Alert structure fields, see zb_zcl_en50523_appl_ev_and_alerts_alert_struct_t */ - zb_zcl_en50523_appl_ev_and_alerts_alert_struct_t alert_struct[ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_MAX_ALERTS_NUM]; - -} ZB_PACKED_STRUCT zb_zcl_en50523_appl_ev_and_alerts_alerts_notif_t; - -/*! Alerts Notification command payload size */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_NOTIF_PAYLOAD_SIZE(ptr) (sizeof(((zb_zcl_en50523_appl_ev_and_alerts_alerts_notif_t *)(ptr))->alerts_count) + \ - (ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_COUNT_GET_NUM(((zb_zcl_en50523_appl_ev_and_alerts_alerts_notif_t *)(ptr))->alerts_count)* \ - sizeof(zb_zcl_en50523_appl_ev_and_alerts_alert_struct_t))) - -/*! @brief Start Alerts Notification command, ZCL spec 15.4.2.3.2 - @param buffer - to put packet to - @param def_resp - enable/disable default response - @param alerts_count - Alerts count field - @param ptr - [out] (zb_uint8_t*) current position for @ref ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_ALERTS_NOTIF_ADD - and @ref ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_ALERTS_NOTIF_END -*/ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_ALERTS_NOTIF_START( \ - buffer, def_resp, alerts_count, ptr) \ -{ \ - (ptr) = zb_zcl_start_command_header(buffer, \ - ZB_ZCL_CONSTRUCT_FRAME_CONTROL( \ - ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, \ - (def_resp)), \ - 0, /* No manuf_code */ \ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_ALERTS_NOTIFICATION_ID, \ - NULL); \ - ZB_ZCL_PACKET_PUT_DATA8((ptr), (alerts_count)); \ -} - -/*! @brief Add Alert Structure to Alerts Notification command, ZCL spec 15.4.2.3.2 - @param ptr - [in/out] (zb_uint8_t*) current position - @param alert_struct - pointer to Alert structure to put into packet -*/ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_ALERTS_NOTIF_ADD(ptr, alert_struct) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA24(ptr, (alert_struct)); \ -} - -/*! @brief End form Alerts Notification command and send it, ZCL spec 15.4.2.3.2 - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_ALERTS_NOTIF_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS, cb); \ -} - -/** @brief Macro for getting Alerts Notification command, ZCL spec 15.4.2.3.2 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_en50523_appl_ev_and_alerts_alerts_notif_t - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_NOTIF(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < \ - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_NOTIF_PAYLOAD_SIZE(data)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->alerts_count, data); \ - ZB_ZCL_PACKET_GET_DATA_N((data_ptr)->alert_struct, data, \ - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_COUNT_GET_NUM((data_ptr)->alerts_count)*sizeof(zb_zcl_en50523_appl_ev_and_alerts_alert_struct_t)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/******************************* Event Notification Command ******************************/ - -/*! @brief Event Identification */ -enum zb_zcl_en50523_appl_ev_and_alerts_event_identification_e -{ - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_EVENT_ID_END_OF_CYCLE = 0x01, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_EVENT_ID_TEMP_REACHED = 0x04, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_EVENT_ID_END_OF_COOKING = 0x05, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_EVENT_ID_SWITCHING_OFF = 0x06, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_EVENT_ID_WRONG_DATA = 0xf7, -}; - -/*! @brief Structure representation of Event Notification command - @param event_header - Event header field - @param event_identification - Event Identification field, see zb_zcl_en50523_appl_ev_and_alerts_event_identification_e -*/ -typedef ZB_PACKED_PRE struct zb_zcl_en50523_appl_ev_and_alerts_event_notif_s -{ - zb_uint8_t event_header; - zb_uint8_t event_identification; - -} ZB_PACKED_STRUCT zb_zcl_en50523_appl_ev_and_alerts_event_notif_t; - -/*! @brief Event Notification command, ZCL spec 15.4.2.3.3 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param event_identification - Event ID -*/ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_EVENT_NOTIF( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - event_identification) \ -{ \ - zb_uint8_t* ptr = zb_zcl_start_command_header(buffer, \ - ZB_ZCL_CONSTRUCT_FRAME_CONTROL( \ - ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, \ - (def_resp)), \ - 0, /* No manuf_code */ \ - ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_EVENT_NOTIFICATION_ID, \ - NULL); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, 0); \ - ZB_ZCL1_PACKET_PUT_DATA8(ptr, (event_identification)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS, cb); \ -} - -/** @brief Macro for getting Event Notification command, see ZCL spec 15.4.2.3.3 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type zb_zcl_en50523_appl_ev_and_alerts_event_notif_e - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_EVENT_NOTIF(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < \ - sizeof(zb_zcl_en50523_appl_ev_and_alerts_event_notif_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->event_header, data); \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->event_identification, data); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} -/*! @} */ /* Appliance events and alerts cluster commands */ -/*! @} */ /*ZB_ZCL_EN50523_APP_EVENTS_ALERTS */ -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_en50523_appliance_events_and_alerts_init_server(void); -void zb_zcl_en50523_appliance_events_and_alerts_init_client(void); -#define ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS_SERVER_ROLE_INIT zb_zcl_en50523_appliance_events_and_alerts_init_server -#define ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS_CLIENT_ROLE_INIT zb_zcl_en50523_appliance_events_and_alerts_init_client - -#endif /* ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_H */ diff --git a/zboss/development/include/zcl/zb_zcl_fan_control.h b/zboss/development/include/zcl/zb_zcl_fan_control.h deleted file mode 100644 index 134c40edcd..0000000000 --- a/zboss/development/include/zcl/zb_zcl_fan_control.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Fan Control cluster definitions -*/ - -#ifndef ZB_ZCL_FAN_CONTROL_H -#define ZB_ZCL_FAN_CONTROL_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond DOXYGEN_ZCL_SECTION */ - - -/* Cluster ZB_ZCL_CLUSTER_ID_FAN_CONTROL */ - -/*! @addtogroup ZB_ZCL_FAN_CONTROL - @{ - @name Fan Control cluster attributes - @{ -*/ - -/*! @brief Fan Control cluster attribute identifiers - @see ZCL spec, subclause 6.4.2.2 -*/ -enum zb_zcl_fan_control_attr_e -{ - /*! @brief Fan Mode attribute */ - ZB_ZCL_ATTR_FAN_CONTROL_FAN_MODE_ID = 0x0000, - /*! @brief Fan Mode Sequence attribute */ - ZB_ZCL_ATTR_FAN_CONTROL_FAN_MODE_SEQUENCE_ID = 0x0001 -}; - -/*! @brief Values for Fan Mode attribute, - @see ZCL spec, subclause 6.4.2.2.1 */ -enum zb_zcl_fan_control_fan_mode_e -{ - /*! Off value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_OFF = 0x00, - /*! Low value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_LOW = 0x01, - /*! Medium value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_MEDIUM = 0x02, - /*! High value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_HIGH = 0x03, - /*! On value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_ON = 0x04, - /*! Auto value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_AUTO = 0x05, - /*! Smart value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_SMART = 0x06, - - ZB_ZCL_FAN_CONTROL_FAN_MODE_RESERVED = 0x07 -}; - -/*! @brief Values for Fan Mode Sequence attribute, - @see ZCL spec, subclause 6.4.2.2.2 */ -enum zb_zcl_fan_control_fan_mode_sequence_e -{ - /*! Low/Med/High value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_LOW_MED_HIGH = 0x00, - /*! Low/High value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_LOW_HIGH = 0x01, - /*! Low/Med/High/Auto value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_LOW_MED_HIGH_AUTO = 0x02, - /*! Low/High/Auto value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_LOW_HIGH_AUTO = 0x03, - /*! On/Auto value */ - ZB_ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_ON_AUTO = 0x04, - - ZB_ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_RESERVED = 0x05 -}; - -/** @brief Default value for Fan Control cluster revision global attribute */ -#define ZB_ZCL_FAN_CONTROL_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/** @brief Default value for Fan Mode attribute */ -#define ZB_ZCL_FAN_CONTROL_FAN_MODE_DEFAULT_VALUE 0x05 - -/** @brief Default value for Fan Mode attribute */ -#define ZB_ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_DEFAULT_VALUE 0x02 - -/** @brief Declare attribute list for Fan Control cluster - @param attr_list - attribute list name - @param fan_mode - pointer to variable to store Fan Mode attribute value - @param fan_mode_sequence - pointer to variable to store Fan Mode Sequence attribute value -*/ -#define ZB_ZCL_DECLARE_FAN_CONTROL_ATTRIB_LIST(attr_list, fan_mode, fan_mode_sequence) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_FAN_CONTROL) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_FAN_CONTROL_FAN_MODE_ID, (fan_mode)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_FAN_CONTROL_FAN_MODE_SEQUENCE_ID, (fan_mode_sequence)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Fan Control cluster attributes */ - -/*! @name Fan Control cluster commands - @{ -*/ - -/*! @} */ /* Fan Control cluster commands */ - -/*! @cond internals_doc - @internal @name Fan Control cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_FAN_CONTROL_FAN_MODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_FAN_CONTROL_FAN_MODE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_FAN_CONTROL_FAN_MODE_SEQUENCE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_FAN_CONTROL_FAN_MODE_SEQUENCE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in Fan Control cluster */ -#define ZB_ZCL_FAN_CONTROL_REPORT_ATTR_COUNT 0 - -/*! @} - @endcond */ /* Fan Control cluster internals */ - -/*! @} */ /* ZCL HA Fan Control cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_fan_control_init_server(void); -void zb_zcl_fan_control_init_client(void); -#define ZB_ZCL_CLUSTER_ID_FAN_CONTROL_SERVER_ROLE_INIT zb_zcl_fan_control_init_server -#define ZB_ZCL_CLUSTER_ID_FAN_CONTROL_CLIENT_ROLE_INIT zb_zcl_fan_control_init_client - -#endif /* ZB_ZCL_FAN_CONTROL_H */ diff --git a/zboss/development/include/zcl/zb_zcl_groups.h b/zboss/development/include/zcl/zb_zcl_groups.h deleted file mode 100644 index cd6ef6d6b4..0000000000 --- a/zboss/development/include/zcl/zb_zcl_groups.h +++ /dev/null @@ -1,786 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Groups cluster definitions -*/ - -#ifndef ZB_ZCL_GROUPS_H -#define ZB_ZCL_GROUPS_H 1 - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_GROUPS - * @{ - * @details - * Groups cluster defined in ZCL spec, clause 3.6. Currently no group name attribute support is - * implemented. However, this attribute must be supported for sending and receiving in commands' - * payload, so it is being sent as zero string (i. e. single zero byte). On receipt of the - * command is able to contain a scene name in the payload, this field will be ignored as a string. - * - * Cluster requests and responses are documented in submodules. - */ - -/** @name Groups cluster attributes - @{ -*/ - -/* ZB_ZCL_CLUSTER_ID_GROUPS = 0x0004 */ - -/** @brief Groups cluster attribute identifiers - @see ZCL spec, subclause 3.6.2.2 -*/ -enum zb_zcl_groups_attr_e -{ - /** @brief NameSupport attribute */ - ZB_ZCL_ATTR_GROUPS_NAME_SUPPORT_ID = 0 -}; - -/** @brief Values for NameSupport attribute */ -enum zb_zcl_groups_name_support_e -{ - /** "Not supported" value */ - ZB_ZCL_ATTR_GROUPS_NAME_NOT_SUPPORTED = 0, - /** "On" value */ - ZB_ZCL_ATTR_GROUPS_NAME_SUPPORTED = 1 << 7 /* set to 1 the most significant bit */ -}; - -/** @brief Default value for Groups cluster revision global attribute */ -#define ZB_ZCL_GROUPS_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/** - * @brief Declare attribute list for Groups cluster. - * @param attr_list - attribute list name. - * @param name_support - pointer to variable to store name_support attribute value - */ -#define ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST(attr_list, name_support) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_GROUPS) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_GROUPS_NAME_SUPPORT_ID, (name_support)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ /* Groups cluster attributes */ - -/** @name Groups cluster command identifiers - @{ -*/ - -/** - * @brief Groups cluster command identifiers. - * @see ZCL spec, subclause 3.6.2.2.2. - */ -enum zb_zcl_groups_cmd_e -{ - ZB_ZCL_CMD_GROUPS_ADD_GROUP = 0x00, /**< Add group command identifier. */ - ZB_ZCL_CMD_GROUPS_VIEW_GROUP = 0x01, /**< View group command identifier. */ - ZB_ZCL_CMD_GROUPS_GET_GROUP_MEMBERSHIP = 0x02, /**< Get group membership command identifier. - */ - ZB_ZCL_CMD_GROUPS_REMOVE_GROUP = 0x03, /**< Remove group command identifier. */ - ZB_ZCL_CMD_GROUPS_REMOVE_ALL_GROUPS = 0x04, /**< Remove all groups command identifier. */ - ZB_ZCL_CMD_GROUPS_ADD_GROUP_IF_IDENTIFYING = 0x05 /**< Add group if identifying command - identifier. */ -}; - -/** @brief Groups cluster response command identifiers - @see ZCL spec, subclause 3.6.2.3 -*/ -enum zb_zcl_groups_cmd_resp_e -{ - ZB_ZCL_CMD_GROUPS_ADD_GROUP_RES = 0x00, /**< Add group response command identifier. */ - ZB_ZCL_CMD_GROUPS_VIEW_GROUP_RES = 0x01, /**< View group response command identifier. - */ - ZB_ZCL_CMD_GROUPS_GET_GROUP_MEMBERSHIP_RES = 0x02, /**< Get group response membership command - identifier. */ - ZB_ZCL_CMD_GROUPS_REMOVE_GROUP_RES = 0x03 /**< Remove group response command identifier. - */ -}; - -/** @cond internals_doc */ -/* GROUPS cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_GROUPS_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_GROUPS_ADD_GROUP_RES, \ - ZB_ZCL_CMD_GROUPS_VIEW_GROUP_RES, \ - ZB_ZCL_CMD_GROUPS_GET_GROUP_MEMBERSHIP_RES, \ - ZB_ZCL_CMD_GROUPS_REMOVE_GROUP_RES - -#define ZB_ZCL_CLUSTER_ID_GROUPS_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_GROUPS_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_GROUPS_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_GROUPS_ADD_GROUP, \ - ZB_ZCL_CMD_GROUPS_VIEW_GROUP, \ - ZB_ZCL_CMD_GROUPS_GET_GROUP_MEMBERSHIP, \ - ZB_ZCL_CMD_GROUPS_REMOVE_GROUP, \ - ZB_ZCL_CMD_GROUPS_REMOVE_ALL_GROUPS, \ - ZB_ZCL_CMD_GROUPS_ADD_GROUP_IF_IDENTIFYING - -#define ZB_ZCL_CLUSTER_ID_GROUPS_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_GROUPS_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/** @} */ /* Groups cluster command identifiers */ - -/************************** Add group command definitions ****************************/ - -/** @defgroup ZB_ZCL_GROUPS_ADD_GROUP Add group command definitions - * @{ - * @details - * Add group request and response commands have simple payload. Response command is being filled - * and sent by ZCL internals. - * - * @par Examples - * - * Filling and sending Add Group request: - * @snippet HA_samples/door_lock/sample_zed.c send_add_group_req - * - * - */ - -/** @brief Add group command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_groups_add_group_req_s -{ - zb_uint16_t group_id; /**< Group id */ - zb_char_t group_name[1]; /**< Group name, optional */ -} -ZB_PACKED_STRUCT -zb_zcl_groups_add_group_req_t; - -/** @cond internals_doc */ - -/** @internal Minimum size of Add group request (group name maybe omitted) */ -#define ZB_ZCL_ADD_GROUP_REQ_SIZE sizeof(zb_uint16_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Add group command and fills in data request - structure. If request contains invalid data, ZB_ZCL_NULL_ID is stored as group_id. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param add_group_req - variable to save command request - @note data_buf buffer should contain command request payload without ZCL header. - */ -#define ZB_ZCL_GROUPS_GET_ADD_GROUP_REQ(data_buf, add_group_req) \ -{ \ - zb_zcl_groups_add_group_req_t *add_group_req_ptr; \ - (add_group_req_ptr) = zb_buf_len(data_buf) >= ZB_ZCL_ADD_GROUP_REQ_SIZE ? \ - (zb_zcl_groups_add_group_req_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (add_group_req_ptr) \ - { \ - ZB_HTOLE16(&(add_group_req).group_id, &add_group_req_ptr->group_id);\ - /* group name currently is not supported - do not check it */ \ - } \ - else \ - { \ - add_group_req.group_id = ZB_ZCL_NULL_ID; \ - } \ -} - -/** @brief Add group response command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_groups_add_group_res_s -{ - zb_uint8_t status; /**< Operation status */ - zb_uint16_t group_id; /**< Group id */ -} -ZB_PACKED_STRUCT -zb_zcl_groups_add_group_res_t; - -/** @cond internals_doc */ - -/** @internal Add group response size */ -#define ZB_ZCL_ADD_GROUP_RES_SIZE sizeof(zb_zcl_groups_add_group_res_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Add group response command and returns response data - structure or NULL if request contains invalid data. - @param data_buf - pointer to zb_buf_t buffer containing command response data - @param add_group_res - out pointer to zb_zcl_groups_add_group_res_t, containing command - response record - @note data_buf buffer should contain response command payload without ZCL header - */ -#define ZB_ZCL_GROUPS_GET_ADD_GROUP_RES(data_buf, add_group_res) \ -{ \ - (add_group_res) = zb_buf_len(data_buf) >= ZB_ZCL_ADD_GROUP_RES_SIZE ? \ - (zb_zcl_groups_add_group_res_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (add_group_res) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(add_group_res)->group_id); \ - /* group name currently is not supported - do not check it */ \ - } \ -} - -/** @brief Send Add group command - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param group_id - group ID to add -*/ -#define ZB_ZCL_GROUPS_SEND_ADD_GROUP_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, group_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_GROUPS_ADD_GROUP); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - /* Group name currently is not supported, put empty string */ \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, ZB_ZCL_NULL_STRING); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_GROUPS, cb); \ -} - -/** @} */ /* Add group command definitions */ - - -/************************** View group command definitions ****************************/ - -/** @defgroup ZB_ZCL_GROUPS_VIEW_GROUP View group command definitions - * @{ - * @details - * View Group command and response have simple payload. View group command is being processed, - * and View Group response command originates from ZCL internals. - * - * @par Examples - * View Group request command can be formed as: - * @snippet HA_samples/door_lock/sample_zed.c view_group_req - * - */ - -/** @brief View group command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_groups_view_group_req_s -{ - zb_uint16_t group_id; /**< Group id */ -} -ZB_PACKED_STRUCT -zb_zcl_groups_view_group_req_t; - -/** @cond internals_doc */ - -/** @internal Size of View group request */ -#define ZB_ZCL_VIEW_GROUP_REQ_SIZE sizeof(zb_zcl_groups_view_group_req_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses View group command and fills in data request - structure. If request contains invalid data, ZB_ZCL_NULL_ID is stored as group_id. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param view_group_req - variable to save command request - @note data_buf buffer should contain command request payload without ZCL header. - */ -#define ZB_ZCL_GROUPS_GET_VIEW_GROUP_REQ(data_buf, view_group_req) \ -{ \ - zb_zcl_groups_view_group_req_t *view_group_req_ptr; \ - (view_group_req_ptr) = zb_buf_len(data_buf) >= ZB_ZCL_VIEW_GROUP_REQ_SIZE ? \ - (zb_zcl_groups_view_group_req_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (view_group_req_ptr) \ - { \ - ZB_HTOLE16(&(view_group_req).group_id, &view_group_req_ptr->group_id); \ - } \ - else \ - { \ - view_group_req.group_id = ZB_ZCL_NULL_ID; \ - } \ -} - -/** @brief View group command response structure */ -typedef ZB_PACKED_PRE struct zb_zcl_groups_view_group_res_s -{ - zb_uint8_t status; /**< Operation status */ - zb_uint16_t group_id; /**< Group id */ - zb_uint8_t group_name[1]; /**< Group name */ -} -ZB_PACKED_STRUCT -zb_zcl_groups_view_group_res_t; - -/** @cond internals_doc */ - -/** @internal View group response size */ -#define ZB_ZCL_VIEW_GROUP_RES_SIZE sizeof(zb_zcl_groups_view_group_res_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses View group response command and returns response data - structure or NULL if request contains invalid data. - @param data_buf - pointer to zb_buf_t buffer containing command response data - @param view_group_res - out pointer to zb_zcl_groups_add_group_res_t, containing command - response record - @note data_buf buffer should contain response command payload without ZCL header - */ -#define ZB_ZCL_GROUPS_GET_VIEW_GROUP_RES(data_buf, view_group_res) \ -{ \ - (view_group_res) = zb_buf_len(data_buf) >= ZB_ZCL_VIEW_GROUP_RES_SIZE ? \ - (zb_zcl_groups_view_group_res_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (view_group_res) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(view_group_res)->group_id); \ - /* group name currently is not supported - empty string is returned */ \ - } \ -} - -/** @brief Send view group command - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param group_id - group ID to add -*/ -#define ZB_ZCL_GROUPS_SEND_VIEW_GROUP_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, group_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_GROUPS_VIEW_GROUP); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_GROUPS, cb); \ -} - -/** @} */ /* View group command definitions */ - -/************************** Get Group Membership command definitions ****************************/ -/** @defgroup ZB_ZCL_GROUPS_GET_GRP_MEMB Get Group Membership command definitions - * @{ - * @details - * Both Get Group Membership command request and response have a complex array-style payload. - * - * @par Examples - * Get Group Membership request can be filled in as: - * @snippet HA_samples/door_lock/sample_zed.c send_get_group_membership_req - * - * - */ - -/** @brief Get Group Membership command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_groups_get_group_membership_req_s -{ - zb_uint8_t group_count; /**< Group count */ - zb_uint16_t group_id[1]; /**< Group id list */ -} -ZB_PACKED_STRUCT -zb_zcl_groups_get_group_membership_req_t; - -/** @cond internals_doc */ - -/** @internal Minimum size of Get Group Membership request */ -#define ZB_ZCL_GET_GROUP_MEMBERSHIP_REQ_SIZE sizeof(zb_uint8_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Get Group Membership command and returns pointer to data request - structure. If request contains invalid data, NULL is returned - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param group_member_req - pointer to command request - @note data_buf buffer should contain command request payload without ZCL header. - */ -#define ZB_ZCL_GROUPS_GET_GROUP_MEMBERSHIP_REQ(data_buf, group_member_req) \ -{ \ - zb_uint8_t i_tmp; \ - zb_uint8_t cmd_size = ZB_ZCL_GET_GROUP_MEMBERSHIP_REQ_SIZE; \ - \ - (group_member_req) = (zb_buf_len(data_buf) >= cmd_size) ? \ - (zb_zcl_groups_get_group_membership_req_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (group_member_req) \ - { \ - cmd_size += sizeof(zb_uint16_t) * (group_member_req)->group_count; \ - if (cmd_size <= zb_buf_len(data_buf)) \ - { \ - for(i_tmp = 0; i_tmp < (group_member_req)->group_count; i_tmp++) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(group_member_req)->group_id[i_tmp]); \ - } \ - } \ - else \ - { \ - group_member_req = NULL; \ - } \ - } \ -} - -/** @brief Get Group Membership command response structure */ -typedef ZB_PACKED_PRE struct zb_zcl_groups_get_group_membership_res_s -{ - zb_uint8_t capacity; /**< Capacity of group table */ - zb_uint8_t group_count; /**< Group count */ - zb_uint16_t group_id[1]; /**< Group id list */ -} -ZB_PACKED_STRUCT -zb_zcl_groups_get_group_membership_res_t; - -/** @cond internals_doc */ - -/** @internal Minimum size of Get Group Membership command response */ -#define ZB_ZCL_GET_GROUP_MEMBERSHIP_RES_SIZE (2*sizeof(zb_uint8_t)) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Get Group Membership command response and returns pointer to data response - structure. If response contains invalid data, NULL is returned. - @param data_buf - pointer to zb_buf_t buffer containing command response data - @param group_member_res - pointer to command response - @note data_buf buffer should contain command response payload without ZCL header. - */ -#define ZB_ZCL_GROUPS_GET_GROUP_MEMBERSHIP_RES(data_buf, group_member_res) \ -{ \ - zb_uint8_t i; \ - zb_uint8_t cmd_size = ZB_ZCL_GET_GROUP_MEMBERSHIP_RES_SIZE; \ - \ - (group_member_res) = (zb_buf_len(data_buf) >= cmd_size) ? \ - (zb_zcl_groups_get_group_membership_res_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (group_member_res) \ - { \ - cmd_size += sizeof(zb_uint16_t) * (group_member_res)->group_count; \ - if (cmd_size <= zb_buf_len(data_buf)) \ - { \ - for(i = 0; i < (group_member_res)->group_count; i++) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(group_member_res)->group_id[i]); \ - } \ - } \ - else \ - { \ - group_member_res = NULL; \ - } \ - } \ -} - -/** @brief Initialize Get group membership command - @param buffer to put packet to - @param ptr - command buffer pointer - @param def_resp - enable/disable default response - @param group_cnt - group count -*/ -#define ZB_ZCL_GROUPS_INIT_GET_GROUP_MEMBERSHIP_REQ(buffer, ptr, def_resp, group_cnt) \ -{ \ - ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_GROUPS_GET_GROUP_MEMBERSHIP); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (group_cnt)); \ -} - -/** @brief Add group id to command payload - @param ptr - command buffer pointer - @param group_id - group ID -*/ -#define ZB_ZCL_GROUPS_ADD_ID_GET_GROUP_MEMBERSHIP_REQ(ptr, group_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ -} - -/** @brief Sends Get group membership command - @param buffer to place data to - @param ptr - pointer to the memory area after the command data end - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_GROUPS_SEND_GET_GROUP_MEMBERSHIP_REQ( \ - buffer, ptr, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_GROUPS, cb); \ -} - -/** @} */ /* Get Group Membership command definitions */ - - -/************************** Remove Group command definitions ****************************/ -/** @defgroup ZB_ZCL_GROUPS_RM_GRP Remove Group command definitions - * @{ - * @details - * Remove Group request and response commands have simple payload. Actual request handling takes - * place in ZCL internals. - * - * @par Examples - * Remove Group request sending: - * @snippet HA_samples/door_lock/sample_zed.c send_remove_group_req - * - * - */ - -/** @brief Remove Group command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_groups_remove_group_req_s -{ - zb_uint16_t group_id; /**< Group id */ -} -ZB_PACKED_STRUCT -zb_zcl_groups_remove_group_req_t; - -/** @cond internals_doc */ - -/** @internal Minimum size of Get Group Membership request */ -#define ZB_ZCL_REMOVE_GROUP_REQ_SIZE sizeof(zb_zcl_groups_remove_group_req_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Remove group command and fills in data request - structure. If request contains invalid data, ZB_ZCL_NULL_ID is stored as group_id. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param rem_group_req - variable to save command request - @note data_buf buffer should contain command request payload without ZCL header. - */ -#define ZB_ZCL_GROUPS_GET_REMOVE_GROUP_REQ(data_buf, rem_group_req) \ -{ \ - zb_zcl_groups_remove_group_req_t *rem_group_req_ptr; \ - (rem_group_req_ptr) = zb_buf_len(data_buf) >= ZB_ZCL_REMOVE_GROUP_REQ_SIZE ? \ - (zb_zcl_groups_remove_group_req_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (rem_group_req_ptr) \ - { \ - ZB_HTOLE16(&(rem_group_req).group_id, &rem_group_req_ptr->group_id); \ - } \ - else \ - { \ - rem_group_req.group_id = ZB_ZCL_NULL_ID; \ - } \ -} - -/** @brief Remove group response command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_groups_remove_group_res_s -{ - zb_uint8_t status; /**< Operation status */ - zb_uint16_t group_id; /**< Group id */ -} -ZB_PACKED_STRUCT -zb_zcl_groups_remove_group_res_t; - -/** @cond internals_doc */ - -/** @internal Add group response size */ -#define ZB_ZCL_REMOVE_GROUP_RES_SIZE sizeof(zb_zcl_groups_remove_group_res_t) - -/** @endcond */ /* internals_doc */ - -/** @brief Parses Remove group response command and returns response data - structure or NULL if request contains invalid data. - @param data_buf - pointer to zb_buf_t buffer containing command response data - @param rem_group_res - out pointer to zb_zcl_groups_remove_group_res_t, containing command - response record - @note data_buf buffer should contain response command payload without ZCL header - */ -#define ZB_ZCL_GROUPS_GET_REMOVE_GROUP_RES(data_buf, rem_group_res) \ -{ \ - (rem_group_res) = zb_buf_len(data_buf) >= ZB_ZCL_REMOVE_GROUP_RES_SIZE ? \ - (zb_zcl_groups_remove_group_res_t*)zb_buf_begin(data_buf) : NULL; \ - \ - if (rem_group_res) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&(rem_group_res)->group_id); \ - } \ -} - -/** @brief Send Remove group command - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param group_id - group ID to remove -*/ -#define ZB_ZCL_GROUPS_SEND_REMOVE_GROUP_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, group_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_GROUPS_REMOVE_GROUP); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_GROUPS, cb); \ -} - -/** @} */ /* Remove Group command definitions */ - - -/************************** Remove All Groups command definitions ****************************/ -/** @defgroup ZB_ZCL_GROUPS_RM_ALL_GRPS Remove All Groups command definitions - * @{ - * @details - * Remove All Groups command has only request form, and has no payload. Command is being - * processed in ZCL internals. If not disabled, command can be responded with Default Response - * command. - * - * @par Example - * Remove All Groups command sending: - * @snippet HA_samples/door_lock/sample_zed.c send_remove_all_groups_req - * @par - * - */ - -/** @brief Send Remove all groups command - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_GROUPS_SEND_REMOVE_ALL_GROUPS_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_GROUPS_REMOVE_ALL_GROUPS); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_GROUPS, cb); \ -} - -/** @} */ /* Remove All Groups command definitions */ - -/************************** Add group if identifying command definitions **************************/ - -/** @defgroup ZB_ZCL_GROUPS_ADD_IDENT Add group if identifying command definitions - * @{ - * @details - * Add Group if Identifying command has simple payload. The command is being processed in ZCL - * internals. Since the command has only request form, it can be responded with Default Response - * command frame, if not disabled explicitly. - * - * @b Example: - * Add Group if Identifying send: - * @snippet HA_samples/door_lock/sample_zed.c add_group_if_ident_req - * - */ - -/** @brief Send Add group if identifying command - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param group_id - group ID to add -*/ -#define ZB_ZCL_GROUPS_SEND_ADD_GROUP_IF_IDENT_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, group_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_GROUPS_ADD_GROUP_IF_IDENTIFYING); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - /* Group name currently is not supported, put empty string */ \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, ZB_ZCL_NULL_STRING); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_GROUPS, cb); \ -} - -/** @} */ /* Add group if identifying command definitions */ - -/** - * Handler for incoming group commands directed to server - * - * @param param - reference to buffer containing command - * - * @return ZB_TRUE - if command was processed - * ZB_FALSE - if command is not for server or is not supported - */ -zb_bool_t zb_zcl_process_groups_commands_srv(zb_uint8_t param); - -/** - * Handler for incoming group commands directed to client - * - * @param param - reference to buffer containing command - * - * @return ZB_TRUE - if command was processed - * ZB_FALSE - if command is not for client or is not supported - */ -zb_bool_t zb_zcl_process_groups_commands_cli(zb_uint8_t param); - -/** @cond internals_doc - @internal @name Groups cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_GROUPS_NAME_SUPPORT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_GROUPS_NAME_SUPPORT_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/** @internal @brief Number of attributes mandatory for reporting in Groups cluster. */ -#define ZB_ZCL_GROUPS_REPORT_ATTR_COUNT 0 - -#if defined ZB_ZCL_SUPPORT_CLUSTER_SCENES -/** Scenes fieldset length for Groups cluster */ -#define ZB_ZCL_CLUSTER_ID_GROUPS_SCENE_FIELD_SETS_LENGTH 0 -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_SCENES */ - -/** @} - @endcond */ /* Groups cluster internals */ - -/** @} */ /* ZCL Groups cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_groups_init_server(void); -void zb_zcl_groups_init_client(void); -#define ZB_ZCL_CLUSTER_ID_GROUPS_SERVER_ROLE_INIT zb_zcl_groups_init_server -#define ZB_ZCL_CLUSTER_ID_GROUPS_CLIENT_ROLE_INIT zb_zcl_groups_init_client - -#endif /* ZB_ZCL_GROUPS_H */ diff --git a/zboss/development/include/zcl/zb_zcl_grpw_bed_sensor.h b/zboss/development/include/zcl/zb_zcl_grpw_bed_sensor.h deleted file mode 100644 index 4a54a83de9..0000000000 --- a/zboss/development/include/zcl/zb_zcl_grpw_bed_sensor.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Bed Sensor for GreenPower cluster -*/ - -#ifndef ZB_ZCL_GRPW_BED_SENSOR_H -#define ZB_ZCL_GRPW_BED_SENSOR_H 1 - -#define ZB_ZCL_CLUSTER_ID_GRPW_BED_SENSOR 0xfd00 - -enum zb_zcl_grpw_bed_sensor_attr_e -{ - ZB_ZCL_ATTR_GRPW_BED_SENSOR_STATUS_ID = 0x0000, - ZB_ZCL_ATTR_GRPW_BED_SENSOR_CALC_DATA_0_ID = 0x0010, - ZB_ZCL_ATTR_GRPW_BED_SENSOR_CALC_DATA_1_ID = 0x0011, - ZB_ZCL_ATTR_GRPW_BED_SENSOR_SENSITIVITY_SETTING = 0x0020, - ZB_ZCL_ATTR_GRPW_BED_SENSOR_CALC_DATA_SEND_INTERVAL = 0x0021, - ZB_ZCL_ATTR_GRPW_BED_SENSOR_CALC_DATA_SEND_MODE = 0x0022, - ZB_ZCL_ATTR_GRPW_BED_SENSOR_EXIT_DETECT_ADD_DELAY = 0x0023, - ZB_ZCL_ATTR_GRPW_BED_SENSOR_OCCUPANCY_DETECT_ALG_SEL = 0x0024, - ZB_ZCL_ATTR_GRPW_BED_SENSOR_TYPE = 0x0025, - ZB_ZCL_ATTR_GRPW_BED_SENSOR_STATUS_REPORT_INTERVAL = 0x0026, - ZB_ZCL_ATTR_GRPW_BED_SENSOR_COMMANDS_FOR_SENSING_MODULE = 0x0030, - ZB_ZCL_ATTR_GRPW_BED_PENDING_CONFIGURATION = 0x00F0, -}; - -#define ZB_ZCL_CLUSTER_ID_GRPW_BED_SENSOR_SERVER_ROLE_INIT (zb_zcl_cluster_init_t)NULL -#define ZB_ZCL_CLUSTER_ID_GRPW_BED_SENSOR_CLIENT_ROLE_INIT (zb_zcl_cluster_init_t)NULL - -#endif /* ZB_ZCL_GRPW_BED_SENSOR_H */ diff --git a/zboss/development/include/zcl/zb_zcl_grpw_freq_agility.h b/zboss/development/include/zcl/zb_zcl_grpw_freq_agility.h deleted file mode 100644 index 20702d34b1..0000000000 --- a/zboss/development/include/zcl/zb_zcl_grpw_freq_agility.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Frequency agility for GreenPower cluster -*/ - -#ifndef ZB_ZCL_GRPW_FREQ_AGILITY_H -#define ZB_ZCL_GRPW_FREQ_AGILITY_H 1 - -#define ZB_ZCL_CLUSTER_ID_GRPW_FREQ_AGILITY 0xFCFA - -enum zb_zcl_grpw_freq_agility_attr_e -{ - ZB_ZCL_ATTR_GRPW_FREQ_AGILITY_BRIDGE_ADDR = 0x0000, - ZB_ZCL_ATTR_GRPW_FREQ_AGILITY_ACTIVE_CHANNEL_MASK = 0x0001, -}; - -#define ZB_ZCL_CLUSTER_ID_GRPW_FREQ_AGILITY_SERVER_ROLE_INIT (zb_zcl_cluster_init_t)NULL -#define ZB_ZCL_CLUSTER_ID_GRPW_FREQ_AGILITY_CLIENT_ROLE_INIT (zb_zcl_cluster_init_t)NULL - -#endif /* ZB_ZCL_GRPW_FREQ_AGILITY_H */ diff --git a/zboss/development/include/zcl/zb_zcl_ias_ace.h b/zboss/development/include/zcl/zb_zcl_ias_ace.h deleted file mode 100644 index 307558e6a4..0000000000 --- a/zboss/development/include/zcl/zb_zcl_ias_ace.h +++ /dev/null @@ -1,1598 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: IAS Ace cluster definitions -*/ - -#ifndef ZB_ZCL_IAS_ACE_H -#define ZB_ZCL_IAS_ACE_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_IAS_ACE - * @{ - */ - - -/* Cluster ZB_ZCL_CLUSTER_ID_IAS_ACE */ - -/*! @name IAS Ace cluster attributes - @{ -*/ - -/*! @brief Structure representsation of IAS ACE Zone Table - * see ZCL spec 8.3.2.3, table 8.11 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_zone_table_s -{ - /** Zone ID */ - zb_uint8_t zone_id; - /** Zone Type, see @ref zb_zcl_ias_zone_zonetype_e */ - zb_uint16_t zone_type; - /** Zone Address */ - zb_ieee_addr_t zone_address; - /** The pointer to a string with Zone Label. If the pointer is zero, the Zone Label - * is not programmed */ - zb_char_t *zone_label; -} ZB_PACKED_STRUCT zb_zcl_ias_ace_zone_table_t; - -/** @brief Default value for IAS ACE cluster revision global attribute */ -#define ZB_ZCL_IAS_ACE_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/** @brief IAS ACE Zone Table maximum length */ -#define ZB_ZCL_IAS_ACE_ZONE_TABLE_LENGTH 255 - -/** @brief IAS ACE ZoneType attribute maximum value */ -#define ZB_ZCL_IAS_ACE_ZONE_TYPE_MAX_VALUE 0xfffe - -/** @brief IAS ACE ZoneID attribute maximum value */ -#define ZB_ZCL_IAS_ACE_ZONE_ID_MAX_VALUE 0xfe - -/** @brief IAS ACE ZoneID attribute default value */ -#define ZB_ZCL_IAS_ACE_ZONE_ID_DEFAULT_VALUE 0 - -/** @brief IAS ACE Set Zone Address default value */ -#define ZB_ZCL_IAS_ACE_SET_ZONE_ADDRESS_DEFAULT_VALUE(ptr) (ZB_IEEE_ADDR_COPY(ptr, &g_unknown_ieee_addr)) - -/*! @brief IAS Ace cluster custom attribute identifiers -*/ -enum zb_zcl_ias_ace_attr_e -{ - /*! @brief Ace table length, ZCL spec 8.3.2.3 */ - ZB_ZCL_ATTR_IAS_ACE_ZONE_TABLE_LENGTH_ID = 0xeffe, - /*! @brief Ace table ZCL spec 8.3.2.3 */ - ZB_ZCL_ATTR_IAS_ACE_ZONE_TABLE_ID = 0xefff, - -}; - -/*! @cond internals_doc - @name IAS Ace cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_ACE_ZONE_TABLE_LENGTH_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_ACE_ZONE_TABLE_LENGTH_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_ACE_ZONE_TABLE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_ACE_ZONE_TABLE_ID, \ - ZB_ZCL_ATTR_TYPE_NULL, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in IAS Ace cluster */ -#define ZB_ZCL_IAS_ACE_REPORT_ATTR_COUNT 0 - -/*! @} - * @endcond*/ /* IAS Ace cluster internals */ - -/** @brief Declare attribute list for IAS Ace cluster - server side - @param attr_list - attribute list name - @param length - (zb_uint16_t*) pointer to variable to store Length of IAS ACE Zone Table attribute, - see ZCL spec 8.3.2.3, table 8.11 - @param table - pointer to variable to store IAS ACE Zone Table attribute, - see ZCL spec 8.3.2.3, table 8.11 -*/ -#define ZB_ZCL_DECLARE_IAS_ACE_ATTRIB_LIST(attr_list, length, table) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_IAS_ACE) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ACE_ZONE_TABLE_LENGTH_ID, (length)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ACE_ZONE_TABLE_ID, (table)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* IAS Ace cluster attributes */ - -/*! @name IAS Ace cluster commands - @{ -*/ - -/*! @brief IAS Ace cluster command identifiers - @see ZCL spec, IAS Ace Cluster, 8.3.2.4 -*/ -enum zb_zcl_ias_ace_cmd_e -{ - /** Arm command, ZCL spec 8.3.2.4.1 */ - ZB_ZCL_CMD_IAS_ACE_ARM_ID = 0x00, - /** Bypass command, ZCL spec 8.3.2.4.2 */ - ZB_ZCL_CMD_IAS_ACE_BYPASS_ID = 0x01, - /** Emergency command, ZCL spec 8.3.2.4.3 */ - ZB_ZCL_CMD_IAS_ACE_EMERGENCY_ID = 0x02, - /** Fire command, ZCL spec 8.3.2.4.3 */ - ZB_ZCL_CMD_IAS_ACE_FIRE_ID = 0x03, - /** Panic command, ZCL spec 8.3.2.4.3 */ - ZB_ZCL_CMD_IAS_ACE_PANIC_ID = 0x04, - /** Get Zone ID Map command, ZCL spec 8.3.2.4.4 */ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_ID_MAP_ID = 0x05, - /** Get Zone Information command, ZCL spec 8.3.2.4.5 */ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_INFO_ID = 0x06, - /** This command is used by ACE clients to request an update to the status - * (e.g. security system arm state) of the ACE server (i.e. the IAS CIE) */ - ZB_ZCL_CMD_IAS_ACE_GET_PANEL_STATUS_ID = 0x07, - /** Provides IAS ACE clients with a way to retrieve the list of zones to be bypassed. */ - ZB_ZCL_CMD_IAS_ACE_GET_BYPASSED_ZONE_LIST_ID = 0x08, - /** This command is used by ACE clients to request an update of the status - * of the IAS Zone devices managed by the ACE server (i.e. the IAS CIE). */ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_STATUS_ID = 0x09, -}; - -/*! @brief IAS Ace cluster response command identifiers - @see ZCL spec, IAS Ace Cluster, 8.3.2.5 -*/ -enum zb_zcl_ias_ace_resp_cmd_e -{ - /** Arm Response command, ZCL spec 8.3.2.5.1 */ - ZB_ZCL_CMD_IAS_ACE_ARM_RESP_ID = 0x00, - /** Get Zone ID Map Response command, ZCL spec 8.3.2.5.2 */ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_ID_MAP_RESP_ID = 0x01, - /** Get Zone Information Response command, ZCL spec 8.3.2.5.3 */ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_INFO_RESP_ID = 0x02, - /** This command updates ACE clients in the system of changes to zone status - * recorded by the ACE server (e.g., IAS CIE device). */ - ZB_ZCL_CMD_IAS_ACE_ZONE_STATUS_CHANGED_ID = 0x03, - /** This command updates ACE clients in the system of changes to zone status - * recorded by the ACE server (e.g., IAS CIE device). */ - ZB_ZCL_CMD_IAS_ACE_PANEL_STATUS_CHANGED_ID = 0x04, - /** This command updates ACE clients in the system of changes to panel status - * recorded by the ACE server (e.g., IAS CIE device). */ - ZB_ZCL_CMD_IAS_ACE_GET_PANEL_STATUS_RESPONSE_ID = 0x05, - /** Sets the list of bypassed zones on the IAS ACE client. */ - ZB_ZCL_CMD_IAS_ACE_SET_BYPASSED_ZONE_LIST_ID = 0x06, - /** Provides the response of the security panel to the request from the IAS ACE client - * to bypass zones via a Bypass command. */ - ZB_ZCL_CMD_IAS_ACE_BYPASS_RESPONSE_ID = 0x07, - /** Get Zone Status Response Command. */ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_STATUS_RESPONSE_ID = 0x08, -}; - -/** @cond internals_doc */ -/* IAS ACE cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_IAS_ACE_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_IAS_ACE_ARM_RESP_ID, \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_ID_MAP_RESP_ID, \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_INFO_RESP_ID, \ - ZB_ZCL_CMD_IAS_ACE_ZONE_STATUS_CHANGED_ID, \ - ZB_ZCL_CMD_IAS_ACE_PANEL_STATUS_CHANGED_ID, \ - ZB_ZCL_CMD_IAS_ACE_GET_PANEL_STATUS_RESPONSE_ID, \ - ZB_ZCL_CMD_IAS_ACE_SET_BYPASSED_ZONE_LIST_ID, \ - ZB_ZCL_CMD_IAS_ACE_BYPASS_RESPONSE_ID, \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_STATUS_RESPONSE_ID - -#define ZB_ZCL_CLUSTER_ID_IAS_ACE_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_IAS_ACE_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_IAS_ACE_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_IAS_ACE_ARM_ID, \ - ZB_ZCL_CMD_IAS_ACE_BYPASS_ID, \ - ZB_ZCL_CMD_IAS_ACE_EMERGENCY_ID, \ - ZB_ZCL_CMD_IAS_ACE_FIRE_ID, \ - ZB_ZCL_CMD_IAS_ACE_PANIC_ID, \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_ID_MAP_ID, \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_INFO_ID, \ - ZB_ZCL_CMD_IAS_ACE_GET_PANEL_STATUS_ID, \ - ZB_ZCL_CMD_IAS_ACE_GET_BYPASSED_ZONE_LIST_ID, \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_STATUS_ID - -#define ZB_ZCL_CLUSTER_ID_IAS_ACE_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_IAS_ACE_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - - -/******************************* Arm Command ******************************/ - -/** @brief Values of the Arm Mode - * see ZCL spec 8.3.2.4.1.2 -*/ -enum zb_zcl_ias_ace_arm_mode_e -{ - /** Disarm */ - ZB_ZCL_IAS_ACE_ARM_MODE_DISARM = 0x00, - /** Arm Day/Home Zones Only */ - ZB_ZCL_IAS_ACE_ARM_MODE_DAY = 0x01, - /** Arm Night/Sleep Zones Only */ - ZB_ZCL_IAS_ACE_ARM_MODE_NIGHT = 0x02, - /** Arm All Zones */ - ZB_ZCL_IAS_ACE_ARM_MODE_ALL = 0x03, -}; - -/*! @brief Structure representsation of Arm command, ZCL spec 8.3.2.4.1.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_arm_s -{ - /** Arm Mode, see @ref zb_zcl_ias_ace_arm_mode_e*/ - zb_uint8_t arm_mode; - /** Arm/Disarm Code */ - zb_uchar_t arm_disarm_code[ZB_ZCL_MAX_STRING_SIZE]; - /** Zone ID */ - zb_uint8_t zone_id; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_arm_t; - -/*! Arm request command payload size */ -#define ZB_ZCL_IAS_ACE_ARM_REQ_PAYLOAD_SIZE(ptr) (sizeof(zb_zcl_ias_ace_arm_t)-sizeof(((zb_zcl_ias_ace_arm_t *)(ptr))->arm_disarm_code)+ \ - 1+ZB_ZCL_GET_STRING_LENGTH(((zb_zcl_ias_ace_arm_t *)(ptr))->arm_disarm_code)) - -/*! @brief Arm command, ZCL spec 8.3.2.4.1 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param arm_mode - Arm Mode, see @ref zb_zcl_ias_ace_arm_mode_e - @param arm_disarm_code - Arm/Disarm Code string - @param zone_id - Zone ID -*/ -#define ZB_ZCL_IAS_ACE_SEND_ARM_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - arm_mode, arm_disarm_code, zone_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_ARM_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (arm_mode)); \ - ZB_ZCL_PACKET_PUT_STRING(ptr, (arm_disarm_code)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_id)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/** @brief Macro for getting Arm command, see ZCL spec 8.3.2.4.1 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_arm_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_ARM_REQ(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < \ - ZB_ZCL_IAS_ACE_ARM_REQ_PAYLOAD_SIZE(data)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->arm_mode, data); \ - ZB_ZCL_PACKET_GET_STATIC_STRING((data_ptr)->arm_disarm_code, data); \ - if (!data) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->zone_id, data); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - } \ -} - -/******************************* Bypass Command ******************************/ - -/*! @brief Structure representsation of Bypass command, ZCL spec 8.3.2.4.2.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_bypass_s -{ - /** Number of Zones */ - zb_uint8_t length; - /** Zone ID array, see @ref zb_zcl_ias_ace_zone_table_s */ - zb_uint8_t zone_id[ZB_ZCL_IAS_ACE_ZONE_TABLE_LENGTH]; - /** Arm/Disarm Code */ - zb_uchar_t arm_disarm_code[ZB_ZCL_MAX_STRING_SIZE]; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_bypass_t; - -/*! Bypass command payload size */ -#define ZB_ZCL_IAS_ACE_BYPASS_PAYLOAD_SIZE(ptr) (zb_uint_t)(1+(ptr)[0]+1+ZB_ZCL_GET_STRING_LENGTH((ptr)+1+(ptr)[0])) - -/*! @brief Start Bypass command, ZCL spec 8.3.2.4.1 - @param buffer - to put packet to - @param def_resp - enable/disable default response - @param length - Number of Zones - @param ptr - [out] (zb_uint8_t*) current position for @ref ZB_ZCL_IAS_ACE_SEND_BYPASS_REQ_ADD - and @ref ZB_ZCL_IAS_ACE_SEND_BYPASS_REQ_END -*/ -#define ZB_ZCL_IAS_ACE_SEND_BYPASS_REQ_START(buffer, def_resp, length, ptr) \ -{ \ - (ptr) = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_BYPASS_ID); \ - ZB_ZCL_PACKET_PUT_DATA8((ptr), (length)); \ -} - -/*! @brief Add Zone Id to Bypass command, ZCL spec 8.3.2.4.1 - @param ptr - [in/out] (zb_uint8_t*) current position - @param zone_id - Zone ID, see @ref zb_zcl_ias_ace_zone_table_s -*/ -#define ZB_ZCL_IAS_ACE_SEND_BYPASS_REQ_ADD(ptr, zone_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_id)); \ -} - -/*! @brief End form Bypass command and send it, ZCL spec 8.3.2.4.1 - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param arm_disarm_code - Arm/Disarm Code string - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_IAS_ACE_SEND_BYPASS_REQ_END( \ - ptr, buffer, arm_disarm_code, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb) \ -{ \ - ZB_ZCL_PACKET_PUT_STRING(ptr, (arm_disarm_code)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/** @brief Macro for getting Bypass command, see ZCL spec 8.3.2.4.1 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_bypass_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_BYPASS_REQ(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < ZB_ZCL_IAS_ACE_BYPASS_PAYLOAD_SIZE(data)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->length, data); \ - ZB_ZCL_PACKET_GET_DATA_N((data_ptr)->zone_id, data, (data_ptr)->length); \ - ZB_ZCL_PACKET_GET_STATIC_STRING((data_ptr)->arm_disarm_code, data); \ - if (!data) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - } \ -} - -/******************************* Emergency Command ******************************/ - -/*! @brief Emergency command, ZCL spec 8.3.2.4.3 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_IAS_ACE_SEND_EMERGENCY_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_EMERGENCY_ID); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/******************************* Fire Command ******************************/ - -/*! @brief Fire command, ZCL spec 8.3.2.4.3 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_IAS_ACE_SEND_FIRE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_FIRE_ID); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/******************************* Panic Command ******************************/ - -/*! @brief Panic command, ZCL spec 8.3.2.4.3 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_IAS_ACE_SEND_PANIC_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_PANIC_ID); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/******************************* Get Zone ID Map command ******************************/ - -/*! @brief Get Zone ID Map command, ZCL spec 8.3.2.4.4 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_ID_MAP_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_ID_MAP_ID); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/******************************* Get Zone Information command ******************************/ - -/*! @brief Structure representsation of Get Zone Information command, ZCL spec 8.3.2.4.5 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_get_zone_info_s -{ - /** Zone ID, see @ref zb_zcl_ias_ace_zone_table_s */ - zb_uint8_t zone_id; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_get_zone_info_t; - -/*! @brief Get Zone Information command, ZCL spec 8.3.2.4.5 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param zone_id - Zone ID, see @ref zb_zcl_ias_ace_zone_table_s -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_INFO_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - zone_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_INFO_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_id)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/** @brief Macro for getting Get Zone Information command, ZCL spec 8.3.2.4.5 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_get_zone_info_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_GET_ZONE_INFO_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_ace_get_zone_info_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ias_ace_get_zone_info_t *src_ptr = \ - (zb_zcl_ias_ace_get_zone_info_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->zone_id = src_ptr->zone_id; \ - } \ -} - -/******************************* Get Panel Status command ******************************/ - -/*! @brief Get Panel Status command, ZCL spec 8.3.2.3.6 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_PANEL_STATUS_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_GET_PANEL_STATUS_ID); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/******************************* Get Bypassed Zone List command ******************************/ - -/*! @brief Get Bypassed Zone List command, ZCL spec 8.3.2.3.7 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_BYPASSED_ZONE_LIST_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_GET_BYPASSED_ZONE_LIST_ID); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/******************************* Get Zone Status command ******************************/ - -/*! @brief Structure representsation of Get Zone Status command, ZCL spec 8.3.2.3.8.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_get_zone_status_s -{ - /** Starting Zone ID, see @ref zb_zcl_ias_ace_zone_table_s */ - zb_uint8_t starting_zone_id; - /** Max Number of Zone IDs Requested Field */ - zb_uint8_t max_num_zone_ids; - /** Zone Status Mask Flag Field */ - zb_uint8_t zone_status_mask_flag; - /** Zone Status Mask Field, see @ref zb_zcl_ias_zone_zonestatus_e */ - zb_uint16_t zone_status_mask; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_get_zone_status_t; - -/*! @brief Get Zone Status command, ZCL spec 8.3.2.3.8 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param starting_zone_id - Starting Zone ID, see @ref zb_zcl_ias_ace_zone_table_s - @param max_num_zone_ids - Max Number of Zone IDs Requested Field - @param zone_status_mask_flag - Zone Status Mask Flag Field - @param zone_status_mask - Zone Status Mask Field -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - starting_zone_id, max_num_zone_ids, zone_status_mask_flag, \ - zone_status_mask) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_STATUS_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (starting_zone_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (max_num_zone_ids)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_status_mask_flag)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (zone_status_mask)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/** @brief Macro for getting Get Zone Status command, ZCL spec 8.3.2.3.8 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_get_zone_status_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_GET_ZONE_STATUS_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_ace_get_zone_status_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ias_ace_get_zone_status_t *src_ptr = \ - (zb_zcl_ias_ace_get_zone_status_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->starting_zone_id = src_ptr->starting_zone_id; \ - (data_ptr)->max_num_zone_ids = src_ptr->max_num_zone_ids; \ - (data_ptr)->zone_status_mask_flag = src_ptr->zone_status_mask_flag; \ - ZB_HTOLE16(&((data_ptr)->zone_status_mask), &(src_ptr->zone_status_mask)); \ - } \ -} - - -/******************************* Arm Response command ******************************/ - -/*! @brief Values of the Arm Notification - * see ZCL8 spec 8.3.2.4.1.2 -*/ -enum zb_zcl_ias_ace_arm_not_e -{ - /*! @brief All Zones Disarmed - @deprecated Enumerator is deprecated. It will be removed after February 2023. Use ZB_ZCL_IAS_ACE_ARM_NOTIF_ALL_ZONES_DISARMED instead.*/ - ZB_ZCL_IAS_ACE_ARM_NOT_DISARM = 0x00, - /*! @brief All Zones Disarmed */ - ZB_ZCL_IAS_ACE_ARM_NOTIF_ALL_ZONES_DISARMED = 0x00, - /*! @brief Only Day/Home Zones Armed - @deprecated Enumerator is deprecated. It will be removed after February 2023. Use ZB_ZCL_IAS_ACE_ARM_NOTIF_ONLY_DAY_HOME_ZONES_ARMED instead.*/ - ZB_ZCL_IAS_ACE_ARM_NOT_DAY = 0x01, - /*! @brief Only Day/Home Zones Armed */ - ZB_ZCL_IAS_ACE_ARM_NOTIF_ONLY_DAY_HOME_ZONES_ARMED = 0x01, - /*! @brief Only Night/Sleep Zones Armed - @deprecated Enumerator is deprecated. It will be removed after February 2023. Use ZB_ZCL_IAS_ACE_ARM_NOTIF_ONLY_NIGHT_SLEEP_ZONES_ARMED instead.*/ - ZB_ZCL_IAS_ACE_ARM_NOT_NIGHT = 0x02, - /*! @brief Only Night/Sleep Zones Armed */ - ZB_ZCL_IAS_ACE_ARM_NOTIF_ONLY_NIGHT_SLEEP_ZONES_ARMED = 0x02, - /*! @brief All Zones Armed - @deprecated Enumerator is deprecated. It will be removed after February 2023. Use ZB_ZCL_IAS_ACE_ARM_NOTIF_ALL_ZONES_ARMED instead.*/ - ZB_ZCL_IAS_ACE_ARM_NOT_ALL = 0x03, - /*! @brief All Zones Armed */ - ZB_ZCL_IAS_ACE_ARM_NOTIF_ALL_ZONES_ARMED = 0x03, - /*! @brief Invalid Arm/Disarm Code */ - ZB_ZCL_IAS_ACE_ARM_NOTIF_INVALID_ARM_DISARM_CODE = 0x04, - /*! @brief Not ready to arm */ - ZB_ZCL_IAS_ACE_ARM_NOTIF_NOT_READY_TO_ARM = 0x05, - /*! @brief Already disarmed */ - ZB_ZCL_IAS_ACE_ARM_NOTIF_ALREADY_DISARMED = 0x06, -}; - -/*! @brief Structure representation of Arm Response command, ZCL spec 8.3.2.5.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_arm_resp_s -{ - /** Arm Notification, see @ref zb_zcl_ias_ace_arm_not_e */ - zb_uint8_t arm_notification; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_arm_resp_t; - - -/*! @brief Arm Response command, ZCL spec 8.3.2.5.1 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequence - @param arm_notification - Arm Notification, see @ref zb_zcl_ias_ace_arm_not_e -*/ -#define ZB_ZCL_IAS_ACE_SEND_ARM_RESP( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq, \ - arm_notification) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_IAS_ACE_ARM_RESP_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (arm_notification)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, NULL); \ -} - -/** @brief Macro for getting Arm Response command, ZCL spec 8.3.2.5.1 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_arm_resp_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_ARM_RESP(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_ace_arm_resp_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ias_ace_arm_resp_t *src_ptr = \ - (zb_zcl_ias_ace_arm_resp_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->arm_notification = src_ptr->arm_notification; \ - } \ -} - -/******************************* Get Zone ID Map Response command ******************************/ - -/*! @brief Length of array of Bitmap of Zone ID Map, ZCL spec 8.3.2.5.2.1 */ -#define ZB_ZCL_IAS_ACE_GET_ZONE_ID_MAP_LENGTH 16 - -/*! @brief Structure representsation of Get Zone ID Map Response command, ZCL spec 8.3.2.5.2.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_get_zone_id_map_resp_s -{ - /** Zone ID Map */ - zb_uint16_t zone_id_map[ZB_ZCL_IAS_ACE_GET_ZONE_ID_MAP_LENGTH]; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_get_zone_id_map_resp_t; - -/*! @brief Get Zone ID Map Response command, ZCL spec 8.3.2.5.2 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequence - @param zone_id_map - Zone ID Map, array[16] of zb_uint16_t -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_ID_MAP_RESP( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq, \ - zone_id_map) \ -{ \ - zb_uint8_t i; \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_ID_MAP_RESP_ID); \ - for(i=0; izone_id_map[i]), &(src_ptr->zone_id_map[i])); \ - } \ - } \ -} - -/******************* Get Zone Information Response command ******************************/ - -/*! @brief Zone Type is empty, ZCL spec 8.3.2.5.3.1 */ -#define ZB_ZCL_IAS_ACE_GET_ZONE_INFO_TYPE_NONE 0xffff - -/*! @brief Structure representsation of Get Zone Information Response command, ZCL spec 8.3.2.5.3.1 - * see @ ref zb_zcl_ias_ace_zone_table_s*/ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_get_zone_info_resp_s -{ - /** Zone ID */ - zb_uint8_t zone_id; - /** Zone Type, see @ref zb_zcl_ias_zone_zonetype_e */ - zb_uint16_t zone_type; - /** Zone Address */ - zb_ieee_addr_t address; - /** Zone Label Field */ - zb_uchar_t zone_label[ZB_ZCL_MAX_STRING_SIZE]; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_get_zone_info_resp_t; - -/*! Get Zone Information Response command payload size */ -#define ZB_ZCL_IAS_ACE_GET_ZONE_INFO_RESP_PAYLOAD_SIZE(ptr) (sizeof(zb_zcl_ias_ace_get_zone_info_resp_t)-sizeof(((zb_zcl_ias_ace_get_zone_info_resp_t *)(ptr))->zone_label)+ \ - 1+ZB_ZCL_GET_STRING_LENGTH(((zb_zcl_ias_ace_get_zone_info_resp_t *)(ptr))->zone_label)) - -/*! @brief Get Zone Information Response command, ZCL spec 8.3.2.5.3 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequence - @param zone_id - Zone ID - @param zone_type - Zone Type, see @ref zb_zcl_ias_zone_zonetype_e - @param address - Zone Address - @param zone_label - Zone Label Field -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_INFO_RESP( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq, \ - zone_id, zone_type, address, zone_label) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_INFO_RESP_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_id)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (zone_type)); \ - ZB_ZCL_PACKET_PUT_DATA_IEEE(ptr, (address)); \ - ZB_ZCL_PACKET_PUT_STRING(ptr, (zone_label)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, NULL); \ -} - -/** @brief Macro for getting Get Zone Information Response command, ZCL spec 8.3.2.5.3 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_get_zone_info_resp_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_GET_ZONE_INFO_RESP(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < ZB_ZCL_IAS_ACE_GET_ZONE_INFO_RESP_PAYLOAD_SIZE(data)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->zone_id, data); \ - ZB_ZCL_PACKET_GET_DATA16(&(data_ptr)->zone_type, data); \ - ZB_ZCL_PACKET_GET_DATA_IEEE(&(data_ptr)->address, data); \ - ZB_ZCL_PACKET_GET_STATIC_STRING((data_ptr)->zone_label, data); \ - if (!data) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - } \ -} - -/******************* Zone Status Changed command ******************************/ - -/*! @brief IAS ACE Audible Notification Field - @see ZCL spec 8.3.2.4.4.4 -*/ -enum zb_zcl_ias_ace_aud_notification_e -{ - /** Mute (i.e., no audible notification) */ - ZB_ZCL_IAS_ACE_AUD_NOTIFICATION_MUTE = 0x00, - /** Default sound */ - ZB_ZCL_IAS_ACE_AUD_NOTIFICATION_DEF_SOUND = 0x01, - /** Manufacturer specific */ - ZB_ZCL_IAS_ACE_AUD_NOTIFICATION_MANUF_SPECIFIC = 0x80, -}; - -/*! @brief Structure representsation of Zone Status Changed command, ZCL spec 8.3.2.4.4 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_zone_status_changed_s -{ - /** Zone ID */ - zb_uint8_t zone_id; - /** Zone Status, see @ref zb_zcl_ias_zone_zonestatus_e */ - zb_uint16_t zone_status; - /** Audible Notification, see @ref zb_zcl_ias_ace_aud_notification_e */ - zb_uint8_t aud_notification; - /** Zone Label Field */ - zb_uchar_t zone_label[ZB_ZCL_MAX_STRING_SIZE]; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_zone_status_changed_t; - -/*! Zone Status Changed command payload size */ -#define ZB_ZCL_IAS_ACE_ZONE_STATUS_CHANGED_PAYLOAD_SIZE(ptr) (sizeof(zb_zcl_ias_ace_zone_status_changed_t)-sizeof(((zb_zcl_ias_ace_zone_status_changed_t *)(ptr))->zone_label)+ \ - 1+ZB_ZCL_GET_STRING_LENGTH(((zb_zcl_ias_ace_zone_status_changed_t *)(ptr))->zone_label)) - -/*! @brief Zone Status Changed command, ZCL spec 8.3.2.4.4 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param zone_id - Zone ID - @param zone_status - Zone Status, see @ref zb_zcl_ias_zone_zonestatus_e - @param aud_notification - Audible Notification, see @ref zb_zcl_ias_ace_aud_notification_e - @param zone_label - Zone Label Field -*/ -#define ZB_ZCL_IAS_ACE_SEND_ZONE_STATUS_CHANGED_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, \ - cb, zone_id, zone_status, aud_notification, zone_label) \ -{ \ - zb_uint8_t* ptr = zb_zcl_start_command_header(buffer, \ - ZB_ZCL_CONSTRUCT_FRAME_CONTROL( \ - ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, \ - (def_resp)), \ - 0, /* No manuf_code */ \ - ZB_ZCL_CMD_IAS_ACE_ZONE_STATUS_CHANGED_ID, \ - NULL); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_id)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (zone_status)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (aud_notification)); \ - ZB_ZCL_PACKET_PUT_STRING(ptr, (zone_label)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/** @brief Macro for getting Zone Status Changed command, ZCL spec 8.3.2.4.4 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_zone_status_changed_t. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_ZONE_STATUS_CHANGED_REQ(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < ZB_ZCL_IAS_ACE_ZONE_STATUS_CHANGED_PAYLOAD_SIZE(data)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->zone_id, data); \ - ZB_ZCL_PACKET_GET_DATA16(&(data_ptr)->zone_status, data); \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->aud_notification, data); \ - ZB_ZCL_PACKET_GET_STATIC_STRING((data_ptr)->zone_label, data); \ - if (!data) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - } \ -} - -/******************* Panel Status Changed command ******************************/ - -/*! @brief IAS ACE PanelStatus Parameter - @see ZCL spec 8.3.2.4.5.2 -*/ -enum zb_zcl_ias_ace_panel_status_e -{ - /** Panel disarmed (all zones disarmed) and ready to arm */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_DISARMED = 0x00, - /** Armed stay */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_ARMED_STAY = 0x01, - /** Armed night */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_ARMED_NIGHT = 0x02, - /** Armed away */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_ARMED_AWAY = 0x03, - /** Exit delay */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_EXIT_DELAY = 0x04, - /** Entry delay */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_ENTRY_DELAY = 0x05, - /** Not ready to arm */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_NOT_READY = 0x06, - /** In alarm */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_IN_ALARM = 0x07, - /** Arming Stay */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_ARMING_STAY = 0x08, - /** Arming Night */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_ARMING_NIGHT = 0x09, - /** Arming Away */ - ZB_ZCL_IAS_ACE_PANEL_STATUS_ARMING_AWAY = 0x0a, -}; - -/*! @brief IAS ACE Alarm Status Field - @see ZCL spec 8.3.2.4.5.4 -*/ -enum zb_zcl_ias_ace_alarm_status_e -{ - /** No alarm */ - ZB_ZCL_IAS_ACE_ALARM_STATUS_NO_ALARM = 0x00, - /** Burglar */ - ZB_ZCL_IAS_ACE_ALARM_STATUS_BURGLAR = 0x01, - /** Fire */ - ZB_ZCL_IAS_ACE_ALARM_STATUS_FIRE = 0x02, - /** Emergency */ - ZB_ZCL_IAS_ACE_ALARM_STATUS_EMERGENCY = 0x03, - /** Police Panic */ - ZB_ZCL_IAS_ACE_ALARM_STATUS_POLICE_PANIC = 0x04, - /** Fire Panic */ - ZB_ZCL_IAS_ACE_ALARM_STATUS_FIRE_PANIC = 0x05, - /** Emergency Panic */ - ZB_ZCL_IAS_ACE_ALARM_STATUS_EMERGENCY_PANIC = 0x06, -}; - -/*! @brief Structure representsation of Panel Status Changed command, ZCL spec 8.3.2.4.5 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_panel_status_changed_s -{ - /** Panel Status, see @ref zb_zcl_ias_ace_panel_status_e */ - zb_uint8_t panel_status; - /** Seconds Remaining Parameter */ - zb_uint8_t seconds_remaining; - /** Audible Notification, see @ref zb_zcl_ias_ace_aud_notification_e */ - zb_uint8_t aud_notification; - /** Alarm Status Field, see @ref zb_zcl_ias_ace_alarm_status_e */ - zb_uint8_t alarm_status; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_panel_status_changed_t; - -/*! @brief Panel Status Changed command, ZCL spec 8.3.2.4.5 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param panel_status - Panel Status, see @ref zb_zcl_ias_ace_panel_status_e - @param seconds_remaining - Seconds Remaining Parameter - @param aud_notification - Audible Notification, see @ref zb_zcl_ias_ace_aud_notification_e - @param alarm_status - Alarm Status Field, see @ref zb_zcl_ias_ace_alarm_status_e -*/ -#define ZB_ZCL_IAS_ACE_SEND_PANEL_STATUS_CHANGED_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, \ - cb, panel_status, seconds_remaining, aud_notification, \ - alarm_status) \ -{ \ - zb_uint8_t* ptr = zb_zcl_start_command_header(buffer, \ - ZB_ZCL_CONSTRUCT_FRAME_CONTROL( \ - ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, \ - (def_resp)), \ - 0, /* No manuf_code */ \ - ZB_ZCL_CMD_IAS_ACE_PANEL_STATUS_CHANGED_ID, \ - NULL); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (panel_status)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (seconds_remaining)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (aud_notification)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (alarm_status)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/** @brief Macro for getting Panel Status Changed command, ZCL spec 8.3.2.4.5 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_panel_status_changed_t. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_PANEL_STATUS_CHANGED_REQ(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_ace_panel_status_changed_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->panel_status, data); \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->seconds_remaining, data); \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->aud_notification, data); \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->alarm_status, data); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/******************* Get Panel Status Response command ******************************/ - -/*! @brief Structure representsation of Get Panel Status Response command, ZCL spec 8.3.2.4.6 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_get_panel_status_resp_s -{ - /** Panel Status, see @ref zb_zcl_ias_ace_panel_status_e */ - zb_uint8_t panel_status; - /** Seconds Remaining Parameter */ - zb_uint8_t seconds_remaining; - /** Audible Notification, see @ref zb_zcl_ias_ace_aud_notification_e */ - zb_uint8_t aud_notification; - /** Alarm Status Field, see @ref zb_zcl_ias_ace_alarm_status_e */ - zb_uint8_t alarm_status; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_get_panel_status_resp_t; - -/*! @brief Get Panel Status Response command, ZCL spec 8.3.2.4.6 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequence - @param panel_status - Panel Status, see @ref zb_zcl_ias_ace_panel_status_e - @param seconds_remaining - Seconds Remaining Parameter - @param aud_notification - Audible Notification, see @ref zb_zcl_ias_ace_aud_notification_e - @param alarm_status - Alarm Status Field, see @ref zb_zcl_ias_ace_alarm_status_e -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_PANEL_STATUS_RESP( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq, \ - panel_status, seconds_remaining, aud_notification, \ - alarm_status) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_IAS_ACE_GET_PANEL_STATUS_RESPONSE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (panel_status)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (seconds_remaining)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (aud_notification)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (alarm_status)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, NULL); \ -} - -/** @brief Macro for getting Get Panel Status Response command, ZCL spec 8.3.2.4.6 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_get_panel_status_resp_t. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_GET_PANEL_STATUS_RESP(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_ace_panel_status_changed_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->panel_status, data); \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->seconds_remaining, data); \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->aud_notification, data); \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->alarm_status, data); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/******************* Set Bypassed Zone List command ******************************/ - -/*! @brief Structure representsation of Set Bypassed Zone List command, ZCL spec 8.3.2.4.7 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_set_bypassed_zone_list_s -{ - /** Number of Zones */ - zb_uint8_t length; - /** Zone ID array, see @ref zb_zcl_ias_ace_zone_table_s */ - zb_uint8_t zone_id[ZB_ZCL_IAS_ACE_ZONE_TABLE_LENGTH]; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_set_bypassed_zone_list_t; - -/*! Set Bypassed Zone List command payload size */ -#define ZB_ZCL_IAS_ACE_SET_BYPASSED_ZONE_LIST_PAYLOAD_SIZE(ptr) (sizeof(zb_zcl_ias_ace_set_bypassed_zone_list_t)-sizeof(((zb_zcl_ias_ace_set_bypassed_zone_list_t *)(ptr))->zone_id)+ \ - ((zb_zcl_ias_ace_set_bypassed_zone_list_t *)(ptr))->length) - -/*! @brief Start Set Bypassed Zone List command, ZCL spec 8.3.2.4.7 - @param buffer - to put packet to - @param length - Number of Zones - @param ptr - [out] (zb_uint8_t*) current position for @ref ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_ADD - and @ref ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_END -*/ -#define ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_START( \ - buffer, length, ptr) \ -{ \ - (ptr) = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ACE_SET_BYPASSED_ZONE_LIST_ID); \ - ZB_ZCL_PACKET_PUT_DATA8((ptr), (length)); \ -} - -/*! @brief Start Set Bypassed Zone List command, ZCL spec 8.3.2.4.7 - (response to the Get Bypassed Zone List command) - @param buffer - to put packet to - @param seq - sequence - @param length - Number of Zones - @param ptr - [out] (zb_uint8_t*) current position for @ref ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_ADD - and @ref ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_END -*/ -#define ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_START_RESP( \ - buffer, seq, length, ptr) \ -{ \ - (ptr) = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_IAS_ACE_SET_BYPASSED_ZONE_LIST_ID); \ - ZB_ZCL_PACKET_PUT_DATA8((ptr), (length)); \ -} - -/*! @brief Start Set Bypassed Zone List command, ZCL spec 8.3.2.4.7 - (unsolicited request) - @param buffer - to put packet to - @param def_resp - enable/disable default response - @param length - Number of Zones - @param ptr - [out] (zb_uint8_t*) current position for @ref ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_ADD - and @ref ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_END -*/ -#define ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_START_REQ( \ - buffer, def_resp, length, ptr) \ -{ \ - (ptr) = zb_zcl_start_command_header(buffer, \ - ZB_ZCL_CONSTRUCT_FRAME_CONTROL( \ - ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, \ - (def_resp)), \ - 0, /* No manuf_code */ \ - ZB_ZCL_CMD_IAS_ACE_SET_BYPASSED_ZONE_LIST_ID, \ - NULL); \ - ZB_ZCL_PACKET_PUT_DATA8((ptr), (length)); \ -} - -/*! @brief Add Zone Id to Set Bypassed Zone List command, ZCL spec 8.3.2.4.7 - @param ptr - [in/out] (zb_uint8_t*) current position - @param zone_id - Zone ID, see @ref zb_zcl_ias_ace_zone_table_s -*/ -#define ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_ADD(ptr, zone_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_id)); \ -} - -/*! @brief End form Set Bypassed Zone List command and send it, ZCL spec 8.3.2.4.7 - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, cb); \ -} - -/** @brief Macro for getting Set Bypassed Zone List command, ZCL spec 8.3.2.4.7 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_set_bypassed_zone_list_t. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_SET_BYPASSED_ZONE_LIST(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < ZB_ZCL_IAS_ACE_SET_BYPASSED_ZONE_LIST_PAYLOAD_SIZE(data)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->length, data); \ - ZB_ZCL_PACKET_GET_DATA_N((data_ptr)->zone_id, data, (data_ptr)->length); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/******************* Bypass Response command ******************************/ - -/*! @brief IAS ACE Bypass Result - @see ZCL spec 8.3.2.4.8.3 -*/ -enum zb_zcl_ias_ace_bypass_result_e -{ - /** The Zone ID requested to be bypassed is successful. Zone is bypassed. */ - ZB_ZCL_IAS_ACE_BYPASS_RESULT_BYPASSED = 0x00, - /** The Zone ID requested to be bypassed is unsuccessful. Zone is not bypassed. */ - ZB_ZCL_IAS_ACE_BYPASS_RESULT_NOT_BYPASSED = 0x01, - /** The Zone ID requested to be bypassed is not eligible to be bypassed per the - * policy or user configurations on the IAS ACE server. Zone is not bypassed. */ - ZB_ZCL_IAS_ACE_BYPASS_RESULT_NOT_ALLOWED = 0x02, - /** The Zone ID requested to be bypassed is not in the valid range of Zone IDs. */ - ZB_ZCL_IAS_ACE_BYPASS_RESULT_INVALID_ZONE_ID = 0x03, - /** The Zone ID requested to be bypassed is in the valid range of Zone IDs, but - * the IAS ACE server does not have a record of the Zone ID requested. */ - ZB_ZCL_IAS_ACE_BYPASS_RESULT_UNKNOWN_ZONE_ID = 0x04, - /** A value returned indicating that the Arm/Disarm Code was entered incorrectly. */ - ZB_ZCL_IAS_ACE_BYPASS_RESULT_INVALID_ARM_CODE = 0x05, -}; - -/*! @brief Structure representsation of Bypass Response command, ZCL spec 8.3.2.4.8 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_bypass_resp_s -{ - /** Number of Zones */ - zb_uint8_t length; - /** Bypass Result for Zone IDs, see @ref zb_zcl_ias_ace_bypass_result_e */ - zb_uint8_t bypass_result[ZB_ZCL_IAS_ACE_ZONE_TABLE_LENGTH]; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_bypass_resp_t; - -/*! Bypass Response command payload size */ -#define ZB_ZCL_IAS_ACE_BYPASS_RESP_PAYLOAD_SIZE(ptr) (sizeof(zb_zcl_ias_ace_bypass_resp_t)-sizeof(((zb_zcl_ias_ace_bypass_resp_t *)(ptr))->bypass_result)+ \ - ((zb_zcl_ias_ace_bypass_resp_t *)(ptr))->length) - -/*! @brief Start Bypass Response command, ZCL spec 8.3.2.4.8 - @param buffer - to put packet to - @param seq - sequence - @param length - Number of Zones - @param ptr - [out] (zb_uint8_t*) current position for @ref ZB_ZCL_IAS_ACE_SEND_BYPASS_RESP_ADD - and @ref ZB_ZCL_IAS_ACE_SEND_BYPASS_RESP_END -*/ -#define ZB_ZCL_IAS_ACE_SEND_BYPASS_RESP_START( \ - buffer, seq, length, ptr) \ -{ \ - (ptr) = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_IAS_ACE_BYPASS_RESPONSE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8((ptr), (length)); \ -} - -/*! @brief Add Bypass results to Bypass Response command, ZCL spec 8.3.2.4.8 - @param ptr - [in/out] (zb_uint8_t*) current position - @param bypass_result - Bypass Result for Zone IDs, see @ref zb_zcl_ias_ace_bypass_result_e -*/ -#define ZB_ZCL_IAS_ACE_SEND_BYPASS_RESP_ADD(ptr, bypass_result) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (bypass_result)); \ -} - -/*! @brief End form Bypass Response command and send it, ZCL spec 8.3.2.4.8 - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier -*/ -#define ZB_ZCL_IAS_ACE_SEND_BYPASS_RESP_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id) \ -{ \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, NULL); \ -} - -/** @brief Macro for getting Bypass Response command, ZCL spec 8.3.2.4.8 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_bypass_resp_t. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_BYPASS_RESP(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < ZB_ZCL_IAS_ACE_BYPASS_RESP_PAYLOAD_SIZE(data)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->length, data); \ - ZB_ZCL_PACKET_GET_DATA_N((data_ptr)->bypass_result, data, (data_ptr)->length); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/******************* Get Zone Status Response command ******************************/ - -/*! @brief IAS ACE Zone Status structure */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_zone_status_s -{ - /** Zone ID, see @ref zb_zcl_ias_ace_zone_table_s */ - zb_uint8_t zone_id; - /** Zone Status, see @ref zb_zcl_ias_zone_zonestatus_e */ - zb_uint16_t zone_status; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_zone_status_t; - -/*! @brief Structure representsation of Get Zone Status Response command, ZCL spec 8.3.2.4.9 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_ace_get_zone_status_resp_s -{ - /** Zone Status Complete Field */ - zb_uint8_t zone_status_complete; - /** Number of Zones */ - zb_uint8_t length; - /** Status of Zone IDs, see @ref zb_zcl_ias_ace_zone_status_t */ - zb_zcl_ias_ace_zone_status_t zone_id_status[ZB_ZCL_IAS_ACE_ZONE_TABLE_LENGTH]; - -} ZB_PACKED_STRUCT zb_zcl_ias_ace_get_zone_status_resp_t; - -/*! Get Zone Status Response command payload size */ -#define ZB_ZCL_IAS_ACE_GET_ZONE_STATUS_RESP_PAYLOAD_SIZE(ptr) ((sizeof(zb_zcl_ias_ace_get_zone_status_resp_t)-sizeof(((zb_zcl_ias_ace_get_zone_status_resp_t *)(ptr))->zone_id_status))+ \ - ((zb_zcl_ias_ace_get_zone_status_resp_t *)(ptr))->length * sizeof(zb_zcl_ias_ace_zone_status_t)) - -/*! @brief Get Zone Status Response command, ZCL spec 8.3.2.4.9 - @param buffer - to put packet to - @param seq - sequence - @param zone_status_complete - Zone Status Complete - @param length - Number of Zones - @param ptr - [out] (zb_uint8_t*) current position for @ref ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_RESP_ADD - and @ref ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_RESP_END -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_RESP_START( \ - buffer, seq, zone_status_complete, length, ptr) \ -{ \ - (ptr) = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_IAS_ACE_GET_ZONE_STATUS_RESPONSE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8((ptr), (zone_status_complete)); \ - ZB_ZCL_PACKET_PUT_DATA8((ptr), (length)); \ -} - -/*! @brief Add Zone Id and Zone Status to Get Zone Status Response command, ZCL spec 8.3.2.4.9 - @param ptr - [in/out] (zb_uint8_t*) current position - @param zone_id - Zone ID, see @ref zb_zcl_ias_ace_zone_table_s - @param zone_status - Zone Status, see @ref zb_zcl_ias_zone_zonestatus_e -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_RESP_ADD( \ - ptr, zone_id, zone_status) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_status)); \ -} - -/*! @brief End form Get Zone Status Response command and send it, ZCL spec 8.3.2.4.9 - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier -*/ -#define ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_RESP_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id) \ -{ \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ACE, NULL); \ -} - -/** @brief Macro for getting Get Zone Status Response command, ZCL spec 8.3.2.4.9 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_ace_get_zone_status_resp_t. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ACE_GET_GET_ZONE_STATUS_RESP(data_ptr, buffer, status) \ -{ \ - zb_uint8_t *data = zb_buf_begin(buffer); \ - if (zb_buf_len((buffer)) < ZB_ZCL_IAS_ACE_GET_ZONE_STATUS_RESP_PAYLOAD_SIZE(data)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->zone_status_complete, data); \ - ZB_ZCL_PACKET_GET_DATA8(&(data_ptr)->length, data); \ - ZB_ZCL_PACKET_GET_DATA_N((data_ptr)->zone_id_status, data, \ - (data_ptr)->length * sizeof(zb_zcl_ias_ace_zone_status_t)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/*! @} */ /* IAS Ace cluster commands */ - -/*! @} */ /* ZCL IAS Ace cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_ias_ace_init_server(void); -void zb_zcl_ias_ace_init_client(void); -#define ZB_ZCL_CLUSTER_ID_IAS_ACE_SERVER_ROLE_INIT zb_zcl_ias_ace_init_server -#define ZB_ZCL_CLUSTER_ID_IAS_ACE_CLIENT_ROLE_INIT zb_zcl_ias_ace_init_client - -#endif /* ZB_ZCL_IAS_ACE_H */ diff --git a/zboss/development/include/zcl/zb_zcl_ias_wd.h b/zboss/development/include/zcl/zb_zcl_ias_wd.h deleted file mode 100644 index 78d6171a92..0000000000 --- a/zboss/development/include/zcl/zb_zcl_ias_wd.h +++ /dev/null @@ -1,473 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: IAS WD cluster definitions -*/ - -#ifndef ZB_ZCL_IAS_WD_H -#define ZB_ZCL_IAS_WD_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_IAS_WD - * @{ - * @details - * IAS WD cluster definitions - */ - - -/* Cluster ZB_ZCL_CLUSTER_ID_IAS_WD */ - -/*! @name IAS WD cluster attributes - @{ -*/ - -/*! @brief IAS WD cluster attribute identifiers - @see ZCL spec, IAS WD Cluster 8.4.2.2 -*/ -enum zb_zcl_ias_wd_attr_e -{ - /*! @brief Max Duration attribute, ZCL spec 8.4.2.2.1 */ - ZB_ZCL_ATTR_IAS_WD_MAX_DURATION_ID = 0x0000, - -}; - -/** @brief Default value for IAS WD cluster revision global attribute */ -#define ZB_ZCL_IAS_WD_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief Max Duration attribute default value */ -#define ZB_ZCL_ATTR_IAS_WD_MAX_DURATION_DEF_VALUE 240 - -/** @brief Max Duration attribute minimum value */ -#define ZB_ZCL_ATTR_IAS_WD_MAX_DURATION_MIN_VALUE 0 - -/** @brief Max Duration attribute maximum value */ -#define ZB_ZCL_ATTR_IAS_WD_MAX_DURATION_MAX_VALUE 0xfffe - -/** @cond internals_doc */ -/*! @internal @name IAS WD cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_WD_MAX_DURATION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_WD_MAX_DURATION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in IAS WD cluster */ -#define ZB_ZCL_IAS_WD_REPORT_ATTR_COUNT 0 - -/*! @} */ /* IAS WD cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for IAS WD cluster - server side - @param attr_list - attribute list name - @param max_duration - pointer to variable to store Max Duration attribute -*/ -#define ZB_ZCL_DECLARE_IAS_WD_ATTRIB_LIST(attr_list, \ - max_duration) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_IAS_WD) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_WD_MAX_DURATION_ID, (max_duration)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* IAS WD cluster attributes */ - -/*! @name IAS WD cluster commands - @{ -*/ - -/*! @brief IAS WD cluster command identifiers - @see ZCL spec, IAS WD Cluster, 8.4.2.3 -*/ -enum zb_zcl_ias_wd_cmd_e -{ - ZB_ZCL_CMD_IAS_WD_START_WARNING_ID = 0x00, /**< Start warning command. ZCL spec 8.4.2.3.1 */ - ZB_ZCL_CMD_IAS_WD_SQUAWK_ID = 0x01 /**< Squawk command. ZCL spec 8.4.2.3.2 */ -}; - -/** @cond internals_doc */ -/* IAS WD cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_IAS_WD_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_IAS_WD_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_IAS_WD_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_IAS_WD_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_IAS_WD_START_WARNING_ID, \ - ZB_ZCL_CMD_IAS_WD_SQUAWK_ID - -#define ZB_ZCL_CLUSTER_ID_IAS_WD_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_IAS_WD_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/******************************* Start warning command ******************************/ - -/** @brief Warning Mode Field, see ZCL spec 8.4.2.3.1.2 */ -enum zb_zcl_ias_wd_warning_mode_e -{ - /** Stop */ - ZB_ZCL_IAS_WD_WARNING_MODE_STOP = 0x00, - /** Burglar */ - ZB_ZCL_IAS_WD_WARNING_MODE_BURGLAR = 0x01, - /** Fire */ - ZB_ZCL_IAS_WD_WARNING_MODE_FIRE = 0x02, - /** Emergency */ - ZB_ZCL_IAS_WD_WARNING_MODE_EMERGENCY = 0x03, - /* Police panic */ - ZB_ZCL_IAS_WD_WARNING_MODE_POLICE_PANIC = 0x04, - /* Fire panic */ - ZB_ZCL_IAS_WD_WARNING_MODE_FIRE_PANIC = 0x05, - /* Emergency panic (i.e., medical issue) */ - ZB_ZCL_IAS_WD_WARNING_MODE_EMERGENCY_PANIC = 0x06, -}; - -/** @brief Strobe Field, see ZCL spec 8.4.2.3.1.3 */ -enum zb_zcl_ias_wd_strobe_e -{ - /** No strobe */ - ZB_ZCL_IAS_WD_STROBE_NO_STROBE = 0x00, - /** Use strobe in parallel to warning */ - ZB_ZCL_IAS_WD_STROBE_USE_STROBE = 0x01, -}; - -/** @brief Siren Level Field, see ZCL spec 8.4.2.3.1.4 */ -enum zb_zcl_ias_wd_siren_level_e -{ - /** Low level sound */ - ZB_ZCL_IAS_WD_SIREN_LEVEL_LOW = 0x00, - /** Medium level sound */ - ZB_ZCL_IAS_WD_SIREN_LEVEL_MEDIUM = 0x01, - /** High level sound */ - ZB_ZCL_IAS_WD_SIREN_LEVEL_HIGH = 0x02, - /** Very high level sound */ - ZB_ZCL_IAS_WD_SIREN_LEVEL_VERY_HIGH = 0x03, -}; - -/** - @brief Strobe Level Field, see ZCL spec 8.4.2.2.1.7 - */ -enum zb_zcl_ias_wd_strobe_level_e -{ - /** Low level strobe */ - ZB_ZCL_IAS_WD_STROBE_LEVEL_LOW = 0x00, - /** Medium level strobe */ - ZB_ZCL_IAS_WD_STROBE_LEVEL_MEDIUM = 0x01, - /** High level strobe */ - ZB_ZCL_IAS_WD_STROBE_LEVEL_HIGH = 0x02, - /** Very high level strobe */ - ZB_ZCL_IAS_WD_STROBE_LEVEL_VERY_HIGH = 0x03, -}; - -/*! @brief Structure representsation Start warning command. ZCL spec 8.4.2.3.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_wd_start_warning_s -{ - /** Status - enum flags Warning mode, Strobe and Siren Level, see ZCL spec 8.4.2.3.1 */ - zb_uint8_t status; - /** Warning duration*/ - zb_uint16_t duration; - /** Strobe Duty Cycle */ - zb_uint8_t strobe_duty_cycle; - /** Strobe Level (enum zb_zcl_ias_wd_strobe_level_e) */ - zb_uint8_t strobe_level; -} ZB_PACKED_STRUCT zb_zcl_ias_wd_start_warning_t; - -/*! @brief Get Warning Mode from payload Start warning command */ -#define ZB_ZCL_IAS_WD_GET_WARNING_MODE(status) (((status) >> 4) & 0x0f) - -/*! @brief Get Strobe from payload Start warning command */ -#define ZB_ZCL_IAS_WD_GET_STROBE(status) (((status) >> 2) & 0x03) - -/*! @brief Get Siren level from payload Start warning command */ -#define ZB_ZCL_IAS_WD_GET_SIREN_LEVEL(status) ((status) & 0x03) - -/*! @brief Make Status field Start warning command from Warning Mode, Strobe and Siren Level */ -#define ZB_ZCL_IAS_WD_MAKE_START_WARNING_STATUS(warning_mode, strobe, siren_level) \ - (((siren_level) & 0x03) | (((strobe) & 0x03) << 2) | (((warning_mode) & 0x0f) << 4)) - -/*! @brief Strobe Duty Cycle default value */ -#define ZB_ZCL_IAS_WD_STROBE_DUTY_CYCLE_DEFAULT_VALUE 0 -/*! @brief Strobe Duty Cycle maximum value */ -#define ZB_ZCL_IAS_WD_STROBE_DUTY_CYCLE_MAX_VALUE 100 - -/*! @brief Start warning command. ZCL spec 8.4.2.3.1 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param status - Status - enum flags Warning mode, Strobe and Siren Level - @param duration - Warning duration - @param strobe_duty_cycle - Strobe Duty Cycle - @param strobe_level - Strobe Level, see @ref zb_zcl_ias_wd_strobe_level_e -*/ -#define ZB_ZCL_IAS_WD_SEND_START_WARNING_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - status, duration, strobe_duty_cycle, strobe_level) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_WD_START_WARNING_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (status)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (duration)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (strobe_duty_cycle)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (strobe_level)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_WD, cb); \ -} - -/** @brief Macro for getting Start warning command. ZCL spec 8.4.2.3.1 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_wd_start_warning_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_WD_GET_START_WARNING_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_wd_start_warning_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ias_wd_start_warning_t *src_ptr = \ - (zb_zcl_ias_wd_start_warning_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->status = src_ptr->status; \ - ZB_HTOLE16(&((data_ptr)->duration), &(src_ptr->duration)); \ - (data_ptr)->strobe_duty_cycle = src_ptr->strobe_duty_cycle; \ - (data_ptr)->strobe_level = src_ptr->strobe_level; \ - } \ -} - -/******************************* Squawk command ******************************/ - -/** @brief Squawk Mode Field, see ZCL spec 8.4.2.3.2.2 */ -enum zb_zcl_ias_wd_squawk_mode_e -{ - /** Notification sound for "System is armed" */ - ZB_ZCL_IAS_WD_SQUAWK_MODE_ARMED = 0x00, - /** Notification sound for "System is disarmed" */ - ZB_ZCL_IAS_WD_SQUAWK_MODE_DISARMED = 0x01, -}; - -/** @brief Strobe Field, see ZCL spec 8.4.2.3.2.3 */ -enum zb_zcl_ias_wd_squawk_strobe_e -{ - /** No strobe*/ - ZB_ZCL_IAS_WD_SQUAWK_STROBE_NO_STROBE = 0x00, - /** Use strobe blink in parallel to squawk */ - ZB_ZCL_IAS_WD_SQUAWK_STROBE_USE_STROBE = 0x01, -}; - -/** @brief Squawk level Field, see ZCL spec 8.4.2.3.2.4 */ -enum zb_zcl_ias_wd_squawk_level_e -{ - /** Low level sound */ - ZB_ZCL_IAS_WD_SQUAWK_LEVEL_LOW = 0x00, - /** Medium level sound */ - ZB_ZCL_IAS_WD_SQUAWK_LEVEL_MEDIUM = 0x01, - /** High level sound */ - ZB_ZCL_IAS_WD_SQUAWK_LEVEL_HIGH = 0x02, - /** Very High level sound */ - ZB_ZCL_IAS_WD_SQUAWK_LEVEL_VERY_HIGH = 0x03, -}; - -/*! @brief Structure representsation Squawk command. ZCL spec 8.4.2.3.2 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_wd_squawk_s -{ - /** Status - enum flags Squawk mode, Strobe and Squawk level, see ZCL spec 8.4.2.3.2 */ - zb_uint8_t status; -} ZB_PACKED_STRUCT zb_zcl_ias_wd_squawk_t; - -/*! @brief Get Squawk Mode from payload Squawk command */ -#define ZB_ZCL_IAS_WD_GET_SQUAWK_MODE(status) (((status) >> 4) & 0x0f) - -/*! @brief Get Squawk Strobe from payload Squawk command */ -#define ZB_ZCL_IAS_WD_GET_SQUAWK_STROBE(status) (((status) >> 3) & 0x01) - -/*! @brief Get Squawk Level from payload Squawk command */ -#define ZB_ZCL_IAS_WD_GET_SQUAWK_LEVEL(status) ((status) & 0x03) - -/*! @brief Make Status field Squawk command from Squawk mode, Strobe and Squawk level */ -#define ZB_ZCL_IAS_WD_MAKE_SQUAWK_STATUS(mode, strobe, level) \ - (((level) & 0x03) | (((strobe) & 0x01) << 3) | (((mode) & 0x0f) << 4)) - -/*! @brief Squawk command. ZCL spec 8.4.2.3.2 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param status - Status, see @ref zb_zcl_ias_wd_squawk_s -*/ -#define ZB_ZCL_IAS_WD_SEND_SQUAWK_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - status) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_WD_SQUAWK_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (status)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_WD, cb); \ -} - -/** @brief Macro for getting Squawk command. ZCL spec 8.4.2.3.2 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_wd_squawk_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_WD_GET_SQUAWK_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_wd_squawk_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ias_wd_squawk_t *src_ptr = \ - (zb_zcl_ias_wd_squawk_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->status = src_ptr->status; \ - } \ -} - -/*! @} */ /* IAS WD cluster commands */ - -/*! @} */ /* ZCL IAS WD cluster definitions */ - - -/** @brief Declare run Start Warning command for User Application -*/ -typedef struct zb_zcl_ias_wd_start_warning_value_param_s -{ - zb_uint8_t warning_mode; /*!< Warning Mode */ - zb_uint8_t strobe; /*!< Strobe */ - zb_uint8_t siren_level; /*!< Siren level */ - zb_uint16_t duration; /*!< Duration */ - zb_uint8_t strobe_duty_cycle; /*!< Strobe duty cycle */ - zb_uint8_t strobe_level; /*!< Strobe level */ -} zb_zcl_ias_wd_start_warning_value_param_t; - -/*! Struct for invoke User App & continue after */ -typedef struct zb_zcl_ias_wd_start_warning_user_app_schedule_e -{ - zb_zcl_parsed_hdr_t cmd_info; /**< Parameters for continue command, - see @ref zb_zcl_parsed_hdr_s */ - zb_zcl_ias_wd_start_warning_value_param_t param; /**< User App command parameters, - see @ref zb_zcl_ias_wd_start_warning_value_param_s */ -} zb_zcl_ias_wd_start_warning_user_app_schedule_t; - -#define ZB_ZCL_IAS_WD_START_WARNING_SCHEDULE_USER_APP(buffer, pcmd_info, \ - warningMode, strobe_, siren_level_, duration_, strobe_duty_cycle_, strobe_level_) \ -{ \ - zb_zcl_ias_wd_start_warning_user_app_schedule_t* user_data = \ - ZB_BUF_GET_PARAM((buffer), zb_zcl_ias_wd_start_warning_user_app_schedule_t); \ - ZB_MEMMOVE(&(user_data->cmd_info), (pcmd_info), sizeof(zb_zcl_parsed_hdr_t)); \ - user_data->param.warning_mode = (warningMode); \ - user_data->param.strobe = (strobe_); \ - user_data->param.siren_level = (siren_level_); \ - user_data->param.duration = (duration_); \ - user_data->param.strobe_duty_cycle = (strobe_duty_cycle_); \ - user_data->param.strobe_level = (strobe_level_); \ - ZB_SCHEDULE_CALLBACK(zb_zcl_ias_wd_start_warning_invoke_user_app, (buffer)); \ -} - -/** @brief Declare run Squawk command for User Application -*/ -typedef struct zb_zcl_ias_wd_squawk_value_param_s -{ - zb_uint8_t squawk_mode; /*!< Squawk Mode */ - zb_uint8_t strobe; /*!< Strobe */ - zb_uint8_t squawk_level; /*!< Squawk level */ -} zb_zcl_ias_wd_squawk_value_param_t; - -/*! Struct for invoke User App & continue after */ -typedef struct zb_zcl_ias_wd_squawk_user_app_schedule_e -{ - zb_zcl_parsed_hdr_t cmd_info; /**< Parameters for continue command, - see @ref zb_zcl_parsed_hdr_s */ - zb_zcl_ias_wd_squawk_value_param_t param; /**< User App command parameters, - see @ref zb_zcl_ias_wd_squawk_value_param_s */ -} zb_zcl_ias_wd_squawk_user_app_schedule_t; - -#define ZB_ZCL_IAS_WD_SQUAWK_SCHEDULE_USER_APP(buffer, pcmd_info, \ - squawkMode, strobe_, level) \ -{ \ - zb_zcl_ias_wd_squawk_user_app_schedule_t* user_data = \ - ZB_BUF_GET_PARAM((buffer), zb_zcl_ias_wd_squawk_user_app_schedule_t); \ - ZB_MEMMOVE(&(user_data->cmd_info), (pcmd_info), sizeof(zb_zcl_parsed_hdr_t)); \ - user_data->param.squawk_mode = (squawkMode); \ - user_data->param.strobe = (strobe_); \ - user_data->param.squawk_level = (level); \ - ZB_SCHEDULE_CALLBACK(zb_zcl_ias_wd_squawk_invoke_user_app, ((buffer))); \ -} - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_ias_wd_init_server(void); -void zb_zcl_ias_wd_init_client(void); -#define ZB_ZCL_CLUSTER_ID_IAS_WD_SERVER_ROLE_INIT zb_zcl_ias_wd_init_server -#define ZB_ZCL_CLUSTER_ID_IAS_WD_CLIENT_ROLE_INIT zb_zcl_ias_wd_init_client - -#endif /* ZB_ZCL_IAS_WD_H */ diff --git a/zboss/development/include/zcl/zb_zcl_ias_zone.h b/zboss/development/include/zcl/zb_zcl_ias_zone.h deleted file mode 100644 index c3a0af83f8..0000000000 --- a/zboss/development/include/zcl/zb_zcl_ias_zone.h +++ /dev/null @@ -1,926 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: IAS Zone cluster definitions -*/ - -#ifndef ZB_ZCL_IAS_ZONE_H -#define ZB_ZCL_IAS_ZONE_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_IAS_ZONE - * @{ - * @details - * IAS Zone cluster definitions - */ - -/** @cond internals_doc */ -/** @brief Hook on Write attribute - * send Zone Status Change Notification Command if change ZoneStatus attribute */ -void zb_zcl_ias_zone_write_attr_hook(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); -/*! @} - * @endcond */ /* internals_doc */ - -/* Cluster ZB_ZCL_CLUSTER_ID_IAS_ZONE */ - -/*! @name IAS Zone cluster attributes - @{ -*/ - -/*! @brief IAS Zone cluster attribute identifiers - @see ZCL spec, IAS Zone Cluster 8.2.2.2 -*/ -enum zb_zcl_ias_zone_attr_e -{ - /*! @brief ZoneState attribute, ZCL spec 8.2.2.2.1.1 */ - ZB_ZCL_ATTR_IAS_ZONE_ZONESTATE_ID = 0x0000, - /*! @brief ZoneType attribute, ZCL spec 8.2.2.2.1.2 */ - ZB_ZCL_ATTR_IAS_ZONE_ZONETYPE_ID = 0x0001, - /*! @brief ZoneStatus attribute, ZCL spec 8.2.2.2.1.3 */ - ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID = 0x0002, - /*! @brief IAS_CIE_Address attribute, ZCL spec 8.2.2.2.2.1. */ - ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID = 0x0010, - /*! @brief ZoneID attribute, ZCL spec 8.2.2.1.2.2 */ - ZB_ZCL_ATTR_IAS_ZONE_ZONEID_ID = 0x0011, - /*! @brief NumberOfZoneSensitivityLevelsSupported attribute, ZCL spec 8.2.2.1.2.3 */ - ZB_ZCL_ATTR_IAS_ZONE_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_ID = 0x0012, - /*! @brief CurrentZoneSensitivityLevel attribute, ZCL spec 8.2.2.1.2.4 */ - ZB_ZCL_ATTR_IAS_ZONE_CURRENT_ZONE_SENSITIVITY_LEVEL_ID = 0x0013, - /* custom attribute */ - ZB_ZCL_ATTR_CUSTOM_ZGP_CALIBRATION = 0x8000, - ZB_ZCL_ATTR_CUSTOM_ZGP_CLOUD_ACK = 0x8003, - /* IAS_CIE_Address can be reassigned via Write attribute only when ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET is equal to ZB_FALSE */ - ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET = 0xE000, - ZB_ZCL_ATTR_CUSTOM_CIE_EP = 0xE001, - ZB_ZCL_ATTR_CUSTOM_CIE_SHORT_ADDR = 0xE002, - /* TODO: move this attribute to IAS Zone ZCL implementation */ - /*! @brief Struct with pointers on User App callbacks */ - ZB_ZCL_ATTR_IAS_ZONE_INT_CTX_ID = 0xeffe, -}; - -/** - * @brief IAS Zone ZoneState value - */ -enum zb_zcl_ias_zone_zonestate_e -{ - /** @brief ZoneState not enrolled value */ - ZB_ZCL_IAS_ZONE_ZONESTATE_NOT_ENROLLED = 0, - - /** @brief ZoneState enrolled value */ - ZB_ZCL_IAS_ZONE_ZONESTATE_ENROLLED = 1, -}; - -/** @brief IAS Zone ZoneState attribute default value */ -#define ZB_ZCL_IAS_ZONE_ZONESTATE_DEF_VALUE ZB_ZCL_IAS_ZONE_ZONESTATE_NOT_ENROLLED - -/** @brief Default value for IAS Zone cluster revision global attribute */ -#define ZB_ZCL_IAS_ZONE_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** - * @brief IAS Zone ZoneType value - */ -enum zb_zcl_ias_zone_zonetype_e -{ - /** @brief ZoneType Standard CIE System Alarm value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_STANDARD_CIE = 0x0000, - - /** @brief ZoneType Motion value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_MOTION = 0x000d, - - /** @brief ZoneType Contact switch value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_CONTACT_SWITCH = 0x0015, - - /** @brief ZoneType Fire sensor value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_FIRE_SENSOR = 0x0028, - - /** @brief ZoneType Water sensor value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_WATER_SENSOR = 0x002a, - - /** @brief ZoneType Gas sensor value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_GAS_SENSOR = 0x002b, - - /** @brief ZoneType Personal emergency value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_PERSONAL_EMERGENCY = 0x002c, - - /** @brief ZoneType Vibration / Movement sensor value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_VIBRATION_MOVEMENT = 0x002d, - - /** @brief ZoneType Remote Control value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_REMOTE_CONTROL = 0x010f, - - /** @brief ZoneType Key fob value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_KEY_FOB = 0x0115, - - /** @brief ZoneType Keypad value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_KEYPAD = 0x021d, - - /** @brief ZoneType Standard Warning Device value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_STANDARD_WARNING = 0x0225, - - /** @brief Manufacturer specific ZoneType value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_MANUF_SPEC = 0x8000, - - /** @brief ZoneType Invalid Zone Type value */ - ZB_ZCL_IAS_ZONE_ZONETYPE_INVALID = 0xffff, - -}; - -/*! @brief IAS Zone ZoneStatus attribute flags - @see ZCL spec 8.2.2.2.1.3 -*/ -enum zb_zcl_ias_zone_zonestatus_e -{ - /** Alarm 1 */ - ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM1 = 1 << 0, - /** Alarm 2 */ - ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM2 = 1 << 1, - /** Tamper */ - ZB_ZCL_IAS_ZONE_ZONE_STATUS_TAMPER = 1 << 2, - /** Battery */ - ZB_ZCL_IAS_ZONE_ZONE_STATUS_BATTERY = 1 << 3, - /** Supervision reports */ - ZB_ZCL_IAS_ZONE_ZONE_STATUS_SUPERVISION = 1 << 4, - /** Restore reports */ - ZB_ZCL_IAS_ZONE_ZONE_STATUS_RESTORE = 1 << 5, - /** Trouble */ - ZB_ZCL_IAS_ZONE_ZONE_STATUS_TROUBLE = 1 << 6, - /** AC (mains) */ - ZB_ZCL_IAS_ZONE_ZONE_STATUS_AC_MAINS = 1 << 7, - /** Test */ - ZB_ZCL_IAS_ZONE_ZONE_STATUS_TEST = 1 << 8, - /** Battery Defect */ - ZB_ZCL_IAS_ZONE_ZONE_STATUS_BATTERY_DEFECT = 1 << 9, -}; - -/** @brief IAS Zone ZoneStatus attribute default value */ -#define ZB_ZCL_IAS_ZONE_ZONE_STATUS_DEF_VALUE 0 - -/** @brief Min value for NumberOfZoneSensitivityLevelsSupported attribute */ -#define ZB_ZCL_IAS_ZONE_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_MIN_VALUE ((zb_uint8_t)0x02) - -/** @brief Default value for NumberOfZoneSensitivityLevelsSupported attribute */ -#define ZB_ZCL_IAS_ZONE_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_DEFAULT_VALUE \ - ZB_ZCL_IAS_ZONE_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_MIN_VALUE - -/** @brief Default value for CurrentZoneSensitivityLevel attribute */ -#define ZB_ZCL_IAS_ZONE_CURRENT_ZONE_SENSITIVITY_LEVEL_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief IAS Zone ZoneID attribute default value */ -#define ZB_ZCL_IAS_ZONEID_ID_DEF_VALUE 0xff - -/** @cond internals_doc */ -/** This macros should not be used by the user application directly */ -/*! @internal @name IAS Zone cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CUSTOM_CIE_EP(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CUSTOM_CIE_EP, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_CUSTOM_CIE_SHORT_ADDR(data_ptr) \ -{ \ - ZB_ZCL_ATTR_CUSTOM_CIE_SHORT_ADDR, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_ZONE_ZONESTATE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_ZONE_ZONETYPE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_ZONE_ZONETYPE_ID, \ - ZB_ZCL_ATTR_TYPE_16BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, \ - ZB_ZCL_ATTR_TYPE_16BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID, \ - ZB_ZCL_ATTR_TYPE_IEEE_ADDR, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_ZONE_ZONEID_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_ZONE_ZONEID_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_ZONE_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_ZONE_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_ZONE_CURRENT_ZONE_SENSITIVITY_LEVEL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_ZONE_CURRENT_ZONE_SENSITIVITY_LEVEL_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IAS_ZONE_INT_CTX_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IAS_ZONE_INT_CTX_ID, \ - ZB_ZCL_ATTR_TYPE_NULL, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in IAS Zone cluster */ -#define ZB_ZCL_IAS_ZONE_REPORT_ATTR_COUNT 1 - -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for IAS Zone cluster - server side - @param attr_list - attribute list name - @param zone_state - pointer to variable to store ZoneState attribute - @param zone_type - pointer to variable to store ZoneType attribute - @param zone_status - pointer to variable to store ZoneStatus attribute - @param ias_cie_address - pointer to variable to store IAS-CIE address attribute - @param cie_short_addr - custom attribute to store CIE short address - @param cie_ep - custom attribute to store CIE Endpoint number -*/ -/* FIXME: declare custom attributes internally */ -#define ZB_ZCL_DECLARE_IAS_ZONE_ATTRIB_LIST( \ - attr_list, zone_state, zone_type, zone_status,ias_cie_address, \ - cie_short_addr, cie_ep) \ - zb_uint8_t cie_addr_is_set_##attr_list; \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_IAS_ZONE) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_ZONESTATE_ID, (zone_state)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_ZONETYPE_ID, (zone_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, (zone_status)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID, (ias_cie_address)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CUSTOM_CIE_SHORT_ADDR, (cie_short_addr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CUSTOM_CIE_EP, (cie_ep)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET, &(cie_addr_is_set_##attr_list)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @brief Declare attribute list for IAS Zone cluster - server side (extended attribute set) - @param attr_list - attribute list name - @param zone_state - pointer to variable to store ZoneState attribute - @param zone_type - pointer to variable to store ZoneType attribute - @param zone_status - pointer to variable to store ZoneStatus attribute - @param ias_cie_address - pointer to variable to store IAS-CIE address attribute - @param zone_id - pointer to variable to store Zone ID attribute - @param number_of_zone_sens_levels_supported - pointer to variable to store - NumberOfZoneSensitivityLevelsSupported attribute - @param current_zone_sens_level - pointer to variable to store CurrentZoneSensitivityLevel attribute - @param cie_short_addr - custom attribute to store CIE short address - @param cie_ep - custom attribute to store CIE Endpoint number -*/ -/* FIXME: declare custom attributes internally */ -#define ZB_ZCL_DECLARE_IAS_ZONE_ATTRIB_LIST_EXT( \ - attr_list, zone_state, zone_type, zone_status, number_of_zone_sens_levels_supported, current_zone_sens_level, \ - ias_cie_address, zone_id, cie_short_addr, cie_ep) \ - zb_uint8_t cie_addr_is_set_##attr_list; \ - zb_uint16_t last_change_##attr_list; \ - zb_zcl_ias_zone_int_ctx_t int_ctx_##attr_list; \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_IAS_ZONE) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_ZONESTATE_ID, (zone_state)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_ZONETYPE_ID, (zone_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID, (zone_status)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID, (ias_cie_address)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_ZONEID_ID, (zone_id)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_ID, \ - (number_of_zone_sens_levels_supported)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_CURRENT_ZONE_SENSITIVITY_LEVEL_ID, \ - (current_zone_sens_level)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IAS_ZONE_INT_CTX_ID, &(int_ctx_##attr_list)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CUSTOM_CIE_SHORT_ADDR, (cie_short_addr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CUSTOM_CIE_EP, (cie_ep)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET, &(cie_addr_is_set_##attr_list)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* IAS Zone cluster attributes */ - -/*! @name IAS Zone cluster commands - @{ -*/ - -/*! @brief IAS Zone cluster command identifiers - @see ZCL spec, IAS Zone Cluster, 8.2.2.3 -*/ -enum zb_zcl_ias_zone_cmd_e -{ - ZB_ZCL_CMD_IAS_ZONE_ZONE_ENROLL_RESPONSE_ID = 0x00, /**< "Zone Enroll Response" command, - * ZCL spec 8.2.2.3.1 */ - /**< "Initiate Normal Operation Mode" command, ZCL spec 8.2.2.2.1 */ - ZB_ZCL_CMD_IAS_ZONE_INITIATE_NORMAL_OPERATION_MODE_ID = 0x01, - /**< "Initiate Test Mode" command, ZCL spec 8.2.2.2.2.3 */ - ZB_ZCL_CMD_IAS_ZONE_INITIATE_TEST_MODE_ID = 0x02, -}; - - -/*! @brief IAS Zone cluster response command identifiers - @see ZCL spec, IAS Zone Cluster, 8.2.2.4 -*/ -enum zb_zcl_ias_zone_resp_cmd_e -{ - ZB_ZCL_CMD_IAS_ZONE_ZONE_STATUS_CHANGE_NOT_ID = 0x00, /**< "Zone Status Change Notification" command. - ZCL spec 8.2.2.4.1 */ - ZB_ZCL_CMD_IAS_ZONE_ZONE_ENROLL_REQUEST_ID = 0x01 /**< "Zone Enroll Request" command. - ZCL spec 8.2.2.4.2 */ -}; - -/** @cond internals_doc */ -/* Ias zone cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_IAS_ZONE_SERVER_ROLE_RECEIVED_CMD_LIST \ - ZB_ZCL_CMD_IAS_ZONE_ZONE_ENROLL_RESPONSE_ID, \ - ZB_ZCL_CMD_IAS_ZONE_INITIATE_NORMAL_OPERATION_MODE_ID, \ - ZB_ZCL_CMD_IAS_ZONE_INITIATE_TEST_MODE_ID - -#define ZB_ZCL_CLUSTER_ID_IAS_ZONE_CLIENT_ROLE_RECEIVED_CMD_LIST \ - ZB_ZCL_CMD_IAS_ZONE_ZONE_STATUS_CHANGE_NOT_ID, \ - ZB_ZCL_CMD_IAS_ZONE_ZONE_ENROLL_REQUEST_ID - -#define ZB_ZCL_CLUSTER_ID_IAS_ZONE_SERVER_ROLE_GENERATED_CMD_LIST ZB_ZCL_CLUSTER_ID_IAS_ZONE_CLIENT_ROLE_RECEIVED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_IAS_ZONE_CLIENT_ROLE_GENERATED_CMD_LIST ZB_ZCL_CLUSTER_ID_IAS_ZONE_SERVER_ROLE_RECEIVED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/*! @brief Structure representsation of Initiate Test Mode - Errata to 05-3520-29 Spec, 1.1.23.2.2.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_zone_init_test_mode_ha_s -{ - /** Test mode duration */ - zb_uint8_t test_mode_duration; - /** Current Zone Sensitivity Level */ - zb_uint8_t current_zone_sens_level; -} ZB_PACKED_STRUCT zb_zcl_ias_zone_init_test_mode_t; - -/** @brief Macro for getting "Initiate Test Mode" command - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_zone_init_test_mode_t. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ZONE_GET_INITIATE_TEST_MODE_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_zone_init_test_mode_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ias_zone_init_test_mode_t *src_ptr = \ - (zb_zcl_ias_zone_init_test_mode_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->test_mode_duration = src_ptr->test_mode_duration; \ - (data_ptr)->current_zone_sens_level = src_ptr->current_zone_sens_level; \ - } \ -} - -/*! @brief Initiate Test Mode command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status - @param test_mode_duration - Test Mode duration - @param current_zone_sens_level - CurrentZoneSensitivityLevel -*/ -#define ZB_ZCL_IAS_ZONE_SEND_INITIATE_TEST_MODE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb, \ - test_mode_duration, current_zone_sens_level) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ZONE_INITIATE_TEST_MODE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (test_mode_duration)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (current_zone_sens_level)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ZONE, cb); \ -} - -/*! @brief Initiate Normal Operation Mode command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_IAS_ZONE_SEND_INITIATE_NORMAL_OPERATION_MODE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ZONE_INITIATE_NORMAL_OPERATION_MODE_ID); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ZONE, cb); \ -} - -/******************************* Zone Status Change Notification ******************************/ - -/*! @brief Structure representsation of Zone Status Change Notification - * see ZCL spec 8.2.2.4.1.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_zone_status_change_not_s -{ - /** Zone Status, see @ref zb_zcl_ias_zone_zonestatus_e*/ - zb_uint16_t zone_status; - /** Extended Status */ - zb_uint8_t extended_status; - /** Zone ID*/ - zb_uint8_t zone_id; - /** Delay */ - zb_uint16_t delay; -} ZB_PACKED_STRUCT zb_zcl_ias_zone_status_change_not_t; - - -/*! @brief Zone Status Change Notification command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status - @param zone_status - Zone Status, see @ref zb_zcl_ias_zone_zonestatus_e - @param extended_status - Extended Status - @param zone_id - Zone ID - @param delay - Delay -*/ -#define ZB_ZCL_IAS_ZONE_SEND_STATUS_CHANGE_NOTIFICATION_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb, \ - zone_status, extended_status, zone_id, delay ) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ZONE_ZONE_STATUS_CHANGE_NOT_ID); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (zone_status)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (extended_status)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_id)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (delay)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ZONE, cb); \ -} - -/** @brief Macro for getting Zone Status Change Notification command - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_zone_status_change_not_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ZONE_GET_STATUS_CHANGE_NOTIFICATION_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_zone_status_change_not_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ias_zone_status_change_not_t *src_ptr = \ - (zb_zcl_ias_zone_status_change_not_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&((data_ptr)->zone_status), &(src_ptr->zone_status)); \ - (data_ptr)->extended_status = src_ptr->extended_status; \ - (data_ptr)->zone_id = src_ptr->zone_id; \ - ZB_HTOLE16(&((data_ptr)->delay), &(src_ptr->delay)); \ - } \ -} - -/******************************* Zone Enroll Request command ******************************/ - -/*! @brief Structure representsation of "Zone Enroll Request" command - * see ZCL spec 8.2.2.4.1.2 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_zone_enroll_request_s -{ - /** Zone Type, see @ref zb_zcl_ias_zone_zonetype_e*/ - zb_uint16_t zone_type; - /** Manufacturer code */ - zb_uint16_t manufacturer_code; -} ZB_PACKED_STRUCT zb_zcl_ias_zone_enroll_request_t; - - -/*! @brief Zone "Zone Enroll Request" command, see ZCL spec 8.2.2.4.2 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status - @param zone_type - Zone Type, see @ref zb_zcl_ias_zone_zonetype_e - @param manufacturer_code - Manufacture code -*/ -#define ZB_ZCL_IAS_ZONE_SEND_ZONE_ENROLL_REQUEST_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb, \ - zone_type, manufacturer_code) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ZONE_ZONE_ENROLL_REQUEST_ID); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (zone_type)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (manufacturer_code)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ZONE, cb); \ -} - -/** @brief Macro for getting Zone Status Change Notification command, see ZCL spec 8.2.2.4.1 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_zone_enroll_request_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ZONE_GET_ZONE_ENROLL_REQUEST_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_zone_enroll_request_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ias_zone_enroll_request_t *src_ptr = \ - (zb_zcl_ias_zone_enroll_request_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&((data_ptr)->zone_type), &(src_ptr->zone_type)); \ - ZB_HTOLE16(&((data_ptr)->manufacturer_code), &(src_ptr->manufacturer_code)); \ - } \ -} - -/******************************* Zone Enroll response ******************************/ - -/** @brief Values of the Enroll Response Code - * see ZCL spec 8.2.2.3.1.1 */ -enum zb_zcl_ias_zone_enroll_responce_code_e -{ - /** Success */ - ZB_ZCL_IAS_ZONE_ENROLL_RESPONCE_CODE_SUCCESS = 0x00, - /** Not supported */ - ZB_ZCL_IAS_ZONE_ENROLL_RESPONCE_CODE_NOT_SUPPORTED = 0x01, - /** No enroll permit */ - ZB_ZCL_IAS_ZONE_ENROLL_RESPONCE_CODE_NO_ENROLL = 0x02, - /** Too many zones */ - ZB_ZCL_IAS_ZONE_ENROLL_RESPONCE_CODE_TOO_MANY_ZONES = 0x03, -}; - -/*! @brief Structure representsation of Enroll response command payload - * see ZCL spec 8.2.2.3.1.1 */ -typedef ZB_PACKED_PRE struct zb_zcl_ias_zone_enroll_res_s -{ - /** Enroll response code */ - zb_uint8_t code; - /** Zone ID */ - zb_uint8_t zone_id; -} ZB_PACKED_STRUCT zb_zcl_ias_zone_enroll_res_t; - -/*! @brief Send "Zone Enroll response" command, see ZCL spec 8.2.2.3.1 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback - @param code - Enroll response code, see @ref zb_zcl_ias_zone_enroll_responce_code_e - @param zone_id - Zone ID -*/ -#define ZB_ZCL_IAS_ZONE_SEND_ZONE_ENROLL_RES( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - code, zone_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_IAS_ZONE_ZONE_ENROLL_RESPONSE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (code)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_id)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ZONE, cb); \ -} - -/*! @brief Send "Zone Enroll response with add parameters - sequency" command, see ZCL spec 8.2.2.3.1 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback - @param code - Enroll response code, see @ref zb_zcl_ias_zone_enroll_responce_code_e - @param zone_id - Zone ID - @param seq - known sequency -*/ -#define ZB_ZCL_IAS_ZONE_SEND_ZONE_ENROLL_RES_EXT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - code, zone_id, seq) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, (seq), \ - ZB_ZCL_CMD_IAS_ZONE_ZONE_ENROLL_RESPONSE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (code)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (zone_id)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_IAS_ZONE, cb); \ -} - -/** @brief Macro for getting "Zone Enroll response" command - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ias_zone_enroll_res_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IAS_ZONE_GET_ZONE_ENROLL_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ias_zone_enroll_res_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ias_zone_enroll_res_t *src_ptr = \ - (zb_zcl_ias_zone_enroll_res_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->code = src_ptr->code; \ - (data_ptr)->zone_id = src_ptr->zone_id; \ - } \ -} - -/*! @} */ /* IAS Zone cluster commands */ - -/******************************* Set/Clear Zone Status bits ******************************/ - -/* Set or clear Zone Status bits - */ -void zb_zcl_ias_zone_change_status(zb_uint8_t param); - -/** @brief Declare Set/Clear Zone Status bits -*/ -typedef struct zb_zcl_ias_zone_status_param_s -{ - zb_uint16_t bits; /*!< Bits map, see @ref zb_zcl_ias_zone_zonestatus_e */ - zb_bool_t is_set; /*!< true - set, false - clean */ - zb_uint8_t endpoint; /*!< endpoint */ - -} zb_zcl_ias_zone_status_param_t; - -/*! @brief Set Zone Status bits custom server command - @param buffer - to put packet to - @param ep - endpoint - @param set_bits - flag set of Zone Status, see @ref zb_zcl_ias_zone_zonestatus_e -*/ -#define ZB_ZCL_IAS_ZONE_SET_BITS(buffer, ep, set_bits) \ -{ \ - zb_zcl_ias_zone_status_param_t* cmd_data = \ - ZB_BUF_GET_PARAM((buffer), zb_zcl_ias_zone_status_param_t); \ - cmd_data->endpoint = (ep); \ - cmd_data->bits = (set_bits); \ - cmd_data->is_set = ZB_TRUE; \ - ZB_SCHEDULE_CALLBACK(zb_zcl_ias_zone_change_status, ((buffer))); \ -} - -/*! @brief Clear Zone Status bits custom server command - @param buffer - to put packet to - @param ep - sending endpoint - @param set_bits - flag set of Zone Status, see @ref zb_zcl_ias_zone_zonestatus_e -*/ -#define ZB_ZCL_IAS_ZONE_CLEAR_BITS(buffer, ep, set_bits) \ -{ \ - zb_zcl_ias_zone_status_param_t* cmd_data = \ - ZB_BUF_GET_PARAM((buffer), zb_zcl_ias_zone_status_param_t); \ - cmd_data->endpoint = (ep); \ - cmd_data->bits = (set_bits); \ - cmd_data->is_set = ZB_FALSE; \ - ZB_SCHEDULE_CALLBACK(zb_zcl_ias_zone_change_status, ((buffer))); \ -} - -/** - @brief Structure is used to pass parameters for ZoneStatus - notification command - */ -typedef struct zb_zcl_ias_zone_notification_param_s -{ - zb_uint8_t ep; /*!< endpoint number */ - zb_uint16_t status_val; /*!< new value of zone_zone_status, see @ref zb_zcl_ias_zone_zonestatus_e */ - zb_uint16_t delay; /*!< Delay */ -} -zb_zcl_ias_zone_notification_param_t; - - -/** - @brief Use this function to change IAS Zone status. This function - will set new value of ZoneStatus and will send Zone status change - notification. - @note If another API (ZB_ZCL_SET_ATTRIBUTE()) is used for modifying - ZoneStatus, notification will NOT be send. This is limitation of - the current implementation. - @param ep - local endpoint number - @param new_val - new value for ZoneStatus - @param delay - delay in quarter seconds (actual only for HA ZCL - version, is ignored for pure ZCL implementation) - @param buf_param - reference to a buffer that will be used for - sending notification. If buffer reference is not specified, - notification will NOT be sent - @return Returns ZB_TRUE if notification is scheduled for send, - ZB_FALSE otherwise - @note Notification send result is reported to user App using - callback that is registered with zb_zcl_ias_zone_register_cb() -*/ -zb_bool_t zb_zcl_ias_zone_set_status( - zb_uint8_t ep, - zb_uint16_t new_val, - zb_uint16_t delay, - zb_uint8_t buf_param); - -enum zb_zcl_general_cb_params_e -{ - ZB_ZCL_VALID_CIE_ADDR_SET = 1, - ZB_ZCL_CURR_ZONE_SENSITIVITY_LEVEL_SET = 2, - ZB_ZCL_INIT_TEST_MODE = 3, - ZB_ZCL_INIT_NORMAL_MODE = 4, -}; - -typedef zb_ret_t (ZB_CODE * zb_ias_zone_app_callback_t)(zb_uint8_t param, zb_uint16_t general_val); - -typedef struct zb_zcl_ias_zone_int_ctx_s -{ - zb_callback_t process_result_cb; - zb_ias_zone_app_callback_t general_cb; - zb_uint8_t restore_current_zone_sens_level; - zb_uint8_t new_current_zone_sens_level; -} -zb_zcl_ias_zone_int_ctx_t; - -/** @brief Declare run Enroll Response command for User Application -*/ -typedef struct zb_zcl_ias_zone_enroll_response_value_param_s -{ - zb_uint8_t enroll_response; /*!< Enroll response code */ - zb_uint8_t zone_id; /*!< Zone ID */ -} zb_zcl_ias_zone_enroll_response_value_param_t; - -/*! Struct for invoke User App & continue after */ -typedef struct zb_zcl_ias_zone_enroll_response_user_app_schedule_e -{ - /**< Parameters for continue command, see @ref zb_zcl_parsed_hdr_s */ - zb_zcl_parsed_hdr_t cmd_info; - /**< User App command parameters, see @ref zb_zcl_ias_zone_enroll_response_value_param_s */ - zb_zcl_ias_zone_enroll_response_value_param_t param; -} zb_zcl_ias_zone_enroll_response_user_app_schedule_t; - -#define ZB_ZCL_IAS_ZONE_ENROLL_RESPONSE_SCHEDULE_USER_APP(buffer, pcmd_info, enroll_response_, zone_id_) \ -{ \ - zb_zcl_ias_zone_enroll_response_user_app_schedule_t* user_data = \ - ZB_BUF_GET_PARAM((buffer), zb_zcl_ias_zone_enroll_response_user_app_schedule_t); \ - ZB_MEMMOVE(&(user_data->cmd_info), (pcmd_info), sizeof(zb_zcl_parsed_hdr_t)); \ - user_data->param.enroll_response = (enroll_response_); \ - user_data->param.zone_id = (zone_id_); \ - ZB_SCHEDULE_CALLBACK(zb_zcl_ias_zone_enroll_response_invoke_user_app, ((buffer))); \ -} - -/** @brief Registry callbacks to get status of Zone Status Change Notification command - @param endpoint - local endpoint number - @param process_result_cb - notification sent callback function - @param general_cb - general callback function -*/ -void zb_zcl_ias_zone_register_cb( - zb_uint8_t endpoint, - zb_callback_t process_result_cb, - zb_ias_zone_app_callback_t general_cb); - -/** - @brief checks, if Zone Status change notification should be sent - and schedules command if it is needed - @return ZB_TRUE if command is sent -*/ -zb_bool_t zb_zcl_ias_zone_check_attr_notify( - zb_uint8_t buf_param); - -/** - @brief fills in notification command and sends it -*/ -void zb_zcl_ias_zone_send_status_change_not(zb_uint8_t param); - -/** - @brief checks cie address on zcl initialization -*/ -void zb_zcl_ias_zone_check_cie_addr_on_zcl_initialization(zb_uint8_t ep_id); - -/** - @brief puts cie command to binding whitelist table -*/ -zb_ret_t zb_zcl_ias_zone_put_cie_address_to_binding_whitelist(zb_uint8_t endpoint); - -/** - @brief IAS Zone specific set attribute value postprocessing -*/ -void zb_zcl_ias_set_attr_val_post_process(zb_zcl_parsed_hdr_t *cmd_info, zb_uint16_t attr_id, zb_uint8_t *value); - -/*! @} */ /* ZCL IAS Zone cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_ias_zone_init_server(void); -void zb_zcl_ias_zone_init_client(void); -#define ZB_ZCL_CLUSTER_ID_IAS_ZONE_SERVER_ROLE_INIT zb_zcl_ias_zone_init_server -#define ZB_ZCL_CLUSTER_ID_IAS_ZONE_CLIENT_ROLE_INIT zb_zcl_ias_zone_init_client - -zb_bool_t zb_zcl_process_ias_zone_specific_commands(zb_uint8_t param); - -#endif /* ZB_ZCL_IAS_ZONE_H */ diff --git a/zboss/development/include/zcl/zb_zcl_identify.h b/zboss/development/include/zcl/zb_zcl_identify.h deleted file mode 100644 index 91c044c910..0000000000 --- a/zboss/development/include/zcl/zb_zcl_identify.h +++ /dev/null @@ -1,466 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL "Identify cluster" definitions -*/ - -#ifndef ZB_ZCL_IDENTIFY_H -#define ZB_ZCL_IDENTIFY_H 1 - -#if defined(ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY) || defined(DOXYGEN) - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_IDENTIFY - * @{ - * @details - * Identify cluster implementation supports Identify command and Identify Query request-response - * command pair. All these commands have simple payload. Both Identify and Identify Query - * request are being processed, and Identify Query response is being generated in ZCL internals. - * - * @par Example - * Identify sending: - * @snippet HA_samples/door_lock/sample_zed.c send_identify_req - * - * Identify Query request sending: - * @snippet HA_samples/on_off_switch/sample_zed.c identify_send_identify_query_req - */ - -/** @name Identify cluster attributes - * @{ - */ - -/** @brief Identify cluster attribute identifier - @see ZCL8 spec, subclause 3.5.2.2 -*/ -enum zb_zcl_identify_attr_e -{ - /*! Identify time attribute */ - ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID = 0x0000 -}; - -/** @brief Default value for Identify cluster revision global attribute */ -#define ZB_ZCL_IDENTIFY_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief Default value for Identify attribute */ -#define ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE 0x0000 - -/** @} */ /* Identify cluster attributes */ - -/*! @name Identify cluster command structures and definitions - @{ -*/ - -/** @brief Command identifiers for "Identify" cluster - @see ZCL8 spec, subclauses 3.5.2.3, 3.5.2.4 -*/ -enum zb_zcl_identify_cmd_e -{ - ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID = 0x00, /**< Identify command */ - ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_ID = 0x01, /**< Identify query command */ - ZB_ZCL_CMD_IDENTIFY_TRIGGER_EFFECT_ID = 0x40, /**< "Trigger effect" command identifier. */ - ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_RSP_ID = 0x00 /**< Identify query response */ -}; - -/** @cond internals_doc */ -/* Identify cluster commands lists : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_IDENTIFY_SERVER_ROLE_RECEIVED_CMD_LIST \ - ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID, \ - ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_ID, \ - ZB_ZCL_CMD_IDENTIFY_TRIGGER_EFFECT_ID, - -#define ZB_ZCL_CLUSTER_ID_IDENTIFY_CLIENT_ROLE_RECEIVED_CMD_LIST \ - ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_RSP_ID, - -#define ZB_ZCL_CLUSTER_ID_IDENTIFY_SERVER_ROLE_GENERATED_CMD_LIST ZB_ZCL_CLUSTER_ID_IDENTIFY_CLIENT_ROLE_RECEIVED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_IDENTIFY_CLIENT_ROLE_GENERATED_CMD_LIST ZB_ZCL_CLUSTER_ID_IDENTIFY_SERVER_ROLE_RECEIVED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/** Effect identifier enum - * @see ZCL8 spec 3.5.2.3.3.1 */ -enum zb_zcl_identify_trigger_effect_e -{ - /**< Effect identifier field value: Light is turned on/off once */ - ZB_ZCL_IDENTIFY_EFFECT_ID_BLINK = 0x00, - /**< Effect identifier field value: Light turned on/off over 1 second and - * repeated 15 times */ - ZB_ZCL_IDENTIFY_EFFECT_ID_BREATHE = 0x01, - /**< Effect identifier field value: Colored light turns green for 1 second; - * non-colored light flashes twice */ - ZB_ZCL_IDENTIFY_EFFECT_ID_OKAY = 0x02, - /**< Effect identifier field value: Colored light turns orange for 8 seconds; non-colored - * light switches to maximum brightness for 0.5s and then minimum brightness for 7.5s */ - ZB_ZCL_IDENTIFY_EFFECT_ID_CHANNEL_CHANGE = 0x0b, - /**< Effect identifier field value: Complete the current effect sequence before terminating. - * E.g., if in the middle of a breathe effect (as above), first complete the current 1s - * breathe effect and then terminate the effect*/ - ZB_ZCL_IDENTIFY_EFFECT_ID_FINISH_EFFECT = 0xfe, - /**< Effect identifier field value: Terminate the effect as soon as possible */ - ZB_ZCL_IDENTIFY_EFFECT_ID_STOP = 0xff, -}; - - -/** Effect variant enum - * @see ZCL8 spec 3.5.2.3.3.2 */ -enum zb_zcl_identify_trigger_variant_e -{ - /**< Effect variant field value: Default */ - ZB_ZCL_IDENTIFY_EFFECT_ID_VARIANT_DEFAULT = 0x00, -}; - - -/*! @brief Structured representation of Trigger effect command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_identify_effect_req_s -{ - zb_uint8_t effect_id; /*!< Effect identify, see @ref zb_zcl_identify_trigger_effect_e */ - zb_uint8_t effect_variant; /*!< Effect variant, see @ref zb_zcl_identify_trigger_variant_e */ -} ZB_PACKED_STRUCT zb_zcl_identify_effect_req_t; - - -/*! @brief Send Trigger effect command - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - flag "Default response required" - @param cb - callback for getting command send status - @param effect_id - effect identify, see @ref zb_zcl_identify_trigger_effect_e - @param effect_var - effect variant, see @ref zb_zcl_identify_trigger_variant_e -*/ -#define ZB_ZCL_IDENTIFY_SEND_TRIGGER_VARIANT_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, def_resp, cb, effect_id, effect_var) \ -{ \ -zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ -ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_IDENTIFY_TRIGGER_EFFECT_ID); \ -ZB_ZCL_PACKET_PUT_DATA8(ptr, (effect_id)); \ -ZB_ZCL_PACKET_PUT_DATA8(ptr, (effect_var)); \ -ZB_ZCL_FINISH_PACKET(buffer, ptr) \ -ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, cb); \ -} - - -/** @brief Parses Trigger effect command - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_identify_effect_req_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IDENTIFY_GET_TRIGGER_VARIANT_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_identify_effect_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_identify_effect_req_t *src_ptr = \ - (zb_zcl_identify_effect_req_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_MEMCPY((data_ptr), src_ptr, sizeof(zb_zcl_identify_effect_req_t)); \ - } \ -} - -/** - * @name Inform User App about ZCL Identify cluster command and change attributes. - * Internal structures and define-procedure for inform User App about ZCL Identify - * cluster command and change attributes. - * @internal - * @{ - */ - -/** @brief Declare change Identify attribute for User Application -*/ -typedef struct zb_zcl_identify_effect_value_param_s -{ - zb_uint8_t effect_id; /*!< Effect identify */ - zb_uint8_t effect_variant; /*!< Effect variant */ -} zb_zcl_identify_effect_value_param_t; - - -/*! Struct for invoke User App & continue after */ -typedef struct zb_zcl_identify_effect_user_app_schedule_e -{ - zb_zcl_parsed_hdr_t cmd_info; /**< Parameters for continue command, - see @ref zb_zcl_parsed_hdr_s */ - zb_zcl_identify_effect_value_param_t param; /**< User App command parameters, - see @ref zb_zcl_identify_effect_value_param_s */ -} zb_zcl_identify_effect_user_app_schedule_t; - -#define ZB_ZCL_IDENTIFY_EFFECT_SCHEDULE_USER_APP(buffer, pcmd_info, effectId, effectVar) \ -{ \ - zb_zcl_identify_effect_user_app_schedule_t* data = \ - ZB_BUF_GET_PARAM((buffer), zb_zcl_identify_effect_user_app_schedule_t); \ - ZB_MEMMOVE(&(data->cmd_info), (pcmd_info), sizeof(zb_zcl_parsed_hdr_t)); \ - data->param.effect_id = (effectId); \ - data->param.effect_variant = (effectVar); \ - ZB_SCHEDULE_CALLBACK(zb_zcl_identify_effect_invoke_user_app, (buffer)); \ -} -/*! @} */ /* internal */ - -/*! @brief Send Identify command - @param buffer to put packet to - @param time the device will be identifying - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - flag "Default response required" - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_IDENTIFY_SEND_IDENTIFY_REQ( \ - buffer, time, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, time); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, cb); \ -} - -/*! @brief Send Identify Query command - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - flag "Default response required" - @param cb - callback for getting command send status - - @snippet on_off_switch/sample_zed.c identify_send_identify_query_req -*/ -#define ZB_ZCL_IDENTIFY_SEND_IDENTIFY_QUERY_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, cb); \ -} - -/*! @brief Send Identify Query Response command - @param buffer to put packet to - @param time the device will be identifying - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq_num - sequence number - @param aps_secured - APS security mode -*/ -#define ZB_ZCL_IDENTIFY_SEND_IDENTIFY_QUERY_RES( \ - buffer, time, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq_num, aps_secured) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq_num, ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_RSP_ID); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, time); \ - ZB_ZCL_FINISH_N_SEND_PACKET_NEW(buffer, ptr, \ - addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, NULL, aps_secured, \ - ZB_FALSE, 0); \ -} - -/** - * @brief Start identify process on given endpoint - * - * @param endpoint - endpoint to start identifying on - * @param timeout - time (in seconds) after which identifying will stop - */ -zb_uint8_t zb_zcl_start_identifying(zb_uint8_t endpoint, zb_uint16_t timeout); - -/** - * @brief Stop identify process on given endpoint - * Complimentary function to @ref zb_zcl_start_identifying. - * Used to force identify termination before timeout provided to - * @ref zb_zcl_start_identifying is elapsed - * - * @param endpoint Endpoint - */ -void zb_zcl_stop_identifying(zb_uint8_t endpoint); - -/** - * @brief Indicates that endpoint supports Identify cluster and is identifying - * @param endpoint number to analyze - * @return ZB_TRUE if endpoint is in the "identifying" state, ZB_FALSE otherwise. - */ -zb_uint8_t zb_zcl_is_identifying(zb_uint8_t endpoint); - -/*! @brief Structured representation of Identify command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_identify_req_s -{ - zb_uint16_t timeout; /*!< Time to identify */ -} ZB_PACKED_STRUCT zb_zcl_identify_req_t; - -/*! @brief Structured representation of Identify Query Response command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_identify_query_res_s -{ - zb_uint16_t timeout; /*!< Reported time to identify */ -} ZB_PACKED_STRUCT zb_zcl_identify_query_res_t; - -/*! @brief Identify cluster Identify command payload structured read - * @param data_ptr - pointer to a variable of type @ref zb_zcl_identify_req_t - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). -*/ -#define ZB_ZCL_IDENTIFY_GET_IDENTIFY_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_identify_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_identify_req_t *src_ptr = \ - (zb_zcl_identify_req_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&((data_ptr)->timeout), &(src_ptr->timeout)); \ - } \ -} - -/*! @brief Identify cluster Identify Query Response command payload structured - read - * @param data_ptr - pointer to a variable of type @ref zb_zcl_identify_query_res_t - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_IDENTIFY_GET_IDENTIFY_QUERY_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_identify_query_res_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_identify_query_res_t *src_ptr = \ - (zb_zcl_identify_query_res_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&((data_ptr)->timeout), &(src_ptr->timeout)); \ - } \ -} - -/*! @} */ /* Identify cluster command structures and definitions */ - -/** @cond internals_doc */ -/*! - @name Identify cluster internals - @internal - Internal structures for attribute representation in cluster definitions. - @{ -*/ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#if defined ZB_ZCL_SUPPORT_CLUSTER_SCENES -/*! Scenes fieldset length for Identify cluster */ -#define ZB_ZCL_CLUSTER_ID_IDENTIFY_SCENE_FIELD_SETS_LENGTH 0 -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_SCENES */ - -/*! @} */ /* Identify cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for Identify cluster - @param attr_list - attribute list name - @param identify_time - pointer to variable to store identify time attribute value -*/ -#define ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(attr_list, identify_time) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_IDENTIFY) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID, (identify_time)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** - * @brief Identify cluster attributes - */ -typedef struct zb_zcl_identify_attrs_s -{ - /** @copydoc ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID - * @see ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID - */ - zb_uint16_t identify_time; -} zb_zcl_identify_attrs_t; - - -/** @brief Declare attribute list for Identify cluster cluster - * @param[in] attr_list - attribute list variable name - * @param[in] attrs - variable of zb_zcl_identify_attrs_t type (containing Identify cluster attributes) - */ -#define ZB_ZCL_DECLARE_IDENTIFY_ATTR_LIST(attr_list, attrs) \ - ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(attr_list, &attrs.identify_time) - - - -#if defined ZB_ENABLE_HA - -zb_uint8_t zb_zcl_get_cmd_list_identify(zb_bool_t is_client_generated, zb_uint8_t **cmd_list); - -#endif /* defined ZB_ENABLE_HA */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_identify_init_server(void); -void zb_zcl_identify_init_client(void); -#define ZB_ZCL_CLUSTER_ID_IDENTIFY_SERVER_ROLE_INIT zb_zcl_identify_init_server -#define ZB_ZCL_CLUSTER_ID_IDENTIFY_CLIENT_ROLE_INIT zb_zcl_identify_init_client - -#endif /* defined(ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY) */ - -#endif /* ZB_ZCL_IDENTIFY_H */ diff --git a/zboss/development/include/zcl/zb_zcl_illuminance_measurement.h b/zboss/development/include/zcl/zb_zcl_illuminance_measurement.h deleted file mode 100644 index 25d13e4377..0000000000 --- a/zboss/development/include/zcl/zb_zcl_illuminance_measurement.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Illuminance Measurement cluster definitions -*/ - -#ifndef ZB_ZCL_ILLUMINANCE_MEASUREMENT_H -#define ZB_ZCL_ILLUMINANCE_MEASUREMENT_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_ILLUMINANCE_MEASUREMENT - * @{ - */ - - -/* Cluster ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT */ - -/*! @name Illuminance Measurement cluster attributes - @{ -*/ - -/*! @brief Illuminance Measurement cluster attribute identifiers - @see ZCL spec, Illuminance Measurement Cluster 4.2.2.2.1 -*/ -enum zb_zcl_illuminance_measurement_attr_e -{ - /** @brief MeasuredValue, ZCL spec 4.2.2.2.1.1 */ - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID = 0x0000, - /** @brief MinMeasuredValue, ZCL spec 4.2.2.2.1.2 */ - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_ID = 0x0001, - /** @brief MaxMeasuredValue, ZCL spec 4.2.2.2.1.3 */ - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_ID = 0x0002, - /** The Tolerance attribute SHALL indicate the magnitude of the - * possible error that is associated with MeasuredValue, using the - * same units and resolution. */ - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_TOLERANCE_ID = 0x0003, - /** The LightSensorType attribute specifies the electronic type of - * the light sensor. */ - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_LIGHT_SENSOR_TYPE_ID = 0x0004, -}; - -/** @brief Default value for Illuminance Measurement cluster revision global attribute */ -#define ZB_ZCL_ILLUMINANCE_MEASUREMENT_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief MeasuredValue attribute too-low value */ -#define ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_TOO_LOW 0 - -/** @brief MeasuredValue attribute invalid value */ -#define ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_INVALID 0xFFFF - -/** @brief MeasuredValue attribute default value */ -#define ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_DEFAULT \ - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_TOO_LOW - -/** @brief Default value for LightSensorType attribute */ -#define ZB_ZCL_ILLUMINANCE_MEASUREMENT_LIGHT_SENSOR_TYPE_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief MinMeasuredValue attribute minimum value */ -#define ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_MIN_VALUE 0x0001 - -/** @brief MinMeasuredValue attribute maximum value */ -#define ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_MAX_VALUE 0xFFFD - -/** @brief MinMeasuredValue attribute not-defined value */ -#define ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_UNDEFINED 0xFFFF - -/** @brief MaxMeasuredValue attribute minimum value */ -#define ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_MIN_VALUE 0x0002 - -/** @brief MaxMeasuredValue attribute maximum value */ -#define ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_MAX_VALUE 0xFFFE - -/** @brief MaxMeasuredValue attribute not-defined value */ -#define ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_UNDEFINED 0xFFFF - - -/** @cond internals_doc */ -/*! @internal @name Illuminance Measurement cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_ZCL_ILLUMINANCE_MEASUREMENT_REPORT_ATTR_COUNT 1 - -/*! @} */ /* Illuminance Measurement cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for Illuminance Measurement cluster - server side - @param attr_list - attribute list name - @param value - pointer to variable to store MeasuredValue attribute - @param min_value - pointer to variable to store MinMeasuredValue attribute - @param max_value - pointer to variable to store MAxMeasuredValue attribute -*/ -#define ZB_ZCL_DECLARE_ILLUMINANCE_MEASUREMENT_ATTRIB_LIST(attr_list, \ - value, min_value, max_value) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_ILLUMINANCE_MEASUREMENT) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID, (value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_ID, (min_value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_ID, (max_value)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Illuminance Measurement cluster attributes */ - -/*! @name Illuminance Measurement cluster commands - @{ -*/ - -/*! @} */ /* Illuminance Measurement cluster commands */ - -/*! @} */ /* ZCL Illuminance Measurement cluster definitions */ - -/** @endcond */ - -void zb_zcl_illuminance_measurement_init_server(void); -void zb_zcl_illuminance_measurement_init_client(void); -#define ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT_SERVER_ROLE_INIT zb_zcl_illuminance_measurement_init_server -#define ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT_CLIENT_ROLE_INIT zb_zcl_illuminance_measurement_init_client - -#endif /* ZB_ZCL_ILLUMINANCE_MEASUREMENT_H */ diff --git a/zboss/development/include/zcl/zb_zcl_keep_alive.h b/zboss/development/include/zcl/zb_zcl_keep_alive.h deleted file mode 100644 index c51c1b3455..0000000000 --- a/zboss/development/include/zcl/zb_zcl_keep_alive.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Keep-Alive cluster (ZCL8 spec, 3.18, previously SE spec, Annex A.3) -*/ - -#ifndef ZB_ZCL_KEEP_ALIVE_H -#define ZB_ZCL_KEEP_ALIVE_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_KEEP_ALIVE - * @{ - * @details - * This cluster supports the commands and attributes directed to the network Trust Center in - * order to determine whether communication with the Trust Center is still available. - * - */ - -/* Cluster ZB_ZCL_CLUSTER_ID_KEEP_ALIVE */ - -/*! @name Keep-Alive cluster attributes - @{ -*/ - -/*! @brief Keep-Alive cluster attribute identifiers - @see SE spec, subclause A.3.2 -*/ -enum zb_zcl_keep_alive_attr_e -{ - /*! @brief TC Keep-Alive Base attribute */ - ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_BASE_ID = 0, - /*! @brief TC Keep-Alive Jitter attribute */ - ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_JITTER_ID = 1 -}; - -/** @brief Default value for Keep alive cluster revision global attribute */ -#define ZB_ZCL_KEEP_ALIVE_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/** @brief Default value for TC Keep-Alive Base attribute */ -#define ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_BASE_DEFAULT_VALUE 0x0a -/** @brief Default value for TC Keep-Alive Jitter attribute */ -#define ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_JITTER_DEFAULT_VALUE 0x012c - -/*! @} */ /* Keep-Alive cluster attributes */ - -/*! @name Keep-Alive cluster commands - @{ -*/ -/*! @} */ /* Keep-Alive cluster commands */ - -/*! @cond internals_doc - @internal @name Keep-Alive cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_BASE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_BASE_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_JITTER_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_JITTER_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/** @internal @brief Declare attribute list for Keep-Alive cluster - @param attr_list - attribute list name - @param base - pointer to variable to store TC Keep-Alive Base attribute value - @param jitter - pointer to variable to store TC Keep-Alive Jitter attribute value -*/ -#define ZB_ZCL_DECLARE_KEEP_ALIVE_ATTR_LIST_FULL(attr_list, base, jitter) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_KEEP_ALIVE) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_BASE_ID, (base)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_JITTER_ID, (jitter)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @internal Number of attributes mandatory for reporting in Keep-Alive cluster */ -#define ZB_ZCL_KEEP_ALIVE_REPORT_ATTR_COUNT 0 - -/*! @} - @endcond */ /* Keep-Alive cluster internals */ - - -/** - * @brief Keep-Alive cluster attributes - */ -typedef struct zb_zcl_keep_alive_attrs_s -{ - - /** @copydoc ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_BASE_ID - * @see ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_BASE_ID - */ - zb_uint8_t base; - - /** @copydoc ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_JITTER_ID - * @see ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_JITTER_ID - */ - zb_uint16_t jitter; -} zb_zcl_keep_alive_attrs_t; - - -/** @brief Declare attribute list for Keep-Alive cluster cluster - * @param[in] attr_list - attribute list variable name - * @param[in] attrs - pointer to @ref zb_zcl_keep_alive_attrs_s structure - */ -#define ZB_ZCL_DECLARE_KEEP_ALIVE_ATTR_LIST(attr_list, attrs) \ - ZB_ZCL_DECLARE_KEEP_ALIVE_ATTR_LIST_FULL(attr_list, &attrs.base, &attrs.jitter ) - - -/*! @} */ /* Keep-Alive cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#define ZB_ZCL_CLUSTER_ID_KEEP_ALIVE_SERVER_ROLE_INIT (zb_zcl_cluster_init_t)NULL -#define ZB_ZCL_CLUSTER_ID_KEEP_ALIVE_CLIENT_ROLE_INIT (zb_zcl_cluster_init_t)NULL - -#endif /* ZB_ZCL_KEEP_ALIVE_H */ diff --git a/zboss/development/include/zcl/zb_zcl_level_control.h b/zboss/development/include/zcl/zb_zcl_level_control.h deleted file mode 100644 index 0d9a639eac..0000000000 --- a/zboss/development/include/zcl/zb_zcl_level_control.h +++ /dev/null @@ -1,1398 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Level control cluster definitions -*/ - -#ifndef ZB_ZCL_LEVEL_CONTROL_H -#define ZB_ZCL_LEVEL_CONTROL_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_LEVEL_CONTROL - @{ -*/ - -/* ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL = 0x0008 defined in zb_zcl_common.h */ - -/*! @name Level Control cluster attributes - @{ -*/ - -/** @brief Level Control cluster information attribute identifiers - @see ZCL spec, subclause 3.10.2.2 -*/ - -/** - * @brief Level control attribute list - */ -enum zb_zcl_level_control_attr_e -{ - /** @brief Current Level attribute */ - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID = 0x0000, - /** @brief Remaining Time attribute */ - ZB_ZCL_ATTR_LEVEL_CONTROL_REMAINING_TIME_ID = 0x0001, - /** @brief On Off Transition Time attribute */ - /** The MinLevel attribute indicates the minimum value of CurrentLevel that is capable - * of being assigned. */ - ZB_ZCL_ATTR_LEVEL_CONTROL_MIN_LEVEL_ID = 0x0002, - /** The MaxLevel attribute indicates the maximum value of CurrentLevel that is capable - * of being assigned. */ - ZB_ZCL_ATTR_LEVEL_CONTROL_MAX_LEVEL_ID = 0x0003, - /** The CurrentFrequency attribute represents the frequency that the devices is - * at CurrentLevel. */ - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_FREQUENCY_ID = 0x0004, - /** The MinFrequency attribute indicates the minimum value of CurrentFrequency that - * is capable of being assigned. */ - ZB_ZCL_ATTR_LEVEL_CONTROL_MIN_FREQUENCY_ID = 0x0005, - /** The MaxFrequency attribute indicates the maximum value of CurrentFrequency that - * is capable of being assigned. */ - ZB_ZCL_ATTR_LEVEL_CONTROL_MAX_FREQUENCY_ID = 0x0006, - - ZB_ZCL_ATTR_LEVEL_CONTROL_ON_OFF_TRANSITION_TIME_ID = 0x0010, - /** @brief On Level attribute */ - - /* TODO: A close relationship between this cluster and the On/Off - * cluster is needed. Refer to ZCL spec, subclause 3.10.2.1 */ - ZB_ZCL_ATTR_LEVEL_CONTROL_ON_LEVEL_ID = 0x0011, - - /** The OnTransitionTime attribute represents the time taken to move the current level - * from the minimum level to the maximum level when an On command is received by - * an On/Off cluster on the same endpoint. */ - ZB_ZCL_ATTR_LEVEL_CONTROL_ON_TRANSITION_TIME_ID = 0x0012, - /** The OffTransitionTime attribute represents the time taken to move the current level - * from the maximum level to the minimum level when an Off command is received by - * an On/Off cluster on the same endpoint. */ - ZB_ZCL_ATTR_LEVEL_CONTROL_OFF_TRANSITION_TIME_ID = 0x0013, - /** The DefaultMoveRate attribute determines the movement rate, in units per second, - * when a Move command is received with a Rate parameter of 0xFF. */ - ZB_ZCL_ATTR_LEVEL_CONTROL_DEFAULT_MOVE_RATE_ID = 0x0014, - /** The Options attribute is a bitmap that determines the default behavior of some - * cluster commands. */ - ZB_ZCL_ATTR_LEVEL_CONTROL_OPTIONS_ID = 0x000F, - /** The StartUpCurrentLevel attribute SHALL define the desired startup level for a - * device when it is supplied with power and this level SHALL be reflected in - * the CurrentLevel attribute. */ - ZB_ZCL_ATTR_LEVEL_CONTROL_START_UP_CURRENT_LEVEL_ID = 0x4000, - - /** @internal Special Move Variables attribute */ - ZB_ZCL_ATTR_LEVEL_CONTROL_MOVE_STATUS_ID = 0xefff -}; - -/** - * @brief Level control Options attribute, ZCL spec 3.10.2.2.8 - */ -enum zb_zcl_level_control_options_e -{ - /** @brief ExecuteIfOff bit */ - ZB_ZCL_LEVEL_CONTROL_OPTIONS_EXECUTE_IF_OFF = 0, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_RESERVED = 1, -}; - -/** @brief Default value for Level control cluster revision global attribute */ -#define ZB_ZCL_LEVEL_CONTROL_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/** @brief Maximal value for implemented Level control cluster revision global attribute */ -#define ZB_ZCL_LEVEL_CONTROL_CLUSTER_REVISION_MAX ZB_ZCL_LEVEL_CONTROL_CLUSTER_REVISION_DEFAULT - -/** @brief Current Level attribute minimum value */ -#define ZB_ZCL_LEVEL_CONTROL_LEVEL_MIN_VALUE 0x00 - -/** @brief Current Level attribute maximum value */ -#define ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE 0xff -/** @brief Current Level attribute maximum value */ -#define ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE_SHADE 0xff - -/** @brief Current Level attribute default value */ -#define ZB_ZCL_LEVEL_CONTROL_CURRENT_LEVEL_DEFAULT_VALUE ((zb_uint8_t)0xFF) -/** @brief Default value for RemainingTime attribute */ -#define ZB_ZCL_LEVEL_CONTROL_REMAINING_TIME_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for MinLevel attribute */ -#define ZB_ZCL_LEVEL_CONTROL_MIN_LEVEL_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for MaxLevel attribute */ -#define ZB_ZCL_LEVEL_CONTROL_MAX_LEVEL_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for CurrentFrequency attribute */ -#define ZB_ZCL_LEVEL_CONTROL_CURRENT_FREQUENCY_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for MinFrequency attribute */ -#define ZB_ZCL_LEVEL_CONTROL_MIN_FREQUENCY_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for MaxFrequency attribute */ -#define ZB_ZCL_LEVEL_CONTROL_MAX_FREQUENCY_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for OnOffTransitionTime attribute */ -#define ZB_ZCL_LEVEL_CONTROL_ON_OFF_TRANSITION_TIME_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for OnLevel attribute */ -#define ZB_ZCL_LEVEL_CONTROL_ON_LEVEL_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for OnTransitionTime attribute */ -#define ZB_ZCL_LEVEL_CONTROL_ON_TRANSITION_TIME_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for OffTransitionTime attribute */ -#define ZB_ZCL_LEVEL_CONTROL_OFF_TRANSITION_TIME_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for Options attribute */ -#define ZB_ZCL_LEVEL_CONTROL_OPTIONS_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for OnLevel attribute */ -#define ZB_ZCL_LEVEL_CONTROL_START_UP_CURRENT_LEVEL_USE_PREVIOUS_VALUE ((zb_uint8_t)0xFF) - -/** @brief Transition Time as fast as able value - see ZCL spec 3.10.2.3.1.2 */ -#define ZB_ZCL_LEVEL_CONTROL_TRANSITION_TIME_AS_FAST_AS_ABLE 0xffff - -//#define ZB_ZCL_LEVEL_CONTROL_TRANSITION_TIME_ERROR 20 - -/** @cond internals_doc */ -#define ZB_ZCL_LEVEL_CONTROL_RATE_AS_FAST_AS_ABLE 0xff -/*! @} - * @endcond */ /* internals_doc */ - -/*! - @brief Declare attribute list for Level Control cluster - @param attr_list - attribute list name - @param current_level - pointer to variable to store current_level attribute value - @param remaining_time - pointer to variable to store remaining_time attribute value -*/ -#define ZB_ZCL_DECLARE_LEVEL_CONTROL_ATTRIB_LIST(attr_list, current_level, remaining_time) \ - zb_zcl_level_control_move_status_t move_status_data_ctx## _attr_list; \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_LEVEL_CONTROL) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, (current_level)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_LEVEL_CONTROL_REMAINING_TIME_ID, (remaining_time)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_LEVEL_CONTROL_MOVE_STATUS_ID, \ - (&(move_status_data_ctx## _attr_list))) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - - -/*! - @brief Declare attribute list for Level Control cluster - @param attr_list - attribute list name - @param current_level - pointer to variable to store current_level attribute value - @param remaining_time - pointer to variable to store remaining_time attribute value - @param options - pointer to variable to store options attribute value - @param start_up_current_level - pointer to variable to store start_up_current_level attribute value -*/ -#define ZB_ZCL_DECLARE_LEVEL_CONTROL_ATTRIB_LIST_EXT(attr_list, current_level, remaining_time, \ - start_up_current_level, options) \ - zb_zcl_level_control_move_status_t move_status_data_ctx## _attr_list; \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_LEVEL_CONTROL) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, (current_level)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_LEVEL_CONTROL_REMAINING_TIME_ID, (remaining_time)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_LEVEL_CONTROL_OPTIONS_ID, (options)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_LEVEL_CONTROL_START_UP_CURRENT_LEVEL_ID, (start_up_current_level)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_LEVEL_CONTROL_MOVE_STATUS_ID, \ - (&(move_status_data_ctx## _attr_list))) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Level Control cluster attributes */ - -/** @cond internals_doc */ -/*! @name Level Control cluster internals - Internal structures for Level Control cluster - @internal - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_LEVEL_CONTROL_REMAINING_TIME_ID(data_ptr)\ -{ \ - ZB_ZCL_ATTR_LEVEL_CONTROL_REMAINING_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_LEVEL_CONTROL_OPTIONS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_LEVEL_CONTROL_OPTIONS_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_LEVEL_CONTROL_MOVE_STATUS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_LEVEL_CONTROL_MOVE_STATUS_ID, \ - ZB_ZCL_ATTR_TYPE_NULL, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_LEVEL_CONTROL_START_UP_CURRENT_LEVEL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_LEVEL_CONTROL_START_UP_CURRENT_LEVEL_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} -/** @internal Structure of addr variables for Move commands - */ -typedef struct zb_zcl_level_control_move_addr_s -{ - zb_uint16_t src_addr; - zb_uint8_t src_endpoint; - zb_uint8_t dst_endpoint; - zb_uint8_t cmd_id; - zb_uint8_t seq_number; - zb_bool_t disable_default_response; - zb_uint16_t profile_id; -} zb_zcl_level_control_move_addr_t; - -/** @internal Structure of Move variables for Move alarm - */ -typedef struct zb_zcl_level_control_move_variables_s -{ - /** @brief Level to set */ - zb_uint8_t curr_level; - /** @brief End level */ - zb_uint8_t end_level; - /** @brief On/Off flag: ZB_TRUE - need to setting On/Off attribute, ZB_FALSE - do not need */ - zb_bool_t is_onoff; - /** @brief Address for response sending */ - zb_zcl_level_control_move_addr_t addr; - /** @brief Start time for set Remaining Time attribute */ - zb_uint16_t start_time; -} zb_zcl_level_control_move_variables_t; - -/** @internal Structure of Move Status attribute for Move alarm - */ -typedef struct zb_zcl_level_control_move_status_s -{ - zb_zcl_level_control_move_variables_t move_var; - zb_uint8_t buf_id; -} zb_zcl_level_control_move_status_t; - -/*! Number of attributes mandatory for reporting in Level Control cluster */ -#define ZB_ZCL_LEVEL_CONTROL_REPORT_ATTR_COUNT 1 - -/*! @} */ /* Level Control cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/*! @name Level Control cluster commands - @{ -*/ - -/*! @brief Level control cluster command identifiers - @see ZCL spec, subclause 3.10.2.3 -*/ -enum zb_zcl_level_control_cmd_e -{ - /** Move To Level command */ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL = 0x00, - /** Move command */ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE = 0x01, - /** Step command */ - ZB_ZCL_CMD_LEVEL_CONTROL_STEP = 0x02, - /** Stop command */ - ZB_ZCL_CMD_LEVEL_CONTROL_STOP = 0x03, - /** Move To Level with On/Off command */ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL_WITH_ON_OFF = 0x04, - /** Move with On/Off command */ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_WITH_ON_OFF = 0x05, - /** Step with On/Off command */ - ZB_ZCL_CMD_LEVEL_CONTROL_STEP_WITH_ON_OFF = 0x06, - /** Step with On/Off command */ - ZB_ZCL_CMD_LEVEL_CONTROL_STOP_WITH_ON_OFF = 0x07, - /** Upon receipt of "Move to Closest Frequency" command, the device shall change - * its current frequency to the requested frequency, or to the closest frequency - * that it can generate */ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_CLOSEST_FREQUENCY = 0x08, -}; - -/** @cond internals_doc */ -/* LEVEL control cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_LEVEL_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_LEVEL_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_LEVEL_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_LEVEL_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE, \ - ZB_ZCL_CMD_LEVEL_CONTROL_STEP, \ - ZB_ZCL_CMD_LEVEL_CONTROL_STOP, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL_WITH_ON_OFF, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_WITH_ON_OFF, \ - ZB_ZCL_CMD_LEVEL_CONTROL_STEP_WITH_ON_OFF, \ - ZB_ZCL_CMD_LEVEL_CONTROL_STOP_WITH_ON_OFF - -#define ZB_ZCL_CLUSTER_ID_LEVEL_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_LEVEL_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/*! Default OptionsMask value */ -#define ZB_ZCL_LEVEL_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE ((zb_uint8_t)0x00) - -/*! Default OptionsOverride value */ -#define ZB_ZCL_LEVEL_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE ((zb_uint8_t)0x00) - -/************************** Level Control cluster command definitions ****************************/ - -/* command request structure */ - -/*! @brief Structured representation of Level Control command payload (optional part) - @see ZCL spec, subclause 3.10.2.3.1.1*/ -typedef ZB_PACKED_PRE struct zb_zcl_level_control_req_options_s -{ - /** OptionsMask field */ - zb_uint8_t options_mask; - /** OptionsOverride field */ - zb_uint8_t options_override; -} ZB_PACKED_STRUCT zb_zcl_level_control_req_options_t; - -/** @brief Move to Level payload length macro */ -#define ZB_ZCL_LEVEL_CONTROL_REQ_OPTIONS_PAYLOAD_LEN \ - sizeof(zb_zcl_level_control_req_options_t) - -/** @internal Macro for getting Move to Level command */ -#define ZB_ZCL_LEVEL_CONTROL_GET_CMD_OPTIONS(data_buf, req_options) \ -{ \ - zb_zcl_level_control_req_options_t *req_options_ptr; \ - (req_options_ptr) = zb_buf_len(data_buf) >= \ - ZB_ZCL_LEVEL_CONTROL_REQ_OPTIONS_PAYLOAD_LEN ? \ - (zb_zcl_level_control_req_options_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_options_ptr != NULL) \ - { \ - req_options.options_mask = req_options_ptr->options_mask; \ - req_options.options_override = req_options_ptr->options_override; \ - (void)zb_buf_cut_left(data_buf, sizeof(zb_zcl_level_control_req_options_t)); \ - } \ - else \ - { \ - req_options.options_mask = (zb_uint8_t)0x00; \ - req_options.options_override = (zb_uint8_t)0x00; \ - } \ -} - -/*! @brief Structured representation of MOVE_TO_LEVEL command payload - @see ZCL spec, subclause 3.10.2.3.1.1*/ -typedef ZB_PACKED_PRE struct zb_zcl_level_control_move_to_level_req_s -{ - /** Level field */ - zb_uint8_t level; - /** Transition time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_level_control_move_to_level_req_t; - -/** @brief Move to Level payload length macro */ -#define ZB_ZCL_LEVEL_CONTROL_MOVE_TO_LEVEL_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_level_control_move_to_level_req_t) - -/*! @brief Send Move to Level command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param level - Level value - @param transition_time - Transition Time value - @param options_mask - Options Mask value - @param options_override - Options Override value - @param cmd_id - command id -*/ -void zb_zcl_level_control_send_move_to_level_cmd_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t level, zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override, - zb_uint8_t cmd_id); - -/*! @brief Send Move to Level command (pre-ZCL8) - Use @ref zb_zcl_level_control_send_move_to_level_cmd_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param level - Level value - @param transition_time - Transition Time value - @param cmd_id - command id -*/ -void zb_zcl_level_control_send_move_to_level_cmd(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t level, zb_uint16_t transition_time, - zb_uint8_t cmd_id); - -/** @internal Macro for sending Move to Level command */ -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_CMD_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, level, transition_time, options_mask, \ - options_override, cmd_id) \ -{ \ - zb_zcl_level_control_send_move_to_level_cmd_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, dst_ep, \ - ep, prfl_id, def_resp, cb, level, transition_time, \ - options_mask, options_override, cmd_id); \ -} - -/** Macro for calling @ref zb_zcl_level_control_send_move_to_level_cmd function - */ -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_CMD(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, level, transition_time, cmd_id) \ -{ \ - zb_zcl_level_control_send_move_to_level_cmd(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, dst_ep, \ - ep, prfl_id, def_resp, cb, level, transition_time, cmd_id); \ -} - -/** @internal Macro for getting Move to Level command */ -#define ZB_ZCL_LEVEL_CONTROL_GET_MOVE_TO_LEVEL_CMD(data_buf, move_to_level_req, status) \ -{ \ - zb_zcl_level_control_move_to_level_req_t *move_to_level_req_ptr; \ - (move_to_level_req_ptr) = zb_buf_len(data_buf) >= \ - ZB_ZCL_LEVEL_CONTROL_MOVE_TO_LEVEL_REQ_PAYLOAD_LEN ? \ - (zb_zcl_level_control_move_to_level_req_t*)zb_buf_begin(data_buf) : NULL; \ - if (move_to_level_req_ptr != NULL) \ - { \ - ZB_HTOLE16(&(move_to_level_req).transition_time, &(move_to_level_req_ptr->transition_time)); \ - move_to_level_req.level = move_to_level_req_ptr->level; \ - status = ZB_TRUE; \ - (void)zb_buf_cut_left(data_buf, sizeof(zb_zcl_level_control_move_to_level_req_t)); \ - } \ - else \ - { \ - status = ZB_FALSE; \ - } \ -} - -/*! @brief Send Move to Level command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param level - Level value - @param transition_time - Transition Time value - @param options_mask - Options Mask value - @param options_override - Options Override value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, level, transition_time, options_mask, \ - options_override) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_CMD_ZCL8( \ - buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - level, \ - transition_time, \ - options_mask, \ - options_override, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL) \ -} - -/*! @brief Send Move to Level command (pre-ZCL8) - Use #ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_REQ_ZCL8 for ZCL8 revision call. - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param level - Level value - @param transition_time - Transition Time value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, level, transition_time) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_CMD(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - level, \ - transition_time, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL) \ -} - -/*! - @brief Parses Get Move to Level command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param move_to_level_req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ - -#define ZB_ZCL_LEVEL_CONTROL_GET_MOVE_TO_LEVEL_REQ(data_buf, move_to_level_req, status) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_GET_MOVE_TO_LEVEL_CMD(data_buf, move_to_level_req, status); \ -} - -/*! @brief Send Move to Level with On/Off command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param level - Level value - @param transition_time - Transition Time value - @param options_mask - Options Mask value - @param options_override - Options Override value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_WITH_ON_OFF_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, level, transition_time, options_mask, options_override) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_CMD_ZCL8( \ - buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - level, \ - transition_time, \ - options_mask, \ - options_override, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL_WITH_ON_OFF) \ -} - -/*! @brief Send Move to Level with On/Off command (pre-ZCL8) - Use #ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_WITH_ON_OFF_REQ_ZCL8 for ZCL8 revision call. - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param level - Level value - @param transition_time - Transition Time value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_WITH_ON_OFF_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, level, transition_time) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_CMD(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - level, \ - transition_time, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL_WITH_ON_OFF) \ -} - -/*! - @brief Parses Get Move to Level with On/Off command and fills data request - structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param move_to_level_req - variable to save command request. - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ - -#define ZB_ZCL_LEVEL_CONTROL_GET_MOVE_TO_LEVEL_WITH_ON_OFF_REQ( \ - data_buf, move_to_level_req, status) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_GET_MOVE_TO_LEVEL_CMD(data_buf, move_to_level_req, status); \ -} - - -enum zb_zcl_level_control_move_mode_e -{ - ZB_ZCL_LEVEL_CONTROL_MOVE_MODE_UP = 0x00, - ZB_ZCL_LEVEL_CONTROL_MOVE_MODE_DOWN = 0x01 -}; - -/*! @brief Structured representation of MOVE command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_level_control_move_req_s -{ - /** Move Mode field */ - zb_uint8_t move_mode; - /** Rate field */ - zb_uint8_t rate; -} ZB_PACKED_STRUCT zb_zcl_level_control_move_req_t; - -/** @brief Move payload length macro */ -#define ZB_ZCL_LEVEL_CONTROL_MOVE_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_level_control_move_req_t) - -/*! @brief Send Move command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move Mode value - @param rate - Rate value - @param options_mask - Options Mask value - @param options_override - Options Override value - @param cmd_id - command id -*/ -void zb_zcl_level_control_send_move_cmd_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override, - zb_uint8_t cmd_id); - -/*! @brief Send Move command (pre-ZCL8) - Use @ref zb_zcl_level_control_send_move_cmd_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move Mode value - @param rate - Rate value - @param cmd_id - command id -*/ -void zb_zcl_level_control_send_move_cmd(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t cmd_id); - -/** @internal Macro for sending Move command */ -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_CMD_ZCL8( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate, \ - options_mask, options_override, cmd_id) \ -{ \ - zb_zcl_level_control_send_move_cmd_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, dst_ep, \ - ep, prfl_id, def_resp, cb, move_mode, rate, \ - options_mask, options_override, cmd_id); \ -} - -/** Macro for calling @ref zb_zcl_level_control_send_move_cmd function - */ -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_CMD( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate, cmd_id) \ -{ \ - zb_zcl_level_control_send_move_cmd(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, dst_ep, \ - ep, prfl_id, def_resp, cb, move_mode, rate, cmd_id); \ -} - -/** @internal Macro for getting Move command */ -#define ZB_ZCL_LEVEL_CONTROL_GET_MOVE_CMD(data_buf, move_req, status) \ -{ \ - zb_zcl_level_control_move_req_t *move_req_ptr; \ - (move_req_ptr) = zb_buf_len(data_buf) >= ZB_ZCL_LEVEL_CONTROL_MOVE_REQ_PAYLOAD_LEN ? \ - (zb_zcl_level_control_move_req_t*)zb_buf_begin(data_buf) : NULL; \ - if (move_req_ptr != NULL) \ - { \ - ZB_MEMCPY(&(move_req), move_req_ptr, sizeof(zb_zcl_level_control_move_req_t)); \ - (void)zb_buf_cut_left(data_buf, sizeof(zb_zcl_level_control_move_req_t)); \ - status = ZB_TRUE; \ - } \ - else \ - { \ - status = ZB_FALSE; \ - } \ -} - -/*! @brief Send Move command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move Mode value - @param rate - Rate value - @param options_mask - Options Mask value - @param options_override - Options Override value -*/ -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_REQ_ZCL8(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate, options_mask, \ - options_override) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_CMD_ZCL8(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - move_mode, \ - rate, \ - options_mask, \ - options_override, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE); \ -} - -/*! @brief Send Move command (pre-ZCL8) - Use #ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_REQ_ZCL8 for ZCL8 revision call. - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move Mode value - @param rate - Rate value -*/ -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_REQ(buffer, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_CMD(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - move_mode, \ - rate, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE); \ -} - -/*! - @brief Parses Get Move command and fills data request - structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param move_req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ - -#define ZB_ZCL_LEVEL_CONTROL_GET_MOVE_REQ(data_buf, move_req, status) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_GET_MOVE_CMD(data_buf, move_req, status); \ -} - -/*! @brief Send Move with On/Off command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move Mode value - @param rate - Rate value - @param options_mask - Options Mask value - @param options_override - Options Override value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_WITH_ON_OFF_REQ_ZCL8( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate, \ - options_mask, options_override) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_CMD_ZCL8(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - move_mode, \ - rate, \ - options_mask, \ - options_override, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_WITH_ON_OFF); \ -} - -/*! @brief Send Move with On/Off command (pre-ZCL8) - Use #ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_WITH_ON_OFF_REQ_ZCL8 for ZCL8 revision call. - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param move_mode - Move Mode value - @param rate - Rate value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_WITH_ON_OFF_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, move_mode, rate) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_CMD(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - move_mode, \ - rate, \ - ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_WITH_ON_OFF); \ -} - -/*! - @brief Parses Get Move with On/Off command and fills data request - structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param move_req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ - -#define ZB_ZCL_LEVEL_CONTROL_GET_MOVE_WITH_ON_OFF_REQ(data_buf, move_req, status) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_GET_MOVE_CMD(data_buf, move_req, status); \ -} - -enum zb_zcl_level_control_step_mode_e -{ - ZB_ZCL_LEVEL_CONTROL_STEP_MODE_UP = 0x00, - ZB_ZCL_LEVEL_CONTROL_STEP_MODE_DOWN = 0x01 -}; - -/*! @brief Structured representation of STEP command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_level_control_step_req_s -{ - /** Step Mode field */ - zb_uint8_t step_mode; - /** Step Size field */ - zb_uint8_t step_size; - /** Transition Time field */ - zb_uint16_t transition_time; -} ZB_PACKED_STRUCT zb_zcl_level_control_step_req_t; - -/** @brief Step payload length macro */ -#define ZB_ZCL_LEVEL_CONTROL_STEP_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_level_control_step_req_t) - -/*! @brief Send Step command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - Step Mode value - @param step_size - Step Size value - @param transition_time - Transition Time value - @param options_mask - Options Mask value - @param options_override - Options Override value - @param cmd_id - command id -*/ -void zb_zcl_level_control_send_step_cmd_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override, - zb_uint8_t cmd_id); - -/*! @brief Send Step command (pre-ZCL8) - Use @ref zb_zcl_level_control_send_step_cmd_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - Step Mode value - @param step_size - Step Size value - @param transition_time - Transition Time value - @param cmd_id - command id -*/ -void zb_zcl_level_control_send_step_cmd(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint16_t transition_time, - zb_uint8_t cmd_id); - -/** @brief Macro for sending Step command */ -#define ZB_ZCL_LEVEL_CONTROL_SEND_STEP_CMD_ZCL8(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - options_mask, \ - options_override, \ - cmd_id) \ -{ \ - zb_zcl_level_control_send_step_cmd_zcl8(buffer, \ - ZB_ADDR_U_CAST(addr), \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - options_mask, \ - options_override, \ - cmd_id); \ -} - -/** Macro for calling @ref zb_zcl_level_control_send_step_cmd function - */ -#define ZB_ZCL_LEVEL_CONTROL_SEND_STEP_CMD(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - cmd_id) \ -{ \ - zb_zcl_level_control_send_step_cmd(buffer, \ - ZB_ADDR_U_CAST(addr), \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - cmd_id); \ -} - - -/** @internal Macro for getting Step command */ -#define ZB_ZCL_LEVEL_CONTROL_GET_STEP_CMD(data_buf, step_req, status) \ -{ \ - zb_zcl_level_control_step_req_t *step_req_ptr; \ - (step_req_ptr) = zb_buf_len(data_buf) >= ZB_ZCL_LEVEL_CONTROL_STEP_REQ_PAYLOAD_LEN ? \ - (zb_zcl_level_control_step_req_t*)zb_buf_begin(data_buf) : NULL; \ - if (step_req_ptr != NULL) \ - { \ - step_req.step_mode = step_req_ptr->step_mode; \ - step_req.step_size = step_req_ptr->step_size; \ - ZB_HTOLE16(&(step_req).transition_time, &step_req_ptr->transition_time); \ - (void)zb_buf_cut_left(data_buf, sizeof(zb_zcl_level_control_step_req_t)); \ - status = ZB_TRUE; \ - } \ - else \ - { \ - status = ZB_FALSE; \ - } \ -} - -/*! @brief Send Step command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - Step Mode value - @param step_size - Step Size value - @param transition_time - Transition Time value - @param options_mask - Options Mask value - @param options_override - Options Override value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_STEP_REQ_ZCL8(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - options_mask, \ - options_override) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_STEP_CMD_ZCL8(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - options_mask, \ - options_override, \ - ZB_ZCL_CMD_LEVEL_CONTROL_STEP); \ -} - -/*! @brief Send Step command (pre-ZCL8) - Use #ZB_ZCL_LEVEL_CONTROL_SEND_STEP_REQ_ZCL8 for ZCL8 revision call. - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - Step Mode value - @param step_size - Step Size value - @param transition_time - Transition Time value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_STEP_REQ(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_STEP_CMD(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - ZB_ZCL_CMD_LEVEL_CONTROL_STEP); \ -} - -/*! - @brief Parses Get Step command and fills data request - structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param step_req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ - -#define ZB_ZCL_LEVEL_CONTROL_GET_STEP_REQ(data_buf, step_req, status) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_GET_STEP_CMD(data_buf, step_req, status); \ -} - -/*! @brief Send Step with On/Off command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - Step Mode value - @param step_size - Step Size value - @param transition_time - Transition Time value - @param options_mask - Options Mask value - @param options_override - Options Override value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_STEP_WITH_ON_OFF_REQ_ZCL8(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - options_mask, \ - options_override) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_STEP_CMD_ZCL8(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - options_mask, \ - options_override, \ - ZB_ZCL_CMD_LEVEL_CONTROL_STEP_WITH_ON_OFF); \ -} - -/*! @brief Send Step with On/Off command (pre-ZCL8) - Use #ZB_ZCL_LEVEL_CONTROL_SEND_STEP_WITH_ON_OFF_REQ_ZCL8 for ZCL8 revision call. - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param step_mode - Step Mode value - @param step_size - Step Size value - @param transition_time - Transition Time value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_STEP_WITH_ON_OFF_REQ(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_STEP_CMD(buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - def_resp, \ - cb, \ - step_mode, \ - step_size, \ - transition_time, \ - ZB_ZCL_CMD_LEVEL_CONTROL_STEP_WITH_ON_OFF); \ -} - -/*! - @brief Parses Get Step with On/Off command and fills data request - structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param step_req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ - -#define ZB_ZCL_LEVEL_CONTROL_GET_STEP_WITH_ON_OFF_REQ(data_buf, step_req, status) \ - { \ - ZB_ZCL_LEVEL_CONTROL_GET_STEP_CMD(data_buf, step_req, status); \ -} - -/*! @brief Send Stop command - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param options_mask - Options Mask value - @param options_override - Options Override value -*/ -void zb_zcl_level_control_send_stop_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t options_mask, zb_uint8_t options_override); - -/*! @brief Send Stop command (pre-ZCL8) - Use @ref zb_zcl_level_control_send_stop_req_zcl8 for ZCL8 revision call. - @param buffer - to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -void zb_zcl_level_control_send_stop_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb); - -/** Macro for calling @ref zb_zcl_level_control_send_stop_req_zcl8 function - */ -#define ZB_ZCL_LEVEL_CONTROL_SEND_STOP_REQ_ZCL8( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, options_mask, \ - options_override) \ -{ \ - zb_zcl_level_control_send_stop_req_zcl8(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - options_mask, options_override); \ -} - -/** Macro for calling @ref zb_zcl_level_control_send_stop_req function - */ -#define ZB_ZCL_LEVEL_CONTROL_SEND_STOP_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_zcl_level_control_send_stop_req(buffer, ZB_ADDR_U_CAST(addr), dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb); \ -} - -/*! @brief Send Stop with On/off command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param options_mask - Options Mask value - @param options_override - Options Override value -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_STOP_WITH_ON_OFF_REQ_ZCL8( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, options_mask, \ - options_override) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_STOP_REQ_ZCL8(buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - def_resp, cb, options_mask, options_override) \ -} - -/*! @brief Send Stop with On/off command (pre-ZCL8) - Use #ZB_ZCL_LEVEL_CONTROL_SEND_STOP_WITH_ON_OFF_REQ_ZCL8 for ZCL8 revision call. - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ - -#define ZB_ZCL_LEVEL_CONTROL_SEND_STOP_WITH_ON_OFF_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - ZB_ZCL_LEVEL_CONTROL_SEND_STOP_REQ(buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - def_resp, cb) \ -} -/** @cond internals_doc */ -typedef struct zb_zcl_level_control_set_value_param_s -{ - zb_uint8_t new_value; -} zb_zcl_level_control_set_value_param_t; -/*! @} - * @endcond */ /* internals_doc */ - - /* definition to parse request */ - - /* command response structure */ - - /* definition to parse response */ - - /* definition to send command request */ - -/*! @} */ /* Level Control cluster commands */ - -/*! @} */ /* ZCL Level Control cluster definitions */ - -/** @endcond */ - -void zb_zcl_level_control_init_server(void); -void zb_zcl_level_control_init_client(void); -#define ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL_SERVER_ROLE_INIT zb_zcl_level_control_init_server -#define ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL_CLIENT_ROLE_INIT zb_zcl_level_control_init_client - -#endif /* ZB_ZCL_LEVEL_CONTROL_H */ diff --git a/zboss/development/include/zcl/zb_zcl_messaging.h b/zboss/development/include/zcl/zb_zcl_messaging.h deleted file mode 100644 index 39c92f7ef0..0000000000 --- a/zboss/development/include/zcl/zb_zcl_messaging.h +++ /dev/null @@ -1,639 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Messaging cluster definitions -*/ -#ifndef ZB_ZCL_MESSAGING_H_ -#define ZB_ZCL_MESSAGING_H_ - -#include "zboss_api_core.h" /* ZBOSS core API types */ -#include "zboss_api_aps.h" - -#define ZB_ZCL_MESSAGING_DISPLAY_MSG_MAX_NON_FRAG_SIZE 48 -#define ZB_ZCL_MESSAGING_MSG_CONFIRM_RESP_MSG_MAX_SIZE 21 - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_MESSAGING - * @{ - * @details - * The Messaging cluster provides an interface for passing text messages - * between Zigbee devices. - */ - - -/** @defgroup ZB_ZCL_MESSAGING_COMMANDS Messaging cluster commands - * @{ - */ - - -/** Commands generated by Messaging Server - * @see SE spec, subclause D.5.2.3 - */ -typedef enum zb_zcl_messaging_srv_cmd_e -{ - - /** @see SE spec, subclause D.5.2.3.1 - * @see zb_zcl_messaging_display_message_payload_s - */ - ZB_ZCL_MESSAGING_SRV_CMD_DISPLAY_MESSAGE = 0x00, - - /** @e TheCancelMessage command provides the ability - * to cancel the sending or acceptance of previously sent messages. When this - * message is received the recipient device has the option of clearing any - * display or user interfaces it supports, or has the option of logging the - * message for future reference. - * @see SE spec, subclause D.5.2.3.2 - * @see zb_zcl_messaging_cancel_message_payload_s - */ - ZB_ZCL_MESSAGING_SRV_CMD_CANCEL_MESSAGE = 0x01, - - /** The Display Protected Message command is for use with messages that are - * protected by a password or PIN. - * @see zb_zcl_messaging_display_message_payload_s - */ - ZB_ZCL_MESSAGING_SRV_CMD_DISPLAY_PROTECTED_MESSAGE = 0x02, - - /** @e TheCancelAllMessages command indicates to a client device that it should - * cancel all display messages currently held by it. - * @note @e TheCancelAllMessages command in this revision of this specification - * is provisional and not certifiable. This feature may change before reaching - * certifiable status in a future revision of this specification. - * @see zb_zcl_messaging_cancel_all_message_payload_s - */ - ZB_ZCL_MESSAGING_SRV_CMD_CANCEL_ALL_MESSAGES = 0x03 -} zb_zcl_messaging_srv_cmd_t; - - -/** Commands generated by Messaging Client - * @see SE spec, D.5.3.3 - */ -typedef enum zb_zcl_messaging_cli_cmd_e -{ - - /** On receipt of this command, the device shall send a @e DisplayMessage or - * @e DisplayProtectedMessage command as appropriate. A ZCL Default Response - * with status @e NOT_FOUND shall be returned if no message is available. - * @see SE spec, subclause D.5.3.3.1 - * @note This command has no payload. - */ - ZB_ZCL_MESSAGING_CLI_CMD_GET_LAST_MESSAGE = 0x00, - - /** @e TheMessageConfirmation command provides an indication that a Utility - * Customer has acknowledged and/or accepted the contents of a message - * previously received from the Messaging cluster server. Enhanced Message - * Confirmation commands shall contain an answer of ‘NO’, ‘YES’ and/or a - * message confirmation string. - * If the optional Message Confirmation Response is required, the Message - * Confirmation Control field shall also be present. - * @see SE spec, subclause D.5.3.3.2 - * @see zb_zcl_messaging_message_confirm_payload_s - */ - ZB_ZCL_MESSAGING_CLI_CMD_MESSAGE_CONFIRMATION = 0x01, - - /** This command initiates the return of the first (and maybe only) @e - * CancelAllMessages command held on the associated server, and which has an - * implementation time equal to or later than the value indicated in the payload. - * @note The @e GetMessageCancellation command in this revision of this - * specification is provisional and not certifiable. This feature may change - * before reaching certifiable status in a future revision of this specification. - * @see zb_zcl_messaging_get_message_cancellation_payload_s - */ - ZB_ZCL_MESSAGING_CLI_CMD_GET_MESSAGE_CANCELLATION = 0x02 -} zb_zcl_messaging_cli_cmd_t; - -/* MESSAGING cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_MESSAGING_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_MESSAGING_SRV_CMD_CANCEL_MESSAGE, \ - ZB_ZCL_MESSAGING_SRV_CMD_DISPLAY_MESSAGE - -#define ZB_ZCL_CLUSTER_ID_MESSAGING_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_MESSAGING_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_MESSAGING_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_MESSAGING_CLI_CMD_GET_LAST_MESSAGE, \ - ZB_ZCL_MESSAGING_CLI_CMD_MESSAGE_CONFIRMATION - -#define ZB_ZCL_CLUSTER_ID_MESSAGING_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_MESSAGING_CLIENT_ROLE_GENERATED_CMD_LIST - - -/* Payload description */ - -/** Extended Message Control Field values - * @see SE spec, Table D-118 - * @see zb_zcl_messaging_display_message_payload_t::extended_message_control - */ -typedef enum zb_zcl_messaging_extended_message_control_e -{ - ZB_ZCL_MESSAGING_MESSAGE_HAS_NOT_BEEN_CONFIRMED = 0, /**< Message has not been confirmed */ - ZB_ZCL_MESSAGING_MESSAGE_HAS_BEEN_CONFIRMED = 1, /**< Message has been confirmed */ -} zb_zcl_messaging_extended_message_control_field_t; - -/** Extended Message Control Field Bit Map - * @see SE spec, Table D-118 - */ -enum zb_zcl_messaging_extended_message_control_field_bitmap_e -{ - ZB_ZCL_MESSAGING_MESSAGE_CONFIRMATION_STATUS = 0, /**< @see zb_zcl_messaging_extended_message_control_field_e*/ -}; - - -/** @ref ZB_ZCL_MESSAGING_SRV_CMD_DISPLAY_MESSAGE "DisplayMessage" command payload - * @see SE spec, subclause D.5.2.3.1.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_messaging_display_message_payload_s -{ - /** 32-bit number identifier for the message. */ - zb_uint32_t message_id; /* (M) */ - - /** BitMap field indicating control information related to the message */ - zb_uint8_t message_control; /* (M) */ - - /** The time at which the message becomes valid */ - zb_uint32_t start_time; /* (M) */ - - /** The amount of time in minutes after the Start Time during which - * the message is displayed */ - zb_uint16_t duration_in_minutes; /* (M) */ - - /** Message (variable): Character String - * WARNING: Variable length of message supported, but remember to pass strings in global memory only! - */ - zb_uint8_t message_len; /* (M) */ - zb_uint8_t *message; /* (M) */ - - /** BitMap field indicating additional control - * and status information for a given message. - */ - zb_uint8_t extended_message_control; /* (O) */ -} ZB_PACKED_STRUCT zb_zcl_messaging_display_message_payload_t; - - -/** @e MessageControl field's transmission mechanism values - * @see SE spec, Table D-117 - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_SET_TRANSMISSION_MECHANISM - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_GET_TRANSMISSION_MECHANISM - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_CLR_TRANSMISSION_MECHANISM - */ -typedef enum zb_zcl_messaging_message_control_transmission_mechanism_e -{ - ZB_ZCL_MESSAGING_NORMAL_TRANSMISSION_ONLY = 0, /**< Send message through normal command - * function to client. - */ - ZB_ZCL_MESSAGING_NORMAL_AND_INTERNAL_PAN_TRANSMISSION = 1, /**< Send message through normal command - * function to client and pass message onto the - * Inter-PAN transmission mechanism. - */ - ZB_ZCL_MESSAGING_INTER_PAN_TRANSMISSION_ONLY = 2, /**< Send message through the Inter-PAN - * transmission mechanism. - */ -} zb_zcl_messaging_control_field_transmission_mechanism_t; - -/** @brief Default value for Messaging cluster revision global attribute */ -#define ZB_ZCL_MESSAGING_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/*! - @brief Declare attribute list for Messaging cluster (only cluster revision attribute) - @param attr_list - attribute list name -*/ -#define ZB_ZCL_DECLARE_MESSAGING_ATTR_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_MESSAGING) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** - * Set @e MessageControl's transmission mechanism value - * @param x - variable to store transmission mechanism value - * @param val - @ref zb_zcl_messaging_control_field_transmission_mechanism_t value - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_SET_TRANSMISSION_MECHANISM(x, val) ((x) &= (0xFC | ((val) & 0x03))) - - -/** - * Get @e MessageControl's transmission mechanism value - * @param x - variable that stores transmission mechanism value - * @see zb_zcl_messaging_control_field_transmission_mechanism_t - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_GET_TRANSMISSION_MECHANISM(x) ((x) & 0x03) - - -/** - * Clear @e MessageControl's transmission mechanism value - * @param x - variable that stores transmission mechanism value - * @see zb_zcl_messaging_control_field_transmission_mechanism_t - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_CLR_TRANSMISSION_MECHANISM(x) ((x) &= 0xFC) - - -/** @e MessageControl field's control importance values - * @see SE spec, Table D-117 - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_SET_IMPORTANCE_LEVEL - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_GET_IMPORTANCE_LEVEL - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_CLR_IMPORTANCE_LEVEL - */ -typedef enum zb_zcl_messaging_message_control_importance_level_e -{ - ZB_ZCL_MESSAGING_IMPORTANCE_LEVEL_LOW = 0, /**< Low importance level */ - ZB_ZCL_MESSAGING_IMPORTANCE_LEVEL_MEDIUM = 1, /**< Medium importance level */ - ZB_ZCL_MESSAGING_IMPORTANCE_LEVEL_HIGH = 2, /**< High importance level */ - ZB_ZCL_MESSAGING_IMPORTANCE_LEVEL_CRITICAL = 3, /**< Critical importance level */ -} zb_zcl_messaging_message_control_importance_level_t; - - -/** - * Set @e MessageControl's control importance value - * @param x - variable to store control importance value - * @param val - @ref zb_zcl_messaging_message_control_importance_level_t value - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_SET_IMPORTANCE_LEVEL(x, val) ((x) &= (0xF3 | ((val) & 0x03) << 2) - - -/** - * Get @e MessageControl's control importance value - * @param x - variable that stores control importance value - * @see zb_zcl_messaging_message_control_importance_level_t - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_GET_IMPORTANCE_LEVEL(x) (((x) >> 2) & 0x03) - - -/** - * Clear @e MessageControl's control importance value - * @param x - variable that stores control importance value - * @see zb_zcl_messaging_message_control_importance_level_t - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_CLR_IMPORTANCE_LEVEL(x) ((x) &= 0xF3) - - -/** @e MessageControl field's enhanced confirmation values - * @see SE spec, Table D-117 - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_SET_ENHANCED_CONFIRMATION - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_GET_ENHANCED_CONFIRMATION - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_CLR_ENHANCED_CONFIRMATION - */ -typedef enum zb_zcl_messaging_message_control_enhanced_confirmation_e -{ - ZB_ZCL_MESSAGING_ENHANCED_CONFIRMATION_NOT_REQUIRED = 0, /**< Enhanced Confirmation not required */ - ZB_ZCL_MESSAGING_ENHANCED_CONFIRMATION_REQUIRED = 1, /**< Enhanced Confirmation required */ -} zb_zcl_messaging_message_control_enhanced_confirmation_t; - - -/** - * Set @e MessageControl's enhanced confirmation value - * @param x - variable to store enhanced confirmation value - * @param val - @ref zb_zcl_messaging_message_control_enhanced_confirmation_t value - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_SET_ENHANCED_CONFIRMATION(x, val) ((x) &= (0xDF | ((val) & 0x01) << 5) - -/** - * Get @e MessageControl's enhanced confirmation value - * @param x - variable that stores enhanced confirmation value - * @see zb_zcl_messaging_message_control_enhanced_confirmation_t - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_GET_ENHANCED_CONFIRMATION(x) (((x) >> 5) & 0x01) - -/** - * Clear @e MessageControl's enhanced confirmation value - * @param x - variable that stores enhanced confirmation value - * @see zb_zcl_messaging_message_control_enhanced_confirmation_t - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_CLR_ENHANCED_CONFIRMATION(x) ((x) &= 0xDF ) - - -/** @e MessageControl field's message confirmation values - * @see SE spec, Table D-117 - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_SET_MESSAGE_CONFIRMATION - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_GET_MESSAGE_CONFIRMATION - * @see ZB_ZCL_MESSAGING_MESSAGE_CONTROL_CLR_MESSAGE_CONFIRMATION - */ -typedef enum zb_zcl_messaging_message_control_message_confirmation_e -{ - ZB_ZCL_MESSAGING_MESSAGE_CONFIRMATION_NOT_REQUIRED = 0x00, /**< Message Confirmation not required. */ - ZB_ZCL_MESSAGING_MESSAGE_CONFIRMATION_REQUIRED = 0x01, /**< Message Confirmation required. */ -} zb_zcl_messaging_message_control_message_confirmation_t; - - -/** - * Set @e MessageControl's message confirmation value - * @param x - variable to store message confirmation value - * @param val - @ref zb_zcl_messaging_message_control_message_confirmation_t value - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_SET_MESSAGE_CONFIRMATION(x, val) ((x) &= (0x7F | ((val) & 0x01) << 7) - - -/** - * Get @e MessageControl's message confirmation value - * @param x - variable that stores message confirmation value - * @see zb_zcl_messaging_message_control_message_confirmation_t - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_GET_MESSAGE_CONFIRMATION(x) (((x) >> 7) & 0x01) - -/** - * Clear @e MessageControl's message confirmation value - * @param x - variable that stores message confirmation value - * @see zb_zcl_messaging_message_control_message_confirmation_t - */ -#define ZB_ZCL_MESSAGING_MESSAGE_CONTROL_CLR_MESSAGE_CONFIRMATION(x) ((x) &= 0x7F) - - -/** Check if some size in range of variable size of specified payload. - */ -#define ZB_ZCL_MESSAGING_DISPLAY_MSG_PAYLOAD_SIZE_IS_VALID(size) \ -((size) >= ((zb_int16_t)sizeof(zb_zcl_messaging_display_message_payload_t) - \ -(zb_int16_t)ZB_SIZEOF_FIELD(zb_zcl_messaging_display_message_payload_t, message) -\ -(zb_int16_t)ZB_SIZEOF_FIELD(zb_zcl_messaging_display_message_payload_t, extended_message_control))) - -/* 8/16/2017 NK CR:MINOR Do all compilers support such initializing? More common way to initialize - * is to provide pointer as parameter and operate with it inside the macro. */ -/* 8/21/2017 IA: It is C99 features. I hope, they are supported by all "our" compilers. */ - -/** @ref zb_zcl_messaging_display_message_payload_t initializer */ -#define ZB_ZCL_MESSAGING_DISPLAY_MSG_PAYLOAD_INIT \ - (zb_zcl_messaging_display_message_payload_t)\ - { \ - .extended_message_control = 0x00, \ - } - -/** @ref ZB_ZCL_MESSAGING_SRV_CMD_CANCEL_MESSAGE "CancelMessage" command payload - * @see SE spec, subclause D.5.2.3.2.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_messaging_cancel_message_payload_s -{ - /** 32-bit number identifier for the message. */ - zb_uint32_t message_id; /* (M) */ - - /** This field is deprecated and should be set to 0x00 */ - zb_uint8_t message_control; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_messaging_cancel_message_payload_t; - -/** @ref zb_zcl_messaging_cancel_message_payload_t initializer */ -#define ZB_ZCL_MESSAGING_CANCEL_MSG_PAYLOAD_INIT \ - (zb_zcl_messaging_cancel_message_payload_t) {0} - -/** Check if some size in range of variable size of specified payload. */ -#define ZB_ZCL_MESSAGING_MSG_CANCEL_MESSAGE_SIZE_IS_VALID(size) \ - ((size) >= sizeof(zb_zcl_messaging_cancel_message_payload_t)) - -/** Message Confirmation Control - * @see SE spec, Table D-120 - * @see zb_zcl_messaging_message_confirm_payload_t::message_confirmation_control - */ -typedef enum zb_zcl_messaging_message_confirmation_control_e -{ - ZB_ZCL_MESSAGING_NO_RETURNED = 1 << 0, /**< The answer is ‘NO’ */ - ZB_ZCL_MESSAGING_YES_RETURNED = 1 << 1, /**< The answer is ‘YES’ */ -} zb_zcl_messaging_message_confirmation_control_t; - - -/** @ref ZB_ZCL_MESSAGING_CLI_CMD_MESSAGE_CONFIRMATION "MessageConfirmation" command payload - * @see SE spec, subclause D.5.3.3.2.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_messaging_message_confirm_payload_s -{ - /** 32-bit number identifier for the message being confirmed. */ - zb_uint32_t message_id; /* (M) */ - - /** UTCTime of user confirmation of message */ - zb_uint32_t confirmation_time; /* (M) */ - - /** BitMap field indicating the simple confirmation that is - * contained within the response. - */ - zb_uint8_t message_confirmation_control; /* (O) */ - - /** ZCL Octet String containing the message to be returned. - * The first Octet indicates length (21 is max). - * The string shall be encoded in the UTF-8 format. - * If this optional field is not available, a default value of 0x00 shall be used. - */ - zb_uint8_t message_confirmation_response[ZB_ZCL_MESSAGING_MSG_CONFIRM_RESP_MSG_MAX_SIZE]; /* (O) */ -} ZB_PACKED_STRUCT zb_zcl_messaging_message_confirm_payload_t; - - -/** @ref ZB_ZCL_MESSAGING_SRV_CMD_CANCEL_ALL_MESSAGES "CancelAllMessages" command payload - * @see SE spec, subclause D.5.2.3.4.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_messaging_cancel_all_message_payload_s -{ - /** A UTC Time field to indicate the date/time at which all existing display - * messages should be cleared. - */ - zb_uint32_t implementation_date; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_messaging_cancel_all_message_payload_t; - - -/** @ref ZB_ZCL_MESSAGING_CLI_CMD_GET_MESSAGE_CANCELLATION "GetMessageCancellation" command payload - * @see SE spec, subclause D.5.3.3.3.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_messaging_get_message_cancellation_payload_s -{ - /** UTC Timestamp indicating the earliest implementation time of a @e CancelAllMessages - * command to be returned. - */ - zb_uint32_t earliest_implementation_time; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_messaging_get_message_cancellation_payload_t; - - -/** Check if some size in range of variable size of specified payload. */ -#define ZB_ZCL_MESSAGING_MSG_CONFIRM_PAYLOAD_SIZE_IS_VALID(size) \ - ((size) >= sizeof(zb_zcl_messaging_message_confirm_payload_t) - \ - ZB_SIZEOF_FIELD(zb_zcl_messaging_message_confirm_payload_t, message_confirmation_control) -\ - ZB_SIZEOF_FIELD(zb_zcl_messaging_message_confirm_payload_t, message_confirmation_response)) - -typedef enum zb_zcl_messaging_response_type_e { - ZB_ZCL_MESSAGING_RESPONSE_TYPE_NORMAL, - ZB_ZCL_MESSAGING_RESPONSE_TYPE_PROTECTED, - ZB_ZCL_MESSAGING_RESPONSE_TYPE_NOT_FOUND, -} zb_zcl_messaging_response_type_t; - -/** According to SE spec, server could send following responses to - * @ref ZB_ZCL_MESSAGING_CLI_CMD_GET_LAST_MESSAGE "GetLastMessage" command: - *
    - *
  • - * \b NOT_FOUND as default response - *
  • - *
  • - * \b DisplayMessage command - *
  • - *
  • - * \b DisplayProtectedMessage command - *
  • - *
- */ -typedef struct zb_zcl_messaging_get_last_message_response_s { - zb_zcl_messaging_response_type_t resp_type; - union { - zb_zcl_messaging_display_message_payload_t display_message; - zb_zcl_messaging_display_message_payload_t display_protected_message; - } resp; -} zb_zcl_messaging_get_last_message_response_t; - -/** @ref zb_zcl_messaging_get_last_message_response_t initializer */ -#define ZB_ZCL_MESSAGING_GET_LAST_MESSAGE_RESPONSE_INIT \ - (zb_zcl_messaging_get_last_message_response_t) \ - { \ - .resp_type = ZB_ZCL_MESSAGING_RESPONSE_TYPE_NOT_FOUND, \ - .resp.display_message = ZB_ZCL_MESSAGING_DISPLAY_MSG_PAYLOAD_INIT, \ - } - -/** @ref zb_zcl_messaging_message_confirm_payload_t initializer */ -#define ZB_ZCL_MESSAGING_MSG_CONFIRM_PAYLOAD_INIT \ - (zb_zcl_messaging_message_confirm_payload_t) \ - {\ - .message_confirmation_response = {0x00} \ - } - -/** Function for send @ref ZB_ZCL_MESSAGING_CLI_CMD_GET_LAST_MESSAGE "GetLastMessage" command - * @n On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_MESSAGING_GET_LAST_MSG_CB_ID callback id. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - * @par Usage - * @n Example of sending ZB_ZCL_MESSAGING_CLI_CMD_GET_LAST_MESSAGE "GetLastMessage" command - */ -void zb_zcl_messaging_send_get_last_msg(zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_callback_t cb); - -/** Function for send @ref ZB_ZCL_MESSAGING_SRV_CMD_DISPLAY_MESSAGE "DisplayMessage" command. - * On sender's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with @ref ZB_ZCL_MESSAGING_GET_LAST_MSG_CB_ID - * callback id on reception of @ref ZB_ZCL_MESSAGING_CLI_CMD_GET_LAST_MESSAGE "GetLastMessage" command. - * @n On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_MESSAGING_DISPLAY_MSG_CB_ID callback id. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (@ref zb_zcl_messaging_display_message_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - * @par Usage - * @n Handle @ref ZB_ZCL_MESSAGING_CLI_CMD_GET_LAST_MESSAGE "GetLastMessage" command - */ -void zb_zcl_messaging_send_display_msg(zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_messaging_display_message_payload_t *payload, - zb_callback_t cb); - -/** Function for send @ref ZB_ZCL_MESSAGING_CLI_CMD_MESSAGE_CONFIRMATION "MessageConfirmation" command - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_MESSAGING_MSG_CONFIRMATION_CB_ID callback id. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (@ref zb_zcl_messaging_message_confirm_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - */ -void zb_zcl_messaging_send_msg_confirmation(zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_messaging_message_confirm_payload_t *payload, - zb_callback_t cb); - -/** Function for send @ref ZB_ZCL_MESSAGING_SRV_CMD_CANCEL_MESSAGE "CancelMessage" command - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_MESSAGING_CANCEL_MSG_CB_ID callback id. - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (@ref zb_zcl_messaging_cancel_message_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - */ -void zb_zcl_messaging_send_cancel_msg(zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_messaging_cancel_message_payload_t *payload, - zb_callback_t cb); - -/** Macro for call @ref zb_zcl_messaging_send_get_last_msg function */ -#define ZB_ZCL_MESSAGING_SEND_GET_LAST_MSG(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep) \ - zb_zcl_messaging_send_get_last_msg(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, NULL) \ - -/** Macro for call @ref zb_zcl_messaging_send_display_msg function */ -#define ZB_ZCL_MESSAGING_SEND_DISPLAY_MSG(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload) \ - zb_zcl_messaging_send_display_msg(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, NULL) - -/** Macro for call @ref zb_zcl_messaging_send_msg_confirmation function */ -#define ZB_ZCL_MESSAGING_SEND_MSG_CONFIRMATION(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload) \ - zb_zcl_messaging_send_msg_confirmation(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, NULL) - -/** Macro for call @ref zb_zcl_messaging_send_cancel_msg function */ -#define ZB_ZCL_MESSAGING_SEND_CANCEL_MSG(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload) \ - zb_zcl_messaging_send_cancel_msg(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, NULL) - -/** @cond internals_doc */ - -void zb_zcl_messaging_init_server(void); -void zb_zcl_messaging_init_client(void); -#define ZB_ZCL_CLUSTER_ID_MESSAGING_SERVER_ROLE_INIT zb_zcl_messaging_init_server -#define ZB_ZCL_CLUSTER_ID_MESSAGING_CLIENT_ROLE_INIT zb_zcl_messaging_init_client - -/** @endcond */ /* internal_doc */ - -/** @} */ /* ZB_ZCL_MESSAGING_COMMANDS */ - -/** @} */ /* ZCL Messaging cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#endif /* ZB_ZCL_MESSAGING_H_ */ diff --git a/zboss/development/include/zcl/zb_zcl_meter_identification.h b/zboss/development/include/zcl/zb_zcl_meter_identification.h deleted file mode 100644 index bd57d8ed48..0000000000 --- a/zboss/development/include/zcl/zb_zcl_meter_identification.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Meter Identification cluster definitions -*/ - -#ifndef ZB_ZCL_METER_IDENTIFICATION_H -#define ZB_ZCL_METER_IDENTIFICATION_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond DOXYGEN_ZCL_SECTION */ - -/* Cluster ZB_ZCL_CLUSTER_ID_METER_IDENTIFICATION */ - -/** @addtogroup ZB_ZCL_METER_IDENTIFICATION - * @{ - * @name Meter Identification cluster attributes - * @{ - */ - -/** @brief Meter Identification server attributes identifiers - @see ZCL spec, subclause 3.18.2.1 -*/ -enum zb_zcl_meter_identification_attr_e -{ - /* (M) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_COMPANY_NAME = 0x0000, /**< @e CompanyName is a ZCL Octet String field capable - * of storing up to 16 character string (the first - * Octet indicates length) encoded in the UTF-8 format. - * Company Name defines the meter manufacturer name, - * decided by manufacturer - */ - /* (M) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_METER_TYPE_ID = 0x0001, /**< @e MeterTypeID defines the Meter installation features, - * decided by manufacturer. - */ - /* (M) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_DATA_QUALITY_ID = 0x0004, /**< @e DataQualityID defines the Meter Simple Metering - * information certification type, decided by manufacturer. - */ - /* (O) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_CUSTOMER_NAME = 0x0005, /**< @e CustomerName is a ZCL Character String field capable - * of storing up to 16 character string (the first Octet - * indicates length) encoded in the ASCII format. - */ - /* (O) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_MODEL = 0x0006, /**< @e Model is a ZCL Octet String field capable of storing - * up to 16 character string (the first Octet indicates length) - * encoded in the UTF-8 format. @e Model defines the meter model - * name, decided by manufacturer. - */ - /* (O) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_PART_NUMBER = 0x0007, /**< @e PartNumber is a ZCL Octet String field capable of storing - * up to 16 character string (the first Octet indicates length) - * encoded in the UTF-8 format. @e PartNumber defines the meter part - * number, decided by manufacturer. - */ - /* (O) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_PRODUCT_REVISION = 0x0008, /**< @e ProductRevision is a ZCL Octet String field capable - * of storing up to 6 character string (the first Octet - * indicates length) encoded in the UTF-8 format. - * @e ProductRevision defines the meter revision code, - * decided by manufacturer. - */ - /* (O) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_SOFTWARE_REVISION = 0x000A, /**< @e SoftwareRevision is a ZCL Octet String field capable - * of storing up to 6 character string (the first Octet indicates - * length) encoded in the UTF-8 format. SoftwareRevision defines - * the meter software revision code, decided by manufacturer. - */ - /* (O) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_UTILITY_NAME = 0x000B, /**< @e UtilityName is a ZCL Character String field capable of - * storing up to 16 character string (the first Octet indicates - * length) encoded in the ASCII format. - */ - /* (M) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_POD = 0x000C, /**< @e POD (Point of Delivery) is a ZCL Character String field - * capable of storing up to 16 character string (the first Octet - * indicates length) encoded in the ASCII format. POD is the unique - * identification ID of the premise connection point. It is also a - * contractual information known by the clients and indicated in the bill. - */ - /* (M) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_AVAILABLE_POWER = 0x000D, /**< @e AvailablePower represents the @e InstantaneousDemand that - * can be distributed to the customer (e.g., @e 3.3KW power) - * without any risk of overload. The Available Power SHALL use - * the same formatting conventions as the one used in the simple - * metering cluster formatting attribute set for the - * @e InstantaneousDemand attribute, i.e., - * the @e UnitOfMeasure and @e DemandFormatting. - */ - /* (M) */ - ZB_ZCl_ATTR_METER_IDENTIFICATION_POWER_THRESHOLD = 0x000E /**< @e PowerThreshold represents a threshold of @e InstantaneousDemand - * distributed to the customer (e.g., 4.191KW) that will lead to an - * imminent risk of overload. - */ -}; - - -/** @ref ZB_ZCl_ATTR_METER_IDENTIFICATION_METER_TYPE_ID "MeterTypeID" attribute values - * @see ZCL spec, subclause 3.18.2.1.2 - */ -typedef enum zb_zcl_meter_identification_meter_type_e -{ - ZB_ZCL_METER_TYPE_UTILITY_PRIMARY = 0x0000, /**< Utility Primary Meter */ - ZB_ZCL_METER_TYPE_UTILITY_PRODUCTION = 0x0001, /**< Utility Production Meter */ - ZB_ZCL_METER_TYPE_UTILITY_SECONDARY = 0x0002, /**< Utility Secondary Meter */ - ZB_ZCL_METER_TYPE_PRIVATE_PRIMARY = 0x0100, /**< Private Primary Meter */ - ZB_ZCL_METER_TYPE_PRIVATE_PRODUCTION = 0x0101, /**< Private Production Meter */ - ZB_ZCL_METER_TYPE_PRIVATE_SECONDARY = 0x0102, /**< Private Secondary Meters */ - ZB_ZCL_METER_TYPE_GENERIC = 0x0110 /**< Generic Meter */ -} zb_zcl_meter_identification_meter_type_t; - - -/** @ref ZB_ZCl_ATTR_METER_IDENTIFICATION_DATA_QUALITY_ID "DataQualityID" attribute values - * @see ZCL spec, subclause 3.18.2.1.3 - */ -typedef enum zb_zcl_meter_identification_data_quality_e -{ - ZB_ZCL_DATA_QUALITY_ALL_DATA_CERTIFIED = 0x0000, /**< All Data Certified */ - ZB_ZCL_DATA_QUALITY_ONLY_INSTANTANEOUS_POWER_NOT_CERTIFIED = 0x0001, /**< Only Instantaneous Power not Certified */ - ZB_ZCL_DATA_QUALITY_ONLY_CUMULATED_CONSUMPTION_NOT_CERTIFIED = 0x0002, /**< Only Cumulated Consumption not Certified */ - ZB_ZCL_DATA_QUALITY_NOT_CERTIFIED_DATA = 0x0003 /**< Not Certified data */ -} zb_zcl_meter_identification_data_quality_t; - -/** @brief Default value for Meter Identification cluster revision global attribute */ -#define ZB_ZCL_METER_IDENTIFICATION_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief Default value for Company Name attribute */ -#define ZB_ZCl_ATTR_METER_IDENTIFICATION_COMPANY_NAME_DEFAULT_VALUE { 0 } - -/** @brief Default value for Meter Type ID attribute */ -#define ZB_ZCl_ATTR_METER_IDENTIFICATION_METER_TYPE_ID_DEFAULT_VALUE 0 - -/** @brief Default value for Data Quality ID attribute */ -#define ZB_ZCl_ATTR_METER_IDENTIFICATION_DATA_QUALITY_ID_DEFAULT_VALUE 0 - -/** @brief Default value for POD (Point of Delivery) attribute */ -#define ZB_ZCl_ATTR_METER_IDENTIFICATION_POD_DEFAULT_VALUE { 0 } - -/** @brief Default value for Available Power attribute */ -#define ZB_ZCl_ATTR_METER_IDENTIFICATION_AVAILABLE_POWER_DEFAULT_VALUE ZB_INIT_UINT24(0,0) - -/** @brief Default value for Power Threshold attribute */ -#define ZB_ZCl_ATTR_METER_IDENTIFICATION_POWER_THRESHOLD_DEFAULT_VALUE ZB_INIT_UINT24(0, 0) - -/** @brief Max length of Company Name attribute */ -#define ZB_ZCl_ATTR_METER_IDENTIFICATION_COMPANY_NAME_MAX_LENGTH 16 - -/** @brief Max length of POD (Point of Delivery) attribute */ -#define ZB_ZCl_ATTR_METER_IDENTIFICATION_POD_MAX_LENGTH 16 - -/** @brief Declare attribute list for Thermostat cluster - @param attr_list - attribute list name - @param company_name - pointer to variable to store Company Name attribute value - @param meter_type_id - pointer to variable to store Meter Type ID attribute value - @param data_quality_id - pointer to variable to store Data Quality ID attribute value - @param pod - pointer to variable to store POD (Point of Delivery) attribute value - @param available_power - pointer to variable to store Available Power attribute value - @param power_threshold - pointer to variable to store Power Threshold attribute value -*/ -#define ZB_ZCL_DECLARE_METER_IDENTIFICATION_ATTRIB_LIST(attr_list, \ - company_name, meter_type_id, data_quality_id, \ - pod, available_power, power_threshold) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_METER_IDENTIFICATION) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METER_IDENTIFICATION_COMPANY_NAME, (company_name)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METER_IDENTIFICATION_METER_TYPE_ID, (meter_type_id)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METER_IDENTIFICATION_DATA_QUALITY_ID, (data_quality_id)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METER_IDENTIFICATION_POD, (pod)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METER_IDENTIFICATION_AVAILABLE_POWER, (available_power)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METER_IDENTIFICATION_POWER_THRESHOLD, (power_threshold)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ /* Meter Identification cluster attributes */ - - - -/*! @name Meter Identification cluster commands - @{ -*/ - -/*! @} */ /* Meter Identification cluster commands */ - - -/*! - @cond internals_doc - @internal @name Meter Identification cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METER_IDENTIFICATION_COMPANY_NAME(data_ptr) \ -{ \ - ZB_ZCl_ATTR_METER_IDENTIFICATION_COMPANY_NAME, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METER_IDENTIFICATION_METER_TYPE_ID(data_ptr) \ -{ \ - ZB_ZCl_ATTR_METER_IDENTIFICATION_METER_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METER_IDENTIFICATION_DATA_QUALITY_ID(data_ptr) \ -{ \ - ZB_ZCl_ATTR_METER_IDENTIFICATION_DATA_QUALITY_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METER_IDENTIFICATION_POD(data_ptr) \ -{ \ - ZB_ZCl_ATTR_METER_IDENTIFICATION_POD, \ - ZB_ZCL_ATTR_TYPE_CHAR_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METER_IDENTIFICATION_AVAILABLE_POWER(data_ptr) \ -{ \ - ZB_ZCl_ATTR_METER_IDENTIFICATION_AVAILABLE_POWER, \ - ZB_ZCL_ATTR_TYPE_S24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METER_IDENTIFICATION_POWER_THRESHOLD(data_ptr) \ -{ \ - ZB_ZCl_ATTR_METER_IDENTIFICATION_POWER_THRESHOLD, \ - ZB_ZCL_ATTR_TYPE_S24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in Meter Identification cluster */ -#define ZB_ZCL_METER_IDENTIFICATION_REPORT_ATTR_COUNT 0 - -/*! @} - @endcond */ /* Thermostat cluster internals */ - -/*! @} */ /* ZB_ZCL_METER_IDENTIFICATION */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_meter_identification_init_server(void); -void zb_zcl_meter_identification_init_client(void); - -#define ZB_ZCL_CLUSTER_ID_METER_IDENTIFICATION_SERVER_ROLE_INIT zb_zcl_meter_identification_init_server -#define ZB_ZCL_CLUSTER_ID_METER_IDENTIFICATION_CLIENT_ROLE_INIT zb_zcl_meter_identification_init_client - -#endif /* ZB_ZCL_METER_IDENTIFICATION_H */ diff --git a/zboss/development/include/zcl/zb_zcl_metering.h b/zboss/development/include/zcl/zb_zcl_metering.h deleted file mode 100644 index aa0c9a4e90..0000000000 --- a/zboss/development/include/zcl/zb_zcl_metering.h +++ /dev/null @@ -1,2547 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Metering cluster definitions -*/ - -#ifndef ZB_ZCL_METERING_H -#define ZB_ZCL_METERING_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_METERING - * @{ - * @details - * The Metering Cluster provides a mechanism to retrieve usage information - * from Electric, Gas, Water, and potentially Thermal metering devices. - */ - -/** @defgroup ZB_ZCL_METERING_CLI_ATTRS Metering cluster client attributes and enumerations - * @{ - */ - -/** @brief Metering cluster client attribute sets - * @see SE 1.4 spec, table D.58. - */ -enum zb_zcl_metering_cli_attr_set_e -{ - ZB_ZCL_METERING_SET_CLI_NOTIFICATION_ATTRIBUTE = 0x00, /**< Notification Attribute Set */ -}; - - -/** @brief Metering cluster client attributes */ -enum zb_zcl_metering_cli_attr_e -{ - ZB_ZCL_ATTR_METERING_CLI_FUNCTIONAL_NOTIFICATION_FLAGS = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_CLI_NOTIFICATION_ATTRIBUTE, 0x00), - /**< @e FunctionalNotificationFlags attribute is implemented as a set of bit flags - * which are have a predefined action associated with a bit that is not based on a specific command, - * but may require the Mirrored device to trigger some additional functionality within the system */ - ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS2, /**< @e NotificationFlagsN are 32-bit bitmaps that each represent a series of flags. - * Each flag represents an outstanding command that the Mirror is holding on behalf of the BOMD. - * Each flag represents a different command. - * The format of these attributes is dictated by the scheme that is currently in operation. */ - ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS3, /**< @copydoc ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS2 */ - ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS4, /**< @copydoc ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS2 */ - ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS5, /**< @copydoc ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS2 */ - ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS6, /**< @copydoc ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS2 */ - ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS7, /**< @copydoc ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS2 */ - ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS8, /**< @copydoc ZB_ZCL_ATTR_METERING_CLI_NOTIFICATION_FLAGS2 */ -}; - -/** @} */ /* ZB_ZCL_METERING_CLI_ATTRS */ - -/** @defgroup ZB_ZCL_METERING_SRV_ATTRS Metering cluster server attributes and enumerations - * @{ - */ - -/** @brief Metering cluster server attribute sets - * @see SE 1.4 spec, table D.10. - */ -enum zb_zcl_metering_srv_attr_set_e -{ - ZB_ZCL_METERING_SET_READ_INFO = 0x00, /**< Reading Information Set */ - ZB_ZCL_METERING_SET_TOU_INFORMATION = 0x01, /**< TOU Information Set */ - ZB_ZCL_METERING_SET_METER_STATUS = 0x02, /**< Meter Status */ - ZB_ZCL_METERING_SET_FORMATTING = 0x03, /**< Formatting */ - ZB_ZCL_METERING_SET_HISTORICAL_CONSUMPTION = 0x04, /**< Historical Consumption */ - ZB_ZCL_METERING_SET_LOAD_PROFILE_CONFIGURATION = 0x05, /**< Load Profile Configuration */ - ZB_ZCL_METERING_SET_SUPPLY_LIMIT = 0x06, /**< Supply Limit */ - ZB_ZCL_METERING_SET_BLOCK_INFORMATION_DELIVERED = 0x07, /**< Block Information (Delivered) */ - ZB_ZCL_METERING_SET_ALARMS = 0x08, /**< Alarms */ - ZB_ZCL_METERING_SET_BLOCK_INFORMATION_RECEIVED = 0x09, /**< Block Information (Received) */ - ZB_ZCL_METERING_SET_METER_BILLING = 0x0A, /**< Meter Billing Attribute Set */ - ZB_ZCL_METERING_SET_SUPPLY_CONTROL = 0x0B, /**< Supply Control Attribute Set */ - ZB_ZCL_METERING_SET_ALTERNATIVE_HISTORICAL_CONSUMPTION = 0x0C, /**< Alternative Historical Consumption */ - ZB_ZCL_METERING_SET_FOUR_QUADRANT_ELECTRICITY = 0x0D, /**< Four-Quadrant Electricity */ -}; - - -/** @brief Metering cluster server attributes */ -enum zb_zcl_metering_attr_e -{ - /* Reading Information Attribute Set, table D.11 */ - ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_DELIVERED_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_READ_INFO, 0x00), /**< @e CurrentSummationDelivered attribute - * represents the most recent summed value of Energy, Gas, or Water delivered and consumed - * in the premises. */ - ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_RECEIVED_ID, /**< @e CurrentSummationReceived attribute represents the most recent summed value of Energy, - * Gas, or Water generated and delivered from the premises. */ - ZB_ZCL_ATTR_METERING_CURRENT_MAX_DEMAND_DELIVERED_ID, /**< @e CurrentMaxDemandDelivered attribute represents the maximum demand or rate of delivered - * value of Energy, Gas, or Water being utilized at the premises. */ - ZB_ZCL_ATTR_METERING_CURRENT_MAX_DEMAND_RECEIVED_ID, /**< @e CurrentMaxDemandReceived attribute represents the maximum demand or rate of received - * value of Energy, Gas, or Water being utilized by the utility. */ - ZB_ZCL_ATTR_METERING_DFT_SUMMATION_ID, /**< @e DFTSummation attribute represents a snapshot of attribute CurrentSummationDelivered - * captured at the time indicated by attribute @ref ZB_ZCL_ATTR_METERING_DAILY_FREEZE_TIME_ID "DailyFreezeTime". */ - ZB_ZCL_ATTR_METERING_DAILY_FREEZE_TIME_ID, /**< @e DailyFreezeTime attribute represents the time of day when DFTSummation is captured - * (hour and minutes). */ - ZB_ZCL_ATTR_METERING_POWER_FACTOR_ID, /**< @e PowerFactor attribute contains the Average Power Factor ratio in 1/100th. Valid - * values are 0 to 99. */ - ZB_ZCL_ATTR_METERING_READING_SNAPSHOT_TIME_ID, /**< @e ReadingSnapshotTime attribute represents the last time all of the - * @ref ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_DELIVERED_ID "CurrentSummationDelivered", - * @ref ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_RECEIVED_ID "CurrentSummationReceived", - * @ref ZB_ZCL_ATTR_METERING_CURRENT_MAX_DEMAND_DELIVERED_ID "CurrentMaxDemandDelivered" and - * @ref ZB_ZCL_ATTR_METERING_CURRENT_MAX_DEMAND_RECEIVED_ID "CurrentMaxDemandReceived" - * attributes that are supported by the device were updated. */ - ZB_ZCL_ATTR_METERING_CURRENT_MAX_DEMAND_DELIVERED_TIME_ID, /**< @e CurrentMaxDemandDeliveredTime attribute represents the represents the time when - * @ref ZB_ZCL_ATTR_METERING_CURRENT_MAX_DEMAND_DELIVERED_ID "CurrentMaxDemandDelivered" reading - * was captured. */ - ZB_ZCL_ATTR_METERING_CURRENT_MAX_DEMAND_RECEIVED_TIME_ID, /**< @e CurrentMaxDemandReceivedTime attribute represents the time when - * @ref ZB_ZCL_ATTR_METERING_CURRENT_MAX_DEMAND_RECEIVED_ID "CurrentMaxDemandReceived reading - * was captured. */ - ZB_ZCL_ATTR_METERING_DEFAULT_UPDATE_PERIOD_ID, /**< @e DefaultUpdatePeriod attribute represents the interval (seconds) at which the - * @ref ZB_ZCL_ATTR_METERING_INSTANTANEOUS_DEMAND_ID "InstantaneousDemand" attribute is - * updated when not in fast poll mode. */ - ZB_ZCL_ATTR_METERING_FAST_POLL_UPDATE_PERIOD_ID, /**< @e FastPollUpdatePeriod attribute represents the interval (seconds) at which the - * @ref ZB_ZCL_ATTR_METERING_INSTANTANEOUS_DEMAND_ID "InstantaneousDemand" attribute is - * updated when in fast poll mode. */ - ZB_ZCL_ATTR_METERING_CURRENT_BLOCK_PERIOD_CONSUMPTION_DELIVERED_ID, /**< @e CurrentBlockPeriodConsumptionDelivered attribute represents the most recent summed - * value of Energy, Gas or Water delivered and consumed in the premises during the Block - * Tariff Period. */ - ZB_ZCL_ATTR_METERING_DAILY_CONSUMPTION_TARGET_ID, /**< @e DailyConsumptionTarget attribute is a daily target consumption amount that can be - * displayed to the consumer on a HAN device, with the intent that it can be used to compare - * to actual daily consumption. */ - ZB_ZCL_ATTR_METERING_CURRENT_BLOCK_ID, /**< @e CurrentBlock attribute is an 8-bit Enumeration which indicates the currently active - * block, when Block Tariffs are enabled. @see zb_zcl_metering_block_e */ - ZB_ZCL_ATTR_METERING_PROFILE_INTERVAL_PERIOD_ID, /**< @e ProfileIntervalPeriod attribute is currently included in the @e GetProfileResponse - * command payload, but does not appear in an attribute set. It represents the interval or - * time frame used to capture metered Energy, Gas, and Water consumption for profiling purposes. */ - /* 0x0010 attribute is deprecated */ - ZB_ZCL_ATTR_METERING_PRESET_READING_TIME_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_READ_INFO, 0x11), /**< @e PresetReadingTime attribute */ - ZB_ZCL_ATTR_METERING_SUMMATION_DELIVERED_PER_REPORT_ID, /**< @e SummationDeliveredPerReport attribute represents the summation increment per report - * from the water or gas meter. */ - ZB_ZCL_ATTR_METERING_FLOW_RESTRICTION_ID, /**< @e FlowRestriction attribute represents the volume per minute limit set in the flow - * restrictor. This applies to water but not for gas. A setting of 0xFF indicates this - * feature is disabled. */ - ZB_ZCL_ATTR_METERING_SUPPLY_STATUS_ID, /**< @e SupplyStatus attribute represents the state of the supply at the customer's premises. - * @see zb_zcl_metering_supply_status_e */ - ZB_ZCL_ATTR_METERING_CURRENT_INLET_ENERGY_CARRIER_SUMMATION_ID, /**< @e CurrentInletEnergyCarrierSummation attribute is the current integrated volume of a - * given energy carrier measured on the inlet. */ - ZB_ZCL_ATTR_METERING_CURRENT_OUTLET_ENERGY_CARRIER_SUMMATION_ID, /**< @e CurrentOutletEnergyCarrierSummation attribute is the current integrated volume of a - * given energy carrier measured on the outlet. */ - ZB_ZCL_ATTR_METERING_INLET_TEMPERATURE_ID, /**< @e InletTemperature attribute is the temperature measured on the energy carrier inlet. */ - ZB_ZCL_ATTR_METERING_OUTLET_TEMPERATURE_ID, /**< @e OutletTemperature attribute is the temperature measured on the energy carrier outlet. */ - ZB_ZCL_ATTR_METERING_CONTROL_TEMPERATURE_ID, /**< @e ControlTemperature attribute is a reference temperature measured on the meter used to - * validate the Inlet/Outlet temperatures. */ - ZB_ZCL_ATTR_METERING_CURRENT_INLET_ENERGY_CARRIER_DEMAND_ID, /**< @e CurrentInletEnergyCarrierDemand attribute is the current absolute demand on the energy - * carrier inlet. */ - ZB_ZCL_ATTR_METERING_CURRENT_OUTLET_ENERGY_CARRIER_DEMAND_ID, /**< @e CurrentOutletEnergyCarrierDemand attribute is the current absolute demand on the energy - * carrier outlet. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_BLOCK_PERIOD_CONSUMPTION_DELIVERED_ID, /**< @e PreviousBlockPeriodConsumptionDelivered attribute represents the total value of Energy, - * Gas or Water delivered and consumed in the premises at the end of the previous Block Tariff - * period. */ - ZB_ZCL_ATTR_METERING_CURRENT_BLOCK_PERIOD_CONSUMPTION_RECEIVED_ID, /**< @e CurrentBlockPeriodConsumptionReceived attribute represents the most recent summed - * value of Energy, Gas or Water received by the energy supplier from the premises during - * the Block Tariff Period. */ - ZB_ZCL_ATTR_METERING_CURRENT_BLOCK_RECEIVED_ID, /**< @e CurrentBlockReceived attribute is an 8-bit Enumeration which indicates the currently - * active block, when Block Tariffs are enabled. */ - ZB_ZCL_ATTR_METERING_DFT_SUMMATION_RECEIVED_ID, /**< @e DFTSummationReceived attribute represents a snapshot of attribute - * @ref ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_RECEIVED_ID "CurrentSummationReceived" - * captured at the time indicated by the - * @ref ZB_ZCL_ATTR_METERING_DAILY_FREEZE_TIME_ID "DailyFreezeTime" attribute. */ - ZB_ZCL_ATTR_METERING_ACTIVE_REGISTER_TIER_DELIVERED_ID, /**< @e ActiveRegisterTierDelivered attribute indicates the current register tier that the - * energy consumed is being accumulated against. @see SE 1.4 spec, table D.98. */ - ZB_ZCL_ATTR_METERING_ACTIVE_REGISTER_TIER_RECEIVED_ID, /**< @e ActiveRegisterTierReceived attribute indicates the current register tier that the - * energy generated is being accumulated against. @see SE 1.4 spec, table D.101. */ - ZB_ZCL_ATTR_METERING_LAST_BLOCK_SWITCH_TIME_ID, /**< @e LastBlockSwitchTime attribute allows other devices to determine the time at which - * a meter switches from one block to another. */ - ZB_ZCL_ATTR_METERING_NUMBER_OF_TIERS_IN_USE, /**< @e NumberofTiersInUse */ - - /* 0x0024 to 0x00FF reserved */ - - - /* TOU Information Attribute Set, table D.14 */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_TOU_INFORMATION, 0x00), /**< @e CurrentTierNSummationDelivered - * attributes represent the most recent summed value of Energy, Gas, or Water delivered to the premises at a - * specific price tier as defined by a TOU schedule or a real time pricing period. */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID, /**< @e CurrentTierNSummationReceived attributes represent the most recent summed value of Energy, Gas, or Water - * provided by the premises (i.e. received by the utility from the customer) at a specific price tier as defined - * by a TOU schedule or a real time pricing period. */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER2_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER2_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER3_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER3_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER4_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER4_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER5_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER5_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER6_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER6_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER7_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER7_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER8_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER8_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER9_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER9_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER10_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER10_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER11_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER11_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER12_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER12_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER13_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER13_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER14_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER14_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER15_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER15_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER16_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER16_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER17_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER17_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER18_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER18_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER19_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER19_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER20_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER20_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER21_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER21_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER22_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER22_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER23_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER23_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER24_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER24_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER25_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER25_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER26_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER26_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER27_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER27_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER28_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER28_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER29_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER29_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER30_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER30_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER31_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER31_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER32_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER32_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER33_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER33_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER34_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER34_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER35_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER35_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER36_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER36_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER37_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER37_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER38_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER38_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER39_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER39_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER40_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER40_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER41_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER41_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER42_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER42_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER43_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER43_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER44_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER44_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER45_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER45_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER46_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER46_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER47_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER47_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER48_SUMMATION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_CURRENT_TIER48_SUMMATION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_CURRENT_TIER1_SUMMATION_RECEIVED_ID */ - /* 0x0160 to 0x01FB reserved */ - ZB_ZCL_ATTR_METERING_CPP1_SUMMATION_DELIVERED_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_TOU_INFORMATION, 0xFC), /**< @e CPP1SummationDelivered attribute - * represents the most recent summed value of Energy, Gas, or Water delivered to the premises (i.e. - * delivered to the customer from the utility) while Critical Peak Price CPP1 was being applied. */ - /* 0x01FD reserved */ - ZB_ZCL_ATTR_METERING_CPP2_SUMMATION_DELIVERED_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_TOU_INFORMATION, 0xFE), /**< @e CPP2SummationDelivered attribute - * represents the most recent summed value of Energy, Gas, or Water delivered to the premises (i.e. - * delivered to the customer from the utility) while Critical Peak Price CPP2 was being applied. */ - /* 0x01FF reserved */ - - - /* Meter Status Attribute Set, table D.15. */ - ZB_ZCL_ATTR_METERING_STATUS_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_METER_STATUS, 0x00), /**< @e Status attribute provides indicators reflecting the current - * error conditions found by the metering device. Status depends on the device type. - * @see zb_zcl_metering_status_electricity_e - * @see zb_zcl_metering_status_gas_e - * @see zb_zcl_metering_status_water_e - * @see zb_zcl_metering_status_heat_cooling_e */ - ZB_ZCL_ATTR_METERING_REMAINING_BATTERY_LIFE_ID, /**< @e RemainingBatteryLife attribute represents the estimated remaining life of the battery in % of capacity. - * A setting of 0xFF indicates this feature is disabled. */ - ZB_ZCL_ATTR_METERING_HOURS_IN_OPERATION_ID, /**< @e HoursInOperation attribute is a counter that increments once every hour during operation. */ - ZB_ZCL_ATTR_METERING_HOURS_IN_FAULT_ID, /**< @e HoursInFault attribute is a counter that increments once every hour when the device is in operation - * with a fault detected. */ - ZB_ZCL_ATTR_METERING_EXTENDED_STATUS_ID, /**< @e ExtendedStatus attribute reflects the state of items in a meter that the standard Status attribute - * cannot show. The Extended Status BitMap is split into two groups of flags: general flags and metering - * type specific flags. - * @see zb_zcl_metering_extstatus_general_e - * @see zb_zcl_metering_extstatus_electricity_e - * @see zb_zcl_metering_extstatus_gas_e */ - ZB_ZCL_ATTR_METERING_REMAINING_BATTERY_LIFE_DAYS_ID, /**< @e RemainingBatteryLifeInDays attribute represents the estimated remaining life of the battery in days - * of capacity. The range is 0 - 0xFFFE, where 0xFFFF represents 'Invalid', 'Unused' and 'Disabled'. */ - ZB_ZCL_ATTR_METERING_CURRENT_METER_ID_ID, /**< @e CurrentMeterID attribute is the current id for the Meter. This could be the current firmware - * version supported on the meter. */ - ZB_ZCL_ATTR_METERING_AMBIENT_CONSUMPTION_INDICATOR_ID, /**< @e AmbientConsumptionIndicator attribute is an 8-bit enumeration which provides a simple indication - * (Low/Medium/High) of the amount of a commodity being consumed within the premises. - * @see @ref zb_zcl_metering_low_medium_high_status_e. */ - ZB_ZCL_ATTR_METERING_SERVICE_DISCONNECT_REASON_ID, /**< The Service Disconnect Reason attribute is an 8-bit enumeration which indicates why the supply - * to the premises has been disconnected */ - ZB_ZCL_ATTR_METERING_LINKY_MODE_OF_OPERATION_ID, /**< The @e LinkyModeOfOperation attribute is specific to Linky devices. It consists of a single flag - * (bit 0) which shall be set to FALSE (0) when in 'Simple' Mode and set to TRUE (1) when in - * Advanced Mode. Bits 1 to 7 are reserved. */ - /* 0x020A to 0x02FF reserved */ - - - /* Formatting Attribute Set, table D.25 */ - ZB_ZCL_ATTR_METERING_UNIT_OF_MEASURE_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_FORMATTING, 0x00), /**< @e UnitOfMeasure attribute provides a label for - * the Energy, Gas, or Water being measured by the metering device. - * @see zb_zcl_metering_unit_of_measure_e */ - ZB_ZCL_ATTR_METERING_MULTIPLIER_ID, /**< @e Multiplier attribute provides a value to be multiplied against a raw or uncompensated sensor - * count of Energy, Gas, or Water being measured by the metering device. */ - ZB_ZCL_ATTR_METERING_DIVISOR_ID, /**< @e Divisor attribute provides a value to divide the results of applying the - * @ref ZB_ZCL_ATTR_METERING_MULTIPLIER_ID "Multiplier Attribute" against a raw or uncompensated - * sensor count of Energy, Gas, or Water being measured by the metering device. */ - ZB_ZCL_ATTR_METERING_SUMMATION_FORMATTING_ID, /**< @e SummationFormatting attribute provides a method to properly decipher the number of digits - * and the decimal location of the values found in the Summation Information Set of attributes. */ - ZB_ZCL_ATTR_METERING_DEMAND_FORMATTING_ID, /**< @e DemandFormatting attribute provides a method to properly decipher the number of digits and - * the decimal location of the values found in the Demand-related attributes. */ - ZB_ZCL_ATTR_METERING_HISTORICAL_CONSUMPTION_FORMATTING_ID, /**< @e HistoricalConsumptionFormatting attribute provides a method to properly decipher the number - * of digits and the decimal location of the values found in the Historical Consumption Set of - * attributes. */ - ZB_ZCL_ATTR_METERING_METERING_DEVICE_TYPE_ID, /**< @e MeteringDeviceType attribute provides a label for identifying the type of metering device - * present (Energy, Gas, Water, Thermal, Heat, Cooling, and mirrored metering devices). - * @see zb_zcl_metering_device_type_e */ - ZB_ZCL_ATTR_METERING_SITE_ID_ID, /**< @e SiteID attribute is a text string, known in the UK as the MPAN number for electricity, - * MPRN for gas and 'Stand Point' in South Africa. */ - ZB_ZCL_ATTR_METERING_METER_SERIAL_NUMBER_ID, /**< @e MeterSerialNumber attribute is used to provide a unique identification of the metering - * device. */ - ZB_ZCL_ATTR_METERING_ENERGY_CARRIER_UNIT_OF_MEASURE_ID, /**< @e EnergyCarrierUnitOfMeasure attribute specifies the unit of measure that the EnergyCarrier - * is measured in. */ - ZB_ZCL_ATTR_METERING_ENERGY_CARRIER_SUMMATION_FORMATTING_ID, /**< @e EnergyCarrierSummationFormatting attribute provides a method to properly decipher the number - * of digits and the decimal location of the values found in the Summation- related attributes. */ - ZB_ZCL_ATTR_METERING_ENERGY_CARRIER_DEMAND_FORMATTING_ID, /**< @e EnergyCarrierDemandFormatting attribute provides a method to properly decipher the number - * of digits and the decimal location of the values found in the Demand- related attributes. */ - ZB_ZCL_ATTR_METERING_TEMPERATURE_UNIT_OF_MEASURE_ID, /**< @e TemperatureUnitOfMeasure attribute specifies the unit of measure that temperatures are - * measured in. - * @see zb_zcl_metering_temperature_unit_of_measure_e */ - ZB_ZCL_ATTR_METERING_TEMPERATURE_FORMATTING_ID, /**< @e TemperatureFormatting attribute provides a method to properly decipher the number of digits - * and the decimal location of the values found in the Temperature-related attributes. */ - ZB_ZCL_ATTR_METERING_MODULE_SERIAL_NUMBER_ID, /**< @e ModuleSerialNumber attribute represents the serial number (unique identifier) of the - * meter module. */ - ZB_ZCL_ATTR_METERING_OPERATING_TARIFF_LABEL_DELIVERED_ID, /**< @e OperatingTariffLabelDelivered attribute is the meter's version of the @e TariffLabel attribute - * that is found within the Tariff Information attribute set of the Price Cluster. */ - ZB_ZCL_ATTR_METERING_OPERATING_TARIFF_LABEL_RECEIVED_ID, /**< @e OperatingTariffLabelReceived attribute is the meter's version of the @e ReceivedTariffLabel - * attribute that is found within the Tariff Information attribute set of the Price Cluster. */ - ZB_ZCL_ATTR_METERING_CUSTOMER_ID_NUMBER_ID, /**< @e CustomerIDNumber attribute provides a customer identification which may be used to confirm - * the customer at the premises. */ - ZB_ZCL_ATTR_METERING_ALTERNATIVE_UNIT_OF_MEASURE_ID, /**< @e AlternativeUnitOfMeasure attribute provides a base for the attributes in the Alternative - * Historical Consumption attribute set. */ - ZB_ZCL_ATTR_METERING_ALTERNATIVE_DEMAND_FORMATTING_ID, /**< @e AlternativeDemandFormatting attribute provides a method to properly decipher the number of - * digits and the decimal location of the values found in the Alternative Demand-related attributes. */ - ZB_ZCL_ATTR_METERING_ALTERNATIVE_CONSUMPTION_FORMATTING_ID, /**< @e AlternativeConsumptionFormatting attribute provides a method to properly decipher the - * number of digits and the decimal location of the consumption values found in the Alternative - * Historical Consumption Set of attributes. */ - /* 0x0313 to 0x03FF reserved */ - - - /* Historical Consumption Attribute Set, table D.29 */ - ZB_ZCL_ATTR_METERING_INSTANTANEOUS_DEMAND_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_HISTORICAL_CONSUMPTION, 0x00), /**< @e InstantaneousDemand attribute - * represents the current Demand of Energy, Gas, or Water delivered or received at the premises.*/ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_CONSUMPTION_DELIVERED_ID, /**< @e CurrentDayConsumptionDelivered attribute represents the summed value of Energy, - * Gas, or Water delivered to the premises since the Historical Freeze Time (HFT).*/ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_CONSUMPTION_RECEIVED_ID, /**< @e CurrentDayConsumptionReceived attribute represents the summed value of Energy, - * Gas, or Water received from the premises since the Historical Freeze Time (HFT). */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_CONSUMPTION_DELIVERED_ID, /**< @e PreviousDayConsumptionDelivered attribute represents the summed value of Energy, - * Gas, or Water delivered to the premises within the previous 24 hour period starting - * at the Historical Freeze Time (HFT). */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_CONSUMPTION_RECEIVED_ID, /**< @e PreviousDayConsumptionReceived attribute represents the summed value of Energy, - * Gas, or Water received from the premises within the previous 24 hour period starting - * at the Historical Freeze Time (HFT). */ - ZB_ZCL_ATTR_METERING_CURRENT_PARTIAL_PROFILE_INTERVAL_START_TIME_DELIVERED_ID, /**< @e CurrentPartialProfileIntervalStartTimeDelivered attribute represents the start - * time of the current Load Profile interval being accumulated for commodity delivered. */ - ZB_ZCL_ATTR_METERING_CURRENT_PARTIAL_PROFILE_INTERVAL_START_TIME_RECEIVED_ID, /**< @e CurrentPartialProfileIntervalStartTimeReceived attribute represents the start - * time of the current Load Profile interval being accumulated for commodity received. */ - ZB_ZCL_ATTR_METERING_CURRENT_PARTIAL_PROFILE_INTERVAL_VALUE_DELIVERED_ID, /**< @e CurrentPartialProfileIntervalValueDelivered attribute represents the value of - * the current Load Profile interval being accumulated for commodity delivered. */ - ZB_ZCL_ATTR_METERING_CURRENT_PARTIAL_PROFILE_INTERVAL_VALUE_RECEIVED_ID, /**< @e CurrentPartialProfileIntervalValueReceived attribute represents the value of - * the current Load Profile interval being accumulated for commodity delivered. */ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_MAX_PRESSURE_ID, /**< @e CurrentDayMaxPressure attribute is the maximum pressure reported during a day - * from the water or gas meter. */ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_MIN_PRESSURE_ID, /**< @e CurrentDayMinPressure attribute is the minimum pressure reported during a day - * from the water or gas meter. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_MAX_PRESSURE_ID, /**< @e PreviousDayMaxPressure attribute is the maximum pressure reported during previous - * day from the water or gas meter. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_MIN_PRESSURE_ID, /**< @e PreviousDayMinPressure attribute is the minimum pressure reported during previous - * day from the water or gas meter. */ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_MAX_DEMAND_ID, /**< @e CurrentDayMaxDemand attribute represents the maximum demand or rate of delivered - * value of Energy, Gas, or Water being utilized at the premises. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_MAX_DEMAND_ID, /**< @e PreviousDayMaxDemand attribute represents the maximum demand or rate of delivered - * value of Energy, Gas, or Water being utilized at the premises. */ - ZB_ZCL_ATTR_METERING_CURRENT_MONTH_MAX_DEMAND_ID, /**< @e CurrentMonthMaxDemand attribute is the maximum demand reported during a month - * from the meter. For electricity, heat and cooling meters this is the maximum power - * reported in a month.*/ - ZB_ZCL_ATTR_METERING_CURRENT_YEAR_MAX_DEMAND_ID, /**< @e CurrentYearMaxDemand attribute is the maximum demand reported during a year - * from the meter. For electricity, heat and cooling meters this is the maximum power - * reported in a year.*/ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_MAX_ENERGY_CARRIER_DEMAND_ID, /**< @e CurrentDayMaxEnergyCarrierDemand attribute is the maximum energy carrier demand - * reported during a day from the meter. For heat and cooling meters this is the maximum - * flow rate on the inlet reported in a day. - * @note At the end of a day the meter will transfer the @e CurrentDayMaxEnergyCarrierDemand - * into @ref ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_MAX_ENERGY_CARRIER_DEMAND_ID "PreviousDayMaxEnergyCarrierDemand". */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_MAX_ENERGY_CARRIER_DEMAND_ID, /**< @e PreviousDayMaxEnergyCarrierDemand attribute is the maximum energy carrier demand - * reported during the previous day from the meter. */ - ZB_ZCL_ATTR_METERING_CURRENT_MONTH_MAX_ENERGY_CARRIER_DEMAND_ID, /**< @e CurrentMonthMaxEnergyCarrierDemand attribute is the maximum energy carrier demand - * reported during a month from the meter. For heat and cooling meters this is the - * maximum flow rate on the inlet reported in a month. */ - ZB_ZCL_ATTR_METERING_CURRENT_MONTH_MIN_ENERGY_CARRIER_DEMAND_ID, /**< @e CurrentMonthMinEnergyCarrierDemand attribute is the minimum energy carrier demand - * reported during a month from the meter. For heat and cooling meters this is the - * minimum flow rate on the inlet reported in a month. */ - ZB_ZCL_ATTR_METERING_CURRENT_YEAR_MAX_ENERGY_CARRIER_DEMAND_ID, /**< @e CurrentYearMaxEnergyCarrierDemand attribute is the maximum energy carrier demand - * reported during a year from the meter. For heat and cooling meters this is the maximum - * flow rate on the inlet reported in a year. */ - ZB_ZCL_ATTR_METERING_CURRENT_YEAR_MIN_ENERGY_CARRIER_DEMAND_ID, /**< @e CurrentYearMinEnergyCarrierDemand attribute is the minimum energy carrier demand - * reported during a year from the heat meter. For heat and cooling meters this is the - * minimum flow rate on the inlet reported in a year. */ - /* 0x0417 to 0x041F reserved */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_DELIVERED_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_HISTORICAL_CONSUMPTION, 0x20), /**< @e PreviousDayNConsumptionDelivered - * attribute represents the summed value of Energy, Gas, or Water delivered to the - * premises within the previous 24 hour period starting at the Historical Freeze Time (HFT). */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_RECEIVED_ID, /**< @e PreviousDayNConsumptionReceived attribute represents the summed value of Energy, - * Gas, or Water received from the premises within the previous 24 hour period starting - * at the Historical Freeze Time (HFT). */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY3_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY3_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY4_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY4_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY5_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY5_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY6_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY6_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY7_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY7_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY8_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY8_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_CONSUMPTION_RECEIVED_ID */ - /* 0x042E to 0x042F reserved */ - ZB_ZCL_ATTR_METERING_CURRENT_WEEK_CONSUMPTION_DELIVERED_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_HISTORICAL_CONSUMPTION, 0x30), /**< @e CurrentWeekConsumptionDelivered - * attribute represents the summed value of Energy, Gas, or Water delivered to the premises - * since the Historical Freeze Time (HFT) on Monday to the last HFT read. */ - ZB_ZCL_ATTR_METERING_CURRENT_WEEK_CONSUMPTION_RECEIVED_ID, /**< @e CurrentWeekConsumptionReceived attribute represents the summed value of Energy, - * Gas, or Water received from the premises since the Historical Freeze Time (HFT) on - * Monday to the last HFT read. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_CONSUMPTION_DELIVERED_ID, /**< @e PreviousWeekNConsumptionDelivered attribute represents the summed value of Energy, - * Gas, or Water delivered to the premises within the previous week period starting at - * the Historical Freeze Time (HFT) on the Monday to the Sunday. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_CONSUMPTION_RECEIVED_ID, /**< @e PreviousWeekNConsumptionReceived attribute represents the summed value of Energy, - * Gas, or Water received from the premises within the previous week period starting at - * the Historical Freeze Time (HFT) on the Monday to the Sunday. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK2_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK2_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK3_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK3_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK4_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK4_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK5_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK5_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_CONSUMPTION_RECEIVED_ID */ - /* 0x043C to 0x043F reserved */ - ZB_ZCL_ATTR_METERING_CURRENT_MONTH_CONSUMPTION_DELIVERED_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_HISTORICAL_CONSUMPTION, 0x40), /**< @e CurrentMonthConsumptionDelivered - * attribute represents the summed value of Energy, Gas, or Water delivered to the premises - * since the Historical Freeze Time (HFT) on the 1 st of the month to the last HFT read. */ - ZB_ZCL_ATTR_METERING_CURRENT_MONTH_CONSUMPTION_RECEIVED_ID, /**< @e CurrentMonthConsumptionReceived attribute represents the summed value of Energy, - * Gas, or Water received from the premises since the Historical Freeze Time (HFT) on the - * 1 st of the month to the last HFT read. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID, /**< @e PreviousMonthNConsumptionDelivered attribute represents the summed value of - * Energy, Gas, or Water delivered to the premises within the previous Month period - * starting at the Historical Freeze Time (HFT) on the 1 st of the month to the last - * day of the month.*/ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID, /**< @e PreviousMonthNConsumptionReceived attribute represents the summed value of - * Energy, Gas, or Water received from the premises within the previous month period - * starting at the Historical Freeze Time (HFT) on the 1 st of the month to the last - * day of the month.*/ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH2_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH2_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH3_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH3_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH4_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH4_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH5_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH5_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH6_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH6_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH7_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH7_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH8_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH8_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH9_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH9_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH10_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH10_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH11_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH11_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH12_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH12_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH13_CONSUMPTION_DELIVERED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_DELIVERED_ID */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH13_CONSUMPTION_RECEIVED_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_CONSUMPTION_RECEIVED_ID */ - ZB_ZCL_ATTR_METERING_HISTORICAL_FREEZE_TIME_ID, /**< @e HistoricalFreezeTime attribute represents the time of day, in Local Time, when - * Historical Consumption attributes and/or Alternative Historical Consumption - * attributes are captured (hour and minutes). */ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_MAX_DEMAND_DELIVERED_ID, /**< @e CurrentDayMaxDemandDelivered represents the maximum demand or rate of delivered value of - * Energy, Gas, or Water being utilized at the premises since the Historical Freeze Time (HFT). */ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_MAX_DEMAND_DELIVERED_TIME_ID, /**< The @e CurrentDayMaxDemandDeliveredTime attribute represents the time when - * @e CurrentDayMaxDemandDelivered reading was captured. */ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_MAX_DEMAND_RECEIVED_ID, /**< @e CurrentDayMaxDemandReceived represents the maximum demand or rate of received value of - * Energy, Gas, or Water being utilized by the utility from the premises sinc e the Historical - * Freeze Time (HFT). */ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_MAX_DEMAND_RECEIVED_TIME_ID, /**< The CurrentDayMaxDemandReceivedTime attribute represents the time CurrentDayMaxDemandReceived - * reading was captured */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_MAX_DEMAND_DELIVERED_ID, /**< @e PreviousDayMaxDemandDelivered represents the maximum demand or rate of delivered - * value of Energy, Gas, or Water that was utilized at the premises within the previous 24 - * hour period starting at the Historical Freeze Time (HFT) */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_MAX_DEMAND_DELIVERED_TIME_ID, /**< The @e PreviousDayMaxDemandDeliveredTime attribute represents the time when - * PreviousDayMaxDemandDelivered reading was captured. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_MAX_DEMAND_RECEIVED_ID, /**< @e PreviousDayMaxDemandReceived represents the maximum demand or rate of received value - * of Energy, Gas, or Water that was utilized by the utility from the premises within the - * previous 24 hour period starting at the Historical Freeze Time (HFT). - */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_MAX_DEMAND_RECEIVED_TIME_ID, /**< The @e PreviousDayMaxDem andReceivedTime attribute represents the time when - * @e PreviousDayMaxDemandReceived reading was captured. - */ - /* 0x045D to 0x04FF reserved */ - - - /* Load Profile Configuration Attribute Set, table D.30 */ - ZB_ZCL_ATTR_METERING_MAX_NUMBER_OF_PERIODS_DELIVERED_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_LOAD_PROFILE_CONFIGURATION, 0x00), /**< @e MaxNumberOfPeriodsDelivered - * attribute represents the maximum number of intervals the device is capable of returning - * in one Get Profile Response command. It is required @e MaxNumberOfPeriodsDelivered fit - * within the default Fragmentation ASDU size of 128 bytes, or an optionally agreed upon - * larger Fragmentation ASDU size supported by both devices. - * @see SE spec, sub-clause 5.3.8. */ - /* 0x0501 to 0x05FF reserved */ - - - /* Supply Limit Attribute Set, table D.31 */ - ZB_ZCL_ATTR_METERING_CURRENT_DEMAND_DELIVERED_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_SUPPLY_LIMIT, 0x00), /**< @e CurrentDemandDelivered attribute represents - * the current Demand of Energy, Gas, or Water delivered at the premises. */ - ZB_ZCL_ATTR_METERING_DEMAND_LIMIT_ID, /**< @e DemandLimit attribute reflects the current supply demand limit set in the meter. This value can be - * compared to the @ref ZB_ZCL_ATTR_METERING_CURRENT_DEMAND_DELIVERED_ID "CurrentDemandDelivered" attribute to - * understand if limits are being approached or exceeded. A value of 0xFFFFFF indicates demand limiting - * is switched off.*/ - ZB_ZCL_ATTR_METERING_DEMAND_INTEGRATION_PERIOD_ID, /**< @e DemandIntegrationPeriod attribute is the number of minutes over which the - * @ref ZB_ZCL_ATTR_METERING_CURRENT_DEMAND_DELIVERED_ID "CurrentDemandDelivered" attribute is calculated. Valid - * range is 0x01 to 0xFF. 0x00 is a reserved value. */ - ZB_ZCL_ATTR_METERING_NUMBER_OF_DEMAND_SUBINTERVALS_ID, /**< @e NumberOfDemandSubintervals attribute represents the number of subintervals used within the - * @ref ZB_ZCL_ATTR_METERING_DEMAND_INTEGRATION_PERIOD_ID "DemandIntegrationPeriod". The subinterval - * duration (in minutes) is obtained by dividing the @ref ZB_ZCL_ATTR_METERING_DEMAND_INTEGRATION_PERIOD_ID - * "DemandIntegrationPeriod" by the @ref ZB_ZCL_ATTR_METERING_NUMBER_OF_DEMAND_SUBINTERVALS_ID "NumberOfDemandSubintervals". - * The @ref ZB_ZCL_ATTR_METERING_CURRENT_DEMAND_DELIVERED_ID "CurrentDemandDelivered" attribute is updated at the - * each of each subinterval. Valid range is 0x01 to 0xFF. 0x00 is a reserved value. */ - ZB_ZCL_ATTR_METERING_DEMAND_LIMIT_ARM_DURATION_ID, /**< @e DemandLimitArmDuration attribute defines the length of time, in seconds, that the supply shall be - * disconnected if the @ref ZB_ZCL_ATTR_METERING_DEMAND_LIMIT_ID "DemandLimit" attribute is enabled and - * the limit is exceeded.*/ - ZB_ZCL_ATTR_METERING_LOAD_LIMIT_SUPPLY_STATE_ID, /**< @e LoadLimitSupplyState attribute indicates the required status of the supply once device is in a load - * limit state. @see SE 1.4 spec, table D.68. */ - ZB_ZCL_ATTR_METERING_LOAD_LIMIT_COUNTER_ID, /**< @e LoadLimitCounter attribute is used for counting the number of times that the demand limit has - * exceeded the set threshold. */ - ZB_ZCL_ATTR_METERING_SUPPLY_TAMPER_STATE_ID, /**< @e SupplyTamperState attribute indicates the required status of the supply following the detection of a - * tamper event within the metering device. @see SE 1.4 spec, table D.68. */ - ZB_ZCL_ATTR_METERING_SUPPLY_DEPLETION_STATE_ID, /**< @e SupplyDepletionState attribute indicates the required status of the supply following detection of a - * depleted battery within the metering device. @see SE 1.4 spec, table D.68. */ - ZB_ZCL_ATTR_METERING_SUPPLY_UNCONTROLLED_FLOW_STATE_ID, /**< @e SupplyUncontrolledFlowState attribute indicates the required status of the supply following detection - * of an uncontrolled flow event within the metering device. @see SE 1.4 spec, table D.68. */ - /* 0x060A to 0x06FF reserved */ - - /*TODO: need to add set 0x07 - ZB_ZCL_METERING_SET_BLOCK_INFORMATION_DELIVERED*/ - /*FIXME: Does we need to use _ID suffix in attributes? */ - /*ZB_ZCL_METERING_SET_ALARMS attribute set*/ - ZB_ZCL_ATTR_METERING_GENERIC_ALARM_MASK_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_ALARMS, 0x00), /**< The AlarmMask attributes of the Alarm Attribute Set - * specify whether each of the alarms listed in the - * corresponding alarm group is enabled. When the bit number - * corresponding to the alarm number (minus the group offset) is set to 1, - * the alarm is enabled, else it is disabled. Bits not corresponding - * to a code in the respective table are reserved. - */ - ZB_ZCL_ATTR_METERING_ELECTRICITY_ALARM_MASK_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_GENERIC_ALARM_MASK_ID */ - ZB_ZCL_ATTR_METERING_GENERIC_FLOW_PRESSURE_ALARM_MASK_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_GENERIC_ALARM_MASK_ID */ - ZB_ZCL_ATTR_METERING_WATER_SPECIFIC_ALARM_MASK_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_GENERIC_ALARM_MASK_ID */ - ZB_ZCL_ATTR_METERING_HEAT_AND_COOLING_SPECIFIC_ALARM_MASK_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_GENERIC_ALARM_MASK_ID */ - ZB_ZCL_ATTR_METERING_GAS_SPECIFIC_ALARM_MASK_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_GENERIC_ALARM_MASK_ID */ - ZB_ZCL_ATTR_METERING_EXTENDED_GENERIC_ALARM_MASK_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_GENERIC_ALARM_MASK_ID */ - ZB_ZCL_ATTR_METERING_MANUFACTURER_ALARM_MASK_ID, /**< @copydoc ZB_ZCL_ATTR_METERING_GENERIC_ALARM_MASK_ID */ - - /*TODO: need to add set 0x09 */ - - /* Meter Billing Attribute Set, table D.44 */ - - /**< @e BillToDateDelivered provides a value for the costs in the current billing period.*/ - ZB_ZCL_ATTR_METERING_BILL_TO_DATE_DELIVERED = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_METER_BILLING, 0x00), - ZB_ZCL_ATTR_METERING_BILL_TO_DATE_TIMESTAMP_DELIVERED, /**< @e BillToDateTimeStampDelivered The UTC timestamp - * when the associated BillToDateDelivered attribute was last updated.*/ - ZB_ZCL_ATTR_METERING_PROJECTED_BILL_DELIVERED, /**< @e ProjectedBillDelivered provides a value indicating what the estimated state of the account - * will be at the end of the billing period based on past consumption.*/ - ZB_ZCL_ATTR_METERING_PROJECTED_BILL_TIME_STAMP_DELIVERED, /**< @e ProjectedBillTimeStampDelivered - * The UTC timestamp when the associated ProjectedBillDelivered attribute was last updated. */ - ZB_ZCL_ATTR_METERING_BILL_DELIVERED_TRAILING_DIGIT, /**< @e BillDeliveredTrailingDigit An 8-bit BitMap used to determine where the decimal point is located - * in the BillToDateDelivered and ProjectedBillDelivered attributes. */ - ZB_ZCL_ATTR_METERING_BILL_TO_DATE_RECEIVED = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_METER_BILLING, 0x10), - /**< @e BillToDateReceived provides a value for the costs in the current billing period. - * This attribute is measured in a base unit of Currency with the decimal point located - * as indicated by the BillReceivedTrailingDigit attribute */ - ZB_ZCL_ATTR_METERING_BILL_TO_DATE_TIMESTAMP_RECEIVED, /**< @e BillToDateTimeStampReceived The UTC timestamp - * when the associated BillToDateReceived attribute was last updated */ - ZB_ZCL_ATTR_METERING_PROJECTED_BILL_RECEIVED, /**< @e ProjectedBillReceived provides a value indicating what the estimated state of the account - * will be at the end of the billing period based on past generation.*/ - ZB_ZCL_ATTR_METERING_PROJECTED_BILL_TIME_STAMP_RECEIVED, /**< @e ProjectedBillTimeStampReceived - * The UTC timestamp when the associated ProjectedBillReceived attribute was last updated. */ - ZB_ZCL_ATTR_METERING_BILL_RECEIVED_TRAILING_DIGIT, /**< @e BillReceivedTrailingDigit - * An 8-bit BitMap used to determine where the decimal point is located - * in the BillToDateReceived and ProjectedBillReceived attributes.*/ - - /* Supply Control Attribute, table D.45 */ - - /**< @e ProposedChangeSupplyImplementationTime indicates the time - * at which a proposed change to the supply is to be implemented.*/ - ZB_ZCL_ATTR_METERING_PROPOSED_CHANGE_SUPPLY_IMPLEMENTATION_TIME = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_SUPPLY_CONTROL, 0x00), - ZB_ZCL_ATTR_METERING_PROPOSED_CHANGE_SUPPLY_STATUS, /**< @e ProposedChangeSupplyStatus indicates the proposed status of the supply - * once the change to the supply has be been implemented.*/ - /**< @e UncontrolledFlowThreshold indicates the threshold above which a flow meter (e.g. Gas or Water) - * shall detect an uncontrolled flow.*/ - ZB_ZCL_ATTR_METERING_UNCONTROLLED_FLOW_THRESHOLD = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_SUPPLY_CONTROL, 0x10), - ZB_ZCL_ATTR_METERING_UNCONTROLLED_FLOW_THRESHOLD_UNIT_OF_MEASURE, /**< @e UncontrolledFlowThresholdUnitOfMeasure indicates the unit of measure - * used in conjunction with the Uncontrolled Flow Threshold attribute.*/ - ZB_ZCL_ATTR_METERING_UNCONTROLLED_FLOW_MULTIPLIER, /**< @e UncontrolledFlowMultiplier indicates the multiplier, - * to be used in conjunction with the Uncontrolled Flow Threshold and Uncontrolled Flow Divisor attributes, - * to determine the true flow threshold value.*/ - ZB_ZCL_ATTR_METERING_UNCONTROLLED_FLOW_DIVISOR, /**< @e UncontrolledFlowDivisor - * The Uncontrolled Flow Divisor attribute indicates the divisor, to be used in conjunction - * with the Uncontrolled Flow Threshold and Uncontrolled Flow Multiplier attributes, - * to determine the true flow threshold value.*/ - ZB_ZCL_ATTR_METERING_FLOW_STABILISATION_PERIOD, /**< @e FlowStabilisationPeriod indicates the time given to allow the flow to stabilize.*/ - ZB_ZCL_ATTR_METERING_FLOW_MEASUREMENT_PERIOD, /**< @e FlowMeasurementPeriodAttribute indicates the period - * over which the flow is measured and compared against the Uncontrolled Flow Threshold attribute.*/ - - /* Alternative Historical Consumption Attribute Set, table D.46 */ - /**< @e AlternativeInstantaneousDemand represents the current Demand delivered or received at the premises*/ - ZB_ZCL_ATTR_METERING_ALT_INSTANTANEOUS_DEMAND = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_ALTERNATIVE_HISTORICAL_CONSUMPTION, 0x00), - ZB_ZCL_ATTR_METERING_CURRENT_DAY_ALT_CONSUMPTION_DELIVERED, /**< @e CurrentDayAlternativeConsumptionDelivered represents the summed value - * delivered to the premises since the Historical Freeze Time (HFT). */ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_ALT_CONSUMPTION_RECEIVED, /**< @e CurrentDayAlternativeConsumptionReceived represents the summed value - * received from the premises since the Historical Freeze Time (HFT).*/ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_ALT_CONSUMPTION_DELIVERED, /**< @e PreviousDayAlternativeConsumptionDelivered represents the summed value - * delivered to the premises within the previous 24 hour period - * starting at the alternative Historical Freeze Time (HFT).*/ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_ALT_CONSUMPTION_RECEIVED, /**< @e PreviousDayAlternativeConsumptionReceived represents the summed value - * received to the premises within the previous 24 hour period - * starting at the alternative Historical Freeze Time (HFT).*/ - ZB_ZCL_ATTR_METERING_CURRENT_ALT_PARTIAL_PROFILE_INTERVAL_START_TIME_DELIVERED, /**< @e CurrentAlternativePartialProfileIntervalStartTimeDelivered represents the start time - * of the current Load Profile interval being accumulated for commodity delivered */ - ZB_ZCL_ATTR_METERING_CURRENT_ALT_PARTIAL_PROFILE_INTERVAL_START_TIME_RECEIVED, /**< @e CurrentAlternativePartialProfileIntervalStartTimeReceived represents the start time - * of the current Load Profile interval being accumulated for commodity received */ - ZB_ZCL_ATTR_METERING_CURRENT_ALT_PARTIAL_PROFILE_INTERVAL_VALUE_DELIVERED, /**< @e CurrentAlternativePartialProfileIntervalValueDelivered represents the value -* * of the current Load Profile interval being accumulated for commodity delivered.*/ - ZB_ZCL_ATTR_METERING_CURRENT_ALT_PARTIAL_PROFILE_INTERVAL_VALUE_RECEIVED, /**< @e CurrentAlternativePartialProfileIntervalValueReceived represents the value -* * of the current Load Profile interval being accumulated for commodity received .*/ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_ALT_MAX_PRESSURE, /**< @e CurrentDayAlternativeMaxPressure is the maximum pressure - * reported during a day from the water or gas meter. */ - ZB_ZCL_ATTR_METERING_CURRENT_DAY_ALT_MIN_PRESSURE, /**< @e CurrentDayAlternativeMinPressure is the minimum pressure - * reported during a day from the water or gas meter. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_ALT_MAX_PRESSURE, /**< @e PreviousDayAlternativeMaxPressure represents the maximum pressure - * reported during previous day from the water or gas meter.*/ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_ALT_MIN_PRESSURE, /**< @e PreviousDayAlternativeMinPressure represents the minimum pressure - * reported during previous day from the water or gas meter.*/ - - ZB_ZCL_ATTR_METERING_CURRENT_DAY_ALT_MAX_DEMAND, /**< @e CurrentDayAlternativeMaxDemand represents the maximum demand or rate - * of delivered value of Energy, Gas, or Water being utilized at the premises.*/ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY_ALT_MAX_DEMAND, /**< @e PreviousDayAlternativeMaxDemand represents represents the maximum demand or rate - * of delivered value of Energy, Gas, or Water being utilized at the premises.*/ - - ZB_ZCL_ATTR_METERING_CURRENT_MONTH_ALT_MAX_DEMAND, /**< @e CurrentMonthAlternativeMaxDemand is the maximum demand reported during a month from the meter. */ - ZB_ZCL_ATTR_METERING_CURRENT_YEAR_ALT_MAX_DEMAND, /**< @e CurrentYearAlternativeMaxDemand is the maximum demand reported during a year from the meter.*/ - - /**< @e PreviousDayNAlternativeConsumptionDelivered represents the summed value delivered to the premises - * within the previous 24 hour period starting at the Historical Freeze Time (HFT). */ - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_ALT_CONSUMPTION_DELIVERED = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_ALTERNATIVE_HISTORICAL_CONSUMPTION, 0x20), - ZB_ZCL_ATTR_METERING_PREVIOUS_DAY2_ALT_CONSUMPTION_RECEIVED, /**< @e PreviousDayNAlternativeConsumptionReceived - * represents the summed value received from the premises - * within the previous 24 hour period starting at the Historical Freeze Time (HFT).*/ - - /**< @e CurrentWeekAlternativeConsumptionDelivered represents the summed value - * delivered to the premises since the Historical Freeze Time (HFT) on Monday to the last HFT read. */ - ZB_ZCL_ATTR_METERING_CURRENT_WEEK_ALT_CONSUMPTION_DELIVERED = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_ALTERNATIVE_HISTORICAL_CONSUMPTION, 0x30), - ZB_ZCL_ATTR_METERING_CURRENT_WEEK_ALT_CONSUMPTION_RECEIVED, /**< @e CurrentWeekAlternativeConsumptionReceived represents the summed value - * received from the premises since the Historical Freeze Time (HFT) on Monday to the last HFT read */ - - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_ALT_CONSUMPTION_DELIVERED, /**< @e PreviousWeekNAlternativeConsumptionDelivered represents the summed value - * delivered to the premises within the previous week period - * starting at the Historical Freeze Time (HFT) on the Monday to the Sunday. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_WEEK_ALT_CONSUMPTION_RECEIVED, /**< @e PreviousWeekNAlternativeConsumptionReceived represents the summed value - * received from the premises within the previous week period - * starting at the Historical Freeze Time (HFT) on the Monday to the Sunday*/ - /**< @e CurrentMonthAlternativeConsumptionDelivered represents the summed value delivered to the premises - * since the Historical Freeze Time (HFT) on the 1st of the month to the last HFT read */ - ZB_ZCL_ATTR_METERING_CURRENT_MONTH_ALT_CONSUMPTION_DELIVERED = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_ALTERNATIVE_HISTORICAL_CONSUMPTION, 0x40), - ZB_ZCL_ATTR_METERING_CURRENT_MONTH_ALT_CONSUMPTION_RECEIVED, /**< @e CurrentMonthAlternativeConsumptionReceived represents the summed value - * received from the premises since the Historical Freeze Time (HFT) - * on the 1st of the month to the last HFT read. */ - - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_ALT_CONSUMPTION_DELIVERED, /**< @e PreviousMonthNAlternativeConsumptionDelivered represents the summed value - * delivered to the premises within the previous Month period - * starting at the Historical Freeze Time (HFT) on the 1st of the month to the last day of the month. */ - ZB_ZCL_ATTR_METERING_PREVIOUS_MONTH_ALT_CONSUMPTION_RECEIVED, /**< @e PreviousMonthNAlternativeConsumptionReceived represents the summed value - * received from the premises within the previous month period - * starting at the Historical Freeze Time (HFT) on the 1st of the month to the last day of the month. */ - - /* ZB_ZCL_METERING_SET_FOUR_QUADRANT_ELECTRICITY attribute set */ - /*NOTE: the first attribute from this attribute set starts from 0x0D01 value instead of 0x0D00 */ - /*NOTE: attribute 0x0D04 in one spec it is ZB_ZCL_ATTR_METERING_CURRENT_ACTIVE_SUMMATION_Q4_ID, - in another it is ZB_ZCL_ATTR_METERING_CURRENT_REACTIVE_SUMMATION_Q1_ID - NOTE: It is supposed that ZB_ZCL_ATTR_METERING_CURRENT_ACTIVE_SUMMATION_Q1_ID = 0x0D00 - */ - ZB_ZCL_ATTR_METERING_CURRENT_ACTIVE_SUMMATION_Q1_ID = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_METERING_SET_FOUR_QUADRANT_ELECTRICITY, 0x01), /**< This attribute represents the most - * recent summed value of Active Energy (kWh) - * delivered in the quadrant Q1. - */ - ZB_ZCL_ATTR_METERING_CURRENT_ACTIVE_SUMMATION_Q2_ID, /**< This attribute represents the most - * recent summed value of Active Energy (kWh) - * delivered in the quadrant Q2. - */ - ZB_ZCL_ATTR_METERING_CURRENT_ACTIVE_SUMMATION_Q3_ID, /**< This attribute represents the most - * recent summed value of Active Energy (kWh) - * delivered in the quadrant Q3. - */ - ZB_ZCL_ATTR_METERING_CURRENT_ACTIVE_SUMMATION_Q4_ID, /**< This attribute represents the most - * recent summed value of Active Energy (kWh) - * delivered in the quadrant Q4. - */ - ZB_ZCL_ATTR_METERING_CURRENT_REACTIVE_SUMMATION_Q1_ID, /**< This attribute represents the most recent - * summed value of Reactive Energy (kVarh) delivered - * in quadrant Q1. - */ - ZB_ZCL_ATTR_METERING_CURRENT_REACTIVE_SUMMATION_Q2_ID, /**< This attribute represents the most recent - * summed value of Reactive Energy (kVarh) delivered - * in quadrant Q2. - */ - ZB_ZCL_ATTR_METERING_CURRENT_REACTIVE_SUMMATION_Q3_ID, /**< This attribute represents the most recent - * summed value of Reactive Energy (kVarh) delivered - * in quadrant Q3. - */ - ZB_ZCL_ATTR_METERING_CURRENT_REACTIVE_SUMMATION_Q4_ID /**< This attribute represents the most recent - * summed value of Reactive Energy (kVarh) delivered - * in quadrant Q4. - */ -}; - - -/** @brief @e CurrentBlock attribute values - * @see @ref ZB_ZCL_ATTR_METERING_CURRENT_BLOCK_ID - * @see SE 1.4 spec, Table D.12. - */ -enum zb_zcl_metering_block_e -{ - ZB_ZCL_METERING_BLOCK_NOT_USED = 0x00, /**< No blocks in use */ - ZB_ZCL_METERING_BLOCK_1 = 0x01, /**< Block 1 */ - ZB_ZCL_METERING_BLOCK_2 = 0x02, /**< Block 2 */ - ZB_ZCL_METERING_BLOCK_3 = 0x03, /**< Block 3 */ - ZB_ZCL_METERING_BLOCK_4 = 0x04, /**< Block 4 */ - ZB_ZCL_METERING_BLOCK_5 = 0x05, /**< Block 5 */ - ZB_ZCL_METERING_BLOCK_6 = 0x06, /**< Block 6 */ - ZB_ZCL_METERING_BLOCK_7 = 0x07, /**< Block 7 */ - ZB_ZCL_METERING_BLOCK_8 = 0x08, /**< Block 8 */ - ZB_ZCL_METERING_BLOCK_9 = 0x09, /**< Block 9 */ - ZB_ZCL_METERING_BLOCK_10 = 0x0A, /**< Block 10 */ - ZB_ZCL_METERING_BLOCK_11 = 0x0B, /**< Block 11 */ - ZB_ZCL_METERING_BLOCK_12 = 0x0C, /**< Block 12 */ - ZB_ZCL_METERING_BLOCK_13 = 0x0D, /**< Block 13 */ - ZB_ZCL_METERING_BLOCK_14 = 0x0E, /**< Block 14 */ - ZB_ZCL_METERING_BLOCK_15 = 0x0F, /**< Block 15 */ - ZB_ZCL_METERING_BLOCK_16 = 0x10, /**< Block 16 */ - /* 0x11 to 0xFF reserved */ -}; - - -/** @brief @e SupplyStatus attribute values - * @see @ref ZB_ZCL_ATTR_METERING_SUPPLY_STATUS_ID - * @see SE 1.4 spec, table D.13. - */ -enum zb_zcl_metering_supply_status_e -{ - ZB_ZCL_SUPPLY_STATUS_OFF = 0x00, /**< Supply OFF */ - ZB_ZCL_SUPPLY_STATUS_ARMED = 0x01, /**< Supply OFF/ARMED */ - ZB_ZCL_SUPPLY_STATUS_ON = 0x02 /**< Supply ON */ - /* 0x03 to 0xFF reserved for future use */ -}; - - -/** @brief Bit mapping of the @e Status attribute (Electricity) - * @see @ref ZB_ZCL_ATTR_METERING_STATUS_ID - * @see SE spec, subclause 3.2.2.3.1, table D.16. - */ -enum zb_zcl_metering_status_electricity_e -{ - ZB_ZCL_METERING_ELECTRICITY_CHECK_METER = 1 << 0, /**< @e CheckMeter bit is set to true when a non fatal problem has been detected on the meter such as - * a measurement error, memory error, self check error. */ - ZB_ZCL_METERING_ELECTRICITY_LOW_BATTERY = 1 << 1, /**< @e LowBattery bit is set to true when the battery needs maintenance. */ - ZB_ZCL_METERING_ELECTRICITY_TAMPER_DETECT = 1 << 2, /**< @e TamperDetect bit is set to true if a tamper event has been detected. */ - ZB_ZCL_METERING_ELECTRICITY_POWER_FAILURE = 1 << 3, /**< @e PowerFailure bit is set to true during a power outage. */ - ZB_ZCL_METERING_ELECTRICITY_POWER_QUALITY = 1 << 4, /**< @e PowerQuality bit is set to true if a power quality event has been detected such as a low - * voltage, high voltage. */ - ZB_ZCL_METERING_ELECTRICITY_LEAK_DETECT = 1 << 5, /**< @e LeakDetect bit is set to true when a leak has been detected. */ - ZB_ZCL_METERING_ELECTRICITY_SERVICE_DISCONNECT_OPEN = 1 << 6, /**< @e ServiceDisconnectOpen bit is Set to true when the service has been disconnected to this premises. */ - ZB_ZCL_METERING_ELECTRICITY_RESERVED = 1 << 7 /**< Reserved bit */ -}; - - -/** @brief Bit mapping of the @e Status attribute (Gas) - * @see @ref ZB_ZCL_ATTR_METERING_STATUS_ID - * @see SE spec, subclause 3.2.2.3.1, table D.17. - */ -enum zb_zcl_metering_status_gas_e -{ - ZB_ZCL_METERING_GAS_CHECK_METER = 1 << 0, /**< @e CheckMeter bit is Set to true when a non fatal problem has been detected on the meter such as - * a measurement error, memory error, or self check error. */ - ZB_ZCL_METERING_GAS_LOW_BATTERY = 1 << 1, /**< @e LowBattery bit is set to true when the battery needs maintenance. */ - ZB_ZCL_METERING_GAS_TAMPER_DETECT = 1 << 2, /**< @e TamperDetect bit is set to true if a tamper event has been detected. */ - ZB_ZCL_METERING_GAS_RESERVED = 1 << 3, /**< Reserved bit */ - ZB_ZCL_METERING_GAS_LOW_PRESSURE = 1 << 4, /**< @e LowPressure bit is set to true when the pressure at the meter is below the meter's low - * pressure threshold value. */ - ZB_ZCL_METERING_GAS_LEAK_DETECT = 1 << 5, /**< @e LeakDetect bit is set to true when a leak has been detected. */ - ZB_ZCL_METERING_GAS_SERVICE_DISCONNECT = 1 << 6, /**< @e ServiceDisconnect bit is set to true when the service has been disconnected to this premises. - * Ex. The valve is in the closed position preventing delivery of gas. */ - ZB_ZCL_METERING_GAS_REVERSE_FLOW = 1 << 7 /**< @e ReverseFlow bit is set to true if flow detected in the opposite direction to normal (from - * consumer to supplier). */ -}; - - -/** @brief Bit mapping of the @e Status attribute (Water) - * @see @ref ZB_ZCL_ATTR_METERING_STATUS_ID - * @see SE 1.4 spec, subclause 3.2.2.3.1, table D.18. - */ -enum zb_zcl_metering_status_water_e -{ - ZB_ZCL_METERING_WATER_CHECK_METER = 1 << 0, /**< @e CheckMeter bit is Set to true when a non fatal problem has been detected on the meter such as - * a measurement error, memory error, or self check error. */ - ZB_ZCL_METERING_WATER_LOW_BATTERY = 1 << 1, /**< @e LowBattery bit is set to true when the battery needs maintenance. */ - ZB_ZCL_METERING_WATER_TAMPER_DETECT = 1 << 2, /**< @e TamperDetect bit set to true if a tamper event has been detected. */ - ZB_ZCL_METERING_WATER_PIPE_EMTPY = 1 << 3, /**< @e PipeEmpty bit is set to true when the service pipe at the meter is empty and there is no flow - * in either direction. */ - ZB_ZCL_METERING_WATER_LOW_PRESSURE = 1 << 4, /**< @e LowPressure bit is Set to true when the pressure at the meter is below the meter's low - * pressure threshold value. */ - ZB_ZCL_METERING_WATER_LEAK_DETECT = 1 << 5, /**< @e LeakDetect bit is set to true when a leak has been detected. */ - ZB_ZCL_METERING_WATER_SERVICE_DISCONNECT = 1 << 6, /**< @e ServiceDisconnect bit is set to true when the service has been disconnected to this premises. - * Ex. The valve is in the closed position preventing delivery of water. */ - ZB_ZCL_METERING_WATER_REVERSE_FLOW = 1 << 7 /**< @e ReverseFlow bit is Set to true if flow detected in the opposite direction to normal (from - * consumer to supplier). */ -}; - - -/** @brief Bit mapping of the @e Status attribute (Heat and Cooling) - * @see @ref ZB_ZCL_ATTR_METERING_STATUS_ID - * @see SE 1.4 spec, subclause 3.2.2.3.1, table D.19. - */ -enum zb_zcl_metering_status_heat_cooling_e -{ - ZB_ZCL_METERING_HCOOL_CHECK_METER = 1 << 0, /**< @e CheckMeter bit is Set to true when a non fatal problem has been detected on the meter such - * as a measurement error, memory error, or self check error. */ - ZB_ZCL_METERING_HCOOL_LOW_BATTERY = 1 << 1, /**< @e LowBattery bit is set to true when the battery needs maintenance. */ - ZB_ZCL_METERING_HCOOL_TAMPER_DETECT = 1 << 2, /**< @e TamperDetect bit is set to true if a tamper event has been detected. */ - ZB_ZCL_METERING_HCOOL_TEMPERATURE_SENSOR = 1 << 3, /**< @e TemperatureSensor bit is Set to true when an error is detected on a temperature sensor at - * this premises. */ - ZB_ZCL_METERING_HCOOL_BURST_DETECT = 1 << 4, /**< @e BurstDetect bit is set to true when a burst is detected on pipes at this premises. */ - ZB_ZCL_METERING_HCOOL_LEAK_DETECT = 1 << 5, /**< @e LeakDetect bit is set to true when a leak has been detected. */ - ZB_ZCL_METERING_HCOOL_SERVICE_DISCONNECT = 1 << 6, /**< @e ServiceDisconnect bit is Set to true when the service has been disconnected to this premises. - * Ex. The valve is in the closed position preventing delivery of heat or cooling. */ - ZB_ZCL_METERING_HCOOL_FLOW_SENSOR = 1 << 7 /**< @e FlowSensor bit is set to true when an error is detected on a flow sensor at this premises. */ -}; - - -/** @brief Bit mapping of the @e ExtendedStatus attribute (General Flags) - * @see @ref ZB_ZCL_ATTR_METERING_EXTENDED_STATUS_ID - * @see SE 1.4 spec, subclause D.3.2.2.3.5, table D.20 - */ -enum zb_zcl_metering_extstatus_general_e -{ - ZB_ZCL_METERING_METER_COVER_REMOVED = 1 << 0, /**< @e MeterCoverRemoved bit is set to true when the device detects the meter - * cover being removed. */ - ZB_ZCL_METERING_STRONG_MAGNETIC_FIELD_DETECTED = 1 << 1, /**< @e StrongMagneticFieldDetected bit is set to true when the device detects - * presence of a strong magnetic field */ - ZB_ZCL_METERING_BATTERY_FAILURE = 1 << 2, /**< @e BatteryFailure bit is set to true when the device detects that its battery - * has failed. */ - ZB_ZCL_METERING_PROGRAM_MEMORY_ERROR = 1 << 3, /**< @e ProgramMemoryError bit is set to true when the device detects an error - * within its program (non-volatile) memory. */ - ZB_ZCL_METERING_RAM_ERROR = 1 << 4, /**< @e RAMError bit is set to true when the device detects an instance of a - * Random Access Memory error within the device memory. */ - ZB_ZCL_METERING_NV_MEMORY_ERROR = 1 << 5, /**< @e NVMemoryError bit is set to true when the device detects an instance of a - * Non Volatile memory error within the device memory - this is a fatal meter - * error that will require the meter replacement */ - ZB_ZCL_METERING_MEASUREMENT_SYSTEM_ERROR = 1 << 6, /**< @e MeasurementSystemError bit is set to true when the device detects an error - * within its measurement system. */ - ZB_ZCL_METERING_WATCHDOG_ERROR = 1 << 7, /**< @e WatchdogError bit is set to true when the device has detected an instance - * of a watchdog reset event (following a catastrophic fault within the device). */ - ZB_ZCL_METERING_SUPPLY_DISCONNECT_FAILURE = 1 << 8, /**< @e SupplyDisconnectFailure bit is set to true when the device has detected - * that the valve has not closed as expected (for gas) or the contactor has not - * opened as expected (for electricity). */ - ZB_ZCL_METERING_SUPPLY_CONNECT_FAILURE = 1 << 9, /**< @e SupplyConnectFailure bit is set to true when the device has detected that - * the valve has not opened as expected (for gas) or the contactor has not closed - * as expected (for electricity). */ - ZB_ZCL_METERING_MEASUREMENT_SW_CHANGED = 1 << 10, /**< @e MeasurementSWChanged/Tampered bit is set to true when the device detects that - * its measurement software has changed. */ - ZB_ZCL_METERING_CLOCK_INVALID = 1 << 11, /**< @e ClockInvalid bit is set to true when the device detects that its internal clock - * is invalid. */ - ZB_ZCL_METERING_TEMPERATURE_EXCEEDED = 1 << 12, /**< @e TemperatureExceeded bit is set to true when the metering device's temperature - * exceeds a predefined limit. There are various reasons for temperature rise in - * metering devices. */ - ZB_ZCL_METERING_MOISTURE_DETECTED = 1 << 13 /**< @e MoistureDetected bit is set to true when a sensor has detected the presence of - * moisture e.g. moisture in a gas line which can cause a drop in gas pressure, or - * moisture detected in the sealed component area within a water meter. */ - /* bits 14-23 reserved */ -}; - - -/** @brief Bit mapping of the @e ExtendedStatus attribute (Electricity Meter specific Flags) - * @see @ref ZB_ZCL_ATTR_METERING_EXTENDED_STATUS_ID - * @see SE 1.4 spec, subclause D.3.2.2.3.5, table D.21 - */ -enum zb_zcl_metering_extstatus_electricity_e -{ - ZB_ZCL_METERING_ELECTRICITY_TERMINAL_COVER_REMOVED = 1L << 24, /**< @e TerminalCoverRemoved bit is set to true when the device detects that its - * terminal cover has been removed. */ - ZB_ZCL_METERING_ELECTRICITY_INCORRECT_POLARITY = 1L << 25, /**< @e IncorrectPolarity bit is set to true when the electricity meter detects - * incorrect polarity on the electricity supply. */ - ZB_ZCL_METERING_ELECTRICITY_CURRENT_WITH_NO_VOLTAGE = 1L << 26, /**< @e CurrentWithNoVoltage bit is set to true when the meter has been tampered - * with, to disconnect the measurement function from the supply. Electricity is - * still flowing but not being recorded. */ - ZB_ZCL_METERING_ELECTRICITY_LIMIT_THRESHOLD_EXCEEDED = 1L << 27, /**< @e LimitThresholdExceeded bit is set to true when the electricity meter detects - * that the load has exceeded the load limit threshold. */ - ZB_ZCL_METERING_ELECTRICITY_UNDER_VOLTAGE = 1L << 28, /**< @e UnderVoltage bit is set to true when the electricity meter indicates that - * the voltage measurement over the voltage measurement period is lower than the - * voltage threshold. */ - ZB_ZCL_METERING_ELECTRICITY_OVER_VOLTAGE = 1L << 29, /**< @e OverVoltage bit is set to true when the electricity meter indicates that the - * voltage measurement over the voltage measurement period is higher than the - * voltage threshold. */ - ZB_ZCL_METERING_ELECTRICITY_BIDIRECTION_OPERATION = 1L << 30, /** In (Maximum Current) - short circuit */ - ZB_ZCL_METERING_REASON_OFF_DUE_TO_OVERHEATING_OTHER = 0x06, /**< OFF due to overheating, - I < In (Maximum Current) - other */ -}; - -/** @brief Default value for Metering cluster revision global attribute */ -#define ZB_ZCL_METERING_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/*! @brief If set, suppress leading zeros */ -#define ZB_ZCL_METERING_FORMATTING_SUPPRESS_ZERO(b) (((b) & 0x80)==0x80) - -/*! @brief Number of Digits to the right of the Decimal Point */ -#define ZB_ZCL_METERING_FORMATTING_LEFT(b) (((b)>>3) & 0x07) - -/*! @brief Number of Digits to the left of the Decimal Point */ -#define ZB_ZCL_METERING_FORMATTING_RIGHT(b) ((b) & 0x07) - -/*! @brief Set summation formatting */ -#define ZB_ZCL_METERING_FORMATTING_SET(suppress_zero, left, right) \ - ( ((suppress_zero) ? 0x80 : 0) | (((left) & 7)<<3) | ((right) & 7) ) - -/** @brief Default value for Status attribute */ -#define ZB_ZCL_METERING_STATUS_DEFAULT_VALUE 0x00 - -/** @brief Default value for Status attribute */ -#define ZB_ZCL_METERING_UNIT_OF_MEASURE_DEFAULT_VALUE 0x00 - -/** @brief Default value for Instantaneous Demand attribute */ -#define ZB_ZCL_METERING_INSTANTANEOUS_DEMAND_DEFAULT_VALUE ZB_INIT_UINT24(0x00, 0x0000) - - /** @brief Default value for DailyFreezeTime attribute */ -#define ZB_ZCL_METERING_DAILY_FREEZE_TIME_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for PowerFactor attribute */ -#define ZB_ZCL_METERING_POWER_FACTOR_DEFAULT_VALUE ((zb_int8_t)0x00) - -/** @brief Default value for DefaultUpdatePeriod attribute */ -#define ZB_ZCL_METERING_DEFAULT_UPDATE_PERIOD_DEFAULT_VALUE ((zb_uint8_t)0x1E) - -/** @brief Default value for FastPollUpdatePeriod attribute */ -#define ZB_ZCL_METERING_FAST_POLL_UPDATE_PERIOD_DEFAULT_VALUE ((zb_uint8_t)0x05) - -/** @brief Default value for PresetReadingTime attribute */ -#define ZB_ZCL_METERING_PRESET_READING_TIME_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for MaxNumberOfPeriodsDelivered attribute */ -#define ZB_ZCL_METERING_MAX_NUMBER_OF_PERIODS_DELIVERED_DEFAULT_VALUE ((zb_uint8_t)0x18) - -/** @brief Default value for GenericAlarmMask attribute */ -#define ZB_ZCL_METERING_GENERIC_ALARM_MASK_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for ElectricityAlarmMask attribute */ -#define ZB_ZCL_METERING_ELECTRICITY_ALARM_MASK_DEFAULT_VALUE ((zb_uint32_t)0xFFFFFFFF) - -/** @brief Default value for GenericFlowPressureAlarmMask attribute */ -#define ZB_ZCL_METERING_GENERIC_FLOW_PRESSURE_ALARM_MASK_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for WaterSpecificAlarmMask attribute */ -#define ZB_ZCL_METERING_WATER_SPECIFIC_ALARM_MASK_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for HeatAndCoolingSpecificAlarmMask attribute */ -#define ZB_ZCL_METERING_HEAT_AND_COOLING_SPECIFIC_ALARM_MASK_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for GasSpecificAlarmMask attribute */ -#define ZB_ZCL_METERING_GAS_SPECIFIC_ALARM_MASK_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for FastPollUpdatePeriod attribute */ -#define ZB_ZCL_METERING_LINKY_MODE_ON_OPERATION_DEFAULT_VALUE ((zb_uint8_t)0x00) -/** @} */ /* ZB_ZCL_METERING_SRV_ATTRS */ - - -/** @defgroup ZB_ZCL_METERING_CMDS Metering cluster commands - * @{ - */ - - -/** Metering cluster client command identifiers. - * @see SE spec, subclause D.3.3.3.1 - */ -typedef enum zb_zcl_metering_cli_cmd_e -{ - - /* (O) */ - ZB_ZCL_METERING_CLI_CMD_GET_PROFILE = 0x00, /**< @e GetProfile command */ - /* (O) */ - ZB_ZCL_METERING_CLI_CMD_REQUEST_MIRROR_RESPONSE, /**< The @e RequestMirrorResponse - * command allows the ESI to inform a - * sleepy Metering Device it has the - * ability to store and mirror its data. - */ - /* (O) */ - ZB_ZCL_METERING_CLI_CMD_MIRROR_REMOVED, /**= sizeof(zb_zcl_metering_get_profile_payload_t) ? ZB_TRUE : ZB_FALSE)) - -/** @ref ZB_ZCL_METERING_SRV_CMD_GET_PROFILE_RESPONSE "GetProfileResponse" command payload - * @see SE spec, subclause D.3.2.3.1.1.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_get_profile_response_payload_s -{ - /** It is 32-bit value (in UTC) representing the end time of the most - * chronologically recent interval being requested. - */ - zb_uint32_t end_time; - /** Status - * @see zb_zcl_metering_status_field_e - */ - zb_uint8_t status; - /** Represents the interval or time frame used to capture metered Energy, Gas, - * and Water consumption for profiling purposes. - * @see zb_zcl_metering_profile_interval_period_e - */ - zb_uint8_t profile_interval_period; - /** Represents the number of intervals the device is returning. - */ - zb_uint8_t number_of_periods_delivered; - /** Series of interval data captured using the period specified by the - * @e ProfileIntervalPeriod field. The content of the interval data depends of - * the type of information requested using the @e Channel field in the - * @ref ZB_ZCL_METERING_CLI_CMD_GET_PROFILE "GetProfileCommand", and will - * represent the change in that information since the previous interval. - */ - zb_uint24_t *intervals; -} ZB_PACKED_STRUCT zb_zcl_metering_get_profile_response_payload_t; - - -/** @ref ZB_ZCL_METERING_CLI_CMD_REQUEST_FAST_POLL_MODE "RequestFastPollMode" command payload - * @see SE spec, subclause D.3.3.3.1.4 - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_request_fast_poll_mode_payload_s -{ - /** Desired FastPollUpdatePeriod attribute. - */ - zb_uint8_t fast_poll_update_period; /* (M) */ - /** Desired duration for the server to remain in fast poll mode not to exceed 15 minutes - */ - zb_uint8_t duration_in_minutes; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_request_fast_poll_mode_payload_t; - - -/** @ref ZB_ZCL_METERING_SRV_CMD_REQUEST_FAST_POLL_MODE_RESPONSE "RequestFastPollModeResponse" command payload - * @see SE spec, subclause D.3.3.3.1.4 - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_request_fast_poll_mode_response_payload_s -{ - /** The period at which metering data shall be updated. This may be different than the requested fast poll. - */ - zb_uint8_t applied_update_period_in_seconds; /* (M) */ - /** UTC time that indicates when the metering server will terminate fast poll mode and resume - * updating at the rate specified by @e DefaultUpdatePeriod. - */ - zb_uint32_t fast_poll_mode_end_time; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_request_fast_poll_mode_response_payload_t; - - -/** @ref ZB_ZCL_METERING_SRV_CMD_GET_SAMPLED_DATA_RESPONSE "GetSampledDataResponse" command payload - * @see SE spec, subclause D.3.2.3.1.8 - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_get_sampled_data_response_payload_s -{ - /** Unique identifier allocated to this Sampling session. This field allows devices to match - * response data with the appropriate request. - */ - zb_uint16_t sample_id; /* (M) */ - /** A UTC Time field to denote the time of the first sample returned in this response. */ - zb_uint32_t sample_start_time; /* (M) */ - /** An 8-bit enumeration that identifies the type of data being sampled. */ - zb_uint8_t sample_type; /* (M) */ - /** An unsigned 16-bit field representing the interval or time in seconds between samples. */ - zb_uint16_t sample_request_interval; /* (M) */ - /** Represents the number of samples being requested, This value cannot exceed the size stipulated - * in the @e MaxNumberOfSamples field in the @e StartSampling command. - */ - zb_uint16_t number_of_samples; /* (M) */ - /** Series of data samples captured using the interval specified by the @e SampleRequestInterval - * field in the @e StartSampling command. - */ - zb_uint24_t *samples; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_get_sampled_data_response_payload_t; - - -/** Sample Type Enumerations - * @see SE spec, Table D-54 - */ -enum zb_zcl_metering_sample_type_e -{ - ZB_ZCL_METERING_SAMPLE_TYPE_CONSUMPTION_DELIVERED = 0, /**< Consumption Delivered */ - ZB_ZCL_METERING_SAMPLE_TYPE_CONSUMPTION_RECEIVED = 1, /**< Consumption Received */ - ZB_ZCL_METERING_SAMPLE_TYPE_REACTIVE_CONSUMPTION_DELIVERED = 2, /**< Reactive Consumption Delivered */ - ZB_ZCL_METERING_SAMPLE_TYPE_REACTIVE_CONSUMPTION_RECEIVED = 3, /**< Reactive Consumption Received */ - ZB_ZCL_METERING_SAMPLE_TYPE_INSTANTANEOUS_DEMAND = 4 /**< InstantaneousDemand*/ -}; - - -/** @ref ZB_ZCL_METERING_CLI_CMD_GET_SAMPLED_DATA "GetSampledData" command payload - * @see SE spec, subclause D.3.2.3.1.8 - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_get_sampled_data_payload_s -{ - /** Unique identifier allocated to this Sampling session. This field allows devices to match - * response data with the appropriate request. - */ - zb_uint16_t sample_id; /* (M) */ - /** A UTC Timestamp indicating the earliest time of a sample to be returned. */ - zb_uint32_t earliest_sample_time; /* (M) */ - /** An 8-bit enumeration that identifies the type of data being sampled. */ - zb_uint8_t sample_type; /* (M) */ - /** Represents the number of samples being requested, This value cannot exceed the size stipulated - * in the @e MaxNumberOfSamples field in the @e StartSampling command. - */ - zb_uint16_t number_of_samples; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_get_sampled_data_payload_t; - - -/** @ref ZB_ZCL_METERING_CLI_CMD_GET_SNAPSHOT "GetSnapshot" command payload - * @see SE spec, subclause D.3.3.3.1.7 - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_get_snapshot_payload_s -{ - /** A UTC Timestamp indicating the earliest time of a snapshot to be returned by a corresponding - * Publish Snapshot command. - */ - zb_uint32_t earliest_start_time; /* (M) */ - /** A UTC Timestamp indicating the latest time of a snapshot to be returned by a corresponding - * Publish Snapshot command. - */ - zb_uint32_t latest_end_time; /* (M) */ - /** Where multiple snapshots satisfy the selection criteria specified by the other fields in this - * command, this field identifies the individual snapshot to be returned. - */ - zb_uint8_t snapshot_offset; /* (M) */ - /** This field is used to select only snapshots that were taken due to a specific cause. */ - zb_uint32_t snapshot_cause; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_get_snapshot_payload_t; - - -/** Snapshot Cause BitMap - * @see SE spec, Table D-52 - */ -enum zb_zcl_metering_snapshot_cause_e -{ - ZB_ZCL_METERING_CAUSE_GENERAL = 1 << 0, /**< General */ - ZB_ZCL_METERING_CAUSE_END_OF_BILLING_PERIOD = 1 << 1, /**< End of Billing Period */ - ZB_ZCL_METERING_CAUSE_END_OF_BLOCK_PERIOD = 1 << 2, /**< End of Block Period */ - ZB_ZCL_METERING_CAUSE_CHANGE_OF_TARIFF_INFORMATION = 1 << 3, /**< Change of Tariff Information */ - ZB_ZCL_METERING_CAUSE_CHANGE_OF_PRICE_MATRIX = 1 << 4, /**< Change of Price Matrix */ - ZB_ZCL_METERING_CAUSE_CHANGE_OF_BLOCK_THRESHOLDS = 1 << 5, /**< Change of Block Thresholds */ - ZB_ZCL_METERING_CAUSE_CHANGE_OF_CV = 1 << 6, /**< Change of CV */ - ZB_ZCL_METERING_CAUSE_CHANGE_OF_CF = 1 << 7, /**< Change of CF */ - ZB_ZCL_METERING_CAUSE_CHANGE_OF_CALENDAR = 1 << 8, /**< Change of Calendar */ - ZB_ZCL_METERING_CAUSE_CRITICAL_PEAK_PRICING = 1 << 9, /**< Critical Peak Pricing */ - ZB_ZCL_METERING_CAUSE_MANUALLY_TRIGGERED_FROM_CLIENT = 1 << 10, /**< Manually Triggered from Client */ - ZB_ZCL_METERING_CAUSE_END_OF_RESOLVE_PERIOD = 1 << 11, /**< End of Resolve Period */ - ZB_ZCL_METERING_CAUSE_CHANGE_OF_TENANCY = 1 << 12, /**< Change of Tenancy */ - ZB_ZCL_METERING_CAUSE_CHANGE_OF_SUPPLIER = 1 << 13, /**< Change of Supplier */ - ZB_ZCL_METERING_CAUSE_CHANGE_OF_METER_MODE = 1 << 14, /**< Change of (Meter) Mode */ - ZB_ZCL_METERING_CAUSE_DEBT_PAYMENT = 1 << 15, /**< Debt Payment */ - ZB_ZCL_METERING_CAUSE_SCHEDULED_SNAPSHOT = 1 << 16, /**< Scheduled Snapshot */ - ZB_ZCL_METERING_CAUSE_OTA_FIRMWARE_DOWNLOAD = 1 << 17, /**< OTA Firmware Download */ - ZB_ZCL_METERING_CAUSE_SELECT_ALL_SNAPSHOTS = 0xFFFFFFFF /**< Select All Snapshots */ -}; - - -/** Snapshot Payload Type - * @see SE spec, Table D-53 - */ -enum zb_zcl_metering_snapshot_payload_type_e -{ - ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS = 0, /**< TOU Information Set DeliveredRegisters */ - ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS = 1, /**< TOU Information Set Received Registers */ - ZB_ZCL_METERING_BLOCK_TIER_DELIVERED = 2, /**< Block Tier Information Set Delivered */ - ZB_ZCL_METERING_BLOCK_TIER_RECEIVED = 3, /**< Block Tier Information Set Received */ - ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING = 4, /**< TOU Information Set Delivered (No Billing) */ - ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING = 5, /**< TOU Information Set Received (No Billing) */ - ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING = 6, /**< Block Tier Information Set Delivered (No Billing) */ - ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING = 7, /**< Block Tier Information Set Received (No Billing) */ - ZB_ZCL_METERING_DATA_UNAVAILABLE = 128, /**< Data Unavailable */ -}; - - -/** SnapshotPayloadType 0 = TOU Information Delivered Set - * @see @ref ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_tou_delivered_payload_s -{ - /** An unsigned 48-bit integer that returns the value of the CurrentSummationDelivered - * attribute at the stated snapshot timestamp. - */ - zb_uint48_t current_summation_delivered; /* (M) */ - /** An unsigned 32-bit integer that provides a value for the costs in the current billing period. */ - zb_uint32_t bill_to_date_delivered; /* (M) */ - /** A UTC timestamp that indicates when the value of the associated BillToDateDelivered - * parameter was last updated. - */ - zb_uint32_t bill_to_date_time_stamp_delivered; /* (M) */ - /** An unsigned 32-bit integer that provides a value indicating what the estimated state of the - * account will be at the end of the billing period based on past consumption. - */ - zb_uint32_t projected_bill_delivered; /* (M) */ - /** A UTC timestamp that indicates when the associated ProjectedBillDelivered parameter was - * last updated. - */ - zb_uint32_t projected_bill_time_stamp_delivered; /* (M) */ - /** An 8-bit BitMap used to determine where the decimal point is located in the - * BillToDateDelivered and ProjectedBillDelivered fields. - */ - zb_uint8_t bill_delivered_trailing_digit; /* (M) */ - /** An 8-bit integer representing the number of tiers in use at the time the snapshot was taken. */ - zb_uint8_t number_of_tiers_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of CurrentTierNSummationDelivered attributes - * from the TOU Information Set. The Metering server shall send only the number of tiers in use, - * as stated in this command. - */ - zb_uint48_t *tier_summation; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_tou_delivered_payload_t; - - -/** SnapshotPayloadType 1 = TOU Information Received Set - * @see @ref ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_tou_received_payload_s -{ - /** An unsigned 48-bit integer that returns the value of the CurrentSummationReceived - * attribute at the stated snapshot timestamp. - */ - zb_uint48_t current_summation_received; /* (M) */ - /** An unsigned 32-bit integer that provides a value for the costs in the current billing period. */ - zb_uint32_t bill_to_date_received; /* (M) */ - /** A UTC timestamp that indicates when the value of the associated BillToDateReceived parameter - * was last updated. - */ - zb_uint32_t bill_to_date_time_stamp_received; /* (M) */ - /** An unsigned 32-bit integer that provides a value indicating what the estimated state of the - * account will be at the end of the billing period based on past generation. - */ - zb_uint32_t projected_bill_received; /* (M) */ - /** A UTC timestamp that indicates when the associated ProjectedBillReceived parameter was last - * updated. - */ - zb_uint32_t projected_bill_time_stamp_received; /* (M) */ - /** An 8-bit BitMap used to determine where the decimal point is located in the - * BillToDateReceived and ProjectedBillReceived fields. - */ - zb_uint8_t bill_received_trailing_digit; /* (M) */ - /** An 8-bit integer representing the number of tiers in use at the time the snapshot - * was taken. - */ - zb_uint8_t number_of_tiers_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of CurrentTierNSummationReceived attributes - * from the TOU Information Set. The Metering server shall send only the number of tiers in use, - * as stated in this command. - */ - zb_uint48_t *tier_summation; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_tou_received_payload_t; - - -/** SnapshotPayloadType 2 = Block Information Delivered Set - * @see @ref ZB_ZCL_METERING_BLOCK_TIER_DELIVERED - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_block_delivered_payload_s -{ - /** An unsigned 48-bit integer that returns the value of the CurrentSummationDelivered attribute - * at the stated snapshot timestamp. - */ - zb_uint48_t current_summation_delivered; /* (M) */ - /** An unsigned 32-bit integer that provides a value for the costs in the current billing period. */ - zb_uint32_t bill_to_date_delivered; /* (M) */ - /** A UTC timestamp that indicates when the value of the associated BillToDateDelivered - * parameter was last updated. - */ - zb_uint32_t bill_to_date_time_stamp_delivered; /* (M) */ - /** An unsigned 32-bit integer that provides a value indicating what the estimated state of - * the account will be at the end of the billing period based on past consumption. - */ - zb_uint32_t projected_bill_delivered; /* (M) */ - /** A UTC timestamp that indicates when the associated ProjectedBillDelivered parameter was - * last updated. - */ - zb_uint32_t projected_bill_time_stamp_delivered; /* (M) */ - /** An 8-bit BitMap used to determine where the decimal point is located in the - * BillToDateDelivered and ProjectedBillDelivered fields. - */ - zb_uint8_t bill_delivered_trailing_digit; /* (M) */ - /** An 8-bit integer representing the number of tiers in use at the time the snapshot was taken. */ - zb_uint8_t number_of_tiers_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of CurrentTierNSummationDelivered - * attributes from the TOU Information Set. - */ - zb_uint48_t *tier_summation; /* (M) */ - /** An 8-bit BitMap representing the number of tiers and block thresholds in use at the time the - * snapshot was taken. - */ - zb_uint8_t number_of_tiers_and_block_thresholds_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of the Block Information Attribute Set - * (Delivered). The metering server shall send only the number of Tiers and Blocks in use as - * stated in this command. - */ - zb_uint48_t *tier_block_summation; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_block_delivered_payload_t; - - -/** SnapshotPayloadType 3 = Block Information Received Set - * @see @ref ZB_ZCL_METERING_BLOCK_TIER_RECEIVED - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_block_received_payload_s -{ - /** An unsigned 48-bit integer that returns the value of the CurrentSummationReceived attribute - * at the stated snapshot timestamp. - */ - zb_uint48_t current_summation_received; /* (M) */ - /** An unsigned 32-bit integer that provides a value for the costs in the current billing period. */ - zb_uint32_t bill_to_date_received; /* (M) */ - /** A UTC timestamp that indicates when the value of the associated BillToDateReceived parameter - * was last updated. - */ - zb_uint32_t bill_to_date_time_stamp_received; /* (M) */ - /** An unsigned 32-bit integer that provides a value indicating what the estimated state of the - * account will be at the end of the billing period based on past generation. - */ - zb_uint32_t projected_bill_received; /* (M) */ - /** A UTC timestamp that indicates when the associated ProjectedBillReceived parameter was last - * updated. - */ - zb_uint32_t projected_bill_time_stamp_received; /* (M) */ - /** An 8-bit BitMap used to determine where the decimal point is located in the - * BillToDateReceived and ProjectedBillReceived fields - */ - zb_uint8_t bill_received_trailing_digit; /* (M) */ - /** An 8-bit integer representing the number of tiers in use at the time the snapshot was taken. */ - zb_uint8_t number_of_tiers_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of CurrentTierNSummationReceived attributes - * from the TOU Information Set. - */ - zb_uint48_t *tier_summation; /* (M) */ - /** An 8-bit BitMap representing the number of tiers and block thresholds in use at the time the - * snapshot was taken. - */ - zb_uint8_t number_of_tiers_and_block_thresholds_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of the Block Information Attribute Set - * (Received). - */ - zb_uint48_t *tier_block_summation; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_block_received_payload_t; - - -/** SnapshotPayloadType 4 = TOU Information Set Delivered (No Billing) - * @see @ref ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_tou_delivered_no_billing_payload_s -{ - /** An unsigned 48-bit integer that returns the value of the CurrentSummationDelivered attribute - * at the stated snapshot timestamp. - */ - zb_uint48_t current_summation_delivered; /* (M) */ - /** An 8-bit integer representing the number of tiers in use at the time the snapshot was taken. */ - zb_uint8_t number_of_tiers_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of CurrentTierNSummationDelivered attributes - * from the TOU Information Set. - */ - zb_uint48_t *tier_summation; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_tou_delivered_no_billing_payload_t; - - -/** SnapshotPayloadType 5 = TOU Information Set Received (No Billing) - * @see @ref ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_tou_received_no_billing_payload_s -{ - /** An unsigned 48-bit integer that returns the value of the CurrentSummationReceived attribute - * at the stated snapshot timestamp. - */ - zb_uint48_t current_summation_received; /* (M) */ - /** An 8-bit integer representing the number of tiers in use at the time the snapshot was taken. */ - zb_uint8_t number_of_tiers_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of CurrentTierNSummationReceived attributes - * from the TOU Information Set. - */ - zb_uint48_t *tier_summation; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_tou_received_no_billing_payload_t; - - -/** SnapshotPayloadType 6 = Block Tier Information Set Delivered (No Billing) - * @see @ref ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_block_tier_delivered_no_billing_payload_s -{ - /** An unsigned 48-bit integer that returns the value of the CurrentSummationDelivered attribute - * at the stated snapshot timestamp. - */ - zb_uint48_t current_summation_delivered; /* (M) */ - /** An 8-bit integer representing the number of tiers in use at the time the snapshot was taken. */ - zb_uint8_t number_of_tiers_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of CurrentTierNSummationDelivered attributes - * from the TOU Information Set. - */ - zb_uint48_t *tier_summation; /* (M) */ - /** An 8-bit BitMap representing the number of tiers and block thresholds in use at the time the - * snapshot was taken. - */ - zb_uint8_t number_of_tiers_and_block_thresholds_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of the Block Information Attribute Set - * (Delivered). The metering server shall send only the number of Tiers and Blocks in use as - * stated in this command. - */ - zb_uint48_t *tier_block_summation; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_block_tier_delivered_no_billing_payload_t; - - -/** SnapshotPayloadType 7 = Block Tier Information Set Received (No Billing) - * @see @ref ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_block_tier_received_no_billing_payload_s -{ - /** An unsigned 48-bit integer that returns the value of the CurrentSummationReceived attribute - * at the stated snapshot timestamp. - */ - zb_uint48_t current_summation_received; /* (M) */ - /** An 8-bit integer representing the number of tiers in use at the time the snapshot was taken.*/ - zb_uint8_t number_of_tiers_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of CurrentTierNSummationReceived attributes - * from the TOU Information Set. - */ - zb_uint48_t *tier_summation; /* (M) */ - /** An 8-bit BitMap representing the number of tiers and block thresholds in use at the time the - * snapshot was taken. - */ - zb_uint8_t number_of_tiers_and_block_thresholds_in_use; /* (M) */ - /** The Publish Snapshot command contains N elements of the Block Information Attribute Set - * (Received). - */ - zb_uint48_t *tier_block_summation; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_metering_block_tier_received_no_billing_payload_t; - - -/** The format of the Snapshot Sub-Payload differs depending on the SnapshotPayloadType - * @see SE spec, Table D-53 and D.3.2.3.1.7 - */ -typedef ZB_PACKED_PRE union zb_zcl_metering_snapshot_sub_payload_s -{ - /** @see @ref zb_zcl_metering_tou_delivered_payload_s - * @see @ref ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS */ - zb_zcl_metering_tou_delivered_payload_t tou_delivered; - /** @see @ref zb_zcl_metering_tou_received_payload_s - * @see @ref ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS */ - zb_zcl_metering_tou_received_payload_t tou_received; - /** @see @ref zb_zcl_metering_block_delivered_payload_s - * @see @ref ZB_ZCL_METERING_BLOCK_TIER_DELIVERED */ - zb_zcl_metering_block_delivered_payload_t block_delivered; - /** @see @ref zb_zcl_metering_block_received_payload_s - * @see @ref ZB_ZCL_METERING_BLOCK_TIER_RECEIVED */ - zb_zcl_metering_block_received_payload_t block_received; - /** @see @ref zb_zcl_metering_tou_delivered_no_billing_payload_s - * @see @ref ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING */ - zb_zcl_metering_tou_delivered_no_billing_payload_t tou_delivered_no_billing; - /** @see @ref zb_zcl_metering_tou_received_no_billing_payload_s - * @see @ref ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING */ - zb_zcl_metering_tou_received_no_billing_payload_t tou_received_no_billing; - /** @see @ref zb_zcl_metering_block_tier_delivered_no_billing_payload_s - * @see @ref ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING */ - zb_zcl_metering_block_tier_delivered_no_billing_payload_t block_tier_delivered_no_billing; - /** @see @ref zb_zcl_metering_block_tier_received_no_billing_payload_s - * @see @ref ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING */ - zb_zcl_metering_block_tier_received_no_billing_payload_t block_tier_received_no_billing; - -} ZB_PACKED_STRUCT zb_zcl_metering_snapshot_sub_payload_t; - - -/** @ref ZB_ZCL_METERING_SRV_CMD_PUBLISH_SNAPSHOT "PublishSnapshot" command payload - * @see SE spec, subclause D.3.2.3.1.7 - */ -typedef ZB_PACKED_PRE struct zb_zcl_metering_publish_snapshot_payload_s -{ - /** Unique identifier allocated by the device creating the snapshot. */ - zb_uint32_t snapshot_id; /* (M) */ - /** This is a 32-bit value (in UTC Time) representing the time at which the data snapshot was taken. */ - zb_uint32_t snapshot_time; /* (M) */ - /** An 8-bit Integer indicating the number of snapshots found, based on the search criteria - * defined in the associated GetSnapshot command. - */ - zb_uint8_t total_snapshots_found; /* (M) */ - /** The CommandIndex is used to count the payload fragments in the case where the entire payload - * (snapshot) does not fit into one message - */ - zb_uint8_t command_index; /* (M) */ - /** In the case where the entire payload (snapshot) does not fit into one message, the - * Total Number of Commands field indicates the total number of sub-commands that will be returned. - */ - zb_uint8_t total_number_of_commands; /* (M) */ - /** A 32-bit BitMap indicating the cause of the snapshot */ - zb_uint32_t snapshot_cause; /* (M) */ - /** The SnapshotPayloadType is an 8-bit enumerator defining the format of the Snapshot Sub-Payload - * in this message. - */ - zb_uint8_t snapshot_payload_type; /* (M) */ - - /** @see @ref zb_zcl_metering_snapshot_sub_payload_s */ - zb_zcl_metering_snapshot_sub_payload_t snapshot_sub_payload; -} ZB_PACKED_STRUCT zb_zcl_metering_publish_snapshot_payload_t; - - -/** Function for send @ref ZB_ZCL_METERING_CLI_CMD_GET_SNAPSHOT "GetSnapshot" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_METERING_GET_SNAPSHOT_CB_ID - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (ref to @ref zb_zcl_metering_get_snapshot_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - */ -void zb_zcl_metering_send_cmd_get_snapshot(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_zcl_metering_get_snapshot_payload_t *payload, - zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_METERING_CLI_CMD_GET_SAMPLED_DATA "GetSampledData" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_METERING_GET_SAMPLED_DATA_CB_ID - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (ref to @ref zb_zcl_metering_get_sampled_data_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - */ -void zb_zcl_metering_send_cmd_get_sampled_data(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_zcl_metering_get_sampled_data_payload_t *payload, - zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_METERING_CLI_CMD_REQUEST_FAST_POLL_MODE "RequestFastPollMode" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_METERING_REQUEST_FAST_POLL_MODE_CB_ID - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (ref to @ref zb_zcl_metering_request_fast_poll_mode_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - */ -void zb_zcl_metering_send_cmd_request_fast_poll_mode(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_zcl_metering_request_fast_poll_mode_payload_t *payload, - zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_METERING_CLI_CMD_GET_PROFILE "GetProfile" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_METERING_GET_PROFILE_CB_ID - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param payload - Packet payload (ref to @ref zb_zcl_metering_get_profile_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - */ -void zb_zcl_metering_send_cmd_get_profile(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_zcl_metering_get_profile_payload_t *payload, - zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_METERING_SRV_CMD_PUBLISH_SNAPSHOT "PublishSnapshot" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_METERING_PUBLISH_SNAPSHOT_CB_ID - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param pl - Packet payload (ref to @ref zb_zcl_metering_publish_snapshot_payload_t). - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - */ -void zb_zcl_metering_send_cmd_publish_snapshot(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_metering_publish_snapshot_payload_t *pl, - zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_METERING_SRV_CMD_REQUEST_FAST_POLL_MODE_RESPONSE "RequestFastPollMode" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_METERING_REQUEST_FAST_POLL_MODE_CB_ID - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param pl - Packet payload (ref to @ref zb_zcl_metering_request_fast_poll_mode_response_payload_t). - * @param pl_size - size in bytes of input payload. Stack can calculate actual payload size. - * Set pl_size to 0 for it. - * @param tsn - transaction sequence number of response - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - */ -void zb_zcl_metering_send_cmd_request_fast_poll_mode_response(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_metering_request_fast_poll_mode_response_payload_t *pl, - zb_uint8_t pl_size, zb_uint8_t tsn, zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_METERING_SRV_CMD_GET_PROFILE_RESPONSE "GetProfileResponse" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_METERING_GET_PROFILE_RESPONSE_CB_ID - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param pl - Packet payload (ref to @ref zb_zcl_metering_get_profile_response_payload_t). - * @param pl_size - size in bytes of input payload. Stack can calculate actual payload size. - * Set pl_size to 0 for it. - * @param tsn - transaction sequence number of response - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - */ -void zb_zcl_metering_send_cmd_get_profile_response(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, const zb_zcl_metering_get_profile_response_payload_t *pl, - zb_uint8_t pl_size, zb_uint8_t tsn, zb_callback_t cb); - - -/** Function for send @ref ZB_ZCL_METERING_SRV_CMD_GET_PROFILE_RESPONSE "GetSampledDataResponse" command. - * On receiver's side callback ZCL device callback @ref ZB_ZCL_REGISTER_DEVICE_CB will be called with - * @ref ZB_ZCL_METERING_GET_SAMPLED_DATA_RESPONSE_CB_ID - * @param param - Reference to buffer. - * @param dst_addr - Address of the device to send command to. - * @param dst_addr_mode - Address mode for dst_addr. - * @param dst_ep - Destination endpoint. - * @param src_ep - Current endpoint. - * @param pl - Packet payload (ref to @ref zb_zcl_metering_get_sampled_data_response_payload_t). - * @param pl_size - size in bytes of input payload. Stack can calculate actual payload size. - * Set pl_size to 0 for it. - * @param tsn - transaction sequence number of response - * @param cb - Callback which should be called when the ZCL stack receives APS ack. - */ -void zb_zcl_metering_send_cmd_get_sampled_data_response(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_metering_get_sampled_data_response_payload_t *pl, - zb_uint8_t pl_size, zb_uint8_t tsn, zb_callback_t cb); - -/** Macro for call @ref zb_zcl_metering_send_cmd_get_snapshot function - */ -#define ZB_ZCL_METERING_SEND_CMD_GET_SNAPSHOT(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) \ - zb_zcl_metering_send_cmd_get_snapshot(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) - - -/** Macro for call @ref zb_zcl_metering_send_cmd_get_sampled_data function - */ -#define ZB_ZCL_METERING_SEND_CMD_GET_SAMPLED_DATA(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) \ - zb_zcl_metering_send_cmd_get_sampled_data(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) - - - -/** Macro for call @ref zb_zcl_metering_send_cmd_request_fast_poll_mode function - */ -#define ZB_ZCL_METERING_SEND_CMD_REQUEST_FAST_POLL_MODE(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) \ - zb_zcl_metering_send_cmd_request_fast_poll_mode(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) - - -/** Macro for call @ref zb_zcl_metering_send_cmd_get_profile function - */ -#define ZB_ZCL_METERING_SEND_CMD_GET_PROFILE(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) \ - zb_zcl_metering_send_cmd_get_profile(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) - - -/** Macro for call @ref zb_zcl_metering_send_cmd_publish_snapshot function - */ -#define ZB_ZCL_METERING_SEND_CMD_PUBLISH_SNAPSHOT(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) \ - zb_zcl_metering_send_cmd_publish_snapshot(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) - - -/** Macro for call @ref zb_zcl_metering_send_cmd_request_fast_poll_mode_response function - */ -#define ZB_ZCL_METERING_SEND_CMD_REQUEST_FAST_POLL_MODE_RESPONSE(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) \ - zb_zcl_metering_send_cmd_request_fast_poll_mode_response(_param, _dst_addr, _addr_mode, \ - _dst_ep, _src_ep, _payload, cb) - - -/** Macro for call @ref zb_zcl_metering_send_cmd_get_profile_response function - */ -#define ZB_ZCL_METERING_SEND_CMD_GET_PROFILE_RESPONSE(_param, _dst_addr, _addr_mode, _dst_ep, \ - _src_ep, _payload, _pl_size, cb) \ - zb_zcl_metering_send_cmd_get_profile_response(_param, _dst_addr, _addr_mode, _dst_ep, \ - _src_ep, _payload, _pl_size, cb) - - -/** Macro for call @ref zb_zcl_metering_send_cmd_get_sampled_data_response function - */ -#define ZB_ZCL_METERING_SEND_CMD_GET_SAMPLED_DATA_RESPONSE(_param, _dst_addr, _addr_mode, _dst_ep, \ - _src_ep, _payload, _pl_size, cb) \ - zb_zcl_metering_send_cmd_get_sampled_data_response(_param, _dst_addr, _addr_mode, _dst_ep, \ - _src_ep, _payload, _pl_size, cb) - - -/** @} */ /* ZB_ZCL_METERING_CMDS */ - - -/*! @cond internals_doc */ -/*! @internal @name Metering cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_DELIVERED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_DELIVERED_ID, \ - ZB_ZCL_ATTR_TYPE_U48, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METERING_STATUS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_METERING_STATUS_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METERING_UNIT_OF_MEASURE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_METERING_UNIT_OF_MEASURE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METERING_SUMMATION_FORMATTING_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_METERING_SUMMATION_FORMATTING_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METERING_METERING_DEVICE_TYPE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_METERING_METERING_DEVICE_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METERING_INSTANTANEOUS_DEMAND_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_METERING_INSTANTANEOUS_DEMAND_ID, \ - ZB_ZCL_ATTR_TYPE_S24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METERING_DEMAND_FORMATTING_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_METERING_DEMAND_FORMATTING_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METERING_HISTORICAL_CONSUMPTION_FORMATTING_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_METERING_HISTORICAL_CONSUMPTION_FORMATTING_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METERING_MULTIPLIER_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_METERING_MULTIPLIER_ID, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_METERING_DIVISOR_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_METERING_DIVISOR_ID, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - - -/*! @internal Number of attributes mandatory for reporting in Metering cluster */ -#define ZB_ZCL_METERING_REPORT_ATTR_COUNT 3 - -/*! @} - @endcond */ /* Metering cluster internals */ - - -/** @struct zb_zcl_metering_attrs_t - * @brief Metering cluster attributes - */ -/** @brief Declare attribute list for Electrical Measurement cluster - @param attr_list - attribute list name - @param curr_summ_delivered - pointer to variable to store Current Summation Delivered attribute value - @param status - pointer to variable to store Status attribute value - @param unit_of_measure - pointer to variable to store Unit Of Measure attribute value - @param summation_formatting - pointer to variable to store Summation Formatting attribute value - @param metering_device_type - pointer to variable to store Device Type attribute value -*/ -#define ZB_ZCL_DECLARE_METERING_ATTRIB_LIST(attr_list, curr_summ_delivered, status, unit_of_measure, \ - summation_formatting, metering_device_type) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_METERING) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_DELIVERED_ID, (curr_summ_delivered)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_STATUS_ID, (status)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_UNIT_OF_MEASURE_ID, (unit_of_measure)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_SUMMATION_FORMATTING_ID, (summation_formatting)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_METERING_DEVICE_TYPE_ID, (metering_device_type)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - - -/** @brief Declare attribute list for Electrical Measurement cluster (extended attribute set) - @param attr_list - attribute list name - @param curr_summ_delivered - pointer to variable to store Current Summ Delivered attribute value - @param status - pointer to variable to store Status attribute value - @param unit_of_measure - pointer to variable to store Unit Of Measure attribute value - @param summation_formatting - pointer to variable to store Summation Formatting attribute value - @param metering_device_type - pointer to variable to store Device Type attribute value - @param instantaneous_demand - pointer to variable to store Instantaneous Demand attribute value - @param demand_formatting - pointer to variable to store Demand Formatting attribute value - @param historical_consumption_formatting - pointer to variable to store Historical Consumption Formatting attribute value - @param multiplier - pointer to variable to store Multiplier attribute value - @param divisor - pointer to variable to store Divisor attribute value -*/ -#define ZB_ZCL_DECLARE_METERING_ATTRIB_LIST_EXT(attr_list, \ - curr_summ_delivered, status, unit_of_measure, summation_formatting, metering_device_type, \ - instantaneous_demand, demand_formatting, historical_consumption_formatting, multiplier, divisor) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_METERING) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_DELIVERED_ID, (curr_summ_delivered)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_STATUS_ID, (status)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_UNIT_OF_MEASURE_ID, (unit_of_measure)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_SUMMATION_FORMATTING_ID, (summation_formatting)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_METERING_DEVICE_TYPE_ID, (metering_device_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_INSTANTANEOUS_DEMAND_ID, (instantaneous_demand)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_DEMAND_FORMATTING_ID, (demand_formatting)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_HISTORICAL_CONSUMPTION_FORMATTING_ID, (historical_consumption_formatting)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_MULTIPLIER_ID, (multiplier)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_METERING_DIVISOR_ID, (divisor)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -typedef struct zb_zcl_metering_attrs_s -{ - - /** @copydoc ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_DELIVERED_ID - * @see ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_DELIVERED_ID - */ - zb_uint48_t curr_summ_delivered; - - /** @copydoc ZB_ZCL_ATTR_METERING_STATUS_ID - * @see ZB_ZCL_ATTR_METERING_STATUS_ID - */ - zb_uint8_t status; - - /** @copydoc ZB_ZCL_ATTR_METERING_UNIT_OF_MEASURE_ID - * @see ZB_ZCL_ATTR_METERING_UNIT_OF_MEASURE_ID - */ - zb_uint8_t unit_of_measure; - - /** @copydoc ZB_ZCL_ATTR_METERING_SUMMATION_FORMATTING_ID - * @see ZB_ZCL_ATTR_METERING_SUMMATION_FORMATTING_ID - */ - zb_uint8_t summation_formatting; - - /** @copydoc ZB_ZCL_ATTR_METERING_METERING_DEVICE_TYPE_ID - * @see ZB_ZCL_ATTR_METERING_METERING_DEVICE_TYPE_ID - */ - zb_uint8_t device_type; -} zb_zcl_metering_attrs_t; - - -/** @brief Declare attribute list for Metering cluster cluster - * @param[in] attr_list - attribute list variable name - * @param[in] attrs - variable of @ref zb_zcl_metering_attrs_t type (containing Metering cluster attributes) - */ -#define ZB_ZCL_DECLARE_METERING_ATTR_LIST(attr_list, attrs) \ - ZB_ZCL_DECLARE_METERING_ATTRIB_LIST(attr_list, &attrs.curr_summ_delivered, \ - &attrs.status, &attrs.unit_of_measure, &attrs.summation_formatting, \ - &attrs.device_type) - - -/** @} */ /* ZB_ZCL_METERING ZCL SE Metering cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_metering_init_server(void); -void zb_zcl_metering_init_client(void); - - -#define ZB_ZCL_CLUSTER_ID_METERING_SERVER_ROLE_INIT zb_zcl_metering_init_server -#define ZB_ZCL_CLUSTER_ID_METERING_CLIENT_ROLE_INIT zb_zcl_metering_init_client - -#endif /* ZB_ZCL_METERING_H */ diff --git a/zboss/development/include/zcl/zb_zcl_occupancy_sensing.h b/zboss/development/include/zcl/zb_zcl_occupancy_sensing.h deleted file mode 100644 index a5ea98c523..0000000000 --- a/zboss/development/include/zcl/zb_zcl_occupancy_sensing.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Occupancy Sensing definitoins -*/ - -#ifndef ZB_ZCL_OCCUPANCY_SENSING_H -#define ZB_ZCL_OCCUPANCY_SENSING_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_OCCUPANCY_SENSING - * @{ - * @details - * Occupancy Sensing cluster has no cluster-specific command support. Cluster - * attributes can be queried with @ref ZB_ZCL_COMMANDS "common commands". - */ - -/*! @name Occupancy Sensing cluster attributes - @{ -*/ - -/*! @brief Occupancy Sensing cluster attribute identifiers - @see ZCL spec, subclause 4.8.2.2 -*/ -enum zb_zcl_occupancy_sensing_attr_e -{ - /** Occupancy attribute identifier */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_ID = 0x0000, - /** Occupancy Sensor Type attribute identifier */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_ID = 0x0001, - /** The OccupancySensorTypeBitmap attribute specifies the types of the occupancy - * sensor. */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_BITMAP_ID = 0x0002, - /** PIROccupiedToUnoccupiedDelay identifier */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_ID = 0x0010, - /** PIRUnoccupiedToOccupiedDelay identifier */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_ID = 0x0011, - /** PIRUnoccupiedToOccupiedThreshold identifier */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_ID = 0x0012, - /** The UltrasonicOccupiedToUnoccupiedDelay attribute is 16 bits in length and - * specifies the time delay, in seconds, before the Ultrasonic sensor changes to its - * unoccupied state after the last detection of movement in the sensed area. */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_ID = 0x0020, - /** The UltrasonicUnoccupiedToOccupiedDelay attribute is 16 bits in length and - * specifies the time delay, in seconds, before the Ultrasonic sensor changes - * to its occupied state after the detection of movement in the sensed area. */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_ID = 0x0021, - /** The UltrasonicUnoccupiedToOccupiedThreshold attribute is 8 bits in length and - * specifies the number of movement detection events that must occur in the period - * UltrasonicUnoccupiedToOccupiedDelay, before the Ultrasonic sensor changes to its - * occupied state. */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID = 0x0022, - /** The PhysicalContactOccupiedToUnoccupiedDelay attribute is 16 bits in length and - * specifies the time delay, in seconds, before the physical contact occupancy sensor - * changes to its unoccupied state after detecting the unoccupied event. */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_ID = 0x0030, - /** The PhysicalContactUnoccupiedToOccupiedDelay attribute is 16 bits in length and - * specifies the time delay, in seconds, before the physical contact sensor changes - * to its occupied state after the detection of the occupied event. */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_ID = 0x0031, - /** The PhysicalContactUnoccupiedToOccupiedThreshold attribute is 8 bits in length and - * specifies the number of movement detection events that must occur in the period - * PhysicalContactUnoccupiedToOccupiedDelay, before the PIR sensor changes to its - * occupied state. */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID = 0x0032, - /* Parking Sensor, Attributes for device Configuration, 2.5.1 */ - /** @cond internals_doc */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_REPORTING_MODE_ID = 0x8001, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_DEBUG_MODE_ID = 0x8002, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_SENSING_INTERVAL_ID = 0x8003, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_MAX_NBR_CONFIRM_PINGS_ID = 0x8004, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_CONFIRM_PING_DELAY_ID = 0x8005, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_NBR_CONFIRM_PINGS_TO_VALID_ID = 0x8006, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_LOCAL_TEMPERATURE_OVERRIDE_ID = 0x8007, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_REMOTE_TEMPERATURE_VALUE_ID = 0x8008, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_HUMIDITY_COMPENSATION_ID = 0x800A, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_TRANDUCER_SENSITIVITY_CALIBRATION_SOURCE_ID = 0x800B, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_TRANDUCER_SENSITIVITY_CALIBRATION_OVERRIDE_VALUE_ID = 0x800C, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_SENSOR_TIME_VS_GAIN_LUT_ID = 0x800D, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_LEARN_ID = 0x800E, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_RINGDOWN_DISTANCE_ID = 0x800F, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_REFERENCE_FLOOR_DISTANCE_ID = 0x8010, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_DETECTION_ALGORITHM_SELECTOR_ID = 0x8011, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_FLOOR_DEADBAND_ID = 0x8012, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_MAIN_OBJECT_DEADBAND_ID = 0x8013, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_DETECTION_THRESHOLD_ID = 0x8014, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_FORCE_REPORT_ID = 0x801C, - - /* Parking Sensor, Reportable Attributes, 2.5.2 */ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_LOCAL_TEMPERATURE_VALUE_ID = 0x8009, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_CONFIDENCE_ID = 0x8015, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_ECHO_RETURN_ARRAY_ID = 0x8017, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_RX_SAMPLES_ARRAY_1_ID = 0x8018, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_RX_SAMPLES_ARRAY_2_ID = 0x8019, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_RX_SAMPLES_ARRAY_3_ID = 0x801A, - ZB_ZCL_ATTR_OCCUPANCY_SENSING_CUSTOM_RX_SAMPLES_ARRAY_4_ID = 0x801B - /*! @} - * @endcond */ /* internals_doc */ -}; - -/** @brief Default value for Occupancy Sensing cluster revision global attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief Minimal value for PIROccToUnoccDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_MIN_VALUE ((zb_uint16_t)0x0000) - -/** @brief Maximal value for PIROccToUnoccDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_MAX_VALUE ((zb_uint16_t)0xfffe) - -/** @brief Default value for PIROccToUnoccDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_DEFAULT_VALUE ZB_ZCL_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_MIN_VALUE - -/** @brief Minimal value for PIRUnoccToOccDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_MIN_VALUE ((zb_uint16_t)0x0000) - -/** @brief Maximal value for PIRUnoccToOccDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_MAX_VALUE ((zb_uint16_t)0xfffe) - -/** @brief Default value for PIRUnoccToOccDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_DEFAULT_VALUE ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_MIN_VALUE - -/** @brief Minimal value for PIRUnoccToOccThreshold attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_MIN_VALUE ((zb_uint8_t)0x01) - -/** @brief Maximal value for PIRUnoccToOccThreshold attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_MAX_VALUE ((zb_uint8_t)0xfe) - -/** @brief Default value for PIRUnoccToOccThreshold attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_DEFAULT_VALUE ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_MIN_VALUE - -/** @brief Minimal value for UltrasonicOccupiedToUnoccupiedDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_MIN_VALUE ((zb_uint16_t)0x0000) - -/** @brief Maximal value for UltrasonicOccupiedToUnoccupiedDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_MAX_VALUE ((zb_uint16_t)0xfffe) - -/** @brief Default value for UltrasonicOccupiedToUnoccupiedDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_DEFAULT_VALUE ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_MIN_VALUE - -/** @brief Minimal value for UltrasonicUnoccupiedToOccupiedDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_MIN_VALUE ((zb_uint16_t)0x0000) - -/** @brief Maximal value for UltrasonicUnoccupiedToOccupiedDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_MAX_VALUE ((zb_uint16_t)0xfffe) - -/** @brief Default value for UltrasonicUnoccupiedToOccupiedDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_DEFAULT_VALUE ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_MIN_VALUE - -/** @brief Minimal value for UltrasonicUnoccupiedToOccupiedThreshold attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_MIN_VALUE ((zb_uint8_t)0x01) - -/** @brief Maximal value for UltrasonicUnoccupiedToOccupiedThreshold attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_MAX_VALUE ((zb_uint8_t)0xfe) - -/** @brief Default value for UltrasonicUnoccupiedToOccupiedThreshold attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_DEFAULT_VALUE ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_MIN_VALUE - -/** @brief Default value for PhysicalContactOccupiedToUnoccupiedDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief No-reporting value for PhysicalContactOccupiedToUnoccupiedDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_NO_REPORTING_VALUE ((zb_uint16_t)0xffff) - -/** @brief Default value for PhysicalContactUnoccupiedToOccupiedDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief No-reporting value for PhysicalContactUnoccupiedToOccupiedDelay attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_NO_REPORTING_VALUE ((zb_uint16_t)0xffff) - -/** @brief Minimal value for PhysicalContactUnoccupiedToOccupiedThreshold attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_MIN_VALUE ((zb_uint8_t)0x01) - -/** @brief Maximal value for PhysicalContactUnoccupiedToOccupiedThreshold attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_MAX_VALUE ((zb_uint8_t)0xfe) - -/** @brief Default value for PhysicalContactUnoccupiedToOccupiedThreshold attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_DEFAULT_VALUE ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_DEFAULT_VALUE - -/*! @brief Permissible values for Occupancy attribute - @see ZCL spec, subclause 4.8.2.2.1.1 -*/ -enum zb_zcl_occupancy_sensing_occupancy_e -{ - /*! Unoccupied value */ - ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_UNOCCUPIED = 0, - /*! Occupied value */ - ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_OCCUPIED = 1 -}; - -/* Custom Attributes values */ - -/*! @brief Maximal value for switch type attribute */ -#define ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_MAX_VALUE \ - (ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_UNOCCUPIED) - - -/* Switch type attribute has no default value */ - -/*! @brief Permissible values for Occupancy Sensor Type attribute - @see ZCL spec, subclause 4.8.2.2.1.2 -*/ -enum zb_zcl_occupancy_sensing_occupancy_sensor_type_e -{ - /*! PIR value */ - ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_PIR = 0, - /*! Ultrasonic value */ - ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_ULTRASONIC = 1, - /*! PIR and Ultrasonic value */ - ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_PIR_AND_ULTRASONIC = 2, - /*! Reserved value */ - ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_RESERVED = 3 -}; - -/** @cond internals_doc */ -enum zb_zcl_custom_reporting_mode_type_e -{ - ZB_ZCL_CUSTOM_OCCUPANCY_SENSING_REPORING_MODE_TYPE_REGULAR_REPORTING = 0, - ZB_ZCL_CUSTOM_OCCUPANCY_SENSING_REPORING_MODE_TYPE_LOW_POWER_REPORTING = 1 -}; - - -enum zb_zcl_custom_debug_mode_type_e -{ - ZB_ZCL_OCCUPANCY_SENSING_CUSTOM_DEBUG_MODE_TYPE_SHORT = 0, - ZB_ZCL_OCCUPANCY_SENSING_CUSTOM_DEBUG_MODE_TYPE_ENHANCED = 1, - ZB_ZCL_OCCUPANCY_SENSING_CUSTOM_DEBUG_MODE_TYPE_DEBUG = 2 -}; - -enum zb_zcl_custom_learn_type_e -{ - ZB_ZCL_OCCUPANCY_SENSING_CUSTOM_LEARN_NOT_YET_PERFORMED = 0, - ZB_ZCL_OCCUPANCY_SENSING_CUSTOM_LEARN_IN_PROGRESS = 1, - ZB_ZCL_OCCUPANCY_SENSING_CUSTOM_LEARN_FINISHED_WITH_A_FAILURE = 2, - ZB_ZCL_OCCUPANCY_SENSING_CUSTOM_LEARN_FINISHED_SUCCSESSFULLY = 3 -}; - - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_ID(data_ptr) \ - { \ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ - } - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_ID(data_ptr) \ - { \ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ - } - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_BITMAP_ID(data_ptr) \ - { \ - ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_BITMAP_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ - } -/** @internal Number of attributes mandatory for reporting on Occupancy Sensing cluster */ -#define ZB_ZCL_OCCUPANCY_SENSING_REPORT_ATTR_COUNT 1 - -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for Occupancy Sensing cluster - @param attr_list - attribute list name - @param occupancy - pointer to variable to store Occupancy attribute value - @param occupancy_sensor_type - pointer to variable to store Occupancy Sensor Type attribute value - @param occupancy_sensor_type_bitmap - pointer to variable to store Occupancy Sensor Type Bitmap attribute value -*/ -#define ZB_ZCL_DECLARE_OCCUPANCY_SENSING_ATTRIB_LIST(attr_list, occupancy, occupancy_sensor_type, occupancy_sensor_type_bitmap) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_OCCUPANCY_SENSING) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_ID, (occupancy)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_ID, (occupancy_sensor_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_BITMAP_ID, (occupancy_sensor_type_bitmap)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Occupancy Sensing cluster attribute structures */ - -/*! @} */ /* ZCL Occupancy Sensing cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#define ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING_SERVER_ROLE_INIT (zb_zcl_cluster_init_t)NULL -#define ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING_CLIENT_ROLE_INIT (zb_zcl_cluster_init_t)NULL - -#endif /* ZB_ZCL_OCCUPANCY_SENSING_H */ diff --git a/zboss/development/include/zcl/zb_zcl_on_off.h b/zboss/development/include/zcl/zb_zcl_on_off.h deleted file mode 100644 index 0b14e3e0e8..0000000000 --- a/zboss/development/include/zcl/zb_zcl_on_off.h +++ /dev/null @@ -1,510 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: On/Off cluster definitions -*/ - -#ifndef ZB_ZCL_ON_OFF_H -#define ZB_ZCL_ON_OFF_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_ON_OFF - * @{ - * @details - * All commands in the cluster have only request form, and carry no payload. - * - * @par Example - * On command sending: - * @snippet HA_samples/on_off_output/sample_zed.c onoff_server_send_on_req_param - * @snippet HA_samples/on_off_output/sample_zed.c onoff_server_send_on_req_command - * @par - * - * Other two commands can be sent in the same way using appropriate macros. - * - */ - -/* Cluster ZB_ZCL_CLUSTER_ID_ON_OFF */ - -/*! @name On/Off cluster attributes - @{ -*/ - -/*! @brief On/Off cluster attribute identifiers - @see ZCL spec, subclause 3.8.2.2 -*/ -enum zb_zcl_on_off_attr_e -{ - /*! @brief OnOff attribute */ - ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID = 0, - /*! Global Scene Control attribute identifier. */ - ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL = 0x4000, - /*! On Time attribute identifier. */ - ZB_ZCL_ATTR_ON_OFF_ON_TIME = 0x4001, - /*! Off Wait Time attribute identifier. */ - ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME = 0x4002, - /*! The StartUpOnOff attribute SHALL define the desired startup behavior of a lamp - * device when it is supplied with power and this state SHALL be reflected in the OnOff attribute. */ - ZB_ZCL_ATTR_ON_OFF_START_UP_ON_OFF = 0x4003, -}; - -/*! @brief Permissible values for OnOff attribute */ -enum zb_zcl_on_off_on_off_e -{ - /*! "Off" value */ - ZB_ZCL_ON_OFF_IS_OFF = 0, - /*! "On" value */ - ZB_ZCL_ON_OFF_IS_ON = 1 -}; - -enum zb_zcl_on_off_start_up_on_off_e -{ - /*! "Off" value */ - ZB_ZCL_ON_OFF_START_UP_ON_OFF_IS_OFF = 0, - /*! "ON" value */ - ZB_ZCL_ON_OFF_START_UP_ON_OFF_IS_ON = 1, - /*! "Toggle" value */ - ZB_ZCL_ON_OFF_START_UP_ON_OFF_IS_TOGGLE = 2, - /*! "Previous" value */ - ZB_ZCL_ON_OFF_START_UP_ON_OFF_IS_PREVIOUS = 0xFF -}; - -/** @brief Default value for OnOff cluster revision global attribute */ -#define ZB_ZCL_ON_OFF_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief Default value for OnOff attribute */ -#define ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE (ZB_ZCL_ON_OFF_IS_OFF) - -/** @brief Default value for GlobalSceneControl attribute */ -#define ZB_ZCL_ON_OFF_GLOBAL_SCENE_CONTROL_DEFAULT_VALUE ((zb_bool_t)0x01) - -/** @brief Default value for OnTime attribute */ -#define ZB_ZCL_ON_OFF_ON_TIME_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for OffWaitTime attribute */ -#define ZB_ZCL_ON_OFF_OFF_WAIT_TIME_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Declare attribute list for On/Off cluster - @param attr_list - attribute list name - @param on_off - pointer to variable to store On/Off attribute value -*/ -#define ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST(attr_list, on_off) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_ON_OFF) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, (on_off)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** - * @brief Declare attribute list for On/Off cluster (extended attribute set). - * @param attr_list [IN] - attribute list name being declared by this macro. - * @param on_off [IN] - pointer to a boolean variable storing on/off attribute value. - * @param global_scene_ctrl [IN] - pointer to a boolean variable storing global scene control attribute value. - * @param on_time [IN] - pointer to a unsigned 16-bit integer variable storing on time attribute value. - * @param off_wait_time [IN] - pointer to a unsigned 16-bit integer variable storing off wait time attribute value. - */ -#define ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST_EXT( \ - attr_list, on_off, global_scene_ctrl, on_time, off_wait_time \ - ) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_ON_OFF) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, (on_off)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL, (global_scene_ctrl)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ON_OFF_ON_TIME, (on_time)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME, (off_wait_time)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* On/Off cluster attributes */ - -/*! @name On/Off cluster commands - @{ -*/ - -/*! @brief On/Off cluster command identifiers - @see ZCL spec, subclause 3.8.2.3 -*/ -enum zb_zcl_on_off_cmd_e -{ - ZB_ZCL_CMD_ON_OFF_OFF_ID = 0x00, /**< "Turn off" command. */ - ZB_ZCL_CMD_ON_OFF_ON_ID = 0x01, /**< "Turn on" command. */ - ZB_ZCL_CMD_ON_OFF_TOGGLE_ID = 0x02, /**< "Toggle state" command. */ - ZB_ZCL_CMD_ON_OFF_OFF_WITH_EFFECT_ID = 0x40, /**< "Off with effect" command. */ - ZB_ZCL_CMD_ON_OFF_ON_WITH_RECALL_GLOBAL_SCENE_ID = 0x41, /**< "On with recall global scene" command. */ - ZB_ZCL_CMD_ON_OFF_ON_WITH_TIMED_OFF_ID = 0x42, /**< "On with timed off" command. */ -}; - -/** @cond internals_doc */ -/* ON OFF cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_ON_OFF_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_ON_OFF_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_ON_OFF_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_ON_OFF_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_ON_OFF_OFF_ID, \ - ZB_ZCL_CMD_ON_OFF_ON_ID, \ - ZB_ZCL_CMD_ON_OFF_TOGGLE_ID, \ - ZB_ZCL_CMD_ON_OFF_OFF_WITH_EFFECT_ID, \ - ZB_ZCL_CMD_ON_OFF_ON_WITH_RECALL_GLOBAL_SCENE_ID, \ - ZB_ZCL_CMD_ON_OFF_ON_WITH_TIMED_OFF_ID - -#define ZB_ZCL_CLUSTER_ID_ON_OFF_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_ON_OFF_CLIENT_ROLE_GENERATED_CMD_LIST - -/** @endcond */ /* internals_doc */ - -/*! @brief General macro for sending On/Off cluster command - @param buffer to put data to - @param addr - address of the device to send command to - @param dst_addr_mode - addressing mode - @param dst_ep destination endpoint - @param ep - current endpoint - @param prof_id - profile identifier - @param dis_default_resp - "Disable default response" flag - @param command_id - command identifier - @param cb - callback to call to report send status -*/ -#define ZB_ZCL_ON_OFF_SEND_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, command_id, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), command_id); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_ON_OFF, cb); \ -} - -/*! Specific macro for sending Off command */ -#define ZB_ZCL_ON_OFF_SEND_OFF_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, dis_default_resp, cb) \ - ZB_ZCL_ON_OFF_SEND_REQ( \ - buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - dis_default_resp, \ - ZB_ZCL_CMD_ON_OFF_OFF_ID, \ - cb) - -/*! Specific macro for sending On command */ -#define ZB_ZCL_ON_OFF_SEND_ON_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, dis_default_resp, cb) \ - ZB_ZCL_ON_OFF_SEND_REQ( \ - buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - dis_default_resp, \ - ZB_ZCL_CMD_ON_OFF_ON_ID, \ - cb) - -/*! Specific macro for sending Toggle command */ -#define ZB_ZCL_ON_OFF_SEND_TOGGLE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, dis_default_resp, cb) \ - ZB_ZCL_ON_OFF_SEND_REQ( \ - buffer, \ - addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prfl_id, \ - dis_default_resp, \ - ZB_ZCL_CMD_ON_OFF_TOGGLE_ID, \ - cb) - -/*! Specific macro for sending Off with effect command */ -#define ZB_ZCL_ON_OFF_SEND_OFF_WITH_EFFECT_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, effect_id, effect_var, cb)\ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_ON_OFF_OFF_WITH_EFFECT_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, effect_id); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, effect_var); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_ON_OFF, cb); \ -} - -/*! Specific macro for sending On with recall global scene command */ -#define ZB_ZCL_ON_OFF_SEND_ON_WITH_RECALL_GLOBAL_SCENE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, cb) \ - ZB_ZCL_ON_OFF_SEND_REQ(buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, \ - ZB_ZCL_CMD_ON_OFF_ON_WITH_RECALL_GLOBAL_SCENE_ID, cb) - -/*! Specific macro for sending On with timed off command */ -#define ZB_ZCL_ON_OFF_SEND_ON_WITH_TIMED_OFF_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, dis_default_resp, on_off, on_time, off_wait_time, cb)\ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_ON_OFF_ON_WITH_TIMED_OFF_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, on_off); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, on_time); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, off_wait_time); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_ON_OFF, cb); \ -} - -/** Effect identifier enum - * @see ZCL spec 3.8.2.3.4.1 */ -enum zb_zcl_on_off_effect_e -{ -/**< Effect identifier field value: Delayed all off */ - ZB_ZCL_ON_OFF_EFFECT_ID_DELAYED_ALL_OFF = 0x00, -/**< Effect identifier field value: Dying light */ - ZB_ZCL_ON_OFF_EFFECT_ID_DYING_LIGHT = 0x01 -}; - -/** Effect variant field for delayed enum -* @see ZCL spec 3.8.2.3.4.2 */ -enum zb_zcl_on_off_effect_variant_delayed_e -{ -/**< Effect variant field value: Fade to off in 0.8 seconds */ - ZB_ZCL_ON_OFF_EFFECT_VARIANT_FADE = 0x00, -/**< Effect variant field value: No fade */ - ZB_ZCL_ON_OFF_EFFECT_VARIANT_NO_FADE = 0x01, -/**< Effect variant field value: 50% dim down in 0.8 seconds then fade to off in 12 seconds */ - ZB_ZCL_ON_OFF_EFFECT_VARIANT_50PART_FADE = 0x02 -}; - -/** Effect variant field for delayed enum -* @see ZCL spec 3.8.2.3.4.2 */ -enum zb_zcl_on_off_effect_variant_dying_e -{ -/**< Effect variant field value: 20% dim up in 0.5s then fade to off in 1 second */ - ZB_ZCL_ON_OFF_EFFECT_VARIANT_20PART_FADE = 0x00 -}; - -/** Accept only when on -* @see ZCL spec 3.8.2.3.6.1 */ -#define ZB_ZCL_ON_OFF_ACCEPT_ONLY_WHEN_ON 1 - -/*! @brief Structured representation of Off with effect command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_on_off_off_with_effect_req_s -{ - /** Effect identify */ - zb_uint8_t effect_id; - /** Effect variant */ - zb_uint8_t effect_variant; -} ZB_PACKED_STRUCT zb_zcl_on_off_off_with_effect_req_t; - -/*! @brief Structured representation of On with timed off command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_on_off_on_with_timed_off_req_s -{ - /** On/off control */ - zb_uint8_t on_off; - /** On time variable */ - zb_uint16_t on_time; - /** Off wait time variable */ - zb_uint16_t off_wait_time; -} ZB_PACKED_STRUCT zb_zcl_on_off_on_with_timed_off_req_t; - -/** @brief Parses Off with Effect command - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_on_off_off_with_effect_req_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_ON_OFF_GET_OFF_WITH_EFFECT_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_on_off_off_with_effect_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_on_off_off_with_effect_req_t *src_ptr = \ - (zb_zcl_on_off_off_with_effect_req_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_MEMCPY((data_ptr), src_ptr, sizeof(zb_zcl_on_off_off_with_effect_req_t)); \ - } \ -} - -/** @brief Parses On with timed off command - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_on_off_on_with_timed_off_req_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_ON_OFF_GET_ON_WITH_TIMED_OFF_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_on_off_on_with_timed_off_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_on_off_on_with_timed_off_req_t *src_ptr = \ - (zb_zcl_on_off_on_with_timed_off_req_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->on_off = src_ptr->on_off; \ - ZB_LETOH16(&((data_ptr)->on_time), &(src_ptr->on_time)); \ - ZB_LETOH16(&((data_ptr)->off_wait_time), &(src_ptr->off_wait_time)); \ - } \ -} - -/** @cond internals_doc */ -/** - * @name Inform User App about On/Off cluster command and change attributes. - * Internal structures and define-procedure for inform User App about On/Off - * cluster command and change attributes. - * @internal - * @{ - */ - -/** @brief Declare run Set Effect command for User Application -*/ -typedef struct zb_zcl_on_off_set_effect_value_param_s -{ - zb_uint8_t effect_id; /*!< Effect identify */ - zb_uint8_t effect_variant; /*!< Effect variant */ -} zb_zcl_on_off_set_effect_value_param_t; - -/*! Struct for invoke User App & continue after */ -typedef struct zb_zcl_on_off_effect_user_app_schedule_e -{ - zb_zcl_parsed_hdr_t cmd_info; /**< Parameters for continue command, - see @ref zb_zcl_parsed_hdr_s */ - zb_zcl_on_off_set_effect_value_param_t param; /**< User App command parameters, - see @ref zb_zcl_on_off_set_effect_value_param_s */ -} zb_zcl_on_off_effect_user_app_schedule_t; - -#define ZB_ZCL_ON_OFF_EFFECT_SCHEDULE_USER_APP(buffer, pcmd_info, effectId, effectVar) \ -{ \ - zb_zcl_on_off_effect_user_app_schedule_t* user_data = \ - ZB_BUF_GET_PARAM((buffer), zb_zcl_on_off_effect_user_app_schedule_t); \ - ZB_MEMMOVE(&(user_data->cmd_info), (pcmd_info), sizeof(zb_zcl_parsed_hdr_t)); \ - user_data->param.effect_id = (effectId); \ - user_data->param.effect_variant = (effectVar); \ - ZB_SCHEDULE_CALLBACK(zb_zcl_on_off_effect_invoke_user_app, (buffer)); \ -} - -/*! @} - * @endcond */ /* internals_doc */ - -/*! @} */ /* On/Off cluster commands */ - -/*! @cond internals_doc - @internal @name On/Off cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ON_OFF_ON_TIME(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ON_OFF_ON_TIME, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/** @struct zb_zcl_on_off_attrs_s - * @brief On/Off cluster attributes - */ -typedef struct zb_zcl_on_off_attrs_s -{ - zb_uint8_t on_off; -} zb_zcl_on_off_attrs_t; - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ON_OFF_START_UP_ON_OFF(data_ptr) \ -{ \ - ZB_ZCL_ATTR_ON_OFF_START_UP_ON_OFF, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_ZCL_DECLARE_ON_OFF_ATTR_LIST(attr_list, attrs) \ - ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST(attr_list, &attrs.on_off) - -/*! @internal Number of attributes mandatory for reporting in On/Off cluster */ -#define ZB_ZCL_ON_OFF_REPORT_ATTR_COUNT 1 - -/*! @internal Struct for invoke User App & continue after */ -typedef struct zb_on_off_user_app_schedule_e -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t new_value; - zb_bool_t is_run_timer; -} zb_on_off_user_app_schedule_t; - - -/*! @} - @endcond */ /* On/Off cluster internals */ - -/*! @} */ /* ZCL On/Off cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_on_off_init_server(void); -void zb_zcl_on_off_init_client(void); -#define ZB_ZCL_CLUSTER_ID_ON_OFF_SERVER_ROLE_INIT zb_zcl_on_off_init_server -#define ZB_ZCL_CLUSTER_ID_ON_OFF_CLIENT_ROLE_INIT zb_zcl_on_off_init_client - -#endif /* ZB_ZCL_ON_OFF_H */ diff --git a/zboss/development/include/zcl/zb_zcl_on_off_switch_conf.h b/zboss/development/include/zcl/zb_zcl_on_off_switch_conf.h deleted file mode 100644 index 7f318366d7..0000000000 --- a/zboss/development/include/zcl/zb_zcl_on_off_switch_conf.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: On/Off switch configuration definitions -*/ - -#ifndef ZB_ZCL_ON_OFF_SWITCH_CONF_H -#define ZB_ZCL_ON_OFF_SWITCH_CONF_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_OOSC - * @{ - * @details - * On/Off Switch Configuration cluster has no cluster-specific command support. Cluster - * attributes can be queried with @ref ZB_ZCL_COMMANDS "common commands". - * - * Sample switch config cluster attributes data - * @code - * zb_uint8_t attr_switch_type = ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_TOGGLE; - * zb_uint8_t attr_switch_actions = ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_DEFAULT_VALUE; - * - * ZB_ZCL_DECLARE_ON_OFF_SWITCH_CONFIGURATION_ATTRIB_LIST(switch_cfg_attr_list, &attr_switch_type, &attr_switch_actions); - * @endcode - * - * - */ - -/*! @name On/off switch configuration cluster attributes - @{ -*/ - -/*! @brief On/off switch configuration cluster attribute identifiers - @see ZCL spec, subclause 3.9.2.2 -*/ -enum zb_zcl_on_off_switch_configuration_attr_e -{ - /*! Switch type attribute identifier (switch information) */ - ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_ID = 0x0000, - /*! Switch actions attribute identifier (switch settings) */ - ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_ID = 0x0010 -}; - -/*! @brief Permissible values for switch type attribute - @see ZCL spec, subclause 3.9.2.2.2 -*/ -enum zb_zcl_on_off_switch_configuration_switch_type_e -{ - /*! Toggle switch */ - ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_TOGGLE = 0, - /*! Momentary switch */ - ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_MOMENTARY = 1, - /*! Multifunction switch */ - ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_MULTIFUNCTION = 2 -}; - -/** @brief Default value for On/off switch configuration cluster revision global attribute */ -#define ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/*! @brief Maximal value for switch type attribute */ -#define ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_MAX_VALUE \ - (ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_MULTIFUNCTION) - -/* Switch type attribute has no default value */ - -/*! @brief Permissible values for switch actions attribute - @see ZCL spec, subclause 3.9.2.2.3.1 -*/ -enum zb_zcl_on_off_switch_configuration_switch_actions_e -{ - /*! @brief First type command pattern - - @li Send "On" on arriving to State2 from State1; - @li Send "Off" on arriving to State1 from State2. - */ - ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1 = 0, - /*! @brief Second type command pattern - - @li Send "On" on arriving to State1 from State2; - @li Send "Off" on arriving to State2 from State1. - */ - ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE2 = 1, - /*! @brief Toggle command pattern - - Send "Toggle" on state change - */ - ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TOGGLE = 2 -}; - -/*! @brief Maximal value for switch actions attribute */ -#define ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_MAX_VALUE \ - (ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TOGGLE) - -/** @brief Default value for Switch actions attribute */ -#define ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_DEFAULT_VALUE \ - (ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_TYPE1) - -/*! @} */ /* On/off switch configuration cluster attributes */ - -/** @cond internals_doc - @internal @name On/off switch configuration cluster attribute structures - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_ID(data_ptr) \ - { \ - ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ - } - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_ID(data_ptr) \ - { \ - ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ - } - -/** @internal Number of attributes mandatory for reporting on On/Off switch configuration cluster */ -#define ZB_ZCL_ON_OFF_SWITCH_CONFIG_REPORT_ATTR_COUNT 0 - -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for ON/OFF Switch configuration cluster - @param attr_list - attribute list name - @param switch_type - pointer to variable to store switch type attribute value - @param switch_actions - pointer to variable to store switch action attribute value -*/ -#define ZB_ZCL_DECLARE_ON_OFF_SWITCH_CONFIGURATION_ATTRIB_LIST(attr_list, switch_type, switch_actions) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_ID, (switch_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_ID, (switch_actions)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_on_off_switch_config_init_server(void); -void zb_zcl_on_off_switch_config_init_client(void); -#define ZB_ZCL_CLUSTER_ID_ON_OFF_SWITCH_CONFIG_SERVER_ROLE_INIT zb_zcl_on_off_switch_config_init_server -#define ZB_ZCL_CLUSTER_ID_ON_OFF_SWITCH_CONFIG_CLIENT_ROLE_INIT zb_zcl_on_off_switch_config_init_client - -#endif /* ZB_ZCL_ON_OFF_SWITCH_CONF_H */ diff --git a/zboss/development/include/zcl/zb_zcl_ota_upgrade.h b/zboss/development/include/zcl/zb_zcl_ota_upgrade.h deleted file mode 100644 index 4afcd11a6d..0000000000 --- a/zboss/development/include/zcl/zb_zcl_ota_upgrade.h +++ /dev/null @@ -1,2199 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: OTA Upgrade cluster definitions -*/ - -#ifndef ZB_ZCL_OTA_UPGRADE_H -#define ZB_ZCL_OTA_UPGRADE_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -#if defined ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE || defined ZB_USE_OSIF_OTA_ROUTINES || defined DOXYGEN - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_OTA_UPGRADE - * @{ - * @details - * All commands in the cluster have only request form, and carry no payload. - */ - -/** @brief Hook on Write attribute - * send Check-in if change Check-in interval & Check-in remain time > new check-in interval */ -/* void zb_zcl_ota_upgrade_write_attr_hook(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); */ - -/*! @name OTA File Header format - Structures for representation OTA File Header - @{ -*/ - -/*! @brief Structure representation of OTA File Header, - * see ZCL8 specification, subsection 11.4.2, Table 11-2. OTA Header Fields */ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_file_header_s -{ - zb_uint32_t file_id; /**< OTA upgrade file identifier*/ - zb_uint16_t header_version; /**< OTA Header version */ - zb_uint16_t header_length; /**< OTA Header length */ - zb_uint16_t fc; /**< OTA Header Field control */ - zb_uint16_t manufacturer_code; /**< Manufacturer code */ - zb_uint16_t image_type; /**< Image type */ - zb_uint32_t file_version; /**< File version */ - zb_uint16_t stack_version; /**< Zigbee Stack version */ - zb_char_t header_string[32]; /**< OTA Header string */ - zb_uint32_t total_image_size; /**< Total Image size (including header) */ - - /* Optional fields are moved to additional structure zb_zcl_ota_upgrade_file_header_optional_t */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_file_header_t; - -#define ZB_ZCL_OTA_FILE_IS_FILE_SPECIFIC(head) \ - (((head)->fc) & ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_DEVICE_SPECIFIC) - -/** - Optional parts of the OTA file header - See ZCL8 specification, subsection 11.4.2, Table 11-2. OTA Header Fields - */ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_file_header_optional_s -{ - zb_uint8_t credential_version; /**< Security credential version */ - zb_ieee_addr_t dst_addr; /**< Upgrade file destination */ - zb_uint16_t min_hw_version; /**< Minimum hardware version */ - zb_uint16_t max_hw_version; /**< Maximum hardware version */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_file_header_optional_t; - -/** @cond DOXYGEN_INTERNAL_DOC */ -#define ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FULL_SIZE \ - (sizeof(zb_zcl_ota_upgrade_file_header_t) + 2*sizeof(zb_uint16_t)+sizeof(zb_ieee_addr_t)) -/*! @} - * @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/** @brief Default OTA Upgrade File Identifier, see ZCL8 specification, subsection 11.4.2.1 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FILE_ID 0x0BEEF11E - -/** @brief Default OTA Upgrade File Version, see ZCL8 specification, subsection 11.4.2.2 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FILE_VERSION 0x0100 - -/*! @brief OTA File header - fc fields structure - @see ZCL8 specification, subsection 11.4.2.4, Table 11-3. OTA Header Field Control Bitmask -*/ -enum zb_zcl_ota_upgrade_file_header_fc_e -{ - /*! @brief Security Credential Version Present */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_CREDENTIAL_VER = 1 << 0, - /*! @brief Device Specific File */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_DEVICE_SPECIFIC = 1 << 1, - /*! @brief Hardware Versions Present */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_HW_VER = 1 << 2, -}; - -/** @brief Special Manufacturer Code, see ZCL8 specification, subsection 11.4.2.5 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_HEADER_MANUFACTURE_CODE_WILD_CARD 0xffff - -/*! @brief OTA File header - Image Type Values - @see ZCL8 specification, subsection 11.4.2.6, Table 11-4. Image Type Values -*/ -enum zb_zcl_ota_upgrade_file_header_image_type_e -{ - /*! @brief Manufacturer Specific - maximum value */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_IMAGE_MANUF_SPEC_MAX = 0xffbf, - /*! @brief Client Security credentials */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_IMAGE_SECURITY_CRED = 0xffc0, - /*! @brief Client Configuration */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_IMAGE_CONFIG = 0xffc1, - /*! @brief Server Log */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_IMAGE_LOG = 0xffc2, - /*! @brief Wild card value */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_IMAGE_WILD_CARD = 0xffff, -}; - -/** @brief OTA Upgrade File Version, App release, see ZCL8 specification, subsection 11.4.2.7 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_GET_APP_RELEASE(ver) (((ver) >>24) & 0xff) - -/** @brief OTA Upgrade File Version, App build, see ZCL8 specification, subsection 11.4.2.7 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_GET_APP_BUILD(ver) (((ver) >>16) & 0xff) - -/** @brief OTA Upgrade File Version, Stack release, see ZCL8 specification, subsection 11.4.2.7 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_GET_STACK_RELEASE(ver) (((ver) >>8) & 0xff) - -/** @brief OTA Upgrade File Version, Stack build, see ZCL8 specification, subsection 11.4.2.7 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_GET_STACK_BUILD(ver) ((ver) & 0xff) - -/** @brief OTA Upgrade File Version, make file version, see ZCL8 specification, subsection 11.4.2.7 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_MAKE_VERSION(app_rel, app_build, stack_rel, stack_build) \ - ((app_rel) << 24 | (app_build) << 16 | (stack_rel) << 8 | (stack_build)) - -/* - ZCL8 specification, subsection 11.4.2.7, has done recommendations about versioning (at least to - divide version to 4 parts - Stack Build, Stack Release, Application Build and Application - Release), but does not specify comparing method. Looks like we do not have any limitations and - may upgrade/downgrade any f/w (except re-installation), so this comparing is simply: - ver1 != ver2 - Only one possible limitation now is NVRAM, but if dataset ids are not overlapped, it is also ok. - Any additional comparison logic may be implemented on the application level. - */ -/** @brief Compare 2 OTA versions and decide if it is needed to do upgrade */ -#define ZB_ZCL_OTA_UPGRADE_VERSION_CMP(ver1, ver2) \ - ( (ver1) != (ver2) ) - -/*! @brief OTA File header - Zigbee Stack version - @see ZCL8 specification, subsection 11.4.2.8 -*/ -enum zb_zcl_ota_upgrade_file_header_stack_version_e -{ - /*! @brief Zigbee 2006 */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_STACK_2006 = 0x0000, - /*! @brief Zigbee 2007 */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_STACK_2007 = 0x0001, - /*! @brief Zigbee Pro */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_STACK_PRO = 0x0002, - /*! @brief Zigbee IP */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_STACK_IP = 0x0003, -}; - -/*! @brief OTA File header - Security Credential Version - @see ZCL8 specification, subsection 11.4.2.11 -*/ -enum zb_zcl_ota_upgrade_file_header_security_version_e -{ - /*! @brief SE 1.0 */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_SECURITY_VER_SE1_0 = 0x00, - /*! @brief SE 1.1 */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_SECURITY_VER_SE1_1 = 0x01, - /*! @brief SE 2.0 */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_SECURITY_VER_SE2_0 = 0x02, - /*! @brief SE 1.2 */ - ZB_ZCL_OTA_UPGRADE_FILE_HEADER_SECURITY_VER_SE1_2 = 0x03, -}; - -/** @brief OTA Upgrade HW Version Get Version, see ZCL8 specification, subsection 11.4.2.13 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_GET_HW_VERSION(ver) (((ver) >>8) & 0xff) - -/** @brief OTA Upgrade HW Version Get Revision, see ZCL8 specification, subsection 11.4.2.13 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_GET_HW_REVISION(ver) ((ver) & 0xff) - -/** @brief OTA Upgrade Make HW Version, see ZCL8 specification, subsection 11.4.2.13 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_MAKE_HW_VERSION(ver, rev) \ - ((ver) << 8 | (rev)) - -/** @brief Default value of OTA Upgrade HW Version */ -#define ZB_ZCL_OTA_UPGRADE_FILE_HW_VERSION_DEF_VALUE 0xffff -/** @brief Default value of OTA Upgrade destination address */ -#define ZB_ZCL_OTA_UPGRADE_FILE_DEST_ADDRESS_DEF_VALUE { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } - -/*! @} -*/ - -/*! @name OTA File Sub-element format - Structures for representation OTA File Sub-element - @{ -*/ - -/*! @brief Structure representation of OTA File Sub-element, - * see ZCL8 specification, subsection 11.4.3 */ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_sub_element_s -{ - zb_uint16_t tag_id; /** Tag ID*/ - zb_uint32_t length; /** length */ - zb_uint8_t value[1]; /** data variable, length - see 'length' field */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_sub_element_t; - -/*! @brief Structure representation of OTA File Sub-element header */ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_sub_element_hdr_s -{ - zb_uint16_t tag_id; /** Tag ID*/ - zb_uint32_t length; /** length */ -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_sub_element_hdr_t; - - -/*! @brief OTA File header - Tag Identifiers - @see ZCL8 specification, subsection 11.4.4 -*/ -enum zb_zcl_ota_upgrade_sub_element_tags_e -{ - /*! @brief Upgrade Image */ - ZB_ZCL_OTA_UPGRADE_FILE_TAG_UPGRADE_IMAGE = 0x0000, - /*! @brief ECDSA Signature (Crypto Suite 1) */ - ZB_ZCL_OTA_UPGRADE_FILE_TAG_ECDSA = 0x0001, - /*! @brief ECDSA Signature Certificate (Crypto Suite 1)*/ - ZB_ZCL_OTA_UPGRADE_FILE_TAG_ECDSA_CERT = 0x0002, - /*! @brief Image Integrity Code */ - ZB_ZCL_OTA_UPGRADE_FILE_TAG_IMAGE_INTEGRITY_CODE = 0x0003, - /*! @brief Picture Data */ - ZB_ZCL_OTA_UPGRADE_FILE_TAG_PICTURE_DATA = 0x0004, - /*! @brief ECDSA Signature (Crypto Suite 2) */ - ZB_ZCL_OTA_UPGRADE_FILE_TAG_ECDSA_V_2 = 0x0005, - /*! @brief ECDSA Signature Certificate (Crypto Suite 2)*/ - ZB_ZCL_OTA_UPGRADE_FILE_TAG_ECDSA_CERT_V_2 = 0x0006, - /*! @brief Manufacturer Specific Use - minimum */ - ZB_ZCL_OTA_UPGRADE_FILE_TAG_MANUF_MIN = 0xf000, - /*! @brief Manufacturer Specific Use - maximum */ - ZB_ZCL_OTA_UPGRADE_FILE_TAG_MANUF_MAX = 0xffff, -}; - -/*! @brief Structure representation of OTA ECDSA Signature (Crypto Suite 1), - * see ZCL8 specification, subsection 11.4.6 */ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_ecdsa_s -{ - zb_uint16_t tag_id; /** Tag ID*/ - zb_uint32_t length; /** length */ - zb_ieee_addr_t address; /** address */ - zb_uint8_t value[42]; /** data variable */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_ecdsa_t; - -/** @brief Special Manufacturer Code, see ZCL8 specification, subsection 11.4.6 */ -#define ZB_ZCL_OTA_UPGRADE_ECDSA_TAG_ID ZB_ZCL_OTA_UPGRADE_FILE_TAG_ECDSA - -/** @brief Special Manufacturer Code, see ZCL8 specification, subsection 11.4.6 */ -#define ZB_ZCL_OTA_UPGRADE_ECDSA_LENGTH 0x00000032 - - -/*! @brief Structure representation of OTA ECDSA Signature, - * see OTA spec 6.3.6 */ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_ecdsa_signing_s -{ - zb_uint16_t tag_id; /** Tag ID*/ - zb_uint32_t length; /** length */ - zb_uint8_t certificate[48]; /** data variable, length - see 'length' field */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_ecdsa_signing_t; - -/** @brief Special Manufacturer Code, see spec 6.3.6 */ -#define ZB_ZCL_OTA_UPGRADE_ECDSA_SIGNING_TAG_ID 0x0002 - -/** @brief Special Manufacturer Code, see spec 6.3.6 */ -#define ZB_ZCL_OTA_UPGRADE_ECDSA_SIGNING_LENGTH 0x00000030 - - -/*! @brief Structure representation of OTA ECDSA Certificate, - * see OTA spec 6.3.7 */ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_ecdsa_certificate_s -{ - zb_uint16_t tag_id; /** Tag ID*/ - zb_uint32_t length; /** length */ - zb_uint8_t hash[16]; /** hash */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_ecdsa_ertificate_t; - -/** @brief Special Manufacturer Code, see spec 6.3.7 */ -#define ZB_ZCL_OTA_UPGRADE_ECDSA_CERTIFICATE_TAG_ID 0x0003 - -/** @brief Special Manufacturer Code, see spec 6.3.7 */ -#define ZB_ZCL_OTA_UPGRADE_ECDSA_CERTIFICATE_LENGTH 0x00000010 - - -/*! @} -*/ - -/* Cluster ZB_ZCL_CLUSTER_ID_OTA_UPGRADE */ - -/*! @name OTA Upgrade cluster attributes - @{ -*/ - -/** @brief Default value for OTA Upgrade cluster revision global attribute */ -#define ZB_ZCL_OTA_UPGRADE_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0004u) - -/*! @brief Maximum size data for Query Image Block Request */ -#define ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_DATA_SIZE_MAX 64 - -/*! @brief Callback function for send next data portion - * - */ -typedef zb_ret_t (*zb_zcl_ota_upgrade_next_data_ind_t)(zb_uint8_t index, - zb_zcl_parsed_hdr_t *zcl_header, - zb_uint32_t offset, - zb_uint8_t size, - zb_uint8_t** data); - -#if defined ZB_HA_ENABLE_OTA_UPGRADE_SERVER || defined DOXYGEN - -/** @brief Initialize OTA Upgrade cluster - server part - * For server clear custom data and registry next data indication - * - * @param endpoint - destination endpoint - * @param next_data_ind_cb - callback to be called on received image block - * For client initiate search Upgrade server */ -void zb_zcl_ota_upgrade_init_server(zb_uint8_t endpoint, zb_zcl_ota_upgrade_next_data_ind_t next_data_ind_cb); - -/*! @brief Structure representation of Data for insert OTA file to upgrade mechanism */ -typedef struct zb_zcl_ota_upgrade_server_insert_file_s -{ - zb_uint8_t endpoint; /**< Endpoint */ - zb_uint8_t index; /**< Index of table, index must be less value is set when create attribute */ - zb_uint8_t *ota_file; /**< OTA file, place in memory, see OTA spec 6.3.2 - @note OTA file must saved in memory until call zb_zcl_ota_upgrade_remove_file*/ - zb_uint8_t notify_on; /**< Flag to control Image notification after the file is inserted */ - zb_uint32_t upgrade_time; /**< Upgrade time for this OTA file */ - -} zb_zcl_ota_upgrade_server_insert_file_t; - -/*! @brief Insert upgrade OTA file into Server upgrade table - * - * @param param - buffer with @ref zb_zcl_ota_upgrade_server_insert_file_s structure - * - * @note Takes buffer ownership. - * - * @note OTA file must be saved in memory until call zb_zcl_ota_upgrade_remove_file -*/ -zb_ret_t zb_zcl_ota_upgrade_insert_file(zb_uint8_t param); - -#define ZB_ZCL_OTA_UPGRADE_INSERT_FILE(buf, ep, i, file, upgrade_tm, notify, ret_code) \ -{ \ - zb_zcl_ota_upgrade_server_insert_file_t *file_data = \ - ZB_BUF_GET_PARAM(buf, zb_zcl_ota_upgrade_server_insert_file_t); \ - file_data->endpoint = (ep); \ - file_data->index = (i); \ - file_data->ota_file = (file); \ - file_data->upgrade_time = (upgrade_tm); \ - file_data->notify_on = (notify); \ - (ret_code) = zb_zcl_ota_upgrade_insert_file(buf); \ -} - -/*! @brief Structure representation of Data for insert OTA file to upgrade mechanism */ -typedef struct zb_zcl_ota_upgrade_server_remove_file_s -{ - zb_uint8_t endpoint; /**< Endpoint */ - zb_uint8_t index; /**< Index of table, index must be less value is set when create attribute */ - -} zb_zcl_ota_upgrade_server_remove_file_t; - -/*! @brief Remove upgrade file from Server upgrade table - * - * @param param - buffer with @ref zb_zcl_ota_upgrade_server_remove_file_s structure - * - * @note Takes buffer ownership. - * - * @note After calling this command OTA file may be removed from memory -*/ -zb_ret_t zb_zcl_ota_upgrade_remove_file(zb_uint8_t param); - -#define ZB_ZCL_OTA_UPGRADE_REMOVE_FILE(buf, ep, i, ret_code) \ -{ \ - zb_zcl_ota_upgrade_server_remove_file_t *file_data = \ - ZB_BUF_GET_PARAM(buf, zb_zcl_ota_upgrade_server_remove_file_t); \ - file_data->endpoint = (ep); \ - file_data->index = (i); \ - (ret_code) = zb_zcl_ota_upgrade_remove_file(buf); \ -} - -/*! @brief Structure representation of OTA file on server side */ -typedef struct zb_zcl_ota_upgrade_data_s -{ - zb_zcl_ota_upgrade_file_header_t *file_header; - zb_uint32_t upgrade_time; - -} zb_zcl_ota_upgrade_data_t; - -/*! @brief Structure representation of server side variables */ -typedef struct zb_zcl_ota_upgrade_server_variable_s -{ - zb_uint8_t *query_jitter; /**< QueryJitter */ - //zb_uint8_t data_size; /**< DataSize */ - //zb_uint8_t *ota_image_data; /**< OTAImageData */ - zb_uint32_t *current_time; /**< CurrentTime */ - //zb_uint32_t upgrade_time; /**< UpgradeTime */ - - // custom data - zb_uint8_t table_length; /**< Length of server table with upgrade image data */ - zb_zcl_ota_upgrade_data_t *table; /**< Server table with upgrade image data */ - -} zb_zcl_ota_upgrade_server_variable_t; - -/*! @brief Default value for DataSize, OTA spec */ -#define ZB_ZCL_OTA_UPGRADE_DATA_SIZE_DEF_VALUE 0xff - -/*! @brief Minimum value for QueryJitter, OTA spec */ -#define ZB_ZCL_OTA_UPGRADE_QUERY_JITTER_MIN_VALUE 0x01 -/*! @brief Maximum value for QueryJitter, OTA spec */ -#define ZB_ZCL_OTA_UPGRADE_QUERY_JITTER_MAX_VALUE 0x64 -/*! @brief Default value for QueryJitter, OTA spec */ -#define ZB_ZCL_OTA_UPGRADE_QUERY_JITTER_DEF_VALUE 0x32 - -/*! @brief Default value for currentTime, OTA spec */ -#define ZB_ZCL_OTA_UPGRADE_CURRENT_TIME_DEF_VALUE 0xffffffff - -/*! @brief Default value for UpgradeTime, OTA spec */ -#define ZB_ZCL_OTA_UPGRADE_UPGRADE_TIME_DEF_VALUE 0xffffffff - -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_srv_query_img_param_s -{ - zb_zcl_parsed_hdr_t zcl_parsed_hdr; - zb_zcl_addr_t *zcl_addr; - zb_uint16_t image_type; - zb_uint16_t manufacturer_code; - zb_uint32_t version; - zb_uint8_t *table_idx; -} - ZB_PACKED_STRUCT zb_zcl_ota_upgrade_srv_query_img_param_t; - -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_srv_upgrade_started_param_s -{ - zb_zcl_addr_t *zcl_addr; - zb_uint16_t image_type; - zb_uint32_t version; -} - ZB_PACKED_STRUCT zb_zcl_ota_upgrade_srv_upgrade_started_param_t; - -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_srv_upgrade_aborted_param_s -{ - zb_zcl_addr_t *zcl_addr; - zb_uint16_t image_type; - zb_uint32_t version; -} - ZB_PACKED_STRUCT zb_zcl_ota_upgrade_srv_upgrade_aborted_param_t; - -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_srv_upgrade_end_param_s -{ - zb_zcl_addr_t *zcl_addr; - zb_uint32_t *upgrade_time; - zb_uint8_t status; - zb_uint16_t image_type; - zb_uint32_t version; -} - ZB_PACKED_STRUCT zb_zcl_ota_upgrade_srv_upgrade_end_param_t; - -#endif /* defined ZB_HA_ENABLE_OTA_UPGRADE_SERVER || defined DOXYGEN */ - -#if defined ZB_HA_ENABLE_OTA_UPGRADE_CLIENT || defined DOXYGEN - -/** @brief Initialize OTA Upgrade cluster - client part - * For server clear custom data - * For client initiate search Upgrade server - @param param - empty buffer -*/ -void zb_zcl_ota_upgrade_init_client(zb_uint8_t param); - -/** @brief Start OTA Upgrade client with pre-defined OTA Upgrade Server attributes - * (without Service Discovery) - * - * @param server_ep - OTA Upgrade server endpoint - * @param server_addr - OTA Upgrade server short address - * @return RET_OK on success or RET_ERROR on error -*/ -zb_ret_t zb_zcl_ota_upgrade_start_client(zb_uint8_t server_ep, zb_uint16_t server_addr); - -/** @brief Stop process OTA Upgrade / OTA query new images - * Client stop schedule OTA command & clear OTA status*/ -void zb_zcl_ota_upgrade_stop_client(void); - -/*! @brief Resume process OTA Upgrade if it was previously suspended by the application - * - * @param param - buffer to be resumed - * @param upgrade_status - application upgrade status @see zb_zcl_ota_upgrade_status_e - */ -void zb_zcl_ota_upgrade_resume_client(zb_uint8_t param, zb_uint8_t upgrade_status); - -/*! @brief Set Frequency request server about new upgrade file (minutes) - * @param endpoint - endpoint of the OTA cluster - * @param interval - new interval value (in minutes) - */ -void zb_zcl_ota_upgrade_set_query_interval(zb_uint8_t endpoint, zb_uint16_t interval); - -/*! @brief Clear attribute after upgrade - * - * @param endpoint - endpoint - * - *@note After calling this command OTA file may be removed from memory -*/ -void zb_zcl_ota_upgrade_file_upgraded(zb_uint8_t endpoint); - -/*! @brief Structure representation of client side variables */ -typedef struct zb_zcl_ota_upgrade_client_variable_s -{ - // custom data - zb_uint32_t download_file_size; - zb_uint16_t timer_query; - zb_uint16_t timer_counter; - zb_uint16_t hw_version; - zb_uint8_t max_data_size; - zb_uint8_t img_block_req_sent; - zb_uint8_t pending_img_block_resp; -} zb_zcl_ota_upgrade_client_variable_t; - -#endif /* defined ZB_HA_ENABLE_OTA_UPGRADE_CLIENT || defined DOXYGEN */ - -/*! @brief OTA Upgrade cluster attribute identifiers - @see ZCL8 specification, subsection 11.10, Table 11-10. Attributes of OTA Upgrade Cluster -*/ -enum zb_zcl_ota_upgrade_attr_e -{ - /** @brief UpgradeServerID attribute, ZCL8 specification, subsection 11.10.1 */ - ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ID = 0x0000, - /** @brief FileOffset attribute, ZCL8 specification, subsection 11.10.2 */ - ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID = 0x0001, - /** @brief CurrentFileVersion attribute, ZCL8 specification, subsection 11.10.3 */ - ZB_ZCL_ATTR_OTA_UPGRADE_FILE_VERSION_ID = 0x0002, - /** @brief CurrentZigbeeStackVersion attribute, ZCL8 specification, subsection 11.10.4 */ - ZB_ZCL_ATTR_OTA_UPGRADE_STACK_VERSION_ID = 0x0003, - /** @brief DownloadedFileVersion attribute, ZCL8 specification, subsection 11.10.5*/ - ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID = 0x0004, - /** @brief DownloadedZigbeeStackVersion attribute, ZCL8 specification, subsection 11.10.6 */ - ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_STACK_VERSION_ID = 0x0005, - /** @brief ImageUpgradeStatus attribute, ZCL8 specification, subsection 11.10.7 */ - ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STATUS_ID = 0x0006, - /** @brief Manufacturer ID attribute, ZCL8 specification, subsection 11.10.8 */ - ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID = 0x0007, - /** @brief Image Type ID attribute, ZCL8 specification, subsection 11.10.9 */ - ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID = 0x0008, - /** @brief MinimumBlockPeriod attribute, ZCL8 specification, subsection 11.10.10 */ - ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID = 0x0009, - /** @brief Image Stamp attribute, ZCL8 specification, subsection 11.10.11 */ - ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STAMP_ID = 0x000a, - /** This attribute indicates what behavior the client device supports for activating - * a fully downloaded but not installed upgrade image. - * See ZCL8 specification, subsection 11.10.12 */ - ZB_ZCL_ATTR_OTA_UPGRADE_UPGRADE_ACTIVATION_POLICY_ID = 0x000b, - /** This attribute indicates what behavior the client device supports for activating - * a fully downloaded image when the OTA server cannot be reached. - * See ZCL8 specification, subsection 11.10.13*/ - ZB_ZCL_ATTR_OTA_UPGRADE_UPGRADE_TIMEOUT_POLICY_ID = 0x000c, - - - /*! @brief OTA server endpoint custom attribute */ - ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID = 0xfff3, - /*! @brief OTA server addr custom attribute */ - ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID = 0xfff2, - /*! @brief DownloadedFileSize custom attribute */ - ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID = 0xfff1, - /*! @brief Server variables- see OTA spec 6.8 - * and Custom data */ - ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_DATA_ID = 0xfff0, -}; - -/*! @brief Default value for UpgradeServerID attribute, ZCL8 specification, subsection 11.10.1 */ -#define ZB_ZCL_OTA_UPGRADE_SERVER_DEF_VALUE { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } -/*! @brief Default value for FileOffset attribute, ZCL8 specification, subsection 11.10.2 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_OFFSET_DEF_VALUE 0xffffffff -/*! @brief Default value for CurrentFileVersion attribute, ZCL8 specification, subsection 11.10.3 */ -#define ZB_ZCL_OTA_UPGRADE_FILE_VERSION_DEF_VALUE 0xffffffff -/*! @brief Default value for CurrentZigbeeStackVersion attribute, ZCL8 specification, subsection - * 11.10.4 */ -#define ZB_ZCL_OTA_UPGRADE_STACK_VERSION_DEF_VALUE 0xffff -/*! @brief Default value for DownloadedFileVersion attribute, ZCL8 specification, subsection 11.10.5 */ -#define ZB_ZCL_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_DEF_VALUE 0xffffffff -/*! @brief Default value for DownloadedZigbeeStackVersion attribute, ZCL8 specification, subsection 11.10.6 */ -#define ZB_ZCL_OTA_UPGRADE_DOWNLOADED_STACK_DEF_VALUE 0xffff -/*! @brief Default value for ImageUpgradeStatus attribute, ZCL8 specification, subsection 11.10.7 */ -#define ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DEF_VALUE 0x00 -/*! @brief Maximum value for MinimumBlockPeriod attribute, ZCL8 specification, subsection 11.10.10 */ -#define ZB_ZCL_OTA_UPGRADE_IMAGE_STAMP_MIN_VALUE 0xfffe - -/*! @brief Default value for OTA server endpoint custom attribute */ -#define ZB_ZCL_OTA_UPGRADE_SERVER_ENDPOINT_DEF_VALUE 0xff -/*! @brief Default value for OTA server addr custom attribute */ -#define ZB_ZCL_OTA_UPGRADE_SERVER_ADDR_DEF_VALUE 0xffff - -/*! @brief OTA Image Upgrade Status Attribute Values - @see ZCL8 specification, subsection 11.10.7 -*/ -enum zb_zcl_ota_upgrade_image_status_e -{ - /*! @brief Normal */ - ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL = 0x00, - /*! @brief Download in progress */ - ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DOWNLOADING = 0x01, - /*! @brief Download complete */ - ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DOWNLOADED = 0x02, - /*! @brief Waiting to upgrade */ - ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_WAITING_UPGRADE = 0x03, - /*! @brief Count down */ - ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_COUNT_DOWN = 0x04, - /*! @brief Wait for more */ - ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_WAIT_FOR_MORE = 0x05, - /*! @brief Waiting to Upgrade via External Event */ - ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_WAIT_TO_UPGRADE_VIA_EXT_EVENT = 0x06, -}; - -/*! @brief Default Frequency request server about new upgrade file (minutes) */ -#define ZB_ZCL_OTA_UPGRADE_QUERY_TIMER_COUNT_DEF (24*60) - -/*! @brief Timer interval for Query timer */ -#define ZB_ZCL_OTA_UPGRADE_QUERY_TIMER_INTERVAL \ - 60l * ZB_TIME_ONE_SECOND - -/*! @brief Maximum value of nextImageQuery interval */ -#define ZB_ZCL_OTA_UPGRADE_MAX_INTERVAL 60 - -/*! @brief Resend buffer delay */ -#define ZB_ZCL_OTA_UPGRADE_RESEND_BUFFER_DELAY ZB_TIME_ONE_SECOND * 45 - -/*! @cond internals_doc - @name OTA Upgrade cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ID, \ - ZB_ZCL_ATTR_TYPE_IEEE_ADDR, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_FILE_VERSION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_FILE_VERSION_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_STACK_VERSION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_STACK_VERSION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_STACK_VERSION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_STACK_VERSION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STATUS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STATUS_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STAMP_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STAMP_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID, \ - ZB_ZCL_ATTR_TYPE_NULL, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_DATA_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_DATA_ID, \ - ZB_ZCL_ATTR_TYPE_NULL, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in OTA Upgrade cluster */ -#define ZB_ZCL_OTA_UPGRADE_REPORT_ATTR_COUNT 0 - -/*! @} - * @ - @endcond endcond */ /* OTA Upgrade cluster internals */ - -/** @brief Declare attribute list for OTA Upgrade cluster - client side - @param attr_list - attribute list name - @param upgrade_server - pointer to variable to store UpgradeServerID attribute - @param file_offset - pointer to variable to store FileOffset attribute - @param file_version - pointer to variable to store CurrentFileVersion attribute - @param stack_version - pointer to variable to store CurrentZigbeeStackVersion attribute - @param downloaded_file_ver - pointer to variable to store DownloadedFileVersion attribute - @param downloaded_stack_ver - pointer to variable to store DownloadedZigbeeStackVersion attribute - @param image_status - pointer to variable to store ImageUpgradeStatus attribute - @param manufacturer - pointer to variable to store Manufacturer ID attribute - @param image_type - pointer to variable to store Image Type ID attribute - @param min_block_reque - pointer to variable to store MinimumBlockReque attribute - @param image_stamp - pointer to variable to store Image Stamp attribute - @param server_addr - server short address - @param server_ep - server endpoint - @param hardware_version - (const) hardware version - @param max_data_size - (const) maximum data size Query Block Image commands - @param query_timer - (const) query timer count -*/ -#define ZB_ZCL_DECLARE_OTA_UPGRADE_ATTRIB_LIST(attr_list, \ - upgrade_server, file_offset, file_version, stack_version, downloaded_file_ver, \ - downloaded_stack_ver, image_status, manufacturer, image_type, min_block_reque, image_stamp, \ - server_addr, server_ep, hardware_version, max_data_size, query_timer) \ - zb_zcl_ota_upgrade_client_variable_t client_var_##attr_list = \ - {0, query_timer, 1, hardware_version, max_data_size, 0, 0}; \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_OTA_UPGRADE) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ID , (upgrade_server)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID , (file_offset)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_FILE_VERSION_ID , (file_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_STACK_VERSION_ID , (stack_version)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID , (downloaded_file_ver)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_STACK_VERSION_ID, (downloaded_stack_ver)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STATUS_ID , (image_status)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID , (manufacturer)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID , (image_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID , (min_block_reque)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STAMP_ID , (image_stamp)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID , (server_addr)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID , (server_ep)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID, &(client_var_##attr_list)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @brief Declare attribute list for OTA Upgrade cluster - server side - @param attr_list - attribute list name - @param query_jitter - (8bit) pointer to variable to store QueryJitter value - @param current_time - (32bit) pointer to variable to store CurrentTime - @param length - (const) length of server table with upgrade image data -*/ -#define ZB_ZCL_DECLARE_OTA_UPGRADE_ATTRIB_LIST_SERVER(attr_list, \ - query_jitter, current_time, length) \ - zb_zcl_ota_upgrade_data_t table_##attr_list[length]; \ - zb_zcl_ota_upgrade_server_variable_t server_var_##attr_list = { \ - query_jitter, /* 0, 0,*/ current_time, /*ZB_ZCL_OTA_UPGRADE_UPGRADE_TIME_DEF_VALUE,*/ \ - length, table_##attr_list }; \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_OTA_UPGRADE) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_DATA_ID, &(server_var_##attr_list)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* OTA Upgrade cluster attributes */ - -/*! @name OTA Upgrade cluster commands - @{ -*/ - -/*! @brief OTA Upgrade cluster client to server command identifiers - @see ZCL8 spec, Table 11-16 -*/ -enum zb_zcl_ota_upgrade_cmd_e -{ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_NEXT_IMAGE_ID = 0x01, /**< "Query Next Image Request" command */ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_ID = 0x03, /**< "Image Block Request" command */ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_PAGE_ID = 0x04, /**< "Image Page Request" command */ - ZB_ZCL_CMD_OTA_UPGRADE_UPGRADE_END_ID = 0x06, /**< "Upgrade End Request" command */ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_SPECIFIC_FILE_ID = 0x08, /**< "Query Device Specific File Request" command */ -}; - -/*! @brief OTA Upgrade cluster server to client command identifiers - @see ZCL8 spec, Table 11-16 -*/ -enum zb_zcl_ota_upgrade_resp_cmd_e -{ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_NOTIFY_ID = 0x00, /**< "Image Notify" command */ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_NEXT_IMAGE_RESP_ID = 0x02, /**< "Query Next Image Response" command */ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_RESP_ID = 0x05, /**< "Image Block Response" command */ - ZB_ZCL_CMD_OTA_UPGRADE_UPGRADE_END_RESP_ID = 0x07, /**< "Upgrade End Response" command */ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_SPECIFIC_FILE_RESP_ID = 0x09, /**< "Query Device Specific File Response" command */ - - ZB_ZCL_CMD_OTA_UPGRADE_INTERNAL_ABORT_ID = 0xf9, /**< ZBOSS internal command */ -}; - -/** @cond internals_doc */ -/* OTA Upgrade cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_NOTIFY_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_NEXT_IMAGE_RESP_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_RESP_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_UPGRADE_END_RESP_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_SPECIFIC_FILE_RESP_ID - -#define ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_NEXT_IMAGE_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_PAGE_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_UPGRADE_END_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_SPECIFIC_FILE_ID - -#define ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_SERVER_ROLE_RECEIVED_CMD_LIST \ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_NEXT_IMAGE_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_UPGRADE_END_ID, \ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_SPECIFIC_FILE_ID -/*! @} - * @endcond */ /* internals_doc */ - - -/************************* Query Next Image Request **************************/ - -/*! @brief Structure representation of Query Next Image Request command payload - @see ZCL8 specification, subsection 11.13.4 -*/typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_query_next_image_s -{ - zb_uint8_t fc; /**< Field Control, see @ref zb_zcl_ota_upgrade_image_notify_payload_type_e */ - zb_uint16_t manufacturer; /**< Manufacturer code */ - zb_uint16_t image_type; /**< Image type */ - zb_uint32_t file_version; /**< File version */ - zb_uint16_t hw_version; /**< Hardware version */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_query_next_image_t; - -/*! @brief OTA Image Upgrade Status Attribute Values - @see ZCL8 specification, subsection 11.13.4.2.1 -*/ -enum zb_zcl_ota_upgrade_query_next_image_fc_e -{ - /*! @brief Hardware Version Present */ - ZB_ZCL_OTA_UPGRADE_QUERY_NEXT_IMAGE_HW_VERSION = 1 << 0, -}; - -/*! @brief Send "Query Next Image Request" command, see ZCL8 specification, subsection 11.13.4 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback - @param fc - Field Control, see @ref zb_zcl_ota_upgrade_image_notify_payload_type_e - @param manufacturer - Manufacturer code - @param image_type - Image type - @param file_version - File version - @param hw_version - Hardware version - @param aps_secured - APS security -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_QUERY_NEXT_IMAGE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - fc, manufacturer, image_type, file_version, hw_version, aps_secured) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_NEXT_IMAGE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (fc)); \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (manufacturer), (image_type)); \ - ZB_ZCL_PACKET_PUT_DATA32_VAL(ptr, (file_version)); \ - if( (fc) & ZB_ZCL_OTA_UPGRADE_QUERY_NEXT_IMAGE_HW_VERSION ) \ - { \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (hw_version)); \ - } \ - ZB_ZCL_FINISH_N_SEND_PACKET_NEW((buffer), ptr, addr, dst_addr_mode, \ - dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, cb, aps_secured, \ - ZB_FALSE, 0); \ -} - -/** @brief Macro for getting "Query Next Image Request" command, see ZCL8 specification, subsection 11.13.4 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ota_upgrade_query_next_image_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_OTA_UPGRADE_GET_QUERY_NEXT_IMAGE_REQ(data_ptr, buffer, status) \ -{ \ - zb_zcl_ota_upgrade_query_next_image_t *src_ptr = \ - (zb_zcl_ota_upgrade_query_next_image_t*)zb_buf_begin((buffer)); \ - zb_uint8_t expected_payload_len = sizeof(zb_zcl_ota_upgrade_query_next_image_t); \ - \ - if (!(src_ptr->fc & ZB_ZCL_OTA_UPGRADE_QUERY_NEXT_IMAGE_HW_VERSION)) \ - { \ - expected_payload_len -= sizeof(zb_uint16_t); \ - } \ - \ - if (zb_buf_len((buffer)) < expected_payload_len) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->fc = src_ptr->fc; \ - ZB_HTOLE16(&((data_ptr)->manufacturer), &(src_ptr->manufacturer)); \ - ZB_HTOLE16(&((data_ptr)->image_type), &(src_ptr->image_type)); \ - ZB_HTOLE32(&((data_ptr)->file_version), &(src_ptr->file_version)); \ - if( src_ptr->fc & ZB_ZCL_OTA_UPGRADE_QUERY_NEXT_IMAGE_HW_VERSION ) \ - { \ - ZB_HTOLE16(&((data_ptr)->hw_version), &(src_ptr->hw_version)); \ - } \ - else \ - { \ - (data_ptr)->hw_version = 0; \ - } \ - } \ -} - -/************************* Image Block Request **************************/ - -/*! @brief Structure representation of Image Block Request command payload - @see ZCL8 specification, subsection 11.13.6.1 -*/ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_image_block_s -{ - zb_uint8_t fc; /**< Field Control, see @ref zb_zcl_ota_upgrade_image_block_fc_e */ - zb_uint16_t manufacturer; /**< Manufacturer code */ - zb_uint16_t image_type; /**< Image type */ - zb_uint32_t file_version; /**< File version */ - zb_uint32_t file_offset; /**< File offset */ - zb_uint8_t data_size_max; /**< Maximum data size */ - - zb_ieee_addr_t node_addr; /**< Request node address*/ - zb_uint16_t block_delay; /**< BlockRequestDelay */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_image_block_t; - -/*! @brief OTA Image Upgrade Status Attribute Values - @see ZCL8 specification, subsection 11.13.6.2.1 -*/ -enum zb_zcl_ota_upgrade_image_block_fc_e -{ - /*! @brief Request node's IEEE address Present */ - ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_IEEE_PRESENT = 1 << 0, - /*! @brief BlockRequestDelay present */ - ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_DELAY_PRESENT = 1 << 1, -}; - -/*! @brief Send "Image Block Request" command, see ZCL8 specification, subsection 11.13.6 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback - @param fc - Field Control, see @ref zb_zcl_ota_upgrade_image_block_fc_e - @param manufacturer - Manufacturer code - @param image_type - Image type - @param file_version - File version - @param file_offset - File offset - @param data_size_max - Maximum data size - @param node_addr - Request node address - @param block_delay - BlockRequestDelay - @param current_delay - Delay current send (milliseconds) -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_BLOCK_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - fc, manufacturer, image_type, file_version, file_offset, data_size_max, \ - node_addr, block_delay, current_delay) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (fc)); \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (manufacturer), (image_type)); \ - ZB_ZCL_PACKET_PUT_2DATA32_VAL(ptr, (file_version), (file_offset)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (data_size_max)); \ - if( (fc) & ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_IEEE_PRESENT) \ - { \ - ZB_ZCL_PACKET_PUT_DATA_IEEE(ptr, (node_addr)); \ - } \ - if( (fc) & ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_DELAY_PRESENT) \ - { \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (block_delay)); \ - } \ - ZB_ZCL_FINISH_PACKET_O((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT_SCHEDULE( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, cb, \ - current_delay); \ -} - -/** @brief Macro for getting "Image Block Request" command, see ZCL8 specification, subsection 11.13.6 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ota_upgrade_image_block_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_REQ(data_ptr, buffer, status) \ -{ \ - zb_zcl_ota_upgrade_image_block_t *src_ptr = \ - (zb_zcl_ota_upgrade_image_block_t*)zb_buf_begin((buffer)); \ - \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ota_upgrade_image_block_t) - \ - ( !(src_ptr->fc & ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_IEEE_PRESENT) ? sizeof(zb_ieee_addr_t) : 0) - \ - ( !(src_ptr->fc & ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_DELAY_PRESENT) ? sizeof(zb_uint16_t) : 0) ) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->fc = src_ptr->fc; \ - ZB_HTOLE16(&((data_ptr)->manufacturer), &(src_ptr->manufacturer)); \ - ZB_HTOLE16(&((data_ptr)->image_type), &(src_ptr->image_type)); \ - ZB_HTOLE32(&((data_ptr)->file_version), &(src_ptr->file_version)); \ - ZB_HTOLE32(&((data_ptr)->file_offset), &(src_ptr->file_offset)); \ - (data_ptr)->data_size_max = src_ptr->data_size_max; \ - if( src_ptr->fc & ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_IEEE_PRESENT) \ - { \ - ZB_IEEE_ADDR_COPY((data_ptr)->node_addr, (src_ptr)->node_addr); \ - } \ - if( src_ptr->fc & ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_DELAY_PRESENT) \ - { \ - ZB_HTOLE16(&((data_ptr)->block_delay), &(src_ptr->block_delay)); \ - } \ - } \ -} - -/************************* Image Page Request **************************/ - -/*! @brief Structure representation of Image Page Request command payload - @see ZCL8 specification, subsection 11.13.7 -*/ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_image_page_s -{ - zb_uint8_t fc; /**< Field Control, see @ref zb_zcl_ota_upgrade_image_page_fc_e */ - zb_uint16_t manufacturer; /**< Manufacturer code */ - zb_uint16_t image_type; /**< Image type */ - zb_uint32_t file_version; /**< File version */ - zb_uint32_t file_offset; /**< File offset */ - zb_uint8_t data_size_max; /**< Maximum data size */ - zb_uint16_t page_size; /**< Page size */ - zb_uint16_t response_spacing; /**< Response Spacing */ - - zb_ieee_addr_t node_addr; /**< Request node address */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_image_page_t; - -/*! @brief OTA Image Upgrade Status Attribute Values - @see ZCL8 specification, subsection 11.13.7.2.1 -*/ -enum zb_zcl_ota_upgrade_image_page_fc_e -{ - /*! @brief Request node's IEEE address Present */ - ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_PAGE_IEEE_PRESENT = 1 << 0, -}; - -/*! @brief Send "Image Page Request" command, see ZCL8 specification, subsection 11.13.7 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback - @param fc - Field Control, see @ref zb_zcl_ota_upgrade_image_page_fc_e - @param manufacturer - Manufacturer code - @param image_type - Image type - @param file_version - File version - @param file_offset - File offset - @param data_size_max - Maximum data size - @param page_size - Page size - @param response_spacing - Response Spacing - @param node_addr - Request node address -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_PAGE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - fc, manufacturer, image_type, file_version, file_offset, data_size_max, \ - page_size, response_spacing, node_addr) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_PAGE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (fc)); \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (manufacturer), (image_type)); \ - ZB_ZCL_PACKET_PUT_2DATA32_VAL(ptr, (file_version), (file_offset)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (data_size_max)); \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (page_size), (response_spacing)); \ - if( (fc) & ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_PAGE_IEEE_PRESENT) \ - { \ - ZB_ZCL_PACKET_PUT_DATA_IEEE(ptr, (node_addr)); \ - } \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, cb); \ -} - -/** @brief Macro for getting "Image Page Request" command, see ZCL8 specification, subsection 11.13.7 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ota_upgrade_image_page_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_OTA_UPGRADE_GET_IMAGE_PAGE_REQ(data_ptr, buffer, status) \ -{ \ - zb_zcl_ota_upgrade_image_page_t *src_ptr = \ - (zb_zcl_ota_upgrade_image_page_t*)zb_buf_begin((buffer)); \ - \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ota_upgrade_image_page_t) - \ - ((src_ptr->fc & ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_PAGE_IEEE_PRESENT) ? sizeof(zb_ieee_addr_t) : 0) ) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->fc = src_ptr->fc; \ - ZB_HTOLE16(&((data_ptr)->manufacturer), &(src_ptr->manufacturer)); \ - ZB_HTOLE16(&((data_ptr)->image_type), &(src_ptr->image_type)); \ - ZB_HTOLE32(&((data_ptr)->file_version), &(src_ptr->file_version)); \ - ZB_HTOLE32(&((data_ptr)->file_offset), &(src_ptr->file_offset)); \ - (data_ptr)->data_size_max = src_ptr->data_size_max; \ - ZB_HTOLE16(&((data_ptr)->page_size), &(src_ptr->page_size)); \ - ZB_HTOLE16(&((data_ptr)->response_spacing), &(src_ptr->response_spacing)); \ - if( src_ptr->fc & ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_PAGE_IEEE_PRESENT) \ - { \ - ZB_IEEE_ADDR_COPY((data_ptr)->node_addr, (src_ptr)->node_addr); \ - } \ - } \ -} - -/************************* Upgrade End Request **************************/ - -/*! @brief Structure representation of Upgrade End Request command payload - @see ZCL8 specification, subsection 11.13.9 -*/typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_upgrade_end_s -{ - zb_uint8_t status; /**< Status */ - zb_uint16_t manufacturer; /**< Manufacturer code */ - zb_uint16_t image_type; /**< Image type */ - zb_uint32_t file_version; /**< File version */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_upgrade_end_t; - -/*! @brief Send "Upgrade End Request" command, see ZCL8 specification, subsection 11.13.9 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback - @param status - Status, see @ref zcl_status - @param manufacturer - Manufacturer code - @param image_type - Image type - @param file_version - File version -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_UPGRADE_END_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - status, manufacturer, image_type, file_version) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_OTA_UPGRADE_UPGRADE_END_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (status)); \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (manufacturer), (image_type)); \ - ZB_ZCL_PACKET_PUT_DATA32_VAL(ptr, (file_version)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, cb); \ -} - -/** @brief Macro for getting "Upgrade End Request" command, see ZCL8 specification, subsection 11.13.9 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ota_upgrade_upgrade_end_s. - * @param buffer containing the packet (by pointer). - * @param status_ - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_OTA_UPGRADE_GET_UPGRADE_END_REQ(data_ptr, buffer, status_) \ -{ \ - zb_zcl_ota_upgrade_upgrade_end_t *src_ptr = \ - (zb_zcl_ota_upgrade_upgrade_end_t*)zb_buf_begin((buffer)); \ - \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ota_upgrade_upgrade_end_t) ) \ - { \ - (status_) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (status_) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->status = src_ptr->status; \ - ZB_HTOLE16(&((data_ptr)->manufacturer), &(src_ptr->manufacturer)); \ - ZB_HTOLE16(&((data_ptr)->image_type), &(src_ptr->image_type)); \ - ZB_HTOLE32(&((data_ptr)->file_version), &(src_ptr->file_version)); \ - } \ -} - -/************************* Query Specific File Request **************************/ - -/*! @brief Structure representation of Query Specific File Request command payload - @see ZCL8 specification, subsection 11.13.10 -*/typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_query_specific_file_s -{ - zb_ieee_addr_t node_addr; /**< Node address */ - zb_uint16_t manufacturer; /**< Manufacturer code */ - zb_uint16_t image_type; /**< Image type */ - zb_uint32_t file_version; /**< File version */ - zb_uint16_t stack_version; /**< Zigbee stack version */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_query_specific_file_t; - -/*! @brief Send "Query Specific File Request" command, see ZCL8 specification, subsection 11.13.10 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback - @param node_addr - Node address - @param manufacturer - Manufacturer code - @param image_type - Image type - @param file_version - File version - @param stack_version - Zigbee stack version -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_QUERY_SPECIFIC_FILE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - node_addr, manufacturer, image_type, file_version, stack_version) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_SPECIFIC_FILE_ID); \ - ZB_ZCL_PACKET_PUT_DATA_IEEE(ptr, (node_addr)); \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (manufacturer), (image_type)); \ - ZB_ZCL_PACKET_PUT_DATA32_VAL(ptr, (file_version)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (stack_version)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, cb); \ -} - -/** @brief Macro for getting "Query Specific File Request" command, see ZCL8 specification, subsection 11.13.10 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ota_upgrade_query_specific_file_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_OTA_UPGRADE_GET_QUERY_SPECIFIC_FILE_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ota_upgrade_query_specific_file_t) ) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ota_upgrade_query_specific_file_t *src_ptr = \ - (zb_zcl_ota_upgrade_query_specific_file_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_IEEE_ADDR_COPY((data_ptr)->node_addr, (src_ptr)->node_addr); \ - ZB_HTOLE16(&((data_ptr)->manufacturer), &(src_ptr->manufacturer)); \ - ZB_HTOLE16(&((data_ptr)->image_type), &(src_ptr->image_type)); \ - ZB_HTOLE32(&((data_ptr)->file_version), &(src_ptr->file_version)); \ - ZB_HTOLE16(&((data_ptr)->stack_version), &(src_ptr->stack_version)); \ - } \ -} - -/******************************* Image Notify ******************************/ - -/*! @brief Structure representation of Image Notify response command payload - @see ZCL8 specification, subsection 11.13.3.1 -*/ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_image_notify_s -{ - zb_uint8_t payload_type; /** Payload type, see @ref zb_zcl_ota_upgrade_image_notify_payload_type_e */ - zb_uint8_t query_jitter; /** Query jitter */ - zb_uint16_t manufacturer; /** Manufacturer code */ - zb_uint16_t image_type; /** Image type */ - zb_uint32_t file_version; /** File version */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_image_notify_t; - -/*! @brief OTA Image Upgrade Status Attribute Values - @see ZCL8 specification, subsection 11.13.3.2.1 -*/ -enum zb_zcl_ota_upgrade_image_notify_payload_type_e -{ - /*! @brief Query jitter */ - ZB_ZCL_OTA_UPGRADE_IMAGE_NOTIFY_PAYLOAD_JITTER = 0x00, - /*! @brief Query jitter and manufacturer code */ - ZB_ZCL_OTA_UPGRADE_IMAGE_NOTIFY_PAYLOAD_JITTER_CODE = 0x01, - /*! @brief Query jitter, manufacturer code, and image type */ - ZB_ZCL_OTA_UPGRADE_IMAGE_NOTIFY_PAYLOAD_JITTER_CODE_IMAGE = 0x02, - /*! @brief Query jitter, manufacturer code, image type, and new file version */ - ZB_ZCL_OTA_UPGRADE_IMAGE_NOTIFY_PAYLOAD_JITTER_CODE_IMAGE_VER = 0x03, -}; - -/*! @brief Send Image Notify command, see ZCL8 specification, subsection 11.13.3 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param payload_type - Payload type - @param query_jitter - Query jitter - @param manufacturer - Manufacturer code - @param image_type - Image type - @param file_version - File version -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_NOTIFY_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - payload_type, query_jitter, manufacturer, image_type, file_version) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A( \ - ptr, ZB_ZCL_FRAME_DIRECTION_TO_CLI, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, (def_resp)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_NOTIFY_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (payload_type)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (query_jitter)); \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (manufacturer), (image_type)); \ - ZB_ZCL_PACKET_PUT_DATA32_VAL(ptr, (file_version)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, cb); \ -} - - -#define ZB_ZCL_OTA_UPGRADE_GET_IMAGE_NOTIFY_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) <= sizeof(zb_uint8_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ota_upgrade_image_notify_t *src_ptr = \ - (zb_zcl_ota_upgrade_image_notify_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->payload_type = src_ptr->payload_type; \ - (data_ptr)->query_jitter = src_ptr->query_jitter; \ - switch ( src_ptr->payload_type ) \ - { \ - case 0x03: \ - ZB_HTOLE32(&((data_ptr)->file_version), &(src_ptr->file_version));\ - /* FALLTHROUGH */ \ - case 0x02: \ - ZB_HTOLE16(&((data_ptr)->image_type), &(src_ptr->image_type)); \ - /* FALLTHROUGH */ \ - case 0x01: \ - ZB_HTOLE16(&((data_ptr)->manufacturer), &(src_ptr->manufacturer));\ - /* FALLTHROUGH */ \ - default: \ - break; \ - } \ - } \ -} - - - - -/******************************* Query Next Image Response ******************************/ - -/*! @brief Structure representation of Query Next Image Response command payload - @see ZCL8 specification, subsection 11.13.5.1 -*/typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_query_next_image_res_s -{ - zb_uint8_t status; /** Status, see @ref zcl_status */ - zb_uint16_t manufacturer; /** Manufacturer code */ - zb_uint16_t image_type; /** Image type */ - zb_uint32_t file_version; /** File version */ - zb_uint32_t image_size; /** Image size */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_query_next_image_res_t; - - -/*! @brief Send Query Next Image Response command, see ZCL8 specification, subsection 11.13.5 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequence - @param status - Status, see @ref zcl_status - @param manufacturer - Manufacturer code - @param image_type - Image type - @param file_version - File version - @param image_size - Image size -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_QUERY_NEXT_IMAGE_RES( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq, \ - status, manufacturer, image_type, file_version, image_size) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_NEXT_IMAGE_RESP_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (status)); \ - if( (status) == ZB_ZCL_STATUS_SUCCESS) \ - { \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (manufacturer), (image_type)); \ - ZB_ZCL_PACKET_PUT_2DATA32_VAL(ptr, (file_version), (image_size)); \ - } \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, NULL); \ -} - -/** @brief Macro for getting Query Next Image Response command, see ZCL8 specification, subsection 11.13.5 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ota_upgrade_query_next_image_res_s. - * @param buffer containing the packet (by pointer). - * @param status_ - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_OTA_UPGRADE_GET_QUERY_NEXT_IMAGE_RES(data_ptr, buffer, status_)\ -{ \ - zb_zcl_ota_upgrade_query_next_image_res_t *src_ptr = \ - (zb_zcl_ota_upgrade_query_next_image_res_t*)zb_buf_begin((buffer)); \ - \ - if (zb_buf_len((buffer)) < ( (src_ptr->status)==ZB_ZCL_STATUS_SUCCESS ? \ - sizeof(zb_zcl_ota_upgrade_query_next_image_res_t) : sizeof(zb_uint8_t))) \ - { \ - (status_) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - TRACE_MSG(TRACE_ZLL1, "ERROR: buf_len %i", (FMT__H, zb_buf_len((buffer)))); \ - } \ - else \ - { \ - (status_) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->status = src_ptr->status; \ - if( src_ptr->status == ZB_ZCL_STATUS_SUCCESS) \ - { \ - ZB_HTOLE16(&((data_ptr)->manufacturer), &(src_ptr->manufacturer)); \ - ZB_HTOLE16(&((data_ptr)->image_type), &(src_ptr->image_type)); \ - ZB_HTOLE32(&((data_ptr)->file_version), &(src_ptr->file_version)); \ - ZB_HTOLE32(&((data_ptr)->image_size), &(src_ptr->image_size)); \ - } \ - } \ -} - -/******************************* Image Block Response ******************************/ - -/*! @brief Structure representation of Image Block Response command payload - @see ZCL8 specification, subsection 11.13.8.1 -*/ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_image_block_res_s -{ - /** Status, see @ref zcl_status */ - zb_uint8_t status; - ZB_PACKED_PRE union - { - ZB_PACKED_PRE struct - { - zb_uint16_t manufacturer; /**< Manufacturer code */ - zb_uint16_t image_type; /**< Image type */ - zb_uint32_t file_version; /**< File version */ - zb_uint32_t file_offset; /**< File offset */ - zb_uint8_t data_size; /**< Data size */ - zb_uint8_t *image_data; /**< Image data */ - - } ZB_PACKED_STRUCT success; /**< Success response. */ - - ZB_PACKED_PRE struct - { - zb_uint32_t current_time; /**< Current time */ - zb_uint32_t request_time; /**< Request time */ - zb_uint16_t delay; /**< BlockRequestDelay */ - - } ZB_PACKED_STRUCT wait_for_data; /**< Wait for data */ - - } response; /**< response data */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_image_block_res_t; - -/*! @brief Send Image Block Response command - success status, see ZCL8 specification, subsection 11.13.8 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequence - @param manufacturer - Manufacturer code - @param image_type - Image type - @param file_version - File version - @param file_offset - File offset - @param data_size - data size - @param image_data - image data -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_BLOCK_SUCCESS_RES( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq, \ - manufacturer, image_type, file_version, file_offset, data_size, image_data) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_RESP_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, ZB_ZCL_STATUS_SUCCESS); \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (manufacturer), (image_type)); \ - ZB_ZCL_PACKET_PUT_2DATA32_VAL(ptr, (file_version), (file_offset)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (data_size)); \ - ZB_ASSERT(image_data != NULL); \ - ZB_ZCL_PACKET_PUT_DATA_N(ptr, (image_data), (data_size)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, NULL); \ -} - -/*! @brief Send Image Block Response command - wait for data status, see ZCL8 specification, - subsection 11.13.8 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequence - @param current_time - Current time - @param request_time - Request time - @param delay - BlockRequestDelay -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_BLOCK_WAIT_FOR_DATA_RES( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq, \ - current_time, request_time, delay) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_RESP_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, ZB_ZCL_STATUS_WAIT_FOR_DATA); \ - ZB_ZCL_PACKET_PUT_2DATA32_VAL(ptr, (current_time), (request_time)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (delay)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, NULL); \ -} - -/*! @brief Send Image Block Response command - abort status, see ZCL8 specification, subsection 11.13.8 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequence -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_BLOCK_ABORT_RES( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_RESP_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, ZB_ZCL_STATUS_ABORT); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, NULL); \ -} - -/** @brief Macro for getting Image Block Response command, see ZCL8 specification, subsection 11.13.8 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ota_upgrade_image_block_res_s. - * @param buffer containing the packet (by pointer). - * @param status_ - variable to put parse status to (see @ref zb_zcl_parse_status_t). - * - * @note File data is placed in buffer, payload saves pointer to data only! - */ -#define ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_RES(data_ptr, buffer, status_) \ -{ \ - zb_zcl_ota_upgrade_image_block_res_t *src_ptr = \ - (zb_zcl_ota_upgrade_image_block_res_t*)zb_buf_begin((buffer)); \ - \ - if (zb_buf_len((buffer)) < sizeof(zb_uint8_t) + \ - ((src_ptr->status)==ZB_ZCL_STATUS_SUCCESS ? \ - sizeof(src_ptr->response.success) - sizeof(zb_uint8_t*)+ \ - src_ptr->response.success.data_size : 0) + \ - ((src_ptr->status)==ZB_ZCL_STATUS_WAIT_FOR_DATA ? \ - sizeof(src_ptr->response.wait_for_data) : 0) ) \ - { \ - (status_) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (status_) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->status = src_ptr->status; \ - if( src_ptr->status == ZB_ZCL_STATUS_SUCCESS) \ - { \ - ZB_HTOLE16(&((data_ptr)->response.success.manufacturer), \ - &(src_ptr->response.success.manufacturer)); \ - ZB_HTOLE16(&((data_ptr)->response.success.image_type), \ - &(src_ptr->response.success.image_type)); \ - ZB_HTOLE32(&((data_ptr)->response.success.file_version), \ - &(src_ptr->response.success.file_version)); \ - ZB_HTOLE32(&((data_ptr)->response.success.file_offset), \ - &(src_ptr->response.success.file_offset)); \ - (data_ptr)->response.success.data_size = \ - src_ptr->response.success.data_size; \ - /*ZB_MEMCPY((data_ptr)->response.success.image_data, */ \ - /* src_ptr->response.success.image_data, */ \ - /* src_ptr->response.success.data_size); */ \ - (data_ptr)->response.success.image_data = \ - (zb_uint8_t*)(&(src_ptr->response.success.image_data)); \ - } \ - if( src_ptr->status == ZB_ZCL_STATUS_WAIT_FOR_DATA) \ - { \ - ZB_HTOLE32(&((data_ptr)->response.wait_for_data.current_time), \ - &(src_ptr->response.wait_for_data.current_time)); \ - ZB_HTOLE32(&((data_ptr)->response.wait_for_data.request_time), \ - &(src_ptr->response.wait_for_data.request_time)); \ - ZB_HTOLE16(&((data_ptr)->response.wait_for_data.delay), \ - &(src_ptr->response.wait_for_data.delay)); \ - } \ - } \ -} - -/******************************* Upgrade End Response ******************************/ - -/*! @brief Structure representation of Upgrade End Response command payload - @see ZCL8 specification, subsection 11.13.9.6.1 -*/ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_upgrade_end_res_s -{ - zb_uint16_t manufacturer; /**< Manufacturer code */ - zb_uint16_t image_type; /**< Image type */ - zb_uint32_t file_version; /**< File version */ - zb_uint32_t current_time; /**< Current time */ - zb_uint32_t upgrade_time; /**< Upgrade time */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_upgrade_end_res_t; - - -/*! @brief Send Upgrade End Response command, see ZCL8 specification, subsection 11.13.9.6 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequence - @param manufacturer - Manufacturer code - @param image_type - Image type - @param file_version - File version - @param current_time - Current time - @param upgrade_time - Upgrade time -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_UPGRADE_END_RES( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq, \ - manufacturer, image_type, file_version, current_time, upgrade_time) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_OTA_UPGRADE_UPGRADE_END_RESP_ID); \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (manufacturer), (image_type)); \ - ZB_ZCL_PACKET_PUT_2DATA32_VAL(ptr, (file_version), (current_time)); \ - ZB_ZCL_PACKET_PUT_DATA32_VAL(ptr, (upgrade_time)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, NULL); \ -} - -/** @brief Macro for getting Upgrade End Response command, see ZCL8 specification, subsection 11.13.9.6 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ota_upgrade_upgrade_end_res_s. - * @param buffer containing the packet (by pointer). - * @param status_ - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_OTA_UPGRADE_GET_UPGRADE_END_RES(data_ptr, buffer, status_) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_ota_upgrade_upgrade_end_res_t) ) \ - { \ - (status_) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_ota_upgrade_upgrade_end_res_t *src_ptr = \ - (zb_zcl_ota_upgrade_upgrade_end_res_t*)zb_buf_begin((buffer)); \ - (status_) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&((data_ptr)->manufacturer), &(src_ptr->manufacturer)); \ - ZB_HTOLE16(&((data_ptr)->image_type), &(src_ptr->image_type)); \ - ZB_HTOLE32(&((data_ptr)->file_version), &(src_ptr->file_version)); \ - ZB_HTOLE32(&((data_ptr)->current_time), &(src_ptr->current_time)); \ - ZB_HTOLE32(&((data_ptr)->upgrade_time), &(src_ptr->upgrade_time)); \ - } \ -} - -/******************************* Query Specific File Response ******************************/ - -/*! @brief Structure representation of Query Specific File Response command payload - @see ZCL8 specification, subsection 11.13.11.1 -*/ -typedef ZB_PACKED_PRE struct zb_zcl_ota_upgrade_query_specific_file_res_s -{ - zb_uint8_t status; /** Status, see @ref zcl_status */ - zb_uint16_t manufacturer; /** Manufacturer code */ - zb_uint16_t image_type; /** Image type */ - zb_uint32_t file_version; /** File version */ - zb_uint32_t image_size; /** Image size */ - -} ZB_PACKED_STRUCT zb_zcl_ota_upgrade_query_specific_file_res_t; - - -/*! @brief Send Query Specific File Response command, see ZCL8 specification, subsection 11.13.11 - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequence - @param status - Status, see @ref zcl_status - @param manufacturer - Manufacturer code - @param image_type - Image type - @param file_version - File version - @param image_size - Image size -*/ -#define ZB_ZCL_OTA_UPGRADE_SEND_QUERY_SPECIFIC_FILE_RES( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq, \ - status, manufacturer, image_type, file_version, image_size) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, \ - ZB_ZCL_CMD_OTA_UPGRADE_QUERY_SPECIFIC_FILE_RESP_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (status)); \ - if( (status) == ZB_ZCL_STATUS_SUCCESS) \ - { \ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(ptr, (manufacturer), (image_type)); \ - ZB_ZCL_PACKET_PUT_2DATA32_VAL(ptr, (file_version), (image_size)); \ - } \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, NULL); \ -} - -/** @brief Macro for getting Query Specific File Response command, see ZCL8 specification, - * subsection 11.13.11 - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_ota_upgrade_query_specific_file_res_s. - * @param buffer containing the packet (by pointer). - * @param status_ - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_OTA_UPGRADE_GET_QUERY_SPECIFIC_FILE_RES(data_ptr, buffer, status_) \ -{ \ - zb_zcl_ota_upgrade_query_specific_file_res_t *src_ptr = \ - (zb_zcl_ota_upgrade_query_specific_file_res_t*)zb_buf_begin((buffer)); \ - if (zb_buf_len((buffer)) < ( (src_ptr->status)==ZB_ZCL_STATUS_SUCCESS ? \ - sizeof(zb_zcl_ota_upgrade_query_specific_file_res_t) : sizeof(zb_uint8_t) ) ) \ - { \ - (status_) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (status_) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->status = src_ptr->status; \ - if( src_ptr->status == ZB_ZCL_STATUS_SUCCESS) \ - { \ - ZB_HTOLE32(&((data_ptr)->manufacturer), &(src_ptr->manufacturer)); \ - ZB_HTOLE32(&((data_ptr)->image_type), &(src_ptr->image_type)); \ - ZB_HTOLE32(&((data_ptr)->file_version), &(src_ptr->file_version)); \ - ZB_HTOLE32(&((data_ptr)->image_size), &(src_ptr->image_size)); \ - } \ - } \ -} - -/*! @} */ /* OTA Upgrade cluster commands */ - - - -#if defined ZB_HA_ENABLE_OTA_UPGRADE_CLIENT || defined DOXYGEN - -/** @brief Declare User Application about upgrade status -*/ -typedef struct zb_zcl_ota_upgrade_value_param_s -{ - zb_uint8_t upgrade_status; /**< Upgrade status, see @ref zb_zcl_ota_upgrade_status_e */ - union - { - struct zb_zcl_ota_upgrade_start_s - { - zb_uint16_t manufacturer; /**< Manufacturer code */ - zb_uint16_t image_type; /**< Image type */ - zb_uint32_t file_version; /**< File version */ - zb_uint32_t file_length; /**< File length */ - } start; /**< Parameters for start load upgrade file */ - struct zb_zcl_ota_upgrade_receive_s - { - zb_uint32_t file_offset; /**< File offset */ - zb_uint8_t data_length; /**< Data length */ - zb_uint8_t *block_data; /**< Block data */ - } receive; /**< Parameters for receive part upgrade file */ - - } upgrade; /**< Upgrade data */ - -} zb_zcl_ota_upgrade_value_param_t; - -/** @brief Possible statuses of OTA upgrade - */ -enum zb_zcl_ota_upgrade_status_e -{ - ZB_ZCL_OTA_UPGRADE_STATUS_START, - ZB_ZCL_OTA_UPGRADE_STATUS_APPLY, - ZB_ZCL_OTA_UPGRADE_STATUS_RECEIVE, - ZB_ZCL_OTA_UPGRADE_STATUS_FINISH, - ZB_ZCL_OTA_UPGRADE_STATUS_ABORT, - ZB_ZCL_OTA_UPGRADE_STATUS_CHECK, // ask user app about received file - ZB_ZCL_OTA_UPGRADE_STATUS_OK, // user app return value - ZB_ZCL_OTA_UPGRADE_STATUS_ERROR, // user app return value - ZB_ZCL_OTA_UPGRADE_STATUS_REQUIRE_MORE_IMAGE, // user app return value - ZB_ZCL_OTA_UPGRADE_STATUS_BUSY, // user app return value. - // Application is responsible for resuming OTA Upgrade process when it - // return that error code to the OTA cluster */ - ZB_ZCL_OTA_UPGRADE_STATUS_SERVER_NOT_FOUND, // Notify an application that OTA Upgrade server not found -}; - -/** @cond internals_doc */ -#define ZB_ZCL_OTA_UPGRADE_START_USER_APP(buffer, \ - manufacturer_, image_type_, file_version_, file_length_, result) \ -{ \ - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_OTA_UPGRADE_START_USER_APP", (FMT__0)); \ - if (ZCL_CTX().device_cb) \ - { \ - zb_zcl_device_callback_param_t *user_app_data = \ - ZB_BUF_GET_PARAM(buffer, zb_zcl_device_callback_param_t); \ - zb_zcl_ota_upgrade_value_param_t *value = \ - &(user_app_data->cb_param.ota_value_param); \ - value->upgrade_status = ZB_ZCL_OTA_UPGRADE_STATUS_START; \ - value->upgrade.start.manufacturer = (manufacturer_); \ - value->upgrade.start.image_type = (image_type_); \ - value->upgrade.start.file_version = (file_version_); \ - value->upgrade.start.file_length = (file_length_); \ - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_VALUE_CB_ID; \ - user_app_data->endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); \ - user_app_data->status = RET_OK; \ - (ZCL_CTX().device_cb)(param); \ - result = value->upgrade_status; \ - } \ -} - -// NOTE file data place`s in buffer, payload saves pointer to data only! -#define ZB_ZCL_OTA_UPGRADE_RECEIVE_USER_APP(buffer, \ - file_offset_, data_length_, block_data_, result) \ -{ \ - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_OTA_UPGRADE_RECEIVE_USER_APP", (FMT__0)); \ - if (ZCL_CTX().device_cb) \ - { \ - zb_zcl_device_callback_param_t *user_app_data = \ - ZB_BUF_GET_PARAM(buffer, zb_zcl_device_callback_param_t); \ - zb_zcl_ota_upgrade_value_param_t *value = \ - &(user_app_data->cb_param.ota_value_param); \ - value->upgrade_status = ZB_ZCL_OTA_UPGRADE_STATUS_RECEIVE; \ - value->upgrade.receive.file_offset = (file_offset_); \ - value->upgrade.receive.data_length = (data_length_); \ - value->upgrade.receive.block_data = (block_data_); \ - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_VALUE_CB_ID; \ - user_app_data->endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); \ - user_app_data->status = RET_OK; \ - (ZCL_CTX().device_cb)(param); \ - result = value->upgrade_status; \ - } \ -} - -#define ZB_ZCL_OTA_UPGRADE_FINISH_USER_APP(buffer, result) \ -{ \ - zb_zcl_device_callback_param_t *user_app_data = \ - ZB_BUF_GET_PARAM(buffer, zb_zcl_device_callback_param_t); \ - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_OTA_UPGRADE_FINISH_USER_APP", (FMT__0)); \ - result = ZB_ZCL_OTA_UPGRADE_STATUS_ERROR; \ - if (ZCL_CTX().device_cb) \ - { \ - zb_zcl_ota_upgrade_value_param_t *value = \ - &(user_app_data->cb_param.ota_value_param); \ - value->upgrade_status = ZB_ZCL_OTA_UPGRADE_STATUS_FINISH; \ - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_VALUE_CB_ID; \ - user_app_data->endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); \ - user_app_data->status = RET_OK; \ - (ZCL_CTX().device_cb)(param); \ - if (user_app_data->status == RET_OK) \ - { \ - result = value->upgrade_status; \ - } \ - }else \ - { \ - result = ZB_ZCL_OTA_UPGRADE_STATUS_OK; \ - } \ -} \ - -#define ZB_ZCL_OTA_UPGRADE_APPLY_USER_APP(buffer, result) \ -{ \ - zb_zcl_device_callback_param_t *user_app_data = \ - ZB_BUF_GET_PARAM(buffer, zb_zcl_device_callback_param_t); \ - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_OTA_UPGRADE_APPLY_USER_APP", (FMT__0)); \ - result = ZB_ZCL_OTA_UPGRADE_STATUS_ERROR; \ - if (ZCL_CTX().device_cb) \ - { \ - zb_zcl_ota_upgrade_value_param_t *value = \ - &(user_app_data->cb_param.ota_value_param); \ - value->upgrade_status = ZB_ZCL_OTA_UPGRADE_STATUS_APPLY; \ - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_VALUE_CB_ID; \ - user_app_data->endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); \ - user_app_data->status = RET_OK; \ - (ZCL_CTX().device_cb)(param); \ - if (user_app_data->status == RET_OK) \ - { \ - result = value->upgrade_status; \ - } \ - }else \ - { \ - result = ZB_ZCL_OTA_UPGRADE_STATUS_OK; \ - } \ -} \ - - -#define ZB_ZCL_OTA_UPGRADE_ABORT_USER_APP(buffer) \ -{ \ - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_OTA_UPGRADE_ABORT_USER_APP", (FMT__0)); \ - if (ZCL_CTX().device_cb) \ - { \ - zb_zcl_device_callback_param_t *user_app_data = \ - ZB_BUF_GET_PARAM(buffer, zb_zcl_device_callback_param_t); \ - zb_zcl_ota_upgrade_value_param_t *value = \ - &(user_app_data->cb_param.ota_value_param); \ - value->upgrade_status = ZB_ZCL_OTA_UPGRADE_STATUS_ABORT; \ - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_VALUE_CB_ID; \ - user_app_data->endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); \ - user_app_data->status = RET_OK; \ - (ZCL_CTX().device_cb)(param); \ - } \ -} - -#define ZB_ZCL_OTA_UPGRADE_CHECK_USER_APP(buffer, result) \ -{ \ - zb_zcl_device_callback_param_t *user_app_data = \ - ZB_BUF_GET_PARAM(buffer, zb_zcl_device_callback_param_t); \ - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_OTA_UPGRADE_CHECK_USER_APP", (FMT__0)); \ - result = ZB_ZCL_OTA_UPGRADE_STATUS_ERROR; \ - if (ZCL_CTX().device_cb) \ - { \ - zb_zcl_ota_upgrade_value_param_t *value = \ - &(user_app_data->cb_param.ota_value_param); \ - value->upgrade_status = ZB_ZCL_OTA_UPGRADE_STATUS_CHECK; \ - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_VALUE_CB_ID; \ - user_app_data->endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); \ - user_app_data->status = RET_OK; \ - (ZCL_CTX().device_cb)(param); \ - if (user_app_data->status == RET_OK) \ - { \ - result = value->upgrade_status; \ - } \ - }else \ - { \ - result = ZB_ZCL_OTA_UPGRADE_STATUS_OK; \ - } \ -} \ - -#define ZB_ZCL_OTA_UPGRADE_SERVER_NOT_FOUND_USER_APP(buffer) \ -{ \ - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_OTA_UPGRADE_SERVER_NOT_FOUND_USER_APP", (FMT__0)); \ - if (ZCL_CTX().device_cb) \ - { \ - zb_zcl_device_callback_param_t *user_app_data = \ - ZB_BUF_GET_PARAM(buffer, zb_zcl_device_callback_param_t); \ - zb_zcl_ota_upgrade_value_param_t *value = \ - &(user_app_data->cb_param.ota_value_param); \ - value->upgrade_status = ZB_ZCL_OTA_UPGRADE_STATUS_SERVER_NOT_FOUND; \ - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_VALUE_CB_ID; \ - user_app_data->endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); \ - user_app_data->status = RET_OK; \ - (ZCL_CTX().device_cb)(param); \ - } \ -} - -void zb_zcl_ota_upgrade_set_ota_status(zb_uint8_t endpoint, zb_uint8_t status); - -zb_uint8_t zb_zcl_ota_upgrade_get_ota_status(zb_uint8_t endpoint); - -zb_uint8_t zb_zcl_process_ota_upgrade_default_response_commands(zb_uint8_t param); - -void zb_zcl_ota_upgrade_send_upgrade_end_req(zb_uint8_t param, zb_uint8_t status); - -void zb_zcl_ota_restart_after_rejoin(zb_uint8_t endpoint); - -void zb_zcl_ota_set_file_size(zb_uint8_t endpoint, zb_uint32_t size); - -zb_uint8_t zb_zcl_ota_upgrade_get8(zb_uint8_t endpoint, zb_uint16_t attr_id); - -zb_uint16_t zb_zcl_ota_upgrade_get16(zb_uint8_t endpoint, zb_uint16_t attr_id); - -zb_uint32_t zb_zcl_ota_upgrade_get32(zb_uint8_t endpoint, zb_uint16_t attr_id); -/*! @} - * @endcond */ /* internals_doc */ - -zb_ret_t zb_zcl_check_value_ota_upgrade(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -/*! @brief Abort OTA Upgrade process - * - * @param endpoint - endpoint for OTA Upgrade - * @param param - buffer to be aborted - */ -void zcl_ota_abort(zb_uint8_t endpoint, zb_uint8_t param); - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_WWAH -void zcl_ota_abort_and_set_tc(zb_uint8_t param); -#endif - -#endif /* defined ZB_HA_ENABLE_OTA_UPGRADE_CLIENT || defined DOXYGEN */ - -#if defined ZB_ENABLE_HA -zb_uint8_t zb_zcl_get_cmd_list_ota_upgrade(zb_bool_t is_client_generated, zb_uint8_t **cmd_list); -#endif /* defined ZB_ENABLE_HA */ - -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE || defined DOXYGEN */ -/*! @} */ /* ZCL OTA Upgrade cluster definitions */ - -#ifdef ZB_HA_ENABLE_OTA_UPGRADE_CLIENT -#define ZCL_OTA_MAX_RESEND_RETRIES 3 - -typedef struct zb_zcl_ota_upgrade_cli_ctx_s -{ - zb_zcl_parsed_hdr_t cmd_info_2; - zb_zcl_ota_upgrade_image_block_res_t payload_2; - zb_uint_t resend_retries; - zb_uint8_t ota_restart_after_rejoin; - zb_uint16_t ota_period_backup; -} zb_zcl_ota_upgrade_cli_ctx_t; -#endif - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_ota_upgrade_init_srv(void); -void zb_zcl_ota_upgrade_init_cli(void); - -/** - * Sends Query Next Image Response. - * Should be used only in the following case: - * If application can't return a table index immediately from user app callback - * (which is called by query_next_image_handler()) - * then it should return RET_BLOCKED status and should call zb_zcl_ota_upgrade_send_query_next_image_response(). - * If there is no image available application should call this function with image_present parameter - * set to ZB_FALSE. - * - * @param zcl_parsed_hdr - the header of the Query Next Image packet - * @param image_present - whether the image is present - * @param table_idx - a table index of the image if image_present is ZB_TRUE - * - * @return nothing - */ -void zb_zcl_ota_upgrade_send_query_next_image_response(zb_zcl_parsed_hdr_t *zcl_parsed_hdr, zb_bool_t image_present, zb_uindex_t table_idx); - -/** - * Sends Image Block Response - * Should be used only in the following case: - * If application can't return a pointer to the requested block immediately on request - * it should return RET_BLOCKED status and should call zb_zcl_ota_upgrade_send_image_block_response() - * If there is no block available application should call this function with block_present parameter - * set to ZB_FALSE. - * - * @param zcl_header - the header of the request packet - * @param table_idx - the index of requested block image - * @param block_present - whether the block is present - * @param offset - an offset in the image - * @param data_size - size of the provided block - * @param data - a pointer to the requested data - * - * @return nothing - */ -void zb_zcl_ota_upgrade_send_image_block_response(zb_zcl_parsed_hdr_t *zcl_header, zb_uindex_t table_idx, - zb_bool_t block_present, - zb_uint32_t offset, zb_uint8_t data_size, - const zb_uint8_t* data); - -#define ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_SERVER_ROLE_INIT zb_zcl_ota_upgrade_init_srv -#define ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_CLIENT_ROLE_INIT zb_zcl_ota_upgrade_init_cli - -#endif /* ZB_ZCL_OTA_UPGRADE_H */ diff --git a/zboss/development/include/zcl/zb_zcl_poll_control.h b/zboss/development/include/zcl/zb_zcl_poll_control.h deleted file mode 100644 index 467ba8875d..0000000000 --- a/zboss/development/include/zcl/zb_zcl_poll_control.h +++ /dev/null @@ -1,692 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Poll Control cluster definitions -*/ - -#ifndef ZB_ZCL_POLL_CONTROL_H -#define ZB_ZCL_POLL_CONTROL_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_POLL_CONTROL - * @{ - * @details - * All commands in the cluster have only request form, and carry no payload. - * - */ - -#if defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN - -/*! @brief Schedule poll control process on given endpoint - * First check-in will occur after one check-in interval - * Poll Controll process also starts automatically during ZCL periodic activities - * initialization if Poll Control server cluster is declared - * @param param - buffer for check-in command - * @param endpoint - endpoint to start poll control process on */ -void zb_zcl_poll_control_start(zb_uint8_t param, zb_uint8_t endpoint); - - -/** - * @brief Stop Poll control processing - * - * Checking already scheduled will be canceled - * @return reference to buffer which was previously reserved for check-in. - * It must be reused or explicitly freed. - */ -zb_uint8_t zb_zcl_poll_control_stop(void); - - -/*! @brief Start Poll Control process on Server side - * @param param - buffer for Poll Process -*/ -void zb_zcl_poll_control_start_check_in(zb_uint8_t param); - -/** - @brief Register callback for Poll control cluster. - - This callback will be called when check-in command is sent. - - @param cb - pointer to callback - */ -void zb_zcl_poll_controll_register_cb(zb_callback_t cb); - - -#endif /* defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN */ - -/* Cluster ZB_ZCL_CLUSTER_ID_POLL_CONTROL */ - -/** - * @name Poll Control cluster attribute identifiers - * @anchor zcl_poll_control_attr - * @see HA spec, Poll Control Cluster 9.5.4.1 - * - * Note: These values were members of `enum zb_zcl_poll_control_attr_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -/** Check-in Interval attribute, HA spec 9.5.4.1.1 */ -#define ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID 0x0000U -/** Long Poll Interval attribute, HA spec 9.5.4.1.2 */ -#define ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID 0x0001U -/** Short Poll Interval attribute, HA spec 9.5.4.1.3 */ -#define ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID 0x0002U -/** Fast Poll Timeout attribute, HA spec 9.5.4.1. */ -#define ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_TIMEOUT_ID 0x0003U -/** Check-in Interval Min attribute, HA spec 9.5.4.1.4 */ -#define ZB_ZCL_ATTR_POLL_CONTROL_MIN_CHECKIN_INTERVAL_ID 0x0004U -/** Long Poll Interval Min attribute, HA spec 9.5.4.1.5 */ -#define ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_MIN_INTERVAL_ID 0x0005U -/** Fast Poll Timeout Max attribute, HA spec 9.5.4.1.6 */ -#define ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_MAX_TIMEOUT_ID 0x0006U - -/** Status Data - custom non-spec parameters */ -#define ZB_ZCL_ATTR_POLL_CONTROL_STATUS_DATA_ID 0xefffU -/** Status Data - custom non-spec parameters for server side */ -#define ZB_ZCL_ATTR_POLL_CONTROL_ADDR_DATA_ID 0xeffeU -/** @} */ - -/** @name Poll Control cluster attributes */ -/** @{ */ - -/** @brief Default value for Poll Control cluster revision global attribute */ -#define ZB_ZCL_POLL_CONTROL_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/** @brief Value for stop Check-in process for Check-in Interval attribute */ -#define ZB_ZCL_POLL_CONTROL_CHECKIN_INTERVAL_NO_CHECK_IN_VALUE 0x0000 - -/** @brief Default value for Check-in Interval attribute */ -#define ZB_ZCL_POLL_CONTROL_CHECKIN_INTERVAL_DEFAULT_VALUE 0x3840 - -/** @brief Maximum value for Check-in Interval attribute */ -#define ZB_ZCL_POLL_CONTROL_CHECKIN_INTERVAL_MAX_VALUE 0x6e0000 - -/** @brief Minimum value for Long Poll Interval attribute */ -#define ZB_ZCL_POLL_CONTROL_LONG_POLL_INTERVAL_MIN_VALUE ZB_PIM_MINIMUM_LONG_POLL_INTERVAL_IN_QS - -/** @brief Default value for Long Poll Interval attribute */ -#define ZB_ZCL_POLL_CONTROL_LONG_POLL_INTERVAL_DEFAULT_VALUE ZB_PIM_DEFAULT_LONG_POLL_INTERVAL_IN_QS - -/** @brief Maximum value for Long Poll Interval attribute */ -#define ZB_ZCL_POLL_CONTROL_LONG_POLL_INTERVAL_MAX_VALUE ZB_PIM_MAXIMUM_LONG_POLL_INTERVAL_IN_QS - -/** @brief Minimum value for Short Poll Interval attribute */ -#define ZB_ZCL_POLL_CONTROL_SHORT_POLL_INTERVAL_MIN_VALUE ZB_PIM_MINIMUM_SHORT_POLL_INTERVAL_IN_QS - -/** @brief Default value for Short Poll Interval attribute */ -#define ZB_ZCL_POLL_CONTROL_SHORT_POLL_INTERVAL_DEFAULT_VALUE ZB_PIM_DEFAULT_SHORT_POLL_INTERVAL_IN_QS - -/** @brief Maximum value for Short Poll Interval attribute */ -#define ZB_ZCL_POLL_CONTROL_SHORT_POLL_INTERVAL_MAX_VALUE ZB_PIM_MAXIMUM_SHORT_POLL_INTERVAL_IN_QS - -/** @brief Minimum value for Fast Poll Timeout attribute */ -#define ZB_ZCL_POLL_CONTROL_FAST_POLL_TIMEOUT_MIN_VALUE 0x01 - -/** @brief Default value for Fast Poll Timeout attribute */ -#define ZB_ZCL_POLL_CONTROL_FAST_POLL_TIMEOUT_DEFAULT_VALUE 0x0028 - -/** @brief Maximum value for Fast Poll Timeout attribute */ -#define ZB_ZCL_POLL_CONTROL_FAST_POLL_TIMEOUT_MAX_VALUE 0xffff - -/** @brief Default value for CheckinIntervalMin attribute */ -#define ZB_ZCL_POLL_CONTROL_CHECKIN_MIN_INTERVAL_DEFAULT_VALUE ((zb_uint32_t)0) - -/** @brief Default value for LongPollIntervalMin attribute */ -#define ZB_ZCL_POLL_CONTROL_LONG_POLL_MIN_INTERVAL_DEFAULT_VALUE ((zb_uint32_t)0) - -/** @brief Default value for FastPollTimeoutMax attribute */ -#define ZB_ZCL_POLL_CONTROL_FAST_POLL_MAX_TIMEOUT_DEFAULT_VALUE ((zb_uint16_t)0) -/** @} */ - -/** @cond DOXYGEN_INTERNAL_DOC */ -/** @name Poll Control cluster internals - * Internal structures for attribute representation in cluster definitions. */ -/** @{ */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_TIMEOUT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_TIMEOUT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POLL_CONTROL_MIN_CHECKIN_INTERVAL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POLL_CONTROL_MIN_CHECKIN_INTERVAL_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_MIN_INTERVAL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_MIN_INTERVAL_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_MAX_TIMEOUT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_MAX_TIMEOUT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POLL_CONTROL_STATUS_DATA_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POLL_CONTROL_STATUS_DATA_ID, \ - ZB_ZCL_ATTR_TYPE_NULL, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POLL_CONTROL_ADDR_DATA_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POLL_CONTROL_ADDR_DATA_ID, \ - ZB_ZCL_ATTR_TYPE_NULL, \ - ZB_ZCL_ATTR_ACCESS_INTERNAL, \ - (void*) data_ptr \ -} - - -/*! @brief Structure representation of Client Status attributes */ -typedef ZB_PACKED_PRE struct zb_zcl_poll_control_client_status_s -{ - /** Client is In Poll Mode */ - zb_bool_t is_poll_mode; - /** Client Fast Poll timeout*/ - zb_uint16_t fast_poll_timeout; - -} ZB_PACKED_STRUCT zb_zcl_poll_control_client_status_t; - - -#define ZB_ZCL_POLL_CTRL_INVALID_ADDR 0xFFFF -#define ZB_ZCL_POLL_INVALID_EP 0xFF -/*! @brief Address information that is used for sending check-in command */ -/* Currently not only address info is stored - also status information */ -typedef struct zb_zcl_poll_control_srv_cfg_data_s -{ - /** Short address of the Poll control client */ - zb_uint16_t poll_addr; - /** Endpoint number of the Poll control client */ - zb_uint8_t poll_ep; - /** Flag to check if check-in command is being sent currently */ - zb_bitfield_t sending_cmd:4; - /** Flag to determine fast poll mode / long poll mode */ - zb_bitfield_t fast_poll_mode:1; -} -zb_zcl_poll_control_srv_cfg_data_t; - -/** @brief Default value for Fast Poll Timeout for Client command */ -#define ZB_ZCL_POLL_CONTROL_FAST_POLL_TIMEOUT_CLIENT_DEFAULT_VALUE 0x00f0 - -/*! @internal Number of attributes mandatory for reporting in Poll Control cluster */ -#define ZB_ZCL_POLL_CONTROL_REPORT_ATTR_COUNT 0 - -/** @} */ -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ /* Poll Control cluster internals */ - -/** @name Poll Control cluster attributes */ -/** @{ */ - -/** @brief Declare attribute list for Poll Control cluster - server side - @param attr_list - attribute list name - @param checkin_interval - pointer to variable to store Check-in Interval attribute - @param long_poll_interval - pointer to variable to store Long Poll Interval attribute - @param short_poll_interval - pointer to variable to store Short Poll Interval attribute - @param fast_poll_timeout - pointer to variable to store Fast Poll Timeout attribute - @param checkin_interval_min - pointer to variable to store Check-in Interval Min attribute - @param long_poll_interval_min- pointer to variable to store Long Poll Interval Min attribute - @param fast_poll_timeout_max - pointer to variable to store Fast Poll Timeout Max attribute -*/ -#define ZB_ZCL_DECLARE_POLL_CONTROL_ATTRIB_LIST(attr_list, \ - checkin_interval, long_poll_interval, short_poll_interval, fast_poll_timeout, \ - checkin_interval_min, long_poll_interval_min, fast_poll_timeout_max) \ - zb_zcl_poll_control_srv_cfg_data_t srv_cfg_data_ctx_##attr_list = \ - { ZB_ZCL_POLL_CTRL_INVALID_ADDR, ZB_ZCL_POLL_INVALID_EP, 0, 0 }; \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_POLL_CONTROL) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID, (checkin_interval)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID, (long_poll_interval)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID, (short_poll_interval)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_TIMEOUT_ID, (fast_poll_timeout)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POLL_CONTROL_MIN_CHECKIN_INTERVAL_ID, (checkin_interval_min)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_MIN_INTERVAL_ID, (long_poll_interval_min)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_MAX_TIMEOUT_ID, (fast_poll_timeout_max)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POLL_CONTROL_ADDR_DATA_ID, &(srv_cfg_data_ctx_##attr_list)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @brief Declare attribute list for Poll Control cluster - client side - @param attr_list - attribute list name -*/ -#define ZB_ZCL_DECLARE_POLL_CONTROL_ATTRIB_LIST_CLIENT(attr_list) \ - zb_zcl_poll_control_client_status_t client_status_data_ctx_##attr_list = \ - { ZB_FALSE, ZB_ZCL_POLL_CONTROL_FAST_POLL_TIMEOUT_CLIENT_DEFAULT_VALUE }; \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_POLL_CONTROL) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POLL_CONTROL_STATUS_DATA_ID, \ - (&(client_status_data_ctx_##attr_list))) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ /* Poll Control cluster attributes */ - -/** @name Poll Control cluster commands */ -/** @{ */ - -/*! @brief Poll Control cluster command identifiers - @see HA spec, Poll Control Cluster, 9.5.4.3 -*/ -enum zb_zcl_poll_control_cmd_e -{ - ZB_ZCL_CMD_POLL_CONTROL_CHECK_IN_ID = 0x00 /**< "Check-in" command. HA spec 9.5.4.4 */ -}; - -/*! @brief Poll Control cluster response command identifiers - @see HA spec, Poll Control Cluster, 9.5.5.2 -*/ -enum zb_zcl_poll_control_resp_cmd_e -{ - ZB_ZCL_CMD_POLL_CONTROL_CHECK_IN_RESPONSE_ID = 0x00, /**< "Check-in response" command, HA spec 9.5.5.3 */ - ZB_ZCL_CMD_POLL_CONTROL_FAST_POLL_STOP_ID = 0x01, /**< "Fast Poll Stop" command, HA spec 9.5.5.4 */ - ZB_ZCL_CMD_POLL_CONTROL_SET_LONG_POLL_INTERVAL_ID = 0x02, /**< "Set Long Poll Interval" command, HA spec 9.5.5.5 */ - ZB_ZCL_CMD_POLL_CONTROL_SET_SHORT_POLL_INTERVAL_ID = 0x03, /**< "Set Short Poll Interval" command, HA spec 9.5.5.6 */ -}; - -/** @cond DOXYGEN_INTERNAL_DOC */ -/* Poll control cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_POLL_CONTROL_SERVER_ROLE_GENERATED_CMD_LIST ZB_ZCL_CMD_POLL_CONTROL_CHECK_IN_ID - -#define ZB_ZCL_CLUSTER_ID_POLL_CONTROL_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_POLL_CONTROL_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_POLL_CONTROL_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_POLL_CONTROL_CHECK_IN_RESPONSE_ID, \ - ZB_ZCL_CMD_POLL_CONTROL_FAST_POLL_STOP_ID, \ - ZB_ZCL_CMD_POLL_CONTROL_SET_LONG_POLL_INTERVAL_ID, \ - ZB_ZCL_CMD_POLL_CONTROL_SET_SHORT_POLL_INTERVAL_ID - -#define ZB_ZCL_CLUSTER_ID_POLL_CONTROL_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_POLL_CONTROL_CLIENT_ROLE_GENERATED_CMD_LIST -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/******************************* Check-in ******************************/ - -/*! @brief Send Check-in command, see HA spec 9.5.4.4 - @param _buffer - to put packet to - @param _dst_addr - destination address - @param _dst_addr_mode - addressing mode - @param _dst_ep - destination endpoint - @param _local_ep - source endpoint - @param _prfl_id - profile identifier - @param _cb - callback for getting command send status -*/ -#define ZB_ZCL_POLL_CONTROL_SEND_CHECK_IN_REQ( \ - _buffer, _dst_addr, _dst_addr_mode, _dst_ep, _local_ep, _prfl_id, _cb) \ -{ \ - zb_uint8_t* _ptr = ZB_ZCL_START_PACKET(_buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(_ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_POLL_CONTROL_CHECK_IN_ID); \ - ZB_ZCL_FINISH_PACKET((_buffer), _ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - _buffer, _dst_addr, _dst_addr_mode, _dst_ep, _local_ep, _prfl_id, \ - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, _cb); \ -} - -/*! @brief Parameters to pass to device callback for incoming check in */ -typedef struct zb_zcl_poll_control_check_in_cli_param_s -{ - zb_uint16_t fast_poll_timeout; - zb_uint16_t short_addr; - zb_uint8_t ep; -} -zb_zcl_poll_control_check_in_cli_param_t; - -/** @cond DOXYGEN_INTERNAL_DOC */ -#define ZB_ZCL_POLL_CONTROL_CLI_CALL_USER_APP( \ - _buffer, _short_addr, _ep, _fast_poll_timeout, _result) \ -{ \ - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_POLL_CONTROL_CLI_CALL_USER_APP", (FMT__0)); \ - if (ZCL_CTX().device_cb) \ - { \ - zb_zcl_device_callback_param_t *user_app_data = \ - ZB_BUF_GET_PARAM((_buffer), zb_zcl_device_callback_param_t); \ - zb_zcl_poll_control_check_in_cli_param_t *value = \ - &(user_app_data->cb_param.checkin_cli_param); \ - value->fast_poll_timeout = (_fast_poll_timeout); \ - value->short_addr = (_short_addr); \ - value->ep = (_ep); \ - user_app_data->device_cb_id = ZB_ZCL_POLL_CONTROL_CHECK_IN_CLI_CB_ID; \ - user_app_data->endpoint = (_ep); \ - user_app_data->status = RET_OK; \ - (ZCL_CTX().device_cb)(param); \ - _result = user_app_data->status; \ - } \ - else \ - { \ - _result = RET_OK; \ - } \ -} -/** @endcond */ /* DOXYGEN_INTERNAL_DOC */ - -/******************************* Check-in response ******************************/ - -/*! @brief Structure representation of Check-in response command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_poll_control_check_in_res_s -{ - /** Start Fast Polling */ - zb_uint8_t is_start; - /** Fast Poll Timeout */ - zb_uint16_t timeout; -} ZB_PACKED_STRUCT zb_zcl_poll_control_check_in_res_t; - -/*! @brief Send "Check-in response" command, see HA spec 9.5.5.3 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback - @param is_start - Start Fast Polling - @param timeout - Fast Poll Timeout -*/ -#define ZB_ZCL_POLL_CONTROL_SEND_CHECK_IN_RES( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - is_start, timeout) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_POLL_CONTROL_CHECK_IN_RESPONSE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (is_start)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (timeout)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, cb); \ -} - -/** @brief Macro for getting Check-in response command - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_poll_control_check_in_res_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_POLL_CONTROL_GET_CHECK_IN_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_poll_control_check_in_res_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_poll_control_check_in_res_t *src_ptr = \ - (zb_zcl_poll_control_check_in_res_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (data_ptr)->is_start = src_ptr->is_start; \ - ZB_HTOLE16(&((data_ptr)->timeout), &(src_ptr->timeout)); \ - } \ -} - -/******************************* Fast Poll Stop ******************************/ - -/*! @brief Send "Fast Poll Stop" command, see HA spec 9.5.5.4 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback -*/ -#define ZB_ZCL_POLL_CONTROL_SEND_FAST_POLL_STOP_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_POLL_CONTROL_FAST_POLL_STOP_ID); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, cb); \ -} - -/******************************* Set Long Poll Interval ******************************/ - -/*! @brief Structure representation of Set Long Poll Interval command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_poll_control_set_long_poll_interval_req_s -{ - /** New Long Poll Interval */ - zb_uint32_t interval; -} ZB_PACKED_STRUCT zb_zcl_poll_control_set_long_poll_interval_t; - - -/*! @brief Send "Set Long Poll Interval" command, see HA spec 9.5.5.5 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback - @param interval - New Long Poll Interval -*/ -#define ZB_ZCL_POLL_CONTROL_SEND_SET_LONG_POLL_INTERVAL_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, interval) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_POLL_CONTROL_SET_LONG_POLL_INTERVAL_ID); \ - ZB_ZCL_PACKET_PUT_DATA32_VAL(ptr, (interval)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, cb); \ -} - -/** @brief Macro for getting "Set Long Poll Interval" command - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_poll_control_set_long_poll_interval_t. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_POLL_CONTROL_GET_SET_LONG_POLL_INTERVAL_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_poll_control_set_long_poll_interval_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_poll_control_set_long_poll_interval_t *src_ptr = \ - (zb_zcl_poll_control_set_long_poll_interval_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE32(&((data_ptr)->interval), &(src_ptr->interval)); \ - } \ -} - -/******************************* Set Short Poll Interval ******************************/ - -/*! @brief Structure representation of Set Short Poll Interval command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_poll_control_set_short_poll_interval_req_s -{ - /** New Short Poll Interval */ - zb_uint16_t interval; -} ZB_PACKED_STRUCT zb_zcl_poll_control_set_short_poll_interval_t; - - -/*! @brief Send "Set Short Poll Interval" command, see HA spec 9.5.5.6 - @param buffer to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback - @param interval - New Short Poll Interval -*/ -#define ZB_ZCL_POLL_CONTROL_SEND_SET_SHORT_POLL_INTERVAL_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, interval) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_POLL_CONTROL_SET_SHORT_POLL_INTERVAL_ID); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (interval)); \ - ZB_ZCL_FINISH_PACKET((buffer), ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, \ - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, cb); \ -} - -/** @brief Macro for getting "Set Short Poll Interval" command - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zcl_poll_control_set_short_poll_interval_t. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZCL_POLL_CONTROL_GET_SET_SHORT_POLL_INTERVAL_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zcl_poll_control_set_short_poll_interval_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zcl_poll_control_set_short_poll_interval_t *src_ptr = \ - (zb_zcl_poll_control_set_short_poll_interval_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&((data_ptr)->interval), &(src_ptr->interval)); \ - } \ -} - -#if defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN - -/** - * @brief Set client address information. This address is used to - * send Check-in command. If address information is NOT sent, - * check-in command will be sent assuming binding with client is - * created - * @param local_ep - local endpoint number, is used to find particular attribute - * @param addr - poll control client short address - * @param ep - poll control client end point - * @return RET_ERROR if addr is not a TC (WWAH requirement). - * RET_OK otherwise. - */ -zb_ret_t zb_zcl_poll_control_set_client_addr(zb_uint8_t local_ep, zb_uint16_t addr, zb_uint8_t ep); -#endif - -#if defined ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL || defined DOXYGEN -/** - @brief Function is used by Poll control client to set Fast poll - timeout value. This value is included into Check-in response - command - @param ep - local endpoint number, running Poll control client - @param fast_poll_timeout - Fast poll timeout value (in quarterseconds) -*/ -void zb_zcl_set_fast_poll_timeout(zb_uint8_t ep, zb_uint16_t fast_poll_timeout); - -#if defined ZB_USE_NVRAM || defined DOXYGEN -/** - @brief Save to NVRAM Poll Control dataset - @param param - @note ignore param, set it to 0 -*/ -void zb_zcl_poll_control_save_nvram(zb_uint8_t param); -#endif /* ZB_USE_NVRAM */ -#endif /* ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL */ - -/*! @} */ /* Poll Control cluster commands */ - -/*! @} */ /* ZCL Poll Control cluster definitions */ - -#if defined ZB_ENABLE_HA - -zb_uint8_t zb_zcl_get_cmd_list_poll_control(zb_bool_t is_client_generated, zb_uint8_t **cmd_list); - -#endif /* defined ZB_ENABLE_HA */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#if defined ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL -void zb_zcl_poll_control_init_server(void); -void zb_zcl_poll_control_init_client(void); -#define ZB_ZCL_CLUSTER_ID_POLL_CONTROL_SERVER_ROLE_INIT zb_zcl_poll_control_init_server -#define ZB_ZCL_CLUSTER_ID_POLL_CONTROL_CLIENT_ROLE_INIT zb_zcl_poll_control_init_client -#endif /* ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL */ - -#endif /* ZB_ZCL_POLL_CONTROL_H */ diff --git a/zboss/development/include/zcl/zb_zcl_power_config.h b/zboss/development/include/zcl/zb_zcl_power_config.h deleted file mode 100644 index f87105a18b..0000000000 --- a/zboss/development/include/zcl/zb_zcl_power_config.h +++ /dev/null @@ -1,739 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Power Configuration cluster definitions -*/ - -#ifndef ZB_ZCL_POWER_CONFIG_H -#define ZB_ZCL_POWER_CONFIG_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_POWER_CONFIG - * @{ - */ - -/** - * @brief Hook on Write attribute - * @param endpoint - endpoint number - * @param attr_id - ID of attribute being written - * @param new_value - pointer to new value of attribute - */ -void zb_zcl_power_config_write_attr_hook(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -/* Cluster ZB_ZCL_CLUSTER_ID_POWER_CONFIG */ - -/*! @name Power Configuration cluster attributes - @{ -*/ - -/*! @brief Power Configuration cluster attribute identifiers - @see ZCL spec, Power Configuration Cluster 3.3.2.2 -*/ -enum zb_zcl_power_config_attr_e -{ - /** @brief MainsVoltage attribute, ZCL spec 3.3.2.2.1.1 */ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_ID = 0x0000, - /** @brief MainsFrequency attribute, ZCL spec 3.3.2.2.1.2 */ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_FREQUENCY_ID = 0x0001, - /** @brief MainsAlarmMask attribute, ZCL spec 3.3.2.2.2.1 */ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_ALARM_MASK_ID = 0x0010, - /** @brief MainsVoltageMinThreshold attribute, ZCL spec 3.3.2.2.2.2 */ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD = 0x0011, - /** @brief MainsVoltageMaxThreshold attribute, ZCL spec 3.3.2.2.2.3 */ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD = 0x0012, - /** @brief MainsVoltageDwellTripPoint attribute, ZCL spec 3.3.2.2.2.4 */ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_DWELL_TRIP_POINT = 0x0013, - - /** @brief BatteryVoltage attribute, ZCL spec 3.3.2.2.3.1 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_ID = 0x0020, - /*! @brief BatteryPercentageRemaining attribute, ZCL spec 3.3.2.2.3.2 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID = 0x0021, - - /** The BatteryManufacturer attribute is a maximum of 16 bytes in length - * and specifies the name of the battery manufacturer as a character string. */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_MANUFACTURER_ID = 0x0030, - /** @brief BatterySize attribute, ZCL spec 3.3.2.2.4.2 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_SIZE_ID = 0x0031, - /** The BatteryAHrRating attribute is 16 bits in length and specifies - * the Ampere-hour rating of the battery, measured in units of 10mAHr. */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_A_HR_RATING_ID = 0x0032, - /** @brief BatteryQuantity attribute, ZCL spec 3.3.2.2.4.4 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_QUANTITY_ID = 0x0033, - /** @brief BatteryRatedVoltage attribute, ZCL spec 3.3.2.2.4.5 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_RATED_VOLTAGE_ID = 0x0034, - /** @brief BatteryAlarmMask attribute, ZCL spec 3.3.2.2.4.6 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_ALARM_MASK_ID = 0x0035, - /** @brief BatteryVoltageMinThreshold attribute, ZCL spec 3.3.2.2.4.7 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_MIN_THRESHOLD_ID = 0x0036, - /*! @brief BatteryVoltageThreshold1 attribute, ZCL spec 3.3.2.2.4.8 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD1_ID = 0x0037, - /*! @brief BatteryVoltageThreshold2 attribute, ZCL spec 3.3.2.2.4.8 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD2_ID = 0x0038, - /*! @brief BatteryVoltageThreshold3 attribute, ZCL spec 3.3.2.2.4.8 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD3_ID = 0x0039, - - /*! @brief BatteryPercentageMinThreshold attribute, ZCL spec 3.3.2.2.4.9 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_MIN_THRESHOLD_ID = 0x003a, - - /*! @brief BatteryPercentageThreshold1 attribute, ZCL spec 3.3.2.2.4.10 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD1_ID = 0x003b, - /*! @brief BatteryPercentageThreshold2 attribute, ZCL spec 3.3.2.2.4.10 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD2_ID = 0x003c, - /*! @brief BatteryPercentageThreshold3 attribute, ZCL spec 3.3.2.2.4.10 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD3_ID = 0x003d, - - /*! @brief BatteryAlarmState attribute, ZCL spec 3.3.2.2.4.11 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_ALARM_STATE_ID = 0x003e, - - /*! @brief Battery Information 2 attribute set, ZCL spec 3.3.2.2.5 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_VOLTAGE_ID = 0x0040, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_PERCENTAGE_REMAINING_ID = 0x0041, - - /*! @brief Battery Settings 2 attribute set, ZCL spec 3.3.2.2.6 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_MANUFACTURER_ID = 0x0050, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_SIZE_ID = 0x0051, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_A_HR_RATING_ID = 0x0052, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_QUANTITY_ID = 0x0053, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_RATED_VOLTAGE_ID = 0x0054, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_ALARM_MASK_ID = 0x0055, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_VOLTAGE_MIN_THRESHOLD_ID = 0x0056, - - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_VOLTAGE_THRESHOLD1_ID = 0x0057, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_VOLTAGE_THRESHOLD2_ID = 0x0058, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_VOLTAGE_THRESHOLD3_ID = 0x0059, - - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_PERCENTAGE_MIN_THRESHOLD_ID = 0x005a, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_PERCENTAGE_THRESHOLD1_ID = 0x005b, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_PERCENTAGE_THRESHOLD2_ID = 0x005c, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_PERCENTAGE_THRESHOLD3_ID = 0x005d, - - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_ALARM_STATE_ID = 0x005e, - - /*! @brief Battery Information 3 attribute set, ZCL spec 3.3.2.2.7 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_VOLTAGE_ID = 0x0060, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_PERCENTAGE_REMAINING_ID = 0x0061, - - /*! @brief Battery Settings 3 attribute set, ZCL spec 3.3.2.2.8 */ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_MANUFACTURER_ID = 0x0070, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_SIZE_ID = 0x0071, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_A_HR_RATING_ID = 0x0072, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_QUANTITY_ID = 0x0073, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_RATED_VOLTAGE_ID = 0x0074, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_ALARM_MASK_ID = 0x0075, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_VOLTAGE_MIN_THRESHOLD_ID = 0x0076, - - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_VOLTAGE_THRESHOLD1_ID = 0x0077, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_VOLTAGE_THRESHOLD2_ID = 0x0078, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_VOLTAGE_THRESHOLD3_ID = 0x0079, - - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_PERCENTAGE_MIN_THRESHOLD_ID = 0x007a, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_PERCENTAGE_THRESHOLD1_ID = 0x007b, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_PERCENTAGE_THRESHOLD2_ID = 0x007c, - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_PERCENTAGE_THRESHOLD3_ID = 0x007d, - - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_ALARM_STATE_ID = 0x007e, - /** @cond internals_doc */ - /* Custom attributes */ - ZB_ZCL_ATTR_POWER_CONFIG_CUSTOM_BATTERY_VOLTAGE_SHARP_ID = 0x8020 - /*! @} - * @endcond */ /* internals_doc */ -}; - -/** - * @brief Power Configuration MainsAlarmMask value - * see ZCL spec 3.3.2.2.4.7 - */ -enum zb_zcl_power_config_mains_alarm_mask_e -{ - /** @brief MainsAlarmMask - Mains Voltage too low */ - ZB_ZCL_POWER_CONFIG_MAINS_ALARM_MASK_VOLTAGE_LOW = 0x01, - /** @brief MainsAlarmMask - Mains Voltage too high */ - ZB_ZCL_POWER_CONFIG_MAINS_ALARM_MASK_VOLTAGE_HIGH = 0x02, - /** @brief MainsAlarmMask - Mains power supply lost/unavailable */ - ZB_ZCL_POWER_CONFIG_MAINS_ALARM_MASK_VOLTAGE_UNAVAIL = 0x04, - -}; - -/** @brief Default value for Power Configuration cluster revision global attribute */ -#define ZB_ZCL_POWER_CONFIG_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief Default value for MainsAlarmMask attribute */ -#define ZB_ZCL_POWER_CONFIG_MAINS_ALARM_MASK_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for MainsVoltageMinThreshold attribute */ -#define ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for MainsVoltageMaxThreshold attribute */ -#define ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for MainsDwellTripPoint attribute */ -#define ZB_ZCL_POWER_CONFIG_MAINS_DWELL_TRIP_POINT_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief BatteryVoltage attribute invalid value */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_VOLTAGE_INVALID 0xff - -/** @brief Power Configuration BatteryPercentageRemaining attribute unknown value */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_REMAINING_UNKNOWN 0xff - -/** @brief Default value for BatteryRemainingHA attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_REMAINING_HA_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for BatteryManufacturer attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_MANUFACTURER_DEFAULT_VALUE {0} - -/** @brief BatterySize attribute default value */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_DEFAULT_VALUE 0xff - -/** @brief BatteryAlarmMask attribute default value */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_MASK_DEFAULT_VALUE 0x00 - -/** @brief Default value for BatteryVoltageMinThreshold attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_VOLTAGE_MIN_THRESHOLD_DEFAULT_VALUE ((zb_uint8_t)0x0000) - -/** @brief Default value for BatteryVoltageThreshold1 attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD1_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for BatteryVoltageThreshold2 attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD2_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for BatteryVoltageThreshold3 attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD3_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for BatteryPercentageMinThreshold attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_PERCENTAGE_MIN_THRESHOLD_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for BatteryPercentageThreshold1 attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD1_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for BatteryPercentageThreshold2 attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD2_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for BatteryPercentageThreshold3 attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD3_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for BatteryAlarmState attribute */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_DEFAULT_VALUE ((zb_uint32_t)0x00000000) - -/** @brief MainsVoltageMinThreshold and MainsVoltageMaxThreshold values when alarm should not be generated*/ -#define ZB_ZCL_POWER_CONFIG_THRESHOLD_ALARM_OMISSION_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Mains attribute set the least significant nibble*/ -#define ZB_ZCL_POWER_CONFIG_MAINS_ATTRIBUTE_SET 0 - -/** @brief Battery attribute set the least significant nibble*/ -#define ZB_ZCL_POWER_CONFIG_BATTERY_ATTRIBUTE_SET 0 - -/** @brief Battery Source 2 attribute set the least significant nibble*/ -#define ZB_ZCL_POWER_CONFIG_BATTERY_SOURCE_2_ATTRIBUTE_SET 0x20 - -/** @brief Battery Source 3 attribute set the least significant nibble*/ -#define ZB_ZCL_POWER_CONFIG_BATTERY_SOURCE_3_ATTRIBUTE_SET 0x40 - -/** - * @brief Power Configuration BatterySize value - * see ZCL spec 3.3.2.2.4.2 - */ -enum zb_zcl_power_config_battery_size_e -{ - /** @brief BatterySize - no battery*/ - ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_NO_BATTERY = 0, - /** @brief BatterySize - built in */ - ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_BUILT_IN = 1, - /** @brief BatterySize - other */ - ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_OTHER = 2, - /** @brief BatterySize - AA */ - ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_AA = 3, - /** @brief BatterySize - AAA */ - ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_AAA = 4, - /** @brief BatterySize - C */ - ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_C = 5, - /** @brief BatterySize - D */ - ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_D = 6, - /** @brief BatterySize - CR2 */ - ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_CR2 = 7, - /** @brief BatterySize - CR123A */ - ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_CR123A = 8, - /** @brief BatterySize - unknown */ - ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_UNKNOWN = 0xff, -}; - -/** - * @brief Power Configuration BatteryAlarmMask value - * see ZCL spec 3.3.2.2.4.7 - */ -enum zb_zcl_power_config_battery_alarm_mask_e -{ - /** @brief BatteryAlarmMask - Battery voltage too low */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_MASK_VOLTAGE_LOW = 0, - /** @brief BatteryAlarmMask - Alarm1 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_MASK_ALARM1 = 1, - /** @brief BatteryAlarmMask - Alarm2 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_MASK_ALARM2 = 2, - /** @brief BatteryAlarmMask - Alarm3 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_MASK_ALARM3 = 3, -}; - -/*! @brief Power Configuration Alarm Code for Alarm - @see ZCL spec 3.3.2.2.4.7, Table 3-25 -*/ -enum zb_zcl_power_config_battery_alarm_code_e -{ - /** @brief MainsVoltageAlarmCode - MainsVoltageMinThreshold reached for Mains Voltage**/ - ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_ALARM_CODE_MIN_THRESHOLD = 0x00, - /** @brief MainsVoltageAlarmCode - MainsVoltageMaxThreshold reached for Mains Voltage**/ - ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_ALARM_CODE_MAX_THRESHOLD = 0x01, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold or - * BatteryPercentageMinThreshold reached for Battery Source 1 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE1_MIN_THRESHOLD = 0x10, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold1 or - * BatteryPercentageMinThreshold1 reached for Battery Source 1 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE1_VOLTAGE1 = 0x11, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold2 or - * BatteryPercentageMinThreshold2 reached for Battery Source 1 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE1_VOLTAGE2 = 0x12, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold3 or - * BatteryPercentageMinThreshold3 reached for Battery Source 1 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE1_VOLTAGE3 = 0x13, - - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold or - * BatteryPercentageMinThreshold reached for Battery Source 2 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE2_MIN_THRESHOLD = 0x20, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold1 or - * BatteryPercentageMinThreshold1 reached for Battery Source 2 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE2_VOLTAGE1 = 0x21, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold2 or - * BatteryPercentageMinThreshold2 reached for Battery Source 2 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE2_VOLTAGE2 = 0x22, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold3 or - * BatteryPercentageMinThreshold3 reached for Battery Source 2 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE2_VOLTAGE3 = 0x23, - - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold or - * BatteryPercentageMinThreshold reached for Battery Source 3 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE3_MIN_THRESHOLD = 0x30, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold1 or - * BatteryPercentageMinThreshold1 reached for Battery Source 3 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE3_VOLTAGE1 = 0x31, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold2 or - * BatteryPercentageMinThreshold2 reached for Battery Source 3 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE3_VOLTAGE2 = 0x32, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold3 or - * BatteryPercentageMinThreshold3 reached for Battery Source 3 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_SOURCE3_VOLTAGE3 = 0x33, - /** @brief Mains power supply lost/unavailable (i.e., device is running on battery) */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODE_MAINS_POWER_SUPPLY_LOST_UNAVAILABLE = 0x3a, -}; - - -/*! @brief Power Configuration BatteryAlarmState - @see ZCL spec 3.3.2.2.4.11, Table 3-26 -*/ -enum zb_zcl_power_config_battery_alarm_state_e -{ - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold or - * BatteryPercentageMinThreshold reached for Battery Source 1 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_MIN_THRESHOLD = 1 << 0, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold1 or - * BatteryPercentageMinThreshold1 reached for Battery Source 1 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE1 = 1 << 1, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold2 or - * BatteryPercentageMinThreshold2 reached for Battery Source 1 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE2 = 1 << 2, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold3 or - * BatteryPercentageMinThreshold3 reached for Battery Source 1 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE3 = 1 << 3, - - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold or - * BatteryPercentageMinThreshold reached for Battery Source 2 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE2_MIN_THRESHOLD = 1 << 10, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold1 or - * BatteryPercentageMinThreshold1 reached for Battery Source 2 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE2_VOLTAGE1 = 1 << 11, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold2 or - * BatteryPercentageMinThreshold2 reached for Battery Source 2 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE2_VOLTAGE2 = 1 << 12, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold3 or - * BatteryPercentageMinThreshold3 reached for Battery Source 2 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE2_VOLTAGE3 = 1 << 13, - - /* use 1l to exclude overflow at 16-bit CPU: force 32-bit enum */ - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold or - * BatteryPercentageMinThreshold reached for Battery Source 3 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE3_MIN_THRESHOLD = 1l << 20, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold1 or - * BatteryPercentageMinThreshold1 reached for Battery Source 3 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE3_VOLTAGE1 = 1l << 21, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold2 or - * BatteryPercentageMinThreshold2 reached for Battery Source 3 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE3_VOLTAGE2 = 1l << 22, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold3 or - * BatteryPercentageMinThreshold3 reached for Battery Source 3 */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE3_VOLTAGE3 = 1l << 23, - /** @brief Mains power supply lost/unavailable (i.e., device is running on battery) */ - ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_MAINS_POWER_SUPPLY_LOST_UNAVAILABLE = 1l << 30, -}; - -/** @cond internals_doc */ -/*! @internal @name Power Configuration cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_MAINS_FREQUENCY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_FREQUENCY_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_MAINS_ALARM_MASK_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_ALARM_MASK_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_MAINS_DWELL_TRIP_POINT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_DWELL_TRIP_POINT, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_VOLTAGE_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_SIZE_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_SIZE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_QUANTITY_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_QUANTITY_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_RATED_VOLTAGE_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_RATED_VOLTAGE_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/* DA: HA12 change */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_ALARM_MASK_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_ALARM_MASK_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_MIN_THRESHOLD_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_VOLTAGE_MIN_THRESHOLD_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_PERCENTAGE_REMAINING_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD1_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_VOLTAGE_THRESHOLD1_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD2_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_VOLTAGE_THRESHOLD2_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD3_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_VOLTAGE_THRESHOLD3_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_MIN_THRESHOLD_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_PERCENTAGE_MIN_THRESHOLD_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD1_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_PERCENTAGE_THRESHOLD1_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD2_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_PERCENTAGE_THRESHOLD2_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD3_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_PERCENTAGE_THRESHOLD3_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_ALARM_STATE_ID(data_ptr, bat_num) \ -{ \ - ZB_ZCL_ATTR_POWER_CONFIG_BATTERY##bat_num##_ALARM_STATE_ID, \ - ZB_ZCL_ATTR_TYPE_32BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in Power - * Configuration cluster for 1 battery pack */ -#undef ZB_ZCL_POWER_CONFIG_REPORT_ATTR_COUNT -#define ZB_ZCL_POWER_CONFIG_REPORT_ATTR_COUNT 2 /* Voltage + Alarm State */ -/*! @internal Number of attributes mandatory for reporting in Power - * Configuration cluster for 2 Battery packs included */ -#define ZB_ZCL_POWER_CONFIG_BAT_PACK_2_REPORT_ATTR_COUNT 4 /* Voltage + Voltage 2 + Alarm State + - * Alarm State 2 */ -/*! @internal Number of attributes mandatory for reporting in Power - * Configuration cluster for 3 Battery packs included */ -#define ZB_ZCL_POWER_CONFIG_BAT_PACK_3_REPORT_ATTR_COUNT 6 /* Voltage + Voltage 2 + Voltage 3 + - * Alarm State + Alarm State 2 + Alarm State 3*/ - -/*! @internal Alarm Code for Power Configuration cluster */ -#define ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD_ALARM_CODE 0x00 -#define ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD_ALARM_CODE 0x01 - -/*! @} */ /* Power Configuration cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for Power Configuration cluster - server side - @param attr_list - attribute list name - @param voltage - pointer to variable to store BatteryVoltage attribute - @param size - pointer to variable to store BatterySize attribute - @param quantity - pointer to variable to store BatteryQuantity attribute - @param rated_voltage - pointer to variable to store BatteryRatedVoltage attribute - @param alarm_mask - pointer to variable to store BatteryAlarmMask attribute - @param voltage_min_threshold - pointer to variable to store BatteryVoltageMinThreshold attribute -*/ -#define ZB_ZCL_DECLARE_POWER_CONFIG_ATTRIB_LIST(attr_list, \ - voltage, size, quantity, rated_voltage, \ - alarm_mask, voltage_min_threshold) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_POWER_CONFIG) \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_ID(voltage, ), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_SIZE_ID(size, ), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_QUANTITY_ID(quantity, ), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_RATED_VOLTAGE_ID(rated_voltage, ), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_ALARM_MASK_ID(alarm_mask, ), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_MIN_THRESHOLD_ID(voltage_min_threshold, ), \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @cond internals_doc */ -#define ZB_ZCL_POWER_CONFIG_MAINS_ATTRIB_LIST(voltage, frequency, alarm_mask, \ - voltage_min_threshold, voltage_max_threshold, \ - dwell_trip_point) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_ID, (voltage)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POWER_CONFIG_MAINS_FREQUENCY_ID, (frequency)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POWER_CONFIG_MAINS_ALARM_MASK_ID, (alarm_mask)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD, (voltage_min_threshold)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD, (voltage_max_threshold)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_POWER_CONFIG_MAINS_DWELL_TRIP_POINT, (dwell_trip_point)) -/*! @} - * @endcond */ /* internals_doc */ - - -/** @brief Declare attribute list for Power Configuration cluster - server side (Mains - attribute set) - @param attr_list - attribute list name - @param voltage - pointer to variable to store MainsVoltage attribute - @param frequency - pointer to variable to store MainsFrequency attribute - @param alarm_mask - pointer to variable to store BatteryAlarmMask attribute - @param voltage_min_threshold - pointer to variable to store MainsVoltageMinThreshold attribute - @param voltage_max_threshold - pointer to variable to store MainsVoltageMaxThreshold attribute - @param dwell_trip_point - pointer to variable to store MainsVoltageDwellTripPoint attribute -*/ -#define ZB_ZCL_DECLARE_POWER_CONFIG_MAINS_ATTRIB_LIST(attr_list, voltage, frequency, alarm_mask, \ - voltage_min_threshold, voltage_max_threshold, \ - dwell_trip_point) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_POWER_CONFIG) \ - ZB_ZCL_POWER_CONFIG_MAINS_ATTRIB_LIST(voltage, frequency, alarm_mask, \ - voltage_min_threshold, voltage_max_threshold, \ - dwell_trip_point) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @cond internals_doc */ -#define ZB_ZCL_POWER_CONFIG_BATTERY_ATTRIB_LIST_EXT(bat_num, \ - voltage, size, quantity, rated_voltage, alarm_mask, voltage_min_threshold, \ - remaining, threshold1, threshold2, threshold3, min_threshold, percent_threshold1, \ - percent_threshold2, percent_threshold3, alarm_state) \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_ID(voltage, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_SIZE_ID(size, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_QUANTITY_ID(quantity, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_RATED_VOLTAGE_ID(rated_voltage, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_ALARM_MASK_ID(alarm_mask, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_MIN_THRESHOLD_ID(voltage_min_threshold, bat_num), \ - /* ext attribute */ \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID(remaining, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD1_ID(threshold1, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD2_ID(threshold2, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD3_ID(threshold3, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_MIN_THRESHOLD_ID(min_threshold, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD1_ID(percent_threshold1, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD2_ID(percent_threshold2, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD3_ID(percent_threshold3, bat_num), \ - ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_ALARM_STATE_ID(alarm_state, bat_num), -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for Power Configuration cluster - server side (Battery attribute - list extended) - @param attr_list - attribute list name - @param voltage - pointer to variable to store BatteryVoltage attribute - @param size - pointer to variable to store BatterySize attribute - @param quantity - pointer to variable to store BatteryQuantity attribute - @param rated_voltage - pointer to variable to store BatteryRatedVoltage attribute - @param alarm_mask - pointer to variable to store BatteryAlarmMask attribute - @param voltage_min_threshold - pointer to variable to store BatteryVoltageMinThreshold attribute - - @param remaining - pointer to variable to store BatteryPercentageRemaining attribute - @param threshold1 - pointer to variable to store BatteryVoltageThreshold1 attribute - @param threshold2 - pointer to variable to store BatteryVoltageThreshold2 attribute - @param threshold3 - pointer to variable to store BatteryVoltageThreshold3 attribute - @param min_threshold - pointer to variable to store BatteryPercentageMinThreshold attribute - @param percent_threshold1 - pointer to variable to store BatteryPercentageThreshold1 attribute - @param percent_threshold2 - pointer to variable to store BatteryPercentageThreshold2 attribute - @param percent_threshold3 - pointer to variable to store BatteryPercentageThreshold3 attribute - @param alarm_state - pointer to variable to store BatteryAlarmState attribute -*/ -#define ZB_ZCL_DECLARE_POWER_CONFIG_BATTERY_ATTRIB_LIST_EXT(attr_list, \ - voltage, size, quantity, rated_voltage, alarm_mask, voltage_min_threshold, \ - remaining, threshold1, threshold2, threshold3, min_threshold, percent_threshold1, \ - percent_threshold2, percent_threshold3, alarm_state) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_POWER_CONFIG) \ - ZB_ZCL_POWER_CONFIG_BATTERY_ATTRIB_LIST_EXT(bat_num, \ - voltage, size, quantity, rated_voltage, alarm_mask, voltage_min_threshold, \ - remaining, threshold1, threshold2, threshold3, min_threshold, percent_threshold1, \ - percent_threshold2, percent_threshold3, alarm_state) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Power Configuration cluster attributes */ - -/*! @name Power Configuration cluster commands - @{ -*/ - -/*! @} */ /* Power Configuration cluster commands */ - -/*! @} */ /* ZCL Power Configuration cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_power_config_init_server(void); -void zb_zcl_power_config_init_client(void); -#define ZB_ZCL_CLUSTER_ID_POWER_CONFIG_SERVER_ROLE_INIT zb_zcl_power_config_init_server -#define ZB_ZCL_CLUSTER_ID_POWER_CONFIG_CLIENT_ROLE_INIT zb_zcl_power_config_init_client - -#endif /* ZB_ZCL_POWER_CONFIG_H */ diff --git a/zboss/development/include/zcl/zb_zcl_pressure_measurement.h b/zboss/development/include/zcl/zb_zcl_pressure_measurement.h deleted file mode 100644 index 5ee72117f7..0000000000 --- a/zboss/development/include/zcl/zb_zcl_pressure_measurement.h +++ /dev/null @@ -1,316 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Pressure Measurement cluster definitions -*/ - -#ifndef ZB_ZCL_PRESSURE_MEASUREMENT_H -#define ZB_ZCL_PRESSURE_MEASUREMENT_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_PRESSURE_MEASUREMENT - * @{ - * @details - * All commands in the cluster have only request form, and carry no payload. - */ - - -/* Cluster ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT */ - -/*! @name Pressure Measurement cluster attributes - @{ -*/ - -#if !defined(ZB_DISABLE_PRESSURE_MEASUREMENT_SCALE_TOLERANCE_ID) && defined(ZB_DISABLE_PRESSURE_MEASUREMENT_SCALE_ID) -# error If scale tolerance attribute is enabled, all scale attributes shall be enabled -#endif - -/*! @brief Pressure Measurement cluster attribute identifiers - @see ZCL spec, Pressure Measurement Cluster 4.5.2.2.1 -*/ -enum zb_zcl_pressure_measurement_attr_e -{ - /*! @brief MeasuredValue, ZCL spec 4.5.2.2.1.1 */ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID = 0x0000, - /*! @brief MinMeasuredValue, ZCL spec 4.5.2.2.1.2 */ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_ID = 0x0001, - /*! @brief MaxMeasuredValue, ZCL spec 4.5.2.2.1.3 */ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_ID = 0x0002, - /*! @brief Tolerance, ZCL spec 4.5.2.2.1.4 */ -#ifndef ZB_DISABLE_PRESSURE_MEASUREMENT_TOLERANCE_ID - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_ID = 0x0003, -#else - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_ID = 0xF003, -#endif - - /*! @brief ScaledValue, ZCL spec 4.5.2.1.2.1 */ -#ifndef ZB_DISABLE_PRESSURE_MEASUREMENT_SCALE_ID - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALED_VALUE_ID = 0x0010, -#else - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALED_VALUE_ID = 0xF010, -#endif - /*! @brief MinScaledValue, ZCL spec 4.5.2.1.2.2 */ -#ifndef ZB_DISABLE_PRESSURE_MEASUREMENT_SCALE_ID - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_SCALED_VALUE_ID = 0x0011, -#else - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_SCALED_VALUE_ID = 0xF011, -#endif - /*! @brief MaxScaledValue, ZCL spec 4.5.2.1.2.3 */ -#ifndef ZB_DISABLE_PRESSURE_MEASUREMENT_SCALE_ID - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_SACLED_VALUE_ID = 0x0012, -#else - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_SACLED_VALUE_ID = 0xF012, -#endif - /*! @brief ScaledTolerance, ZCL spec 4.5.2.1.2.4 */ -#ifndef ZB_DISABLE_PRESSURE_MEASUREMENT_SCALE_TOLERANCE_ID - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALED_TOLERANCE_ID = 0x0013, -#else - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALED_TOLERANCE_ID = 0xF013, -#endif - /*! @brief Scale, ZCL spec 4.5.2.1.2.5 */ -#ifndef ZB_DISABLE_PRESSURE_MEASUREMENT_SCALE_ID - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALE_ID = 0x0014, -#else - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALE_ID = 0xF014, -#endif -}; - -/** @brief Default value for Pressure Measurement cluster revision global attribute */ -#define ZB_ZCL_PRESSURE_MEASUREMENT_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - - /* (See: Table 4.15 Pressure Measurement Information Attribute Set) */ - -/** @brief MeasuredValue attribute unknown value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_UNKNOWN ((zb_int16_t)0x8000) - -/** @brief MinMeasuredValue attribute minimum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_MIN_VALUE ((zb_int16_t)0x954d) - -/** @brief MinMeasuredValue attribute maximum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_MAX_VALUE ((zb_int16_t)0x7ffe) - -/** @brief MinMeasuredValue attribute invalid value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_INVALID ((zb_int16_t)0x8000) - -/** @brief MaxMeasuredValue attribute minimum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_MIN_VALUE ((zb_int16_t)0x954e) - -/** @brief MaxMeasuredValue attribute maximum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_MAX_VALUE 0x7fff - -/** @brief MaxMeasuredValue attribute invalid value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_INVALID ((zb_int16_t)0x8000) - -/** @brief Tolerance attribute minimum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_MIN_VALUE ((zb_uint16_t)0x0000) - -/** @brief Tolerance attribute maximum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_MAX_VALUE ((zb_uint16_t)0x0800) - -/** @brief Default value for Value attribute */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_DEFAULT_VALUE ((zb_int16_t)0xFFFF) - -/** @brief Default value for MinValue attribute */ -#define ZB_ZCL_PATTR_RESSURE_MEASUREMENT_MIN_VALUE_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for MaxValue attribute */ -#define ZB_ZCL_PATTR_RESSURE_MEASUREMENT_MAX_VALUE_DEFAULT_VALUE ((zb_int16_t)0x8000) - - - /* (See: Table 4.16 Extended Pressure Measurement Information Attribute Set) */ - -/** @brief MinScaledValue attribute unknown value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_SCALED_VALUE_UNKNOWN ((zb_int16_t)0x8000) - -/** @brief MinScaledValue attribute minimum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_SCALED_VALUE_MIN_VALUE ((zb_int16_t)0x8001) - -/** @brief MinScaledValue attribute maximum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_SCALED_VALUE_MAX_VALUE ((zb_int16_t)0x7ffe) - -/** @brief MaxScaledValue attribute unknown value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_SCALED_VALUE_UNKNOWN ((zb_int16_t)0x8000) - -/** @brief MaxScaledValue attribute minimum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_SCALED_VALUE_MIN_VALUE ((zb_int16_t)0x8002) - -/** @brief MaxScaledValue attribute maximum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_SCALED_VALUE_MAX_VALUE ((zb_int16_t)0x7fff) - -/** @brief MaxScaledValue attribute minimum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALED_TOLERANCE_MIN_VALUE ((zb_uint16_t)0x0000) - -/** @brief MaxScaledValue attribute maximum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALED_TOLERANCE_MAX_VALUE ((zb_uint16_t)0x0800) - -/** @brief MaxScaledValue attribute minimum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALE_MIN_VALUE ((zb_int8_t)0x81) - -/** @brief MaxScaledValue attribute maximum value */ -#define ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALE_MAX_VALUE ((zb_int8_t)0x7f) - -/** @cond internals_doc */ -/*! @internal @name Pressure Measurement cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALED_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALED_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_SCALED_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_SCALED_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_SCALED_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_SCALED_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALED_TOLERANCE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALED_TOLERANCE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_SCALE_ID, \ - ZB_ZCL_ATTR_TYPE_S8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in Pressure Measurement cluster */ -#define ZB_ZCL_PRESSURE_MEASUREMENT_REPORT_ATTR_COUNT 1 - -/*! Write attribute hook is used to set min/max Pressure values */ -void zb_zcl_pressure_measurement_write_attr_hook( - zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -/*! @} */ /* Pressure Measurement cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for Pressure Measurement cluster - server side - @param attr_list - attribute list name - @param value - pointer to variable to store MeasuredValue attribute - @param min_value - pointer to variable to store MinMeasuredValue attribute - @param max_value - pointer to variable to store MAxMeasuredValue attribute - @param tolerance - pointer to variable to store Tolerance attribute -*/ -#define ZB_ZCL_DECLARE_PRESSURE_MEASUREMENT_ATTRIB_LIST(attr_list, \ - value, min_value, max_value, tolerance) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_PRESSURE_MEASUREMENT) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID, (value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_ID, (min_value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_ID, (max_value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_ID, (tolerance)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Pressure Measurement cluster attributes */ - -/*! @name Pressure Measurement cluster commands - @{ -*/ - -/*! @} */ /* Pressure Measurement cluster commands */ - -/*! @} */ /* ZCL Pressure Measurement cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_pressure_measurement_init_server(void); -void zb_zcl_pressure_measurement_init_client(void); -#define ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT_SERVER_ROLE_INIT zb_zcl_pressure_measurement_init_server -#define ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT_CLIENT_ROLE_INIT zb_zcl_pressure_measurement_init_client - - -#endif /* ZB_ZCL_PRESSURE_MEASUREMENT_H */ diff --git a/zboss/development/include/zcl/zb_zcl_price.h b/zboss/development/include/zcl/zb_zcl_price.h deleted file mode 100644 index ebf635752a..0000000000 --- a/zboss/development/include/zcl/zb_zcl_price.h +++ /dev/null @@ -1,4476 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Price cluster definitions -*/ - -#ifndef ZB_ZCL_PRICE_H -#define ZB_ZCL_PRICE_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_PRICE - * @{ - * @details - * The Price Cluster provides the mechanism for communicating Gas, Energy, or - * Water pricing information within the premises. - */ - -/* Cluster ZB_ZCL_CLUSTER_ID_PRICE */ - -/** @defgroup ZB_ZCL_PRICE_ATTRS Price cluster attributes - * @{ - */ - -/** @defgroup ZB_ZCL_PRICE_SRV_ATTRIBUTES_GROUP Price cluster server attributes - * @{ - * @details - * For convenience, the attributes defined in this cluster are arranged into sets - * of related attributes; each set can contain up to 256 attributes. Attribute - * identifiers are encoded such that the most significant Octet specifies the - * attribute set and the least significant Octet specifies the attribute within - * the set. - */ - -/** @brief Price Cluster General server attributes - * @see SE spec, Table D-73 - */ -enum zb_zcl_price_srv_attr_set_e -{ - ZB_ZCL_PRICE_SET_TIER_LABEL = 0x00, /**< Provides a method for utilities to assign a label to the Price Tier. */ - ZB_ZCL_PRICE_SET_BLOCK_THRESHOLD = 0x01, /**< Provides remote access to the Price server Block Thresholds. */ - ZB_ZCL_PRICE_SET_BLOCK_PERIOD = 0x02, /**< Provides remote access to the Price server Block Threshold period. */ - ZB_ZCL_PRICE_SET_COMMODITY = 0x03, /**< Represents items that are associated with a particular commodity. */ - ZB_ZCL_PRICE_SET_BLOCK_PRICE_INFORMATION = 0x04, /**< Provides remote access to the block prices. */ - ZB_ZCL_PRICE_SET_EXTENDED_PRICE_INFORMATION = 0x05, /**< Represents extended price information. */ - ZB_ZCL_PRICE_SET_TARIFF_INFORMATION = 0x06, /**< Represents items that are associated with a particular Price Tariff. */ - ZB_ZCL_PRICE_SET_BILLING_INFORMATION = 0x07, /**< Provides remote access to the Price server Billing information. */ - ZB_ZCL_PRICE_SET_CREDIT_PAYMENT = 0x08, /**< Provides a method for the HAN (IHD) to understand the current status - * of the credit-only payment made to the energy supplier. */ - - /* reserved 0x09 - 0x7F */ - - ZB_ZCL_PRICE_SET_RECEIVED_TIER_LABEL = 0x80, /**< Provides a method for utilities to assign a label to Received Price Tiers. */ - ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_THRESHOLD = 0x81, /**< Provides remote access to the Price server ReceivedBlockThresholds. */ - ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_PERIOD = 0x82, /**< Provides remote access to the Price server Received Block Threshold period. */ - - /* reserved 0x83 */ - - ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_PRICE_INFORMATION = 0x84, /**< @copydetails ZB_ZCL_PRICE_SET_BLOCK_PRICE_INFORMATION_GROUP */ - ZB_ZCL_PRICE_SET_RECEIVED_EXTENDED_PRICE_INFORMATION = 0x85, /**< @copydetails ZB_ZCL_PRICE_SET_EXTENDED_PRICE_INFORMATION_GROUP */ - ZB_ZCL_PRICE_SET_RECEIVED_TARIFF_INFORMATION = 0x86, /**< @copydetails ZB_ZCL_PRICE_SET_TARIFF_INFORMATION_GROUP */ - ZB_ZCL_PRICE_SET_RECEIVED_BILLING_INFORMATION = 0x87, /**< @copydetails ZB_ZCL_PRICE_SET_BILLING_INFORMATION_GROUP */ - - /* reserved 0x88 - 0xFF */ -}; - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_TIER_LABEL_GROUP Tier Label - * @{ - */ - -/** @brief Tier Label (Delivered) Attributes Set - * @see SE spec, D.4.2.2.1 - */ -enum zb_zcl_price_set_tier_label_e -{ - /** The TierNPriceLabel attributes provide a method for utilities to assign a - * label to the Price Tier declared within the Publish Price command. - */ - ZB_ZCL_ATTR_PRICE_SRV_TIER1_PRICE_LABEL = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_TIER_LABEL, 0x00), - ZB_ZCL_ATTR_PRICE_SRV_TIER2_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER16_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER17_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER18_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER19_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER20_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER21_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER22_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER23_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER24_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER25_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER26_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER27_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER28_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER29_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER30_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER31_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER32_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER33_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER34_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER35_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER36_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER37_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER38_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER39_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER40_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER41_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER42_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER43_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER44_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER45_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER46_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER47_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_TIER48_PRICE_LABEL, -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_TIERN_PRICE_LABEL_GNR(tierN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_TIER ## tierN ## _PRICE_LABEL, \ - ZB_ZCL_ATTR_TYPE_OCTET_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_TIER_LABEL_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_BLOCK_THRESHOLD_GROUP Block Threshold - * @{ - * @details - * The following set of attributes provides remote access to the Price server - * Block Thresholds. Block Threshold values are crossed when the - * CurrentBlockPeriodConsumptionDelivered attribute value is greater than a - * BlockNThreshold attribute. The number of block thresholds is indicated by - * the Number of Block Thresholds field in the associated Publish Price command. - * The number of blocks is one greater than the number of thresholds. - */ - -/** @brief Block Threshold (Delivered) Attributes Set - * @see SE spec, D.4.2.2.2 - */ -enum zb_zcl_set_block_threshold_e -{ - /** Attributes Block1Threshold through Block15Threshold represent the block - * threshold values for a given period (typically the billing cycle). - */ - ZB_ZCL_ATTR_PRICE_SRV_BLOCK1_THRESHOLD = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_BLOCK_THRESHOLD, 0x00), - ZB_ZCL_ATTR_PRICE_SRV_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_BLOCK15_THRESHOLD, - - /** Where a single set of thresholds is used, the BlockThresholdCount - * attribute indicates the number of applicable BlockNThresholds. Where more - * than one set of thresholds is used, each set will be accompanied by an - * appropriate TierNBlockThresholdCount attribute - */ - ZB_ZCL_ATTR_PRICE_SRV_BLOCK_THRESHOLD_COUNT, - - /** Attributes Tier1Block1Threshold through Tier15Block15Threshold represent - * the block threshold values applicable to a specific TOU tier for a given - * period (typically the billing cycle). - */ - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK15_THRESHOLD, - - /** The TierNBlockThresholdCount attributes hold the number of block - * thresholds applicable to a given tier. - */ - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK_THRESHOLD_COUNT, - - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK1_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK15_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK_THRESHOLD_COUNT, -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_BLOCKN_THRESHOLD_GNR(blockN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_BLOCK ## blockN ## _THRESHOLD, \ - ZB_ZCL_ATTR_TYPE_48BIT, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_BLOCK_THRESHOLD_COUNT_GNR(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_BLOCK_THRESHOLD_COUNT, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_TIERN_BLOCKM_THRESHOLD_GNR(blockN, tierN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_TIER ## tierN ## _BLOCK ## blockN ## _THRESHOLD, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_TIERN_BLOCK_THRESHOLD_COUNT_GNR(tierN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_TIER ## tierN ## _BLOCK_THRESHOLD_COUNT, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_BLOCK_THRESHOLD_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_BLOCK_PERIOD_GROUP Block Period - * @{ - * @details - * This set of attributes provides remote access to the Price server - * Block Threshold period (typically the billing cycle) information. - */ - -/** @brief Block Period (Delivered) Attributes Set - * @see SE spec, D.4.2.2.3 - */ -enum zb_zcl_price_set_block_period_e -{ - /** The StartOfBlockPeriod attribute represents the start time of the current - * block tariff period. - */ - ZB_ZCL_ATTR_PRICE_SRV_START_OF_BLOCK_PERIOD = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_BLOCK_PERIOD, 0x00), - - /** The BlockPeriodDuration attribute represents the current block tariff - * period duration in units defined by the BlockPeriodDurationType attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_BLOCK_PERIOD_DURATION, - - /** ThresholdMultiplier provides a value to be multiplied against Threshold - * attributes. - */ - ZB_ZCL_ATTR_PRICE_SRV_THRESHOLD_MULTIPLIER, - - /** ThresholdDivisor provides a value to divide the result of applying - * the ThresholdMultiplier attribute to Block Threshold values to derive - * values That can be compared against the CurrentBlockPeriodConsumptionDelivered - * attribute within the Metering cluster. - */ - ZB_ZCL_ATTR_PRICE_SRV_THRESHOLD_DIVISOR, - - /** The BlockPeriodDurationType attribute indicates the timebase used for the - * BlockPeriodDuration attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_BLOCK_PERIOD_DURATION_TYPE, - /* reserved 0x0205 - 0x02FF */ -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_START_OF_BLOCK_PERIOD(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_START_OF_BLOCK_PERIOD, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_BLOCK_PERIOD_DURATION(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_BLOCK_PERIOD_DURATION, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_THRESHOLD_MULTIPLIER(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_THRESHOLD_MULTIPLIER, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_THRESHOLD_DIVISOR(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_THRESHOLD_DIVISOR, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_BLOCK_PERIOD_DURATION_TYPE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_BLOCK_PERIOD_DURATION_TYPE, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @brief @e BlockPeriodDurationType attribute values - * @see SE spec, table D-105. - * @see ZB_ZCL_ATTR_PRICE_SRV_BLOCK_PERIOD_DURATION_TYPE - */ -typedef enum zb_zcl_price_block_period_duration_type_e -{ - ZB_ZCL_PRICE_BLOCK_PERIOD_DURATION_TYPE_MINUTES = 0x00, /**< minutes (default) */ - ZB_ZCL_PRICE_BLOCK_PERIOD_DURATION_TYPE_DAYS = 0x01, /**< days */ - ZB_ZCL_PRICE_BLOCK_PERIOD_DURATION_TYPE_WEEKS = 0x02, /**< weeks */ - ZB_ZCL_PRICE_BLOCK_PERIOD_DURATION_TYPE_MONTHS = 0x03, /**< months */ -} zb_zcl_price_block_period_duration_type_t; - -/** @} */ /* end of ZB_ZCL_PRICE_SET_BLOCK_PERIOD_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_COMMODITY_GROUP Commodity - * @{ - * @details - * This set of attributes represents items that are associated with a - * particular commodity. - */ - -/** Values and Descriptions for the CalorificValueUnit Attribute - * @see SE spec, subclause D.4.2.2.4.6 - */ -typedef enum zb_zcl_price_calorific_value_unit_values_e -{ - ZB_ZCL_PRICE_CALORIFIC_VALUE_UNIT_MJ_M3 = 0x01, /**< MJ/m3 */ - ZB_ZCL_PRICE_CALORIFIC_VALUE_UNIT_MJ_KG, /**< MJ/kg */ -} zb_zcl_price_calorific_value_unit_values_t; - - -/** @brief Commodity Attributes Set - * @see SE spec, D.4.2.2.4 - */ -enum zb_zcl_price_set_commodity_e -{ - /** CommodityType provides a label for identifying the type of pricing server - * present. - */ - ZB_ZCL_ATTR_PRICE_SRV_COMMODITY_TYPE = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_COMMODITY, 0x00), - - /** The value of the Standing Charge is a daily fixed charge associated with - * supplying the commodity, measured in base unit of Currency with the decimal - * point located as indicated by the Trailing Digits field of a Publish Price - * command or PriceTrailingDigit attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_STANDING_CHARGE, - - /** The conversion factor is used for gas meter and takes into account changes - * in the volume of gas based on temperature and pressure. - */ - ZB_ZCL_ATTR_PRICE_SRV_CONVERSION_FACTOR, - - /** An 8-bit BitMap used to determine where the decimal point is located in - * the ConversionFactor attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_CONVERSION_FACTOR_TRAILING_DIGIT, - - /** The amount of heat generated when a given mass of fuel is completely burned. - */ - ZB_ZCL_ATTR_PRICE_SRV_CALORIFIC_VALUE, - - /** This attribute defines the unit for the CalorificValue. - */ - ZB_ZCL_ATTR_PRICE_SRV_CALORIFIC_VALUE_UNIT, - - /** An 8-bit BitMap used to determine where the decimal point is located in - * the CalorificValue attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_CALORIFIC_VALUE_TRAILING_DIGIT, -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_COMMODITY_TYPE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_COMMODITY_TYPE, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_STANDING_CHARGE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_STANDING_CHARGE, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CONVERSION_FACTOR(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CONVERSION_FACTOR, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CONVERSION_FACTOR_TRAILING_DIGIT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CONVERSION_FACTOR_TRAILING_DIGIT, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CALORIFIC_VALUE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CALORIFIC_VALUE, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CALORIFIC_VALUE_UNIT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CALORIFIC_VALUE_UNIT, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CALORIFIC_VALUE_TRAILING_DIGIT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CALORIFIC_VALUE_TRAILING_DIGIT, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_COMMODITY_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_BLOCK_PRICE_INFORMATION_GROUP Block Price Information - * @{ - * @details - * This attributes set provide remote access to the block prices. - * The Block Price Information attribute set supports Block and combined - * Tier-Block pricing, the number of blocks is one greater than the number of - * block thresholds defined in the Pricing cluster - */ - -/** @brief Block Price Information (Delivered) Attributes Set - * @see SE spec, D.4.2.2.5 - */ -enum zb_zcl_price_set_block_price_information_e -{ - /** Attributes PriceNoTierBlock1 through PriceTier15Block16 represent the - * price of Energy, Gas, or Water delivered to the premises (i.e. delivered - * to the customer from the utility) at a specific price tier as defined by - * a TOU schedule, Block Threshold or a real time pricing period. - */ - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK1_PRICE = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_BLOCK_PRICE_INFORMATION, 0x00), - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER1_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER2_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER3_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER4_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER5_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER6_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER7_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER8_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER9_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER10_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER11_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER12_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER13_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER14_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_TIER15_BLOCK16_PRICE, -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCKN_PRICE_GNR(blockN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_NO_TIER_BLOCK ## blockN ## _PRICE, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_TIERN_BLOCKM_PRICE_GNR(tierN, blockM, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_TIER ## tierN ## _BLOCK ## blockM ## _PRICE, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_BLOCK_PRICE_INFORMATION_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_EXTENDED_PRICE_INFORMATION_GROUP Extended Price Information - * @{ - * @details - * In case of TOU charging only, the price server allows support for up to 48 - * TOU rates. To reduce the number of attributes, Tier1Block1Price through - * Tier15Block1Price attributes are reused to represent rates for tiers 1 to 15. - * Rates for tiers 16 to 48 are provided in the extended price information set. - */ - -/** @brief Extended Price Information (Delivered) Attributes Set - * @see SE spec, D.4.2.2.6 - */ -enum zb_zcl_price_set_extended_price_information_e -{ - /* reserved 0x0500 - 0x050E */ - - /** Attributes PriceTier16 through PriceTier48 represent the price of Energy, - * Gas, or Water delivered to the premises (i.e. delivered to the customer - * from the utility) at a specific price tier. - */ - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER16 = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_EXTENDED_PRICE_INFORMATION, 0x0F), - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER17, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER18, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER19, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER20, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER21, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER22, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER23, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER24, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER25, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER26, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER27, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER28, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER29, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER30, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER31, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER32, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER33, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER34, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER35, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER36, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER37, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER38, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER39, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER40, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER41, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER42, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER43, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER44, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER45, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER46, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER47, - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER48, - /* reserved 0x0530 - 0x05FD */ - - /** Attribute CPP1 Price represents the price of Energy, Gas, or Water - * delivered to the premises (i.e. delivered to the customer from the utility) - * while Critical Peak Pricing 'CPP1' is being applied. - */ - ZB_ZCL_ATTR_PRICE_SRV_CPP1_PRICE = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_EXTENDED_PRICE_INFORMATION, 0x0FE), - - /** Attribute CPP2 Price represents the price of Energy, Gas, or Water - * delivered to the premises (i.e. delivered to the customer from the utility) - * while Critical Peak Pricing 'CPP2' is being applied. - */ - ZB_ZCL_ATTR_PRICE_SRV_CPP2_PRICE, -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIERN_GNR(tierN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TIER ## tierN, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CPPN_PRICE_GNR(cppN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CPP ## cppN ## _PRICE, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_EXTENDED_PRICE_INFORMATION_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_TARIFF_INFORMATION_GROUP Tariff Information - * @{ - * @details - * This set of attributes represents items that are associated with a - * particular Price Tariff. - * @note The terms tier and rate are used - * interchangeably here, but do define the same thing. - */ - -/** @brief Tariff Information (Delivered) Attributes Set - * @see SE spec, D.4.2.2.7 - */ -enum zb_zcl_price_set_tariff_information_e -{ - /* reserved 0x0600 - 0x060F */ - - /** The TariffLabel attribute provides a method for utilities to assign a - * label to an entire set of tariff information. - */ - ZB_ZCL_ATTR_PRICE_SRV_TARIFF_LABEL = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_TARIFF_INFORMATION, 0x10), - - /** An 8-bit integer which indicates the number of price tiers used while this - * tariff is active. - */ - ZB_ZCL_ATTR_PRICE_SRV_NUMBER_OF_PRICE_TIERS_IN_USE, - - /** An 8-bit integer which indicates the total number of block thresholds used - * in the currently active tariff. - */ - ZB_ZCL_ATTR_PRICE_SRV_NUMBER_OF_BLOCK_THRESHOLDS_IN_USE, - - /** An 8-bit enumeration indicating how the mixed TOU / Block charging is to - * be applied. - */ - ZB_ZCL_ATTR_PRICE_SRV_TIER_BLOCK_MODE, - /* reserved 0x0614 */ - - /** An 8-bit enumeration identifying the base unit of measure. - */ - ZB_ZCL_ATTR_PRICE_SRV_UNIT_OF_MEASURE = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_TARIFF_INFORMATION, 0x15), - - /** An unsigned 16-bit integer containing identifying information concerning - * the local unit of currency used in the Price cluster. - */ - ZB_ZCL_ATTR_PRICE_SRV_CURRENCY, - - /** An 8-bit BitMap used to determine where the decimal point is located for - * prices provided in the Standing Charge attribute and the Price Matrix command. - */ - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TRAILING_DIGIT, - /* reserved 0x0618 */ - - /** An 8-bit enumeration identifying the resolution period for Block Tariff. - */ - ZB_ZCL_ATTR_PRICE_SRV_TARIFF_RESOLUTION_PERIOD = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_TARIFF_INFORMATION, 0x19), - /* reserved 0x061A - 0x061F */ - - /** Used to calculate the amount of carbon dioxide (CO2) produced from energy use. - */ - ZB_ZCL_ATTR_PRICE_SRV_CO2 = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_TARIFF_INFORMATION, 0x20), - - /** This attribute is an 8-bit enumeration which defines the unit for the CO2 attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_CO2_UNIT, - - /** An 8-bit Bit-Map used to determine where the decimal point is located in - * the CO2 attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_CO2_TRAILING_DIGIT, - /* reserved 0x628 - 0x06FF */ -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_TARIFF_LABEL(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_TARIFF_LABEL, \ - ZB_ZCL_ATTR_TYPE_OCTET_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_NUMBER_OF_PRICE_TIERS_IN_USE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_NUMBER_OF_PRICE_TIERS_IN_USE, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_NUMBER_OF_BLOCK_THRESHOLDS_IN_USE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_NUMBER_OF_BLOCK_THRESHOLDS_IN_USE, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_TIER_BLOCK_MODE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_TIER_BLOCK_MODE, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @see SE spec, table D-82. */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_TIER_BLOCK_MODE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_TIER_BLOCK_MODE, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @see @ref zb_zcl_metering_unit_of_measure_e */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_UNIT_OF_MEASURE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_UNIT_OF_MEASURE, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CURRENCY(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CURRENCY, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_PRICE_TRAILING_DIGIT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_PRICE_TRAILING_DIGIT, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @brief @e TariffResolutionPeriod attribute values - * @see SE spec, Table D-107 - * @see @ref ZB_ZCL_ATTR_PRICE_SRV_TARIFF_RESOLUTION_PERIOD - */ -typedef enum zb_zcl_price_tariff_resolution_period_e -{ - ZB_ZCL_ATTR_PRICE_TARIFF_RESOLUTION_PERIOD_NOT_DEFINED = 0x00, /**< Not defined */ - ZB_ZCL_ATTR_PRICE_TARIFF_RESOLUTION_PERIOD_BLOCK_PERIOD, /**< Block Period */ - ZB_ZCL_ATTR_PRICE_TARIFF_RESOLUTION_PERIOD_1DAY, /**< 1 Day */ -} zb_zcl_price_tariff_resolution_period_t; - -/** @cond internals_doc */ - -/** @see @ref zb_zcl_price_tariff_resolution_period_t. */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_TARIFF_RESOLUTION_PERIOD(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_TARIFF_RESOLUTION_PERIOD, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CO2(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CO2, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @brief @e CO2Unit attribute values - * @see SE spec, Table D-83. - * @see ZB_ZCL_ATTR_PRICE_SRV_CO2_UNIT - */ -typedef enum zb_zcl_price_co2_unit_e -{ - ZB_ZCL_ATTR_PRICE_CO2_UNIT_KG_PER_KWH = 0x01, /**< kg per kWh */ - ZB_ZCL_ATTR_PRICE_CO2_UNIT_KG_PER_GALLON_OF_GASOLINE = 0x02, /**< kg per Gallon of Gasoline */ - ZB_ZCL_ATTR_PRICE_CO2_UNIT_KG_PER_THERM_OF_NATURAL_GAS = 0x03, /**< kg per Therm of Natural Gas */ -} zb_zcl_price_co2_unit_t; - -/** @cond internals_doc */ - -/** @see @ref zb_zcl_price_co2_unit_t */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CO2_UNIT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CO2_UNIT, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CO2_TRAILING_DIGIT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CO2_TRAILING_DIGIT, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_TARIFF_INFORMATION_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_BILLING_INFORMATION_GROUP Billing Information - * @{ - * @details - * This set of attributes provides remote access to the Price server - * Billing information. - */ - -/** @brief Billing Information (Delivered) Attributes Set - * @see SE spec, D.4.2.2.8 - */ -enum zb_zcl_price_set_billing_information_e -{ - /** The CurrentBillingPeriodStart attribute represents the start time of the - * current billing period. - */ - ZB_ZCL_ATTR_PRICE_SRV_CURRENT_BILLING_PERIOD_START = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_BILLING_INFORMATION, 0x00), - - /** The CurrentBillingPeriodDuration attribute represents the current billing - * period duration in minutes. - */ - ZB_ZCL_ATTR_PRICE_SRV_CURRENT_BILLING_PERIOD_DURATION, - - /** The LastBillingPeriodStart attribute represents the start time of the last - * billing period. - */ - ZB_ZCL_ATTR_PRICE_SRV_LAST_BILLING_PERIOD_START, - - /** The LastBillingPeriodDuration attribute is the duration of the last - * billing period in minutes (start to end of last billing period). - */ - ZB_ZCL_ATTR_PRICE_SRV_LAST_BILLING_PERIOD_DURATION, - - /** The LastBillingPeriodConsolidatedBill attribute is an amount for the cost - * of the energy supplied from the date of the LastBillingPeriodStart - * attribute and until the duration of the LastBillingPeriodDuration attribute - * expires, measured in base unit of Currency with the decimal point located - * as indicated by the Trailing Digits attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_LAST_BILLING_PERIOD_CONSOLIDATED_BILL, - /* reserved 0x0705 - 0x07FF */ -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CURRENT_BILLING_PERIOD_START(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CURRENT_BILLING_PERIOD_START, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CURRENT_BILLING_PERIOD_DURATION(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CURRENT_BILLING_PERIOD_DURATION, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_LAST_BILLING_PERIOD_START(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_LAST_BILLING_PERIOD_START, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_LAST_BILLING_PERIOD_DURATION(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_LAST_BILLING_PERIOD_DURATION, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_LAST_BILLING_PERIOD_CONSOLIDATED_BILL(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_LAST_BILLING_PERIOD_CONSOLIDATED_BILL, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_BILLING_INFORMATION_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_CREDIT_PAYMENT_GROUP Credit Payment - * @{ - * @details - * The Credit Payments Attribute set provides a method for the HAN (IHD) to - * understand the current status of the credit-only payment made to the energy - * supplier. These payments are for a credit meter only and do not cover any - * Prepayment Top up or payment. This attribute set is used to display the bill - * on the IHD should this service be required. Devices that require this information - * should use standard ZCL commands to read this information. - */ - -/** @brief Credit Payment Attributes Set - * @see SE spec, D.2.2.9 - */ -enum zb_zcl_price_set_credit_payment_e -{ - /** The CreditPaymentDueDate attribute indicates the date and time when the - * next credit payment is due to be paid by the consumer to the supplier. - */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_DUE_DATE = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_CREDIT_PAYMENT, 0x00), - - /** The CreditPaymentStatus attribute indicates the current status of the last payment. - */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_STATUS, - - /** This is the total of the consolidated bill amounts accumulated since the - * last payment. - */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_OVER_DUE_AMOUNT, - /* reserved 0x0803 - 0x0809 */ - - /** The PaymentDiscount attribute indicates the discount that the energy - * supplier has applied to the consolidated bill. - */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_CREDIT_PAYMENT, 0x0A), - - /** The PaymentDiscountPeriod attribute indicates the period for which this - * discount shall be applied for. - */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_PERIOD, - /* reserved 0x080C - 0x080F */ - - /** The CreditPayment attributes indicate the amount paid by the consumer to - * the energy supplier. - */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_1 = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_CREDIT_PAYMENT, 0x10), - - /** The CreditPaymentDate attributes indicate the last time the consumer made - * a payment to the energy supplier. - */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_DATE_1, - - /** The CreditPaymentRef attributes indicate the reference number given to the - * payment by the energy supplier. - */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_REF_1, - /* reserved 0x0813 - 0x081F */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_2 = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_CREDIT_PAYMENT, 0x20), - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_DATE_2, - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_REF_2, - /* reserved 0x0823 - 0x082F */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_3 = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_CREDIT_PAYMENT, 0x30), - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_DATE_3, - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_REF_3, - /* reserved 0x0833 - 0x083F */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_4 = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_CREDIT_PAYMENT, 0x40), - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_DATE_4, - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_REF_4, - /* reserved 0x0843 - 0x084F */ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_5 = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_CREDIT_PAYMENT, 0x50), - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_DATE_5, - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_REF_5, - /* reserved 0x0853 - 0x08FF */ -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_DUE_DATE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_DUE_DATE, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @brief @e CreditPaymentStatus attribute values - * @see SE spec, Table D-86. - * @see ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_STATUS - */ -typedef enum zb_zcl_price_credit_payment_status_e -{ - ZB_ZCL_PRICE_CREDIT_PAYMENT_PENDING = 0x00, /**< Pending */ - ZB_ZCL_PRICE_CREDIT_PAYMENT_RECEIVED = 0x01, /**< Received/Paid */ - ZB_ZCL_PRICE_CREDIT_PAYMENT_PAID = ZB_ZCL_PRICE_CREDIT_PAYMENT_RECEIVED, /**< @copydoc ZB_ZCL_PRICE_CREDIT_PAYMENT_RECEIVED */ - ZB_ZCL_PRICE_CREDIT_PAYMENT_OVERDUE = 0x02, /**< Overdue */ - ZB_ZCL_PRICE_CREDIT_PAYMENT_2PAYMENTS_OVERDUE = 0x03, /**< 2 Payments overdue */ - ZB_ZCL_PRICE_CREDIT_PAYMENT_3PAYMENTS_OVERDUE = 0x04, /**< 3 Payments overdue */ - /* reserved 0x05 - 0xFF */ -} zb_zcl_price_credit_payment_status_t; - - -/** @cond internals_doc */ - -/** @see @ref zb_zcl_price_credit_payment_status_t */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_STATUS(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_STATUS, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_OVER_DUE_AMOUNT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_OVER_DUE_AMOUNT, \ - ZB_ZCL_ATTR_TYPE_S32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT, \ - ZB_ZCL_ATTR_TYPE_S32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_PERIOD(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_PERIOD, \ - ZB_ZCL_ATTR_TYPE_S32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_N(paymentN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_ ## paymentN, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_DATE_N(paymentN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_DATE_ ## paymentN, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_REF_N(paymentN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_CREDIT_PAYMENT_REF_ ## paymentN, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_CREDIT_PAYMENT_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_RECEIVED_TIER_LABEL_GROUP Tier Label - * @{ - */ - -/** @brief Received Tier Label Attributes Set - * @see SE spec, D.4.2.2.10 - */ -enum zb_zcl_price_set_received_tier_label -{ - /** The ReceivedTierNPriceLabel attributes provide a method for utilities to - * assign a label to Received Price Tiers. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER1_PRICE_LABEL = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_RECEIVED_TIER_LABEL, 0x00), - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER2_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER3_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER4_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER5_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER6_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER7_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER8_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER9_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER10_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER11_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER12_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER13_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER14_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER15_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER16_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER17_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER18_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER19_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER20_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER21_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER22_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER23_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER24_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER25_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER26_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER27_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER28_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER29_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER30_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER31_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER32_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER33_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER34_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER35_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER36_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER37_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER38_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER39_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER40_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER41_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER42_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER43_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER44_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER45_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER46_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER47_PRICE_LABEL, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER48_PRICE_LABEL, - /* reserved 0x8030 - 0x80FF */ -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIERN_PRICE_LABEL_GNR(tierN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER ## tierN ## _PRICE_LABEL, \ - ZB_ZCL_ATTR_TYPE_OCTET_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) (data_ptr) \ -} - -/** @endcond */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_RECEIVED_TIER_LABEL_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_THRESHOLD_GROUP Received Block Threshold - * @{ - * @details - * This set of attributes provides remote access to the Price server - * ReceivedBlockThresholds. The number of block thresholds is indicated by the - * NumberOfBlockThresholds field in the associated PublishTariffInformation - * command. The number of blocks is one greater than the number of thresholds. - */ - -/** @brief Received Block Threshold Attributes Set - * @see SE spec, D.4.2.2.11 - */ -enum zb_zcl_price_set_received_block_threshold_e -{ - /** The format of these attributes is the same as for the 'Delivered' Block Thresholds - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK1_THRESHOLD = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_THRESHOLD, 0x00), - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK2_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK3_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK4_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK5_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK6_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK7_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK8_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK9_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK10_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK11_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK12_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK13_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK14_THRESHOLD, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK15_THRESHOLD, - /* reserved 0x810F - 0x81FF */ -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCKN_THRESHOLD_GNR(blockN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK ## blockN ## _THRESHOLD, \ - ZB_ZCL_ATTR_TYPE_48BIT, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_THRESHOLD_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_PERIOD_GROUP Received Block Period - * @{ - * @details - * This set of attributes provides remote access to the Price server - * Received Block Threshold period (typically the billing cycle) information. - */ - -/** @brief Received Block Period Attributes Set - * @see SE spec, D.4.2.2.12 - */ -enum zb_zcl_price_set_received_block_period_e -{ - /** The format of this attribute is the same as for the 'Delivered' - * StartOfBlockPeriod attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_START_OF_BLOCK_PERIOD = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_PERIOD, 0x00), - - /** The format of this attribute is the same as for the 'Delivered' - * BlockPeriodDuration attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK_PERIOD_DURATION, - - /** The format of this attribute is the same as for the 'Delivered' - * ThresholdMultiplier attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_THRESHOLD_MULTIPLIER, - - /** The format of this attribute is the same as for the 'Delivered' - * ThresholdDivisor attribute - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_THRESHOLD_DIVISOR, - /* reserved 0x8204 - 0x82FF */ -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_START_OF_BLOCK_PERIOD(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_START_OF_BLOCK_PERIOD, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK_PERIOD_DURATION(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_BLOCK_PERIOD_DURATION, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_THRESHOLD_MULTIPLIER(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_THRESHOLD_MULTIPLIER, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_THRESHOLD_DIVISOR(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_THRESHOLD_DIVISOR, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_PERIOD_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_PRICE_INFORMATION_GROUP Received Block Price Information - * @{ - */ - -/** @brief Received Block Price Information Attributes Set - * @see SE spec, D.4.2.2.13 - */ -enum zb_zcl_price_set_received_block_price_information_e -{ - /** The format and use of these attributes is the same as for the - * 'Delivered' TierNBlockNPrice attributes. - */ - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK1_PRICE = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_PRICE_INFORMATION, 0x00), - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER1_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER2_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER3_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER4_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER5_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER6_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER7_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER8_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER9_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER10_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER11_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER12_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER13_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER14_BLOCK16_PRICE, - - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK1_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK2_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK3_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK4_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK5_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK6_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK7_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK8_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK9_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK10_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK11_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK12_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK13_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK14_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK15_PRICE, - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER15_BLOCK16_PRICE, -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCKN_PRICE_GNR(blockN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RX_NO_TIER_BLOCK ## blockN ## _PRICE, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RX_TIERN_BLOCKM_PRICE_GNR(tierN, blockM, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RX_TIER ## tierN ## _BLOCK ## blockM ## _PRICE, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_RECEIVED_BLOCK_PRICE_INFORMATION_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_RECEIVED_EXTENDED_PRICE_INFORMATION_GROUP Received Extended Price Information - * @{ - * @details - * In case of TOU charging only, the price server shall support up to 48 TOU - * rates. To reduce the number of attributes, RxTierNBlock1Price attributes - * are reused to represent rates for tiers 1 to 15. Rates for tiers 16 to 48 - * are provided in the Received Extended Price Information Set. - */ - -/** @brief Received Extended Price Information Attributes Set - * @see SE spec, D.4.2.2.14 - */ -enum zb_zcl_price_set_received_extended_price_information_e -{ - /* reserved 0x8500 - 0x850E */ - - /** The format and use of these attributes is the same as for the - * 'Delivered' PriceTierN attributes. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER16 = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_RECEIVED_EXTENDED_PRICE_INFORMATION, 0x0F), - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER17, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER18, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER19, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER20, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER21, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER22, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER23, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER24, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER25, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER26, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER27, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER28, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER29, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER30, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER31, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER32, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER33, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER34, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER35, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER36, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER37, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER38, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER39, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER40, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER41, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER42, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER43, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER44, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER45, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER46, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER47, - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER48, - /* reserved 0x8530 - 0x85FF */ -}; - -/** @brief Default value for Price cluster revision global attribute */ -#define ZB_ZCL_PRICE_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief Default value for Tier1_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER1_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x31 ,0x00} - -/** @brief Default value for Tier2_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER2_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x32 ,0x00} - -/** @brief Default value for Tier3_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER3_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x33 ,0x00} - -/** @brief Default value for Tier4_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER4_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x34 ,0x00} - -/** @brief Default value for Tier5_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER5_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x35 ,0x00} - -/** @brief Default value for Tier6_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER6_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x36 ,0x00} - -/** @brief Default value for Tier7_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER7_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x37 ,0x00} - -/** @brief Default value for Tier8_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER8_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x38 ,0x00} - -/** @brief Default value for Tier9_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER9_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x39 ,0x00} - -/** @brief Default value for Tier10_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER10_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x31 ,0x30, 0x00} - -/** @brief Default value for Tier11_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER11_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x31 ,0x31, 0x00} - -/** @brief Default value for Tier12_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER12_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x31 ,0x32, 0x00} - -/** @brief Default value for Tier13_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER13_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x31 ,0x33, 0x00} - -/** @brief Default value for Tier14_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER14_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x31 ,0x34, 0x00} - -/** @brief Default value for Tier15_PriceLabel attribute */ -#define ZB_ZCL_PRICE_SRV_TIER15_PRICE_LABEL_DEFAULT_VALUE {0x54, 0x49, 0x45, 0x52, 0x20, 0x31 ,0x35, 0x00} - -/** @brief Default value for ConversionFactor attribute */ -#define ZB_ZCL_PRICE_SRV_CONVERSION_FACTOR_DEFAULT_VALUE ((zb_uint32_t)0x10000000) - -/** @brief Default value for ConversionFactorTrailingDigit attribute */ -#define ZB_ZCL_PRICE_SRV_CONVERSION_FACTOR_TRAILING_DIGIT_DEFAULT_VALUE ((zb_uint8_t)0x70) - -/** @brief Default value for CalorificValue attribute */ -#define ZB_ZCL_PRICE_SRV_CALORIFIC_VALUE_DEFAULT_VALUE ((zb_uint32_t)0x2625A00) - -/** @brief Default value for CalorificValueUnit attribute */ -#define ZB_ZCL_PRICE_SRV_CALORIFIC_VALUE_UNIT_DEFAULT_VALUE ((zb_uint8_t)0x1) - -/** @brief Default value for CalorificValueTrailingDigit attribute */ -#define ZB_ZCL_PRICE_SRV_CALORIFIC_VALUE_TRAILING_DIGIT_DEFAULT_VALUE ((zb_uint8_t)0x60) -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIERN_GNR(tierN, data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_PRICE_TIER ## tierN, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_RECEIVED_EXTENDED_PRICE_INFORMATION_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_RECEIVED_TARIFF_INFORMATION_GROUP Received Tariff Information - * @{ - * @details - * The following set of attributes represents items that are associated with a - * particular Received Price Tariff. - */ - -/** @brief Received Tariff Information Attributes Set - * @see SE spec, D.4.2.2.15 - */ -enum zb_zcl_price_set_received_tariff_information_e -{ - /* reserved 0x8600 - 0x860F */ - - /** The format and use of this attribute is the same as for the - * 'Delivered' TariffLabel attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TARIFF_LABEL = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_RECEIVED_TARIFF_INFORMATION, 0x10), - - /** The format and use of this attribute is the same as for the - * 'Delivered' NumberOfPriceTiersInUse attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_NUMBER_OF_PRICE_TIERS_IN_USE, - - /** The format and use of this attribute is the same as for the - * 'Delivered' NumberOfBlockThresholdsInUse attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_NUMBER_OF_BLOCK_THRESHOLDS_IN_USE, - - /** The format and use of this attribute is the same as for the - * 'Delivered' TierBlockMode attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER_BLOCK_MODE, - /* reserved 0x8614 */ - - /** An 8-bit enumeration identifying the resolution period for Block Tariff. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TARIFF_RESOLUTION_PERIOD = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_RECEIVED_TARIFF_INFORMATION, 0x15), - /* reserved 0x8616 - 0x8624 */ - - /** The format and use of this attribute is the same as for the - * 'Delivered' CO2 attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CO2 = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_RECEIVED_TARIFF_INFORMATION, 0x25), - - /** The format and use of this attribute is the same as for the - * 'Delivered' CO2Unit attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CO2_UNIT, - - /** The format and use of this attribute is the same as for the - * 'Delivered' CO2TrailingDigit attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CO2_TRAILING_DIGIT, - /* reserved 0x8528 - 0x85FF */ -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TARIFF_LABEL(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TARIFF_LABEL, \ - ZB_ZCL_ATTR_TYPE_OCTET_STRING, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_NUMBER_OF_PRICE_TIERS_IN_USE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_NUMBER_OF_PRICE_TIERS_IN_USE, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_NUMBER_OF_BLOCK_THRESHOLDS_IN_USE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_NUMBER_OF_BLOCK_THRESHOLDS_IN_USE, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @see SE spec, table D-82. */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER_BLOCK_MODE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TIER_BLOCK_MODE, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @see @ref zb_zcl_price_tariff_resolution_period_t. */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TARIFF_RESOLUTION_PERIOD(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_TARIFF_RESOLUTION_PERIOD, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CO2(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CO2, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @see @ref zb_zcl_price_co2_unit_t */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CO2_UNIT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CO2_UNIT, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CO2_TRAILING_DIGIT(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CO2_TRAILING_DIGIT, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_RECEIVED_TARIFF_INFORMATION_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_SET_RECEIVED_BILLING_INFORMATION_GROUP Received Billing Information - * @{ - * @details - * The following set of attributes represents items that are associated with - * particular Received Billing information. - */ - -/** @brief Received Billing Information Attributes Set - * @see SE spec, D.4.2.2.16 - */ -enum zb_zcl_price_set_received_billing_information -{ - /** The format and use of this attribute is the same as for the - * 'Delivered' CurrentBillingPeriodStart attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CURRENT_BILLING_PERIOD_START = ZB_ZCL_ATTR_SET_WITH_ATTR_ID(ZB_ZCL_PRICE_SET_RECEIVED_BILLING_INFORMATION, 0x00), - - /** The format and use of this attribute is the same as for the - * 'Delivered' CurrentBillingPeriodDuration attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CURRENT_BILLING_PERIOD_DURATION, - - /** The format and use of this attribute is the same as for the - * 'Delivered' LastBillingPeriodStart attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_LAST_BILLING_PERIOD_START, - - /** The format and use of this attribute is the same as for the - * 'Delivered' LastBillingPeriodDuration attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_LAST_BILLING_PERIOD_DURATION, - - /** The format and use of this attribute is the same as for the - * 'Delivered' LastBillingPeriodConsolidatedBill attribute. - */ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_LAST_BILLING_PERIOD_CONSOLIDATED_BILL, - /* reserved 0x8705 - 0x87FF */ -}; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CURRENT_BILLING_PERIOD_START(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CURRENT_BILLING_PERIOD_START, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CURRENT_BILLING_PERIOD_DURATION(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_CURRENT_BILLING_PERIOD_DURATION, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_LAST_BILLING_PERIOD_START(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_LAST_BILLING_PERIOD_START, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_LAST_BILLING_PERIOD_DURATION(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_LAST_BILLING_PERIOD_DURATION, \ - ZB_ZCL_ATTR_TYPE_U24, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_LAST_BILLING_PERIOD_CONSOLIDATED_BILL(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_SRV_RECEIVED_LAST_BILLING_PERIOD_CONSOLIDATED_BILL, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @} */ /* end of ZB_ZCL_PRICE_SET_RECEIVED_BILLING_INFORMATION_GROUP */ - - -/******************************************************************************/ - -/** @def ZB_ZCL_DECLARE_PRICE_SRV_ATTRIB_LIST - * @brief Declare server-side Price cluster attributes - * @param attr_list - Attribute list name. - * @param commodity_type - pointer to variable to store @ref ZB_ZCL_ATTR_PRICE_SRV_COMMODITY_TYPE "CommodityType" attribute value. -*/ -#define ZB_ZCL_DECLARE_PRICE_SRV_ATTRIB_LIST(attr_list, commodity_type) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_PRICE) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_PRICE_SRV_COMMODITY_TYPE, (commodity_type)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ /* end of ZB_ZCL_PRICE_SRV_ATTRIBUTES_GROUP */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_CLIENT_ATTRIBUTES_GROUP Price cluster client attributes - * @{ - */ - -/** @brief Price Cluster client attributes */ -typedef enum zb_zcl_price_cli_attr_e -{ - /** @e PriceIncreaseRandomizeMinutes attribute represents the maximum amount - * of time to be used when randomizing the response to a price increase. - */ - ZB_ZCL_ATTR_PRICE_CLI_PRICE_INCREASE_RANDOMIZE_MINUTES = 0x0000, - - /** @e PriceDecreaseRandomizeMinutes attribute represents the maximum number - * of minutes to be used when randomizing the response to a price decrease. - */ - ZB_ZCL_ATTR_PRICE_CLI_PRICE_DECREASE_RANDOMIZE_MINUTES = 0x0001, - - /** @e CommodityType attribute provides a label for identifying the type of pricing client present. - */ - ZB_ZCL_ATTR_PRICE_CLI_COMMODITY_TYPE = 0x0002, -} zb_zcl_price_cli_attr_t; - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_CLI_PRICE_INCREASE_RANDOMIZE_MINUTES(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_CLI_PRICE_INCREASE_RANDOMIZE_MINUTES, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_CLI_PRICE_DECREASE_RANDOMIZE_MINUTES(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_CLI_PRICE_DECREASE_RANDOMIZE_MINUTES, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) (data_ptr) \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_PRICE_CLI_COMMODITY_TYPE(data_ptr) \ -{ \ - ZB_ZCL_ATTR_PRICE_CLI_COMMODITY_TYPE, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) (data_ptr) \ -} - -/** @endcond */ /* internals_doc */ - -/** @def ZB_ZCL_DECLARE_PRICE_CLI_ATTRIB_LIST - * @brief Declare client-side Price cluster attributes - * @param attr_list - Attribute list name - * @param inc_rand_min - pointer to variable to store @ref ZB_ZCL_ATTR_PRICE_CLI_PRICE_INCREASE_RANDOMIZE_MINUTES "PriceIncreaseRandomizeMinutes" attribute value. - * @param dec_rand_min - pointer to variable to store @ref ZB_ZCL_ATTR_PRICE_CLI_PRICE_DECREASE_RANDOMIZE_MINUTES "PriceDecreaseRandomizeMinutes" attribute value. - * @param commodity_type - pointer to variable to store "CommodityType" attribute value. - */ -#define ZB_ZCL_DECLARE_PRICE_CLI_ATTRIB_LIST(attr_list, inc_rand_min, dec_rand_min, commodity_type) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_PRICE) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_PRICE_CLI_PRICE_INCREASE_RANDOMIZE_MINUTES, (inc_rand_min)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_PRICE_CLI_PRICE_DECREASE_RANDOMIZE_MINUTES, (dec_rand_min)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_PRICE_CLI_COMMODITY_TYPE, (commodity_type)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ /* end of ZB_ZCL_PRICE_CLIENT_ATTRIBUTES_GROUP */ - -/** @} */ /* end of ZB_ZCL_PRICE_ATTRS */ - - -/******************************************************************************/ - -/** @defgroup ZB_ZCL_PRICE_CLUSTER_COMMANDS Price cluster commands - * @{ - */ - -/** @brief Price cluster client command identifiers. - * @see SE spec, subclause D.4.2.3. - */ -typedef enum zb_zcl_price_client_cmd_e -{ - /** GetCurrentPrice command initiates a PublishPrice command for the current time. - * @see SE spec, subclause D.4.2.3.2. - * @see zb_zcl_price_get_current_price_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_CURRENT_PRICE = 0x00, - - /** GetScheduledPrices command initiates a PublishPrice command for available - * price events. - * @see zb_zcl_price_get_scheduled_prices_payload_s - * @see SE spec, subclause D.4.2.3.3. */ - ZB_ZCL_PRICE_CLI_CMD_GET_SCHEDULED_PRICES = 0x01, - - /** PriceAcknowledgement command provides the ability to acknowledge a - * previously sent PublishPrice command. - * @see SE spec, subclause D.4.2.3.4. - * @see zb_zcl_price_ack_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_PRICE_ACK = 0x02, - - /** GetBlockPeriod(s) command. - * This command initiates a PublishBlockPeriod command for the currently - * scheduled block periods. - * @see SE spec, subclause D.4.2.3.5. - * @see zb_zcl_price_get_block_period_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_BLOCK_PERIOD = 0x03, - - /** GetConversionFactor command. - * This command initiates a PublishConversionFactor command(s) for scheduled - * conversion factor updates. - * @see SE spec, subclause D.4.2.3.6 - * @see zb_zcl_price_get_conversion_factor_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_CONVERSION_FACTOR = 0x04, - - /** GetCalorificValue command. - * This command initiates a PublishCalorificValue command(s) for scheduled - * calorific value updates. - * @see SE spec, subclause D.4.2.3.7. - * @see zb_zcl_price_client_get_calorific_value_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_CALORIFIC_VALUE = 0x05, - - /** GetTariffInformation command. - * This command initiates PublishTariffInformation command(s) for scheduled - * tariff updates. - * @see SE spec, subclause D.4.2.3.8. - * @see zb_zcl_price_get_tariff_information_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_TARIFF_INFORMATION = 0x06, - - /** GetPriceMatrix command. - * This command initiates a PublishPriceMatrix command for the scheduled Price - * Matrix updates. - * @see SE spec, subclause D.4.2.3.9. - * @see zb_zcl_price_get_price_matrix_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_PRICE_MATRIX = 0x07, - - /** GetBlockThresholds command. - * This command initiates a PublishBlockThreshold command for the scheduled - * Block Threshold updates. - * @see SE spec, subclause D.4.2.3.10. - * @see zb_zcl_price_get_block_thresholds_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_BLOCK_THRESHOLDS = 0x08, - - /** GetCO2Value command. - * This command initiates PublishCO2Value command(s) for scheduled CO2 - * conversion factor updates. - * @see SE spec, subclause D.4.2.3.11. - * @see zb_zcl_price_get_co2_value_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_CO2_VALUE = 0x09, - - /** GetTierLabels command. - * This command allows a client to retrieve the tier labels associated with a - * given tariff; this command initiates a PublishTierLabels command from - * the server. - * @see SE spec, subclause D.4.2.3.12. - * @see zb_zcl_price_get_tier_labels_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_TIER_LABELS = 0x0A, - - /** GetBillingPeriod command. - * This command initiates one or more PublishBillingPeriod commands for - * currently scheduled billing periods. - * @see SE spec, subclause D.4.2.3.13. - * @see zb_zcl_price_get_billing_period_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_BILLING_PERIOD = 0x0B, - - /** GetConsolidatedBill command. - * This command initiates one or more PublishConsolidatedBill commands with - * the requested billing information. - * @see SE spec, subclause D.4.2.3.14. - * @see zb_zcl_price_get_consolidated_bill_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_CONSOLIDATED_BILL = 0x0C, - - /** CPPEventResponse command. - * The CPPEventResponse command is sent from a Client (IHD) to the ESI to - * notify it of a Critical Peak Pricing event authorization. - * - * @note The CPPEventResponse command in current revision of SE specification - * is provisional and not certifiable. This feature may change before reaching - * certifiable status in a future revision of SE specification. - * - * @see SE spec, subclause D.4.2.3.15. - * @see zb_zcl_price_cpp_event_response_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_CPP_EVENT_RESPONSE = 0x0D, - - /** GetCreditPayment command. - * This command initiates PublishCreditPayment commands for the requested - * credit payment information. - * @see SE spec, subclause D.4.2.3.16. - * @see zb_zcl_price_get_credit_payment_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_CREDIT_PAYMENT = 0x0E, - - /** GetCurrencyConversion command. - * This command initiates a PublishCurrencyConversion command for the currency - * conversion factor updates. - * @see SE spec, subclause D.4.2.3.17. - * @see zb_zcl_price_publish_currency_conversion_payload_s - */ - ZB_ZCL_PRICE_CLI_CMD_GET_CURRENCY_CONVERSION = 0x0F, - - /** GetTariffCancellation command. - * This command initiates the return of the last CancelTariff command held on - * the associated server. - * @see SE spec, subclauseD.4.2.3.18. - * @note This command has no payload. - */ - ZB_ZCL_PRICE_CLI_CMD_GET_TARIFF_CANCELLATION = 0x10, - - /* reserved 0x11 - 0xFF */ -} zb_zcl_price_client_cmd_t; - -/** @brief Price cluster server command identifiers - * @see SE spec, subclause D.4.2.4. - */ -typedef enum zb_zcl_price_server_cmd_e -{ - /** PublishPrice command. - * The Publish Price command is generated in response to receiving a - * GetCurrentPrice command, in response to a GetScheduledPrices command, - * and when an update to the pricing information is available from the - * commodity provider. - * @see SE spec, subclause D.4.2.4.1. - * @see zb_zcl_price_publish_price_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_PRICE = 0x00, - - /** PublishBlockPeriod command. - * The Publish Block Period command is generated in response to receiving a - * GetBlockPeriod(s) command (see sub-clause D.4.2.3.5) or when an update - * to the block tariff schedule is available from the commodity provider. - * @see SE spec, subclause D.4.2.4.2. - * @see zb_zcl_price_publish_block_period_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_BLOCK_PERIOD = 0x01, - - /** PublishConversionFactor command. - * The PublishConversionFactor command is sent in response to a - * GetConversionFactor command or if a new conversion factor is available. - * @see SE spec, subclause D.4.2.4.3. - * @see zb_zcl_price_publish_conversion_factor_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CONVERSION_FACTOR = 0x02, - - /** PublishCalorificValue command. - * The PublishCalorificValue command is sent in response to a - * GetCalorificValue command or if a new calorific value is available. - * @see SE spec, subclause D.4.2.4.4. - * @see zb_zcl_price_publish_calorific_value_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CALORIFIC_VALUE = 0x03, - - /** PublishTariffInformation command. - * The PublishTariffInformation command is sent in response to a - * GetTariffInformation command or if new tariff information is available - * (including Price Matrix and Block Thresholds). - * @see SE spec, subclause D.4.2.4.5. - * @see zb_zcl_price_publish_tariff_information_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_TARIFF_INFORMATION = 0x04, - - /** PublishPriceMatrix command. - * The PublishPriceMatrix command is used to publish the Block Price - * Information Set (up to 15 tiers x 15 blocks) and - * the Extended Price Information Set (up to 48 tiers). - * The PublishPriceMatrix command is sent in response to - * a GetPriceMatrix command. - * @see SE spec, subclause D.4.2.4.6. - * @see zb_zcl_price_publish_price_matrix_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_PRICE_MATRIX = 0x05, - - /** PublishBlockThresholds command. - * The PublishBlockThresholds command is sent in response to - * a GetBlockThresholds command. - * @see SE spec, subclause D.4.2.4.7. - * @see zb_zcl_price_publish_block_thresholds_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_BLOCK_THRESHOLDS = 0x06, - - /** PublishCO2Value command. - * The PublishCO2Value command is sent in response to a GetCO2Value command or - * if a new CO2 conversion factor is available. - * @see SE spec, subclause D.4.2.4.8. - * @see zb_zcl_price_publish_co2_value_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CO2_VALUE = 0x07, - - /** PublishTierLabels command. - * The PublishTierLabels command is generated in response to receiving a - * GetTierLabels command or when there is a tier label change. - * @see SE spec, subclause D.4.2.4.9. - * @see zb_zcl_price_publish_tier_labels_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_TIER_LABELS = 0x08, - - /** PublishBillingPeriod command. - * The PublishBillingPeriod command is generated in response to receiving a - * GetBillingPeriod(s) command or when an update to the Billing schedule is - * available from the commodity supplier. - * @see SE spec, subclause D.4.2.4.10. - * @see zb_zcl_price_publish_billing_period_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_BILLING_PERIOD = 0x09, - - /** PublishConsolidatedBill command. - * The PublishConsolidatedBill command is used to make consolidated billing - * information from previous billing periods available to other end devices. - * This command is issued in response to a GetConsolidatedBill command or - * if new billing information is available. - * @see SE spec, subclause D.4.2.4.11. - * @see zb_zcl_price_publish_consolidated_bill_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CONSOLIDATED_BILL = 0x0A, - - /** PublishCPPEvent command. - * The PublishCPPEvent command is sent from an ESI to its Price clients to - * notify them of a Critical Peak Pricing (CPP) event. - * - * @note The CPPEventResponse command in current revision of SE specification - * is provisional and not certifiable. This feature may change before reaching - * certifiable status in a future revision of SE specification. - * - * @see SE spec, subclause D.4.2.4.12. - * @see zb_zcl_price_publish_cpp_event_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CPP_EVENT = 0x0B, - - /** PublishCreditPayment command. - * The PublishCreditPayment command is used to update the credit payment - * information when available. - * @see SE spec, subclause D.4.2.4.13. - * @see zb_zcl_price_publish_credit_payment_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CREDIT_PAYMENT = 0x0C, - - /** PublishCurrencyConversion command. - * The PublishCurrencyConversion command is sent in response to a - * GetCurrencyConversion command or when a new currency becomes available. - * @see SE spec, subclause D.4.2.4.14. - * @see zb_zcl_price_publish_currency_conversion_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CURRENCY_CONVERSION = 0x0D, - - /** CancelTariff command. - * The CancelTariff command indicates that all data associated with a - * particular tariff instance should be discarded. - * @see SE spec, subclause D.4.2.4.15. - * @see zb_zcl_price_cancel_tariff_payload_s - */ - ZB_ZCL_PRICE_SRV_CMD_CANCEL_TARIFF = 0x0E, - - /* reserved 0x0F - 0xFF */ -} zb_zcl_price_server_cmd_t; - -/* PRICE cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_PRICE_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_PRICE, \ - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_TIER_LABELS - -#define ZB_ZCL_CLUSTER_ID_PRICE_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_PRICE_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_PRICE_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_PRICE_CLI_CMD_GET_CURRENT_PRICE, \ - ZB_ZCL_PRICE_CLI_CMD_GET_SCHEDULED_PRICES, \ - ZB_ZCL_PRICE_CLI_CMD_PRICE_ACK, \ - ZB_ZCL_PRICE_CLI_CMD_GET_TIER_LABELS - -#define ZB_ZCL_CLUSTER_ID_PRICE_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_PRICE_CLIENT_ROLE_GENERATED_CMD_LIST - - -/** @brief @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_PRICE "PublishPrice" command payload. - * @see SE spec, subclause D.4.2.3.1.1. - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_price_payload_s -{ - /** Unique identifier for the commodity provider. */ - zb_uint32_t provider_id; /* (M) */ - - /** Commodity provider-specific information regarding - * the current billing rate. - */ - zb_uint8_t rate_label[13]; /* (M) */ - - /** Unique identifier generated by the commodity provider - * allows devices to determine which pricing information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** UTC Time field containing the current time as determined - * by the device. - */ - zb_uint32_t current_time; /* (M) */ - - /** Field identifying the commodity as well as this base units of measure. - * @see enum zb_zcl_metering_unit_of_measure_e - */ - zb_uint8_t unit_of_measure; /* (M) */ - - /** Field identifying information concerning the local unit of - * currency used in the price field. - * @see ISO-4217 - */ - zb_uint16_t currency; /* (M) */ - - /** Determines where the decimal point is located in the price field */ - zb_bitfield_t price_trailing_digit:4; /* (M) */ - - /** Indicates the current price tier as chosen by the commodity provider */ - zb_bitfield_t price_tier:4; /* (M) */ - - /** Represents the maximum number of price tiers available. */ - zb_bitfield_t number_of_price_tiers:4; /* (M) */ - - /** Indicates the register tier used with the - * current Price Tier (@ref price_tier). - */ - zb_bitfield_t register_tier:4; /* (M) */ - - /** Denotes the time at which the signal becomes valid. - * Value 0x00000000 is a special time denoting "now". - */ - zb_uint32_t start_time; /* (M) */ - - /** Denotes amount of time in minutes after Start Time (@ref start_time) - * during which the price signal is valid. - */ - zb_uint16_t duration_in_minutes; /* (M) */ - - /** Contains the price of the commodity measured in base unit of - * Currency per Unit of Measure (@ref currency per @ref unit_of_measure) - * with the decimal point located as indicated by - * the Price Trailing Digit field (@ref price_trailing_digit) when - * the commodity is delivered to premises. - */ - zb_uint32_t price; /* (M) */ - - /* Optional fields. */ - - /** Gives the ratio of the price denoted in the Price field (@ref price) - * to the "normal" price, chosen by the commodity provider. - */ - zb_uint8_t price_ratio; /* (O) */ - - /** Contains the price of the commodity measured in base unit of - * Currency per Unit of Measure (@ref currency per @ref unit_of_measure) - * with the decimal point located as indicated by - * the Price Trailing Digit field (@ref price_trailing_digit) when - * the commodity is received from premises. - */ - zb_uint32_t generation_price; /* (O) */ - - /** Gives the ratio of the price denoted in the Generation Price - * field (@ref price) to the "normal" price, - * chosen by the commodity provider. - */ - zb_uint8_t generation_price_ratio; /* (O) */ - - /** Provides mechanism to describe an alternative measure of the cost - * of the energy consumed. - */ - zb_uint32_t alternate_cost_delivered; /* (O) */ - - /** Identifies the unit for Alternate Cost Delivered field - * (@ref alternate_cost_delivered) - */ - zb_uint8_t alternate_cost_unit; /* (O) */ - - /** Determines where the decimal point is located in - * the alternate cost field. - */ - zb_uint8_t alternate_cost_trailing_digit; /* (O) */ - - /** Indicates the number of block thresholds available. */ - zb_uint8_t number_of_block_thresholds; /* (O) */ - - /** Identifies additional control options (PriceAcknowledgement policy and - * total number of tier flag). - */ - zb_uint8_t price_control; /* (O) */ - - /** Specifies the total number of generation tiers applicable in the - * current tariff. - */ - zb_uint8_t number_of_generation_tiers; /* (O) */ - - /** Specifies the current generation tier. */ - zb_uint8_t generation_tier; /* (O) */ - - /** Indicates a maximum number of tier available. - * @see number_of_generation_tiers - */ - zb_uint8_t extended_number_of_price_tiers; /* (O) */ - - /** Indicates the current price tier. - * @see price_tier - */ - zb_uint8_t extended_price_tier; /* (O) */ - - /** Indicates the register tier used with the - * current Price Tier (@ref register_tier). - */ - zb_uint8_t extended_register_tier; /* (O) */ - -} ZB_PACKED_STRUCT zb_zcl_price_publish_price_payload_t; - - -/** @def ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_SIZE_IS_VALID - */ -#define ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_SIZE_IS_VALID(size) \ - (size > (sizeof(zb_zcl_price_publish_price_payload_t) \ - - ZB_SIZEOF_FIELD(zb_zcl_price_publish_price_payload_t, rate_label))) - -/** @def ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_EXPECTED_SIZE - * @brief Returns actual size of payload. - * @details PublishPrice packet payload doesn't have fixed length because of 'rate_label' - * field. This macro can be used to check payload size of incoming packet. - */ -#define ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_EXPECTED_SIZE(pl) \ - (sizeof(*(pl)) \ - - (ZB_ZCL_STRING_CONST_SIZE((pl)->rate_label) - ZB_ZCL_GET_STRING_LENGTH((pl)->rate_label))) - -/** @def ZB_ZCL_PRICE_DEFAULT_PRICE_CONTROL_VALUE - * @brief Controls PriceAck policy for outgoing PublishPrice packets. - * SE devices can enable this field (refer @ref zb_zcl_price_publish_price_payload_t::price_control) - * if they want to receive @ref ZB_ZCL_PRICE_CLI_CMD_PRICE_ACK "PriceAcknowledgement" command as - * response to @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_PRICE "PublishPrice" command, but this behavior - * is valid only for SE version >= 1.1. - * SE 1.2 is used, so this field is set to 1 by default. - */ -#define ZB_ZCL_PRICE_DEFAULT_PRICE_CONTROL_VALUE 0x01 - -/** @def ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_INIT - * @brief Macro for initializing @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_PRICE "PublishPrice" Command payload. - * @see @ref zb_zcl_price_publish_price_payload_t - * @par Example - * @code{C} - * zb_zcl_price_publish_price_payload_t pl = ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_INIT; - * @endcode - */ -#define ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_INIT \ - (zb_zcl_price_publish_price_payload_t) \ -{ \ - .price_ratio = 0xFF, \ - .generation_price = 0xFFFFFFFF, \ - .generation_price_ratio = 0xFF, \ - .alternate_cost_delivered = 0xFFFFFFFF, \ - .alternate_cost_unit = 0xFF, \ - .alternate_cost_trailing_digit = 0xFF, \ - .number_of_block_thresholds = 0xFF, \ - .price_control = ZB_ZCL_PRICE_DEFAULT_PRICE_CONTROL_VALUE, \ - .number_of_generation_tiers = 0x00, \ - .generation_tier = 0x00, \ - .extended_number_of_price_tiers = 0x00, \ - .extended_price_tier = 0x00, \ - .extended_register_tier = 0x00, \ -} - -/** @brief @ref ZB_ZCL_PRICE_CLI_CMD_PRICE_ACK "PriceAcknowledgement" Command payload - * @see SE spec, D.4.2.3.4.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_ack_payload_s -{ - /** Unique identifier for the commodity provider. */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. - * allows devices to determine which pricing information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** @e UTCTime field containing the current time as determined - * by the device. - */ - zb_uint32_t current_time; /* (M) */ - - /** Identifies additional control options (PriceAcknowledgement policy and - * total number of tier flag). - */ - zb_uint8_t price_control; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_ack_payload_t; - - -/** @cond internals_doc */ - -/** Check if @ref ZB_ZCL_PRICE_CLI_CMD_PRICE_ACK "PriceAcknowledgement" Command payload is valid - */ -#define ZB_ZCL_PRICE_ACK_PAYLOAD_SIZE_IS_VALID(size) \ - ((size) >= sizeof(zb_zcl_price_ack_payload_t)) - -/** @ref zb_zcl_price_ack_payload_t initializer */ -#define ZB_ZCL_PRICE_ACK_PAYLOAD_INIT (zb_zcl_price_ack_payload_t) {0} - -/** Initialize @ref zb_zcl_price_ack_payload_t from - * @ref zb_zcl_price_publish_price_payload_t values. - */ -#define ZB_ZCL_PRICE_ACK_PAYLOAD_INIT_FROM_PUBLISH_PRICE_PAYLOAD(pl) \ - (zb_zcl_price_ack_payload_t) { \ - .provider_id = (pl)->provider_id, \ - .issuer_event_id = (pl)->issuer_event_id, \ - .current_time = zb_get_utc_time(), \ - .price_control = (pl)->price_control, \ - } - -/** @endcond */ /* internals_doc */ - -/** @brief @ref ZB_ZCL_PRICE_CLI_CMD_GET_CURRENT_PRICE "GetCurrentPrice" Command Payload Format - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_current_price_payload_s -{ - /** @e CommandOptions field is 8 Bits in length - * @note Zero bit is Requestor Rx On When Idle, others are reserved. - */ - zb_uint8_t command_options; -} ZB_PACKED_STRUCT zb_zcl_price_get_current_price_payload_t; - -/** @def ZB_ZCL_PRICE_GET_CURRENT_PRICE_PAYLOAD_INIT - * @brief Macro for initializing @ref ZB_ZCL_PRICE_CLI_CMD_GET_CURRENT_PRICE "GetCurrentPrice" Command payload - */ -#define ZB_ZCL_PRICE_GET_CURRENT_PRICE_PAYLOAD_INIT \ - (zb_zcl_price_get_current_price_payload_t) {0} - -/** @def ZB_ZCL_PRICE_GET_CURRENT_PRICE_PAYLOAD_SIZE_IS_VALID - * @brief Check if @ref ZB_ZCL_PRICE_CLI_CMD_GET_CURRENT_PRICE "GetCurrentPrice" Command payload is valid - */ -#define ZB_ZCL_PRICE_GET_CURRENT_PRICE_PAYLOAD_SIZE_IS_VALID(size) \ - ((size) >= sizeof(zb_zcl_price_get_current_price_payload_t)) - -/** @brief @ref ZB_ZCL_PRICE_CLI_CMD_GET_SCHEDULED_PRICES "GetScheduledPrices" Command Payload Format - * @see SE spec, D.4.2.3.3.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_scheduled_prices_payload_s -{ - /** @e StartTime represents the minimum ending time for any scheduled or - * currently active pricing events to be resent. - * @note Value 0x00000000 will be replaced with the current time stamp. - */ - zb_uint32_t start_time; - - /** @e NumberOfEvents represents the maximum number of events to be sent. - * @note Value 0 indicates no maximum limit. - */ - zb_uint8_t number_of_events; -} ZB_PACKED_STRUCT zb_zcl_price_get_scheduled_prices_payload_t; - - -/** @def ZB_ZCL_PRICE_GET_SCHEDULED_PRICES_PAYLOAD_INIT - * @brief Macro for initializing @ref ZB_ZCL_PRICE_CLI_CMD_GET_SCHEDULED_PRICES "GetScheduledPrices" Command payload - */ -#define ZB_ZCL_PRICE_GET_SCHEDULED_PRICES_PAYLOAD_INIT \ - (zb_zcl_price_get_scheduled_prices_payload_t) {0} - -/** @def ZB_ZCL_PRICE_GET_SCHEDULED_PRICES_PAYLOAD_SIZE_IS_VALID - * @brief Check if @ref ZB_ZCL_PRICE_CLI_CMD_GET_SCHEDULED_PRICES "GetScheduledPrices" Command payload is valid - */ -#define ZB_ZCL_PRICE_GET_SCHEDULED_PRICES_PAYLOAD_SIZE_IS_VALID(size) \ - ((size) >= sizeof(zb_zcl_price_get_scheduled_prices_payload_t)) - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_BLOCK_PERIOD "GetBlockPeriod" command payload - * @see SE spec, subclause D.4.2.3.5 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_block_period_payload_s -{ - /** UTC Timestamp representing the minimum ending time for any scheduled or currently block period - * events to be resent. - */ - zb_uint32_t start_time; /* (M) */ - - /** An 8-bit Integer which indicates the maximum number of Publish Block Period commands - * that can be sent. - */ - zb_uint8_t number_of_events; /* (M) */ - - /** An 8-bit bitmap identifying the type of tariff published in this command. The least significant - * nibble represents an enumeration of the tariff type. - * @see SE spec, Table D-108 - * @see zb_zcl_price_tariff_type_t - */ - zb_uint8_t tariff_type; /* (O) */ -} ZB_PACKED_STRUCT zb_zcl_price_client_get_block_period_payload_t; - - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_CONVERSION_FACTOR "GetConversionFactor" command payload. - * @see SE spec, subclause D.4.2.3.6.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_conversion_factor_payload_s -{ - /** UTC Timestamp indicating the earliest start time of values to be returned by the corresponding - * @e PublishConversionFactor command. - * */ - zb_uint32_t earliest_start_time; /* (M) */ - - /** A 32-bit integer representing the minimum @e IssuerEventID of values to be returned by the - * corresponding @e PublishCalorificValue command. - */ - zb_uint32_t min_issuer_event_id; /* (M) */ - - /** An 8-bit integer which represents the maximum number of @e PublishConversionFactor commands that - * the client is willing to receive in response to this command. A value of 0 indicates no maximum - * limit. - */ - zb_uint8_t number_of_commands; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_get_conversion_factor_payload_t; - - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_CALORIFIC_VALUE "GetCalorificValue" command payload - * @see SE spec, subclause D.4.2.3.7 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_client_get_calorific_value_payload_s -{ - /** UTC Timestamp indicating the earliest start time of values to be returned by the - * corresponding @e PublishCalorificValue command. - * */ - zb_uint32_t earliest_start_time; /* (M) */ - - /** A 32-bit integer representing the minimum @e IssuerEventID of values to be returned by the - * corresponding @e PublishCalorificValue command. - */ - zb_uint32_t min_issuer_event_id; /* (M) */ - - /** An 8-bit Integer which represents the maximum number of @e PublishCalorificValue commands that the - * client is willing to receive in response to this command. A value of 0 indicates no maximum limit - */ - zb_uint8_t number_of_commands; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_client_get_calorific_value_payload_t; - - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_TARIFF_INFORMATION "GetTariffInformation" command payload - * @see SE spec, subclause D.4.2.3.8.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_tariff_information_payload_s -{ - /** UTC Timestamp indicating the earliest start time of tariffs to be returned by the - * corresponding @e PublishTariffInformation command. - */ - zb_uint32_t earliest_start_time; /* (M) */ - - /** A 32-bit integer representing the minimum @e IssuerEventID of tariffs to be returned by the - * corresponding @e PublishTariffInformation command. - */ - zb_uint32_t min_issuer_event_id; /* (M) */ - - /** An 8-bit integer which represents the maximum number of @e PublishTariffInformation commands that - * the client is willing to receive in response to this command. A value of 0 would indicate all - * available @e PublishTariffInformation commands shall be returned. - */ - zb_uint8_t number_of_commands; /* (M) */ - - /** An 8-bit bitmap identifying the type of tariff published in this command. The least significant - * nibble represents an enumeration of the tariff type. - * The most significant nibble is reserved - * @see SE spec, Table D-108 - * @see zb_zcl_price_tariff_type_t - */ - zb_uint8_t tariff_type; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_get_tariff_information_payload_t; - - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_PRICE_MATRIX "GetPriceMatrix" command payload - * @see SE spec, subclause D.4.2.3.9 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_price_matrix_payload_s -{ - /** @e IssuerTariffID indicates the tariff to which the requested Price Matrix belongs. */ - zb_uint32_t issuer_tariff_id; -} ZB_PACKED_STRUCT zb_zcl_price_get_price_matrix_payload_t; - - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_BLOCK_THRESHOLDS "GetBlockThresholds" command payload - * @see SE spec, subclause D.4.2.3.10 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_block_thresholds_payload_s -{ - /** @e IssuerTariffID indicates the tariff to which the requested Block - * Thresholds belong. - */ - zb_uint32_t issuer_tariff_id; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_get_block_thresholds_payload_t; - - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_CO2_VALUE "GetCO2Value" command payload - * @see SE spec, subclause D.4.2.3.11.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_co2_value_payload_s -{ - /** UTC Timestamp indicating the earliest start time of values to be returned by the corresponding - * @e PublishCO2Value command. The first returned @e PublishCO2Value command shall be the instance - * which is active or becomes active at or after the stated @e EarliestStartTime. If more than one - * instance is requested, the active and scheduled instances shall be sent with ascending ordered - * @e StartTime. - */ - zb_uint32_t earliest_start_time; /* (M) */ - - /** A 32-bit integer representing the minimum @e IssuerEventID of values to be returned by the - * corresponding @e PublishCO2Value command. - */ - zb_uint32_t min_issuer_event_id; /* (M) */ - - /** An 8-bit Integer which represents the maximum number of @e PublishCO2Value commands that the - * client is willing to receive in response to this command. A value of 0 would indicate all - * available @e PublishCO2Value commands shall be returned. - */ - zb_uint8_t number_of_commands; /* (M) */ - - /** An 8-bit bitmap identifying the type of tariff published in this command. The least significant - * nibble represents an enumeration of the tariff type. - * @see SE spec, Table D-108 - * @see zb_zcl_price_tariff_type_t - */ - zb_uint8_t tariff_type; /* (O) */ -} ZB_PACKED_STRUCT zb_zcl_price_get_co2_value_payload_t; - - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_TIER_LABELS "GetTierLabels" command payload - * @see SE spec, subclause D.4.2.3.12.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_tier_labels_payload_s -{ - /** Unique identifier generated by the commodity supplier. This is used to - * identify the tariff that the labels apply to. - */ - zb_uint32_t issuer_tariff_id; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_get_tier_labels_payload_t; - -#define ZB_ZCL_PRICE_GET_TIER_LABELS_PAYLOAD_SIZE_IS_VALID(size) \ - ((size) >= sizeof(zb_zcl_price_get_tier_labels_payload_t)) - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_BILLING_PERIOD "GetBillingPeriod" command payload - * @see SE spec, subclause D.4.2.3.13.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_billing_period_payload_s -{ - /** UTC Timestamp indicating the earliest start time of billing periods to be - * returned by the corresponding @e PublishBillingPeriod command. - */ - zb_uint32_t earliest_start_time; /* (M) */ - - /** A 32-bit integer representing the minimum @e IssuerEventID of billing - * periods to be returned by the corresponding @e PublishBillingPeriod command. - */ - zb_uint32_t min_issuer_event_id; /* (M) */ - - /** An 8-bit Integer which indicates the maximum number of @e PublishBillingPeriod commands - * that the client is willing to receive in response to this command. - */ - zb_uint8_t number_of_commands; /* (M) */ - - /** An 8-bit bitmap identifying the @e TariffType of the requested @e BillingPeriod information. - * The least significant nibble represents an enumeration of the tariff type. - * The most significant nibble is reserved. - * @see SE spec, Table D-108 - * @see zb_zcl_price_tariff_type_t - */ - zb_uint8_t tariff_type; /* (O) */ -} ZB_PACKED_STRUCT zb_zcl_price_get_billing_period_payload_t; - - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_CONSOLIDATED_BILL "GetConsolidatedBill" command payload - * @see SE spec, subclause D.4.2.3.14.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_consolidated_bill_payload_s -{ - /** UTC Timestamp indicating the earliest start time of billing information to be - * returned by the corresponding @e PublishConsolidatedBill command. - */ - zb_uint32_t earliest_start_time; /* (M) */ - - /** A 32-bit integer representing the minimum @e IssuerEventID of billing information - * to be returned by the corresponding @e PublishConsolidatedBill command. - */ - zb_uint32_t min_issuer_event_id; /* (M) */ - - /** An 8-bit Integer which indicates the maximum number of @e PublishConsolidatedBill - * commands that can be sent. A value of 0 would indicate all available @e PublishConsolidatedBill - * commands shall be returned. - */ - zb_uint8_t number_of_commands; /* (M) */ - - /** An 8-bit bitmap identifying the @e TariffType of the requested @e BillingPeriod information. - * The least significant nibble represents an enumeration of the tariff type. - * The most significant nibble is reserved. - * @see SE spec, Table D-108 - * @see zb_zcl_price_tariff_type_t - */ - zb_uint8_t tariff_type; /* (O) */ -} ZB_PACKED_STRUCT zb_zcl_price_get_consolidated_bill_payload_t; - - -/** @ref ZB_ZCL_PRICE_CLI_CMD_CPP_EVENT_RESPONSE "CPPEventResponse" command payload - * @see SE spec, subclause D.4.2.3.15.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_cpp_event_response_payload_s -{ - /** Unique identifier generated by the commodity provider. When new information is provided that - * replaces older information for the same time period, this field allows devices - * to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** An 8-bit enumeration identifying the status of the CPP event. This field shall contain the - * 'Accepted' or 'Rejected' values - * @see SE spec, Table D-113 - * @see zb_zcl_price_cpp_event_status_t - */ - zb_uint8_t cpp_auth; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_cpp_event_response_payload_t; - - -/** @ref ZB_ZCL_PRICE_CLI_CMD_GET_CREDIT_PAYMENT "GetCreditPayment" command payload - * @see SE spec, subclause D.4.2.3.16.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_get_credit_payment_payload_s -{ - /** UTC timestamp indicating the latest @e CreditPaymentDate of records to be returned - * by the corresponding @e PublishCreditPayment commands. The first returned - * @e PublishCreditPayment command shall be the most recent record with its - * @e CreditPaymentDate equal to or older than the @e LatestEndTime provided. - */ - zb_uint32_t latest_end_time; /* (M) */ - - /** An 8-bit integer that represents the maximum number of @e PublishCreditPayment - * commands that the client is willing to receive in response to this command. - */ - zb_uint8_t number_of_commands; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_get_credit_payment_payload_t; - - -/** Block Period Control Field BitMap - * @see SE spec, Table D-104 - * @see zb_zcl_price_publish_block_period_payload_s::block_period_control - */ -typedef enum zb_zcl_price_block_period_control_field_bitmap_e -{ - ZB_ZCL_PRICE_CONTROL_PRICE_ACKNOWLEDGEMENT_REQUIRED = 1 << 0, /**< 1=Price Acknowledgement required,@n - * 0=Price Acknowledgement not required - */ - ZB_ZCL_PRICE_CONTROL_REPEATING_BLOCK = 1 << 1, /**< 1=Repeating Block, @n - * 0=Non Repeating Block - */ -} zb_zcl_price_block_period_control_field_t; - - -/** @brief Block Period Duration Control Enumeration - * @see SE spec, Table D-106 - */ -typedef enum zb_zcl_price_block_period_duration_control_e -{ - ZB_ZCL_PRICE_DURATION_START_OF_TIMEBASE = 0x00, /**< Start of Timebase */ - ZB_ZCL_PRICE_DURATION_END_OF_TIMEBASE, /**< End of Timebase */ - ZB_ZCL_PRICE_DURATION_NOT_SPECIFIED /**< Not Specified */ -} zb_zcl_price_block_period_duration_control_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_BLOCK_PERIOD "PublishBlockPeriod" command payload - * @see SE spec, subclause D.4.2.4.2.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_block_period_payload_s -{ - - /** An unsigned 32-bit field containing a unique identifier for the commodity provider. - * This field allows differentiation in deregulated markets where multiple - * commodity providers may be available. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new block period - * information is provided that replaces older information for the same period, - * this field allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field to denote the time at which the block tariff period starts. - */ - zb_uint32_t block_period_start_time; /* (M) */ - - /** An unsigned 24-bit field to denote the block tariff period . - */ - zb_uint24_t block_period_duration; /* (M) */ - - /** Identifies additional control options for the block period event. A value of - * 0x00 indicates field not used. - */ - zb_uint8_t block_period_control; - - /** An 8-bit bitmap where the least significant nibble is an enumerated sub-field - * indicating the time base used for the duration, and the most significant nibble - * is an enumerated sub-field providing duration control. - * @see zb_zcl_price_block_period_duration_type_e - */ - zb_uint8_t block_period_duration_type; /* (M) */ - - /** An 8-bit bitmap identifying the type of tariff published in this command. - * The least significant nibble represents an enumeration of the tariff type. - * @see SE spec, Table D-108 - * @see zb_zcl_price_tariff_type_t - */ - zb_uint8_t tariff_type; /* (M) */ - - /** An 8-bit enumeration identifying the resolution period for the block tariff. - * @see SE spec, Table D-107 - * @see zb_zcl_price_tariff_resolution_period_t - */ - zb_uint8_t tariff_resolution_period; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_block_period_payload_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CONVERSION_FACTOR "PublishConversionFactor" command payload - * @see SE spec, subclause D.4.2.4.3.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_conversion_factor_payload_s -{ - - /** Unique identifier generated by the commodity provider. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field to denote the time at which the value becomes valid. - * The value remains valid until replaced by a newer one. - */ - zb_uint32_t start_time; /* (M) */ - - /** @see SE spec, subclause D.4.2.2.4.3 */ - zb_uint32_t conversion_factor; /* (M) */ - - /** @see SE spec, subclause D.4.2.2.4.4 */ - zb_uint8_t conversion_factor_trailing_digit; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_conversion_factor_payload_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CALORIFIC_VALUE "PublishCalorificValue" command payload - * @see SE spec, subclause D.4.2.4.4. - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_calorific_value_payload_s -{ - - /** Unique identifier generated by the commodity provider. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field to denote the time at which the value becomes valid. - * The value remains valid until replaced by a newer one. - */ - zb_uint32_t start_time; /* (M) */ - - /** @see sub-clause D.4.2.2.4.5 - */ - zb_uint32_t calorific_value; /* (M) */ - - /** @see sub-clause D.4.2.2.4.6 - */ - zb_uint8_t calorific_value_unit; /* (M) */ - - /** @see sub-clause D.4.2.2.4.7 - */ - zb_uint8_t calorific_value_trailing_digit; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_calorific_value_payload_t; - - -/** Tariff Type Enumeration - * @see SE spec, Table D-108 - */ -typedef enum zb_zcl_price_tariff_type_e -{ - ZB_ZCL_PRICE_TARIFF_TYPE_DELIVERED = 0x00, /**< Delivered Tariff */ - ZB_ZCL_PRICE_TARIFF_TYPE_RECEIVED, /**< Received Tariff */ - ZB_ZCL_PRICE_TARIFF_TYPE_DELIVERED_AND_RECEIVED, /**< Delivered and Received Tariff */ -} zb_zcl_price_tariff_type_t; - - -/** Tariff Charging Scheme Enumeration - * @see SE spec, Table D-109 - */ -typedef enum zb_zcl_price_tariff_charging_scheme_e -{ - ZB_ZCL_PRICE_TOU_TARIFF = 0x00, /**< TOU Tariff */ - ZB_ZCL_PRICE_BLOCK_TARIFF, /**< Block Tariff */ - ZB_ZCL_PRICE_BLOCK_TOU_TARIFF_COMMON, /**< Block/TOU Tariff with common thresholds */ - ZB_ZCL_PRICE_BLOCK_TOU_TARIFF_INDIVIDUAL, /**< Block/TOU Tariff with individual thresholds per tier */ -} zb_zcl_price_tariff_charging_scheme_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_TARIFF_INFORMATION "PublishTariffInformation" command payload - * @see SE spec, subclause D.4.2.4.5.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_tariff_information_payload_s -{ - - - /** A unique identifier for the commodity supplier. */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this field - * allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** Unique identifier generated by the commodity supplier. - */ - zb_uint32_t issuer_tariff_id; /* (M) */ - - /** A UTC Time field to denote the time at which the price signal becomes valid. - */ - zb_uint32_t start_time; /* (M) */ - - /** An 8-bit bitmap identifying the type of tariff published in this command. - * The least significant nibble represents an enumeration of the tariff type, - * the most significant nibble represents an enumeration specifying the charging - * scheme. - * @see SE spec, Table D-108 and Table D-109 - * @see zb_zcl_price_tariff_type_t - * @see zb_zcl_price_tariff_charging_scheme_e - */ - zb_uint8_t tariff_type_charging_scheme; /* (M) */ - - /** The format and use of this field is the same as for the @e TariffLabel attribute - * or @e ReceivedTariffLabel attribute - */ - zb_uint8_t tariff_label[25]; /* (M) */ - - /** The format and use of this field is the same as for the @e NumberOfPriceTiersInUse - * attribute or @e ReceivedNumberOfPriceTiersInUse attribute - */ - zb_uint8_t number_of_price_tiers_in_use; /* (M) */ - - /** The format and use of this field is the same as for the @e NumberOfBlockThresholdsInUse - * attribute or @e ReceivedNumberOfBlockThresholdsInUse attribute - */ - zb_uint8_t number_of_block_thresholds_in_use; /* (M) */ - - /** The format and use of this field is the same as for the @e UnitOfMeasure attribute - */ - zb_uint8_t unit_of_measure; /* (M) */ - - /** The format and use of this field is the same as for the @e Currencyattribute - */ - zb_uint16_t currency; /* (M) */ - - /** The format and use of this field is the same as for the @e PriceTrailingDigit - * attribute - */ - zb_uint8_t price_trailing_digit; /* (M) */ - - /** The format and use of this field is the same as for the @e StandingCharge - * attribute. A value of 0xFFFFFFFF indicates the field is not used - */ - zb_uint32_t standing_charge; /* (M) */ - - /** The format and use of this field is the same as for the @e TierBlockMode - * attribute or @e ReceivedTierBlockMode attribute - */ - zb_uint8_t tier_block_mode; /* (M) */ - - /** @e BlockThresholdMultiplier provides a value to be multiplied against Threshold - * parameter(s). If present, this attribute must be applied to all @e BlockThreshold - * values to derive values that can be compared against the @e CurrentBlockPeriodConsumptionDelivered - * attribute within the Metering cluster. This parameter must be used in conjunction - * with the @e BlockThresholdDivisor parameter(s). - */ - zb_uint24_t block_threshold_multiplier; /* (M) */ - - /** @e BlockThresholdDivisor provides a value to divide the result of applying the - * @e ThresholdMultiplier attribute to @e BlockThreshold values to derive values that - * can be compared against the @e CurrentBlockPeriodConsumptionDelivered attribute - * within the Metering cluster. This attribute must be used in conjunction with - * the @e BlockThresholdMultiplier parameter(s). In case no divisor is defined, - * this field shall be set to 1. - */ - zb_uint24_t block_threshold_devisor; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_tariff_information_payload_t; - - -/** PublishPriceMatrix and PublishBlockThresholds Sub-Payload Control Bitmap - * @see SE spec, Table D-110 - * @see SE spec, Table D-111 - * @see zb_zcl_price_publish_matrix_type_e - * @see zb_zcl_price_publish_block_thresholds_type_e - */ -enum zb_zcl_price_sub_payload_control_bitmap_e -{ - ZB_ZCL_PRICE_SUB_PAYLOAD_TYPE = 0, /**< 0-bit of bitfield */ -}; - - -/** PublishPriceMatrix Sub-Payload Control values. - * @see SE spec, Table D-110 - * @see zb_zcl_price_sub_payload_control_bitmap_e - */ -typedef enum zb_zcl_price_publish_matrix_type_e -{ - ZB_ZCL_PRICE_BLOCK_TOU_BASED_INFORMATION = 0x00, /**< The information stored in the - * sub payload is Block only or Block/TOU based - */ - ZB_ZCL_PRICE_TOU_BASED_INFORMATION = 0x01, /**< The information stored in the sub - * payload is TOU based. - */ -} zb_zcl_price_publish_matrix_type_t; - - -/** PriceMatrix Sub-Payload - * @see SE spec, subclause D.4.2.4.6.2.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_price_matrix_sub_payload_s -{ - /** The @e Tier/Block ID specifies the TOU Tier or the TOU Tier and Block that - * the subsequent @e Price field in the command applies to - */ - zb_uint8_t tier_block_id; /* (M) */ - - /** This field holds the price information for the Block/TOU or TOU identified - * by the previous @e Tier/Block @e ID field. - */ - zb_uint32_t price; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_price_matrix_sub_payload_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_PRICE_MATRIX "PublishPriceMatrix" command payload - * @see SE spec, subclause D.4.2.4.6.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_price_matrix_payload_s -{ - /** A unique identifier for the commodity supplier. */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this field - * allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field to denote the time at which the price signal becomes valid. - */ - zb_uint32_t start_time; /* (M) */ - - - /** Unique identifier generated by the commodity supplier. This must match the - * @e IssuerTariffID sent in the related @e PublishTariffInformation command. - */ - zb_uint32_t issuer_tariff_id; /* (M) */ - - /** The @e CommandIndex is used to count the payload fragments in the case that - * an entire payload does not fit into one message. The @e CommandIndex starts - * at 0 and is incremented for each fragment belonging to the same command. - */ - zb_uint8_t command_index; /* (M) */ - - /** In the case that an entire payload does not fit into one message, the - * @e TotalNumberOfCommands field indicates the total number of sub-commands - * in the message. - */ - zb_uint8_t total_number_of_commands; /* (M) */ - - /** An 8-bit bitmap, the least significant bit of which specifies the information - * type stored in the sub payload. The remaining bits are reserved. - */ - zb_uint8_t sub_payload_control; /* (M) */ - - /** @see zb_zcl_price_price_matrix_sub_payload_s - */ - zb_zcl_price_price_matrix_sub_payload_t *price_matrix_sub_payload; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_price_matrix_payload_t; - - -/** PublishBlockThresholds Sub-Payload Control values - * @see SE spec, Table D-111 - * @see zb_zcl_price_sub_payload_control_bitmap_e - */ -typedef enum zb_zcl_price_publish_block_thresholds_type_e -{ - ZB_ZCL_PRICE_SPECIFIC_TOU_TIER = 0x00, /**< Block Thresholds supplied - * apply to a specific TOU tier - */ - ZB_ZCL_PRICE_ALL_TOU_TIER = 0X01, /**< Block Thresholds supplied apply to - * all TOU tiers or when Block Only charging - * is in operation - */ -} zb_zcl_price_publish_block_thresholds_type_t; - - -/** BlockThreshold Sub-Payload Format - * @see SE spec, subclause D.4.2.4.7.2.1 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_block_threshold_sub_payload_s -{ - /** The Tier/NumberOfBlockThresholds field is an 8 bitmap. The format of the - * bitmap is decided by bit0 of the sub-payload control field. - * @n If Bit0 of the Sub-Payload Control field is 0, then the least significant - * nibble represents a value specifying the number of thresholds to follow in - * the command. The most significant nibble represents the Tier that the subsequent - * block threshold values apply to. - * @n If Bit0 of the Sub-Payload Control field is 1, then the most significant - * nibble is unused and should be set to 0. - * @n Valid values for the NumberOfBlockThresholds sub-field are 0 to 15 - * reflecting no block in use (0) to block 15(15). - * Valid values for the Tiers sub-field are from 0 to 15 reflecting no tier to tier - * fifteen. - */ - zb_uint8_t tier_number_of_block_thresholds; - - /** The Block Thresholds represent the threshold values applicable to an - * individual block period and, where applicable, to a particular tier. - */ - zb_uint48_t block_threshold[15]; -} ZB_PACKED_STRUCT zb_zcl_price_block_threshold_sub_payload_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_BLOCK_THRESHOLDS "PublishBlockThresholds" command payload - * @see SE spec, subclause D.4.2.4.7.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_block_thresholds_payload_s -{ - - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this - * field allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field to denote the time at which the price signal becomes valid. - */ - zb_uint32_t start_time; /* (M) */ - - /** Unique identifier generated by the commodity supplier. This must match the - * @e IssuerTariffID sent in the related @e PublishTariffInformation command. - */ - zb_uint32_t issuer_tariff_id; /* (M) */ - - /** The @e CommandIndex is used to count the payload fragments in the case where - * the entire payload does not fit into one message. The @e CommandIndex starts - * at 0 and is incremented for each fragment belonging to the same command. - */ - zb_uint8_t command_index; /* (M) */ - - /** In the case where the entire payload does not fit into one message, the - * @e TotalNumberOfCommands field indicates the total number of sub-commands - * in the message. - */ - zb_uint8_t total_number_of_commands; /* (M) */ - - /** The Sub-Payload Control bitmap specifies the usage of the information contained - * within the Block Threshold Sub-Payload. - * @see zb_zcl_price_publish_block_thresholds_sub_payload_control_bitmap_e - */ - zb_uint8_t sub_payload_control; /* (M) */ - - /** The BlockThreshold Sub-Payload consists of multiple sets of data which - * consist of a @e TierID, @e BlockThresholdCount and the threshold values - * associated with the stated Tier. - * @see zb_zcl_price_block_threshold_sub_payload_t - */ - zb_zcl_price_block_threshold_sub_payload_t *block_threshold_sub_payload; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_block_thresholds_payload_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CO2_VALUE "PublishCO2Value" command payload - * @see SE spec, subclause D.4.2.4.8.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_co2_value_payload_s -{ - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this field - * allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field to denote the time at which the @e CO2 value becomes valid. - */ - zb_uint32_t start_time; /* (M) */ - - /** An 8-bit bitmap identifying the type of tariff published in this command. - * The least significant nibble represents an enumeration of the tariff type. - * The most significant nibble is reserved. - * @see zb_zcl_price_tariff_type_t - */ - zb_uint8_t tariff_type; /* (M) */ - - /** The format and use of this field is the same as for the @e CO2 attribute or - * @e ReceivedCO2 attribute . A value of 0xFFFFFFFF indicates field not used. - */ - zb_uint32_t co2_value; /* (M) */ - - /** The format and use of this field is the same as for the @e CO2Unit attribute - * or @e ReceivedCO2Unit attribute. A value of 0xFF indicates field not used. - */ - zb_uint8_t co2_value_unit; /* (M) */ - - /** The format and use of this field is the same as for the @e CO2TrailingDigit - * attribute or @e ReceivedCO2TrailingDigit attribute. - * A value of 0xFF indicates field not used. - */ - zb_uint8_t co2_value_trailing_digit; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_co2_value_payload_t; - - -/** @see SE spec, subclause D.4.2.4.9.2 - * @see zb_zcl_price_publish_tier_labels_payload_t::tier_labels - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_tier_labels_sub_payload_s -{ - /** The tier number that the associated @e TierLabel applies to. */ - zb_uint8_t tier_id; /* (M) */ - - /** Octet String field capable of storing a 12 character string (the first - * character indicates the string length, represented in hexadecimal format) - * encoded in the UTF-8 format. - */ - zb_uint8_t tier_label[13]; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_tier_labels_sub_payload_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_TIER_LABELS "PublishTierLabels" command payload - * @see SE spec, subclause D.4.2.4.9.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_tier_labels_payload_s -{ - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this field - * allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** Unique identifier generated by the commodity supplier. This is used to - * identify the tariff that the labels apply to. - */ - zb_uint32_t issuer_tariff_id; /* (M) */ - - /** The @e CommandIndex is used to count the payload fragments in the case where - * the entire payload does not fit into one message. The @e CommandIndex starts - * at 0 and is incremented for each fragment belonging to the same command. - */ - zb_uint8_t command_index; /* (M) */ - - /** In the case where the entire payload does not fit into one message, the - * @e TotalNumberOfCommands field indicates the total number of sub-commands - * in the message. - */ - zb_uint8_t total_number_of_commands; /* (M) */ - - /** The number of @e TierID/Tier Label sets contained within the command. - */ - zb_uint8_t number_of_labels; /* (M) */ - - /** @see zb_zcl_price_publish_tier_labels_sub_payload_t */ - zb_zcl_price_publish_tier_labels_sub_payload_t *tier_labels; - -} ZB_PACKED_STRUCT zb_zcl_price_publish_tier_labels_payload_t; - - -/** Check if @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_TIER_LABELS "PublishTierLabels" command payload size is valid - * @param size - size of received data payload - */ -#define ZB_ZCL_PRICE_PUBLISH_TIER_LABELS_PAYLOAD_SIZE_IS_VALID(size) \ - ((size >= (sizeof(zb_zcl_price_publish_tier_labels_payload_t)-sizeof(void *)) ? ZB_TRUE : ZB_FALSE)) - - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_BILLING_PERIOD "PublishBillingPeriod" command payload - * @see SE spec, D.4.2.4.10 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_billing_period_payload_s -{ - - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information is - * provided that replaces older information for the same time period, this field - * allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field to denote the time at which the billing period starts. - */ - zb_uint32_t billing_period_start_time; /* (M) */ - - /** An unsigned 24-bit field to denote the billing period duration. The - * duration units are defined by the @e BillingPeriodDurationType field. - */ - zb_uint24_t billing_period_duration; /* (M) */ - - /** An 8-bit bitmap where the least significant nibble is an enumerated - * sub-field indicating the time base used for the duration, and the most - * significant nibble is an enumerated sub-field providing duration control. - * @see zb_zcl_price_block_period_duration_type_t - * @see zb_zcl_price_block_period_duration_control_t - */ - zb_uint8_t billing_period_duration_type; /* (M) */ - - /** An 8-bit bitmap identifying the type of tariff published in this command. - * The least significant nibble represents an enumeration of the tariff type. - * The most significant nibble is reserved. - * @see zb_zcl_price_block_period_duration_control_t - */ - zb_uint8_t tariff_type; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_billing_period_payload_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CONSOLIDATED_BILL "PublishConsolidatedBill" command payload - * @see SE spec, subclause D.4.2.4.11.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_consolidated_bill_payload_s -{ - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this field - * allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field containing the start time of the related billing period. - */ - zb_uint32_t billing_period_start_time; /* (M) */ - - /** An unsigned 24-bit field denoting the duration of the related billing period. - */ - zb_uint24_t billing_period_duration; /* (M) */ - - /** An 8-bit bitmap where the least significant nibble is an enumerated sub-field - * indicating the time base used for the duration, and the most significant nibble - * is an enumerated sub-field providing duration control. - * @see SE spec, Table D-105, Table D-106 - */ - zb_uint8_t billing_period_duration_type; /* (M) */ - - /** An 8-bit bitmap identifying the type of tariff published in this command. - * The least significant nibble represents an enumeration of the tariff type. - * The most significant nibble is reserved. - * @see zb_zcl_price_tariff_type_t - */ - zb_uint8_t tariff_type; /* (M) */ - - /** An unsigned 32-bit field containing the consolidated bill value for the - * stated billing period. - */ - zb_uint32_t consolidated_bill; /* (M) */ - - /** An unsigned 16-bit field containing identifying information concerning the - * local unit of currency used in the @e ConsolidatedBill field. - */ - zb_uint16_t currency; /* (M) */ - - /** An 8-bit field used to determine where the decimal point is located in the - * @e ConsolidatedBill field. - */ - zb_uint8_t bill_trailing_digit; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_consolidated_bill_payload_t; - - -/** CPP Auth Enumeration - * @see SE spec, Table D-112 - */ -typedef enum zb_zcl_price_cpp_price_tier_e -{ - ZB_ZCL_PRICE_CPP_PRICE_TIER_CPP1 = 0, /**< CPP1 */ - ZB_ZCL_PRICE_CPP_PRICE_TIER_CPP2 = 1, /**< CPP2 */ -} zb_zcl_price_cpp_price_tier_t; - - -/** CPP Auth Enumeration - * @see SE spec, Table D-113 - */ -typedef enum zb_zcl_price_cpp_event_status_e -{ - ZB_ZCL_PRICE_CPP_EVENT_STATUS_PENDING = 0, /**< Pending */ - ZB_ZCL_PRICE_CPP_EVENT_STATUS_ACCEPTED, /**< Accepted */ - ZB_ZCL_PRICE_CPP_EVENT_STATUS_REJECTED, /**< Rejected */ - ZB_ZCL_PRICE_CPP_EVENT_STATUS_FORCED, /**< Forced */ -} zb_zcl_price_cpp_event_status_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CPP_EVENT "PublishCPPEvent" command payload - * @see SE spec, subclause D.4.2.4.12.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_cpp_event_payload_s -{ - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this field - * allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field to denote the time at which the CPP event begins. A start - * date/time of 0x00000000 shall indicate that the command should be executed - * immediately. - */ - zb_uint32_t start_time; /* (M) */ - - - /** Defines the duration of the CPP event. - */ - zb_uint16_t duration_in_minutes; /* (M) */ - - /** An 8-bit bitmap identifying the type of tariff published in this command. - * The least significant nibble represents an enumeration of the tariff type. - * The most significant nibble is reserved. - * @see zb_zcl_price_tariff_type_t - */ - zb_uint8_t tariff_type; /* (M) */ - - /** An 8-bit enumeration identifying the price tier associated with this CPP event. - * The price(s) contained in the active price matrix for that price tier will override - * the normal pricing scheme. - * @see zb_zcl_price_cpp_price_tier_t - */ - zb_uint8_t cpp_price_tier; /* (M) */ - - /** An 8-bit enumeration identifying the status of the CPP event. - * @see zb_zcl_price_cpp_event_status_t - */ - zb_uint8_t cpp_auth; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_cpp_event_payload_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CREDIT_PAYMENT "PublishCreditPayment" command payload. - * @see SE spec, subclause D.4.2.4.13.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_credit_payment_payload_s -{ - - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this field - * allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field containing the time that the next credit payment is due. */ - zb_uint32_t credit_payment_due_date; /* (M) */ - - /** An unsigned 32-bit field denoting the current amount this is overdue from - * the consumer. This field should be provided in the same currency as used in - * the Price cluster. - */ - zb_uint32_t credit_payment_overdue_amount; /* (M) */ - - /** An 8-bit enumeration identifying the current credit payment status. - */ - zb_uint8_t credit_payment_status; /* (M) */ - - /** An unsigned 32-bit field denoting the last credit payment. This field should - * be provided in the same currency as used in the Price cluster. - */ - zb_uint32_t credit_payment; /* (M) */ - - /** A @e UTCTime field containing the time at which the last credit payment - * was made. - */ - zb_uint32_t credit_payment_date; /* (M) */ - - /** An string of between 0-20 octets used to denote the last credit payment - * reference used by the energy supplier. - */ - zb_uint8_t credit_payment_ref[21]; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_credit_payment_payload_t; - - -/** Currency Change Control Enumeration - * @see SE spec, Table D-114 - */ -typedef enum zb_zcl_price_currency_change_control_e -{ - ZB_ZCL_PRICE_CLEAR_BILLING_INFORMATION = 1 << 0, /**< 1 = Clear Billing Information - * @n 0 = Do Not Clear Billing Information - */ - ZB_ZCL_PRICE_CONVERT_BILLING_INFORMATION = 1 << 1, /**< 1 = Convert Billing Information using the New Currency - * @n 0 = Do Not Convert Billing Information - */ - ZB_ZCL_PRICE_CLEAR_OLD_CONSUMPTION_DATA = 1 << 2, /**< 1 = Clear Old Consumption Data - * @n 0 = Do Not Clear Old Consumption Data - */ - ZB_ZCL_PRICE_CONVERT_OLD_CONSUMPTION_DATA = 1 << 3, /**< 1 = Convert Old Consumption Data using the New Currency - * @n 0 = Do Not Convert Old Consumption Data - */ -} zb_zcl_price_currency_cghange_control_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_CURRENCY_CONVERSION "PublishCurrencyConversion" command payload. - * @see SE spec, subclause D.4.2.4.14.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_publish_currency_conversion_payload_s -{ - - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity provider. When new information - * is provided that replaces older information for the same time period, this - * field allows devices to determine which information is newer. - */ - zb_uint32_t issuer_event_id; /* (M) */ - - /** A @e UTCTime field to denote the time at which the new currency becomes valid. - */ - zb_uint32_t start_time; /* (M) */ - - /** An unsigned 16-bit field containing identifying information concerning the - * old local unit of currency used in the Price cluster. - */ - zb_uint16_t old_currency; /* (M) */ - - /** An unsigned 16-bit field containing identifying information concerning the - * new local unit of currency used in the Price cluster. The value of the @e NewCurrency - * field should match the values defined by ISO 4217. - */ - zb_uint16_t new_currency; /* (M) */ - - /** The format and use of this field is the same as for the @e ConversionFactor - * attribute as defined in D.4.2.2.4.3. - */ - zb_uint32_t conversion_factor; /* (M) */ - - /** The format and use of this field is the same as for the - * @e ConversionFactorTrailingDigit attribute as defined in D.4.2.2.4.4. - */ - zb_uint8_t conversion_factor_trailing_digit; /* (M) */ - - /** A 32-bit mask that denotes the functions that are required to be carried - * out on processing of this command. - */ - zb_uint32_t currency_change_control_flags; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_publish_currency_conversion_payload_t; - - -/** @ref ZB_ZCL_PRICE_SRV_CMD_CANCEL_TARIFF "CancelTariff" command payload - * @see SE spec, subclause D.4.2.4.15.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_price_cancel_tariff_payload_s -{ - - /** An unsigned 32-bit field containing a unique identifier for the commodity - * provider. - */ - zb_uint32_t provider_id; /* (M) */ - - /** Unique identifier generated by the commodity Supplier. All parts of a tariff - * instance shall have the same @e IssuerTariffID. - */ - zb_uint32_t issuer_tariff_id; /* (M) */ - - /** An 8-bit bitmap identifying the type of tariff to be cancelled by this command. - * The least significant nibble represents an enumeration of the tariff type. - * The most significant nibble is reserved. - * @see SE spec, Table D-108 - * @see zb_zcl_price_tariff_type_t - */ - zb_uint8_t tariff_type; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_price_cancel_tariff_payload_t; - - -/** @cond internals_doc */ -/** @def ZB_ZCL_PRICE_GET_REQUESTOR_RX_ON_WHEN_IDLE - * @brief Macro for getting Requestor RX on When Idle state. - * @param x - zb_zcl_price_get_current_price_payload_t value. - */ -#define ZB_ZCL_PRICE_GET_REQUESTOR_RX_ON_WHEN_IDLE(x) ZB_CHECK_BIT_IN_BIT_VECTOR(x, 0) - -/** @def ZB_ZCL_PRICE_SET_REQUESTOR_RX_ON_WHEN_IDLE - * @brief Macro for setting Requestor RX on When Idle state. - * @param x - zb_zcl_price_get_current_price_payload_t value. - */ -#define ZB_ZCL_PRICE_SET_REQUESTOR_RX_ON_WHEN_IDLE(x) ZB_SET_BIT_IN_BIT_VECTOR(x, 0) -/** @endcond */ /* internals_doc */ - -/** @def ZB_ZCL_PRICE_SEND_CMD_GET_CURRENT_PRICE - * @brief Macro for sending @ref ZB_ZCL_PRICE_CLI_CMD_GET_CURRENT_PRICE "GetCurrentPrice" command. - * @param _param - Reference to buffer. - * @param _dst_addr - Address of the device to send command to. - * @param _dst_addr_mode - Address mode for _dst_addr. - * @param _dst_ep - Destination endpoint. - * @param _src_ep - Current endpoint. - * @param _rx_on_when_idle - Helps to determine publishing - * policy for the server, (see SE spec, subclause D.4.2.3.2.1.1) - */ -#define ZB_ZCL_PRICE_SEND_CMD_GET_CURRENT_PRICE( \ - _param, _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _rx_on_when_idle) \ - zb_zcl_price_send_cmd_get_current_price( \ - _param, _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _rx_on_when_idle, NULL) - -/** @def ZB_ZCL_PRICE_SEND_CMD_GET_SCHEDULED_PRICES - * @brief Macro for sending @ref ZB_ZCL_PRICE_CLI_CMD_GET_SCHEDULED_PRICES "GetScheduledPrices" command. - * @param _param - Reference to buffer. - * @param _dst_addr - Address of the device to send command to. - * @param _dst_addr_mode - Address mode for _dst_addr. - * @param _dst_ep - Destination endpoint. - * @param _src_ep - Current endpoint. - * @param _payload - Packet payload (@ref - * zb_zcl_price_get_scheduled_prices_payload_t). - */ -#define ZB_ZCL_PRICE_SEND_CMD_GET_SCHEDULED_PRICES( \ - _param, _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload) \ - zb_zcl_price_send_cmd_get_scheduled_prices( \ - _param, _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload, NULL) - -/** @def ZB_ZCL_PRICE_SEND_CMD_PUBLISH_PRICE - * @brief Macro for sending @ref ZB_ZCL_PRICE_SEND_CMD_PUBLISH_PRICE "PublishPrice" command. - * @param _param - Reference to buffer. - * @param _dst_addr - Address of the device to send command to. - * @param _dst_addr_mode - Address mode for _dst_addr. - * @param _dst_ep - Destination endpoint. - * @param _src_ep - Current endpoint. - * @param _payload - Packet payload (@ref zb_zcl_price_publish_price_payload_t). - */ -#define ZB_ZCL_PRICE_SEND_CMD_PUBLISH_PRICE( \ - _param, _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload) \ - zb_zcl_price_send_cmd_publish_price( \ - _param, _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload, NULL) - - -/** @def ZB_ZCL_PRICE_SEND_CMD_GET_TIER_LABELS - * @brief Macro for sending @ref ZB_ZCL_PRICE_CLI_CMD_GET_TIER_LABELS "GetTierLabels" command. - * @param _param - Reference to buffer. - * @param _dst_addr - Address of the device to send command to. - * @param _dst_addr_mode - Address mode for _dst_addr. - * @param _dst_ep - Destination endpoint. - * @param _src_ep - Current endpoint. - * @param _payload - Packet payload (ref to @ref zb_zcl_price_get_tier_labels_payload_t). - */ -#define ZB_ZCL_PRICE_SEND_CMD_GET_TIER_LABELS(_param, _dst_addr, _dst_addr_mode, \ - _dst_ep, _src_ep, _payload) \ - zb_zcl_price_send_cmd_get_tier_labels(_param, _dst_addr, _dst_addr_mode, \ - _dst_ep, _src_ep, _payload, NULL) - - -/** @def ZB_ZCL_PRICE_SEND_CMD_PUBLISH_TIER_LABELS - * @brief Macro for sending @ref ZB_ZCL_PRICE_SRV_CMD_PUBLISH_TIER_LABELS "PublishTierLabels" command. - * @param _param - Reference to buffer. - * @param _dst_addr - Address of the device to send command to. - * @param _dst_addr_mode - Address mode for _dst_addr. - * @param _dst_ep - Destination endpoint. - * @param _src_ep - Current endpoint. - * @param _payload - Packet payload (ref to @ref zb_zcl_price_publish_tier_labels_payload_t). - */ -#define ZB_ZCL_PRICE_SEND_CMD_PUBLISH_TIER_LABELS(_param, _dst_addr, _dst_addr_mode, \ - _dst_ep, _src_ep, _payload) \ - zb_zcl_price_send_cmd_publish_tier_labels(_param, _dst_addr, _dst_addr_mode, \ - _dst_ep, _src_ep, _payload, NULL) - - -/** @cond internals_doc */ -/** @def ZB_ZCL_PRICE_SEND_CMD_PRICE_ACK - * @brief Macro for sending @ref ZB_ZCL_PRICE_CLI_CMD_PRICE_ACK "PriceAcknowledgement" command. - * @param _param - Reference to buffer. - * @param _dst_addr - Address of the device to send command to. - * @param _dst_addr_mode - Address mode for _dst_addr. - * @param _dst_ep - Destination endpoint. - * @param _src_ep - Current endpoint. - * @param _payload - Packet payload (@ref zb_zcl_price_ack_payload_t). - */ -#define ZB_ZCL_PRICE_SEND_CMD_PRICE_ACK( \ - _param, _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload) \ - zb_zcl_price_send_cmd_price_ack( \ - _param, _dst_addr, _dst_addr_mode, _dst_ep, _src_ep, _payload, NULL) - - -void zb_zcl_price_send_cmd_publish_price(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_price_publish_price_payload_t *payload, - zb_callback_t cb); - -void zb_zcl_price_send_cmd_get_current_price(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_uint8_t rx_on_when_idle, - zb_callback_t cb); - -void zb_zcl_price_send_cmd_price_ack(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_price_ack_payload_t *payload, - zb_callback_t cb); - -void zb_zcl_price_send_cmd_get_scheduled_prices(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_price_get_scheduled_prices_payload_t *payload, - zb_callback_t cb); - - -void zb_zcl_price_send_cmd_get_tier_labels(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_zcl_price_get_tier_labels_payload_t *payload, - zb_callback_t cb); - - -void zb_zcl_price_send_cmd_publish_tier_labels(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_zcl_price_publish_tier_labels_payload_t *payload, - zb_callback_t cb); - -/** @endcond */ /* internals_doc */ - - -/** @} */ /* end of ZB_ZCL_PRICE_CLUSTER_COMMANDS */ - -/** @cond internals_doc */ -/*** Internal handler for Price Cluster commands */ - -void zb_zcl_price_init_server(void); -void zb_zcl_price_init_client(void); -#define ZB_ZCL_CLUSTER_ID_PRICE_SERVER_ROLE_INIT zb_zcl_price_init_server -#define ZB_ZCL_CLUSTER_ID_PRICE_CLIENT_ROLE_INIT zb_zcl_price_init_client - -/** @endcond */ /* internals_doc */ - -/** @} */ /* Price cluster */ -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#endif /* ZB_ZCL_PRICE_H */ diff --git a/zboss/development/include/zcl/zb_zcl_rel_humidity_measurement.h b/zboss/development/include/zcl/zb_zcl_rel_humidity_measurement.h deleted file mode 100644 index d699569629..0000000000 --- a/zboss/development/include/zcl/zb_zcl_rel_humidity_measurement.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Relative Humidity Measurement cluster definitions -*/ - -#ifndef ZB_ZCL_REL_HUMIDITY_MEASUREMENT_H -#define ZB_ZCL_REL_HUMIDITY_MEASUREMENT_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_WATER_CONTENT_MEASUREMENT - * @{ - */ - -/* Cluster ZB_ZCL_WATER_CONTENT_MEASUREMENT */ - -/*! @name Water Content Measurement cluster attributes - @{ -*/ - -/*! @brief Water Content Measurement cluster attribute identifiers - @see ZCL specification revision 7, Relative Humidity MeasuremenWater Content Measurement Cluster 4.7.2.1 -*/ -enum zb_zcl_rel_humidity_measurement_attr_e -{ - /** @brief MeasuredValue, ZCL specification revision 7 subsection 4.7.2.1.1 MeasuredValue Attribute */ - ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID = 0x0000, - /** @brief MinMeasuredValue, ZCL specification revision 7 subsection 4.7.2.1.2 MinMeasuredValue Attribute*/ - ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_ID = 0x0001, - /** @brief MaxMeasuredValue, ZCL specification revision 7 subsection 4.7.2.1.3 MaxMeasuredValue Attribute*/ - ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID = 0x0002, - /** The Tolerance attribute SHALL indicate the magnitude of the - * possible error that is associated with MeasuredValue, using - * the same units and resolution. - * @brief Tolerance, ZCL specification revision 7 subsection 4.7.2.1.4 Tolerance Attribute - */ - ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID = 0x0003, -}; - -/** @brief Default value for Water Content Measurement cluster revision global attribute */ -#define ZB_ZCL_WATER_CONTENT_MEASUREMENT_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief MeasuredValue attribute unknown value */ -#define ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_UNKNOWN 0xFFFF - -/** @brief MinMeasuredValue attribute minimum value */ -#define ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_MIN_VALUE 0x0000 - -/** @brief MinMeasuredValue attribute maximum value */ -#define ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_MAX_VALUE 0x270F - -/** @brief MinMeasuredValue attribute undefined value */ -#define ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_UNDEFINED 0xFFFF - -/** @brief MaxMeasuredValue attribute minimum value */ -#define ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_MIN_VALUE 0x0001 - -/** @brief MaxMeasuredValue attribute maximum value */ -#define ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_MAX_VALUE 0x2710 - -/** @brief MaxMeasuredValue attribute value not defined */ -#define ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_UNDEFINED 0xFFFF - -/** @brief Default value for MeasurementValue attribute */ -#define ZB_ZCL_REL_HUMIDITY_MEASUREMENT_VALUE_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for MeasurementMinValue attribute */ -#define ZB_ZCL_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Default value for MeasurementMaxValue attribute */ -#define ZB_ZCL_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @cond internals_doc */ -/*! @internal @name Relative Humidity Measurement cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_ZCL_REL_HUMIDITY_MEASUREMENT_REPORT_ATTR_COUNT 1 - -/*! @} */ /* Relative Humidity Measurement cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for Relative Humidity Measurement cluster - server side - @param attr_list - attribute list name - @param value - pointer to variable to store MeasuredValue attribute - @param min_value - pointer to variable to store MinMeasuredValue attribute - @param max_value - pointer to variable to store MAxMeasuredValue attribute -*/ -#define ZB_ZCL_DECLARE_REL_HUMIDITY_MEASUREMENT_ATTRIB_LIST(attr_list, \ - value, min_value, max_value) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_WATER_CONTENT_MEASUREMENT) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID, (value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_ID, (min_value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID, (max_value)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Relative Humidity Measurement cluster attributes */ - -/*! @name Relative Humidity Measurement cluster commands - @{ -*/ - -/*! @} */ /* Relative Humidity Measurement cluster commands */ - -/*! @} */ /* ZCL Relative Humidity Measurement cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_rel_humidity_init_server(void); -void zb_zcl_rel_humidity_init_client(void); -#define ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT_SERVER_ROLE_INIT zb_zcl_rel_humidity_init_server -#define ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT_CLIENT_ROLE_INIT zb_zcl_rel_humidity_init_client - -#endif /* ZB_ZCL_REL_HUMIDITY_MEASUREMENT_H */ diff --git a/zboss/development/include/zcl/zb_zcl_reporting.h b/zboss/development/include/zcl/zb_zcl_reporting.h deleted file mode 100644 index 790ae91ad3..0000000000 --- a/zboss/development/include/zcl/zb_zcl_reporting.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Zigbee cluster library definitions for reporting functionality -*/ - -#ifndef ZB_ZCL_REPORTING_H -#define ZB_ZCL_REPORTING_H 1 - -#if !(defined ZB_ZCL_DISABLE_REPORTING) || defined(DOXYGEN) - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** - * @addtogroup ZB_ZCL_REPORTING - * @{ - * @details - * ZCL attribute reporting being described in ZCL spec, subclauses 2.4.7 through 2.4.11, and - * subclauses covering clusters with reportable attributes. - * - * API for attribute reporting configuring and configuration details reading documented in: @ref - * cfg_reporting_cmd, and @ref report_attr_cmd respectively. - * - * Since all events related to attribute reporting are being handled internally, application can - * be provided with information on attribute report receipt event, and attribute report not - * received within predefined interval event. To handle these events, application may set - * "report attribute" and "no reporting" callbacks with @ref ZB_ZCL_SET_REPORT_ATTR_CB() and - * @ref ZB_ZCL_SET_NO_REPORTING_CB() macros respectively. - * - * @par Example - * @snippet light_sample/dimmable_light/bulb.c zb_zcl_set_report_attr_cb - * @snippet light_sample/dimmable_light/bulb.c zb_zcl_set_report_attr_cb_example - * @par - */ - -/* Boundary and default values are defined by application profile */ - -/*! Default value for minimum reporting interval */ -#define ZB_ZCL_MIN_REPORTING_INTERVAL_DEFAULT 0x0005 - -/*! Default value for maximum reporting interval */ -#define ZB_ZCL_MAX_REPORTING_INTERVAL_DEFAULT 0x0000 - -union zb_zcl_attr_var_u -{ - zb_uint8_t u8; - zb_int8_t s8; - zb_uint16_t u16; - zb_int16_t s16; - zb_uint24_t u24; - zb_int24_t s24; - zb_uint32_t u32; - zb_int32_t s32; - zb_uint48_t u48; - zb_uint8_t data_buf[4]; - zb_uint32_t data_buf_crc32; -}; - -/** @cond internals_doc */ - -/** @brief Structure for storing Reporting information */ -typedef struct zb_zcl_reporting_info_s -{ - zb_uint8_t direction; /*!< Direction: report is send or received */ - zb_uint8_t ep; /*!< Endpoint number */ - zb_uint16_t cluster_id; /*!< Cluster ID for reporting */ - zb_uint8_t cluster_role; - zb_uint16_t attr_id; /*!< Attribute ID for reporting */ - zb_uint8_t flags; /*!< Flags to inform status of reporting */ - zb_time_t run_time; /*!< Time to run next reporting activity */ - union - { - struct - { - zb_uint16_t min_interval; /*!< Actual minimum reporting interval */ - zb_uint16_t max_interval; /*!< Actual maximum reporting interval */ - union zb_zcl_attr_var_u delta; /*!< Actual reportable change */ - union zb_zcl_attr_var_u reported_value; /*!< The last reported value */ - zb_uint16_t def_min_interval; /*!< Default minimum reporting interval */ - zb_uint16_t def_max_interval; /*!< Default maximum reporting interval */ - } - send_info; /*!< send_info is stored on cluster server side (as usual) and describes how - attribute should be reported */ - struct - { - zb_uint16_t timeout; /*!< Timeout period */ - } - recv_info; /*!< recv_info is stored on cluster client side (as usual) and describes how - attribute report is received */ - } - u; - - struct - { - zb_uint16_t short_addr; /*!< Destination short address */ - zb_uint8_t endpoint; /*!< Destination endpoint */ - zb_uint16_t profile_id; /*!< Profile id */ - } - dst; -} -zb_zcl_reporting_info_t; - -#if defined ZB_USE_NVRAM - -/* FIXME: Dataset is not aligned (21 bytes)! Fix align and use u48 instead of u32 for delta! */ - -/** @brief Structure for storing Reporting information to NVRAM */ -typedef ZB_PACKED_PRE struct zb_zcl_reporting_info_nvram_s -{ - zb_uint8_t direction; /*!< Direction: report is send or received */ - zb_uint8_t ep; /*!< Endpoint number */ - zb_uint16_t cluster_id; /*!< Cluster ID for reporting */ - zb_uint8_t cluster_role; /*!< Cluster role */ - zb_uint16_t attr_id; /*!< Attribute ID for reporting */ - zb_uint8_t flags; /*!< Flags to inform status of reporting */ - - zb_uint16_t min_interval; /*!< Minimum reporting interval or timeout for client*/ - zb_uint16_t max_interval; /*!< Maximum reporting interval */ - /* FIXME: Should be U48 here! Leave it as is to do not perform migration! U32 delta is enough for - * the most cases... */ - zb_uint32_t delta; /*!< Reportable change */ - - zb_uint16_t short_addr_dest; /*!< Destination short address */ - zb_uint8_t endpoint_dest; /*!< Destination endpoint */ - zb_uint16_t profile_id_dest; /*!< Profile id */ - zb_uint8_t align[3]; -} ZB_PACKED_STRUCT zb_zcl_reporting_info_nvram_t; - -#endif /* defined ZB_USE_NVRAM */ - -typedef struct zb_zcl_reporting_ctx_s -{ - zb_uint16_t min_interval; - zb_uint16_t max_interval; - zb_uint16_t timeout; - - zb_uint8_t buf_ref; -} -zb_zcl_reporting_ctx_t; - -/** @endcond */ /* internals_doc */ - -/** @brief Informs application that some attribute value was not reported during defined time - interval - @param ep - endpoint number - @param cluster_id - cluster ID - @param attr_id - attribute ID -*/ -typedef void (*zb_zcl_no_reporting_cb_t)( - zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint16_t attr_id); - -/** @brief Informs application about received attribute report - @param addr - source address - @param ep - source endpoint number - @param cluster_id - cluster ID - @param attr_id - attribute ID - @param attr_type - attribute type - @param value - pointer to reported data value -*/ - -typedef void (*zb_zcl_report_attr_cb_t)( - zb_zcl_addr_t *addr, zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint16_t attr_id, zb_uint8_t attr_type, zb_uint8_t *value); -/** @cond internals_doc */ - -/** Enumeration of reporting info flag values */ -typedef enum zb_zcl_reporting_flags_e -{ - ZB_ZCL_REPORTING_SLOT_BUSY = 0x01, /*!< Reporting info slot is busy */ - ZB_ZCL_REPORT_ATTR = 0x01 << 1, /*!< Current attribute should be reported */ - ZB_ZCL_REPORT_IS_ALLOWED = 0x01 << 2, /*!< Reporting for attribute is allowed if - * min_interval timeout condition is met */ - ZB_ZCL_REPORTING_STOP = 0x01 << 3, /*!< Stop reporting this attribute */ - ZB_ZCL_REPORT_TIMER_STARTED = 0x01 << 4, - ZB_ZCL_REPORT_IS_SENT = 0x01 << 5, - ZB_ZCL_REPORT_IS_FIRST = 0x01 << 6, /*!< First report for this attribute */ -} -zb_zcl_reporting_flags_t; - -#define ZB_ZCL_SET_REPORTING_FLAG(rep_info, f) ((rep_info)->flags |= (zb_uint8_t)(f)) - -#define ZB_ZCL_CLR_REPORTING_FLAG(rep_info, f) ((rep_info)->flags &= (zb_uint8_t)(f^0xFF)) - -#define ZB_ZCL_GET_REPORTING_FLAG(rep_info, f) ((rep_info)->flags & (zb_uint8_t)(f)) - -#define ZB_ZCL_CLR_ALL_REPORTING_FLAGS(rep_info) ((rep_info)->flags = 0) - - -/*! @internal min_interval zero value */ -#define ZB_ZCL_MIN_INTERVAL_ZERO 0x0000 - -/*! @internal Check, if min_interval should be taken into account */ -#define ZB_ZCL_MIN_INTERVAL_SPECIFIED \ - (ZCL_CTX().reporting_ctx.min_interval != ZB_ZCL_MIN_INTERVAL_ZERO) - -/** @endcond */ /* internals_doc */ - -/** @brief If Maximum reporting interval is set to value 0xFFFF,reporting is not needed for current - attribute -*/ -#define ZB_ZCL_REPORTING_NOT_NEEDED 0xFFFF - -/** @cond internals_doc */ - -#define ZB_ZCL_TIMEOUT_ZERO 0x0000 - -#define ZB_ZCL_INVALID_TIMEOUT 0xFFFF - -#define ZB_ZCL_UNDEFINED_REPORTING_SLOT 0xFF -#define ZB_ZCL_MAX_REPORTING_SLOTS_BY_EP (ZB_ZCL_UNDEFINED_REPORTING_SLOT / ZB_ZCL_MAX_EP_NUMBER) - -/************************** Reporting functions declarations **********************************/ - -#ifdef ZB_ZCL_ENABLE_DEFAULT_REPORT_ATTR_PROCESSING -void zb_zcl_report_attr_cmd_handler(zb_uint8_t param); -#endif - -void zb_zcl_report_received(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id); - -zb_ret_t zb_zcl_put_reporting_info(zb_zcl_reporting_info_t* rep_info_ptr, zb_bool_t override); - -zb_ret_t zb_zcl_put_reporting_info_from_req(zb_zcl_configure_reporting_req_t *config_rep_req, - zb_zcl_attr_addr_info_t* attr_addr_info); - -void zb_zcl_init_reporting_info(void); - -zb_zcl_reporting_info_t* zb_zcl_find_reporting_info( zb_uint8_t ep, - zb_uint16_t cluster_id, - zb_uint8_t cluster_role, - zb_uint16_t attr_id); - -zb_zcl_reporting_info_t* zb_zcl_get_next_reporting_info( - zb_zcl_reporting_info_t *rep_info_init, zb_uint8_t is_manuf_spec); - -void zb_zcl_reporting_cb(zb_uint8_t param); - -void zb_zcl_save_reported_value(zb_zcl_reporting_info_t *rep_info, zb_zcl_attr_t* attr_desc); - -void zb_zcl_mark_attr_for_reporting(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id); - -/** @endcond */ /* internals_doc */ - -/** @brief Start attribute reporting - @param ep - endpoint number - @param cluster_id - cluster ID - @param cluster_role - cluster role - @param attr_id - attribute ID - @return RET_OK if reporting is successfully started \n - RET_DOES_NOT_EXIST if reporting can't be configured with given parameters (i.e cluster not present) -*/ -zb_ret_t zb_zcl_start_attr_reporting(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id); - -/** @brief Stop attribute reporting - @param ep - endpoint number - @param cluster_id - cluster ID - @param cluster_role - cluster role - @param attr_id - attribute ID - @return RET_OK if reporting is successfully stopped \n - RET_DOES_NOT_EXIST if reporting was not set up with given parameters -*/ -zb_ret_t zb_zcl_stop_attr_reporting(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id); - -/** @brief Check if an attribute is configured for reporting or not - @param ep - endpoint number - @param cluster_id - cluster ID - @param cluster_role - cluster role - @param attr_id - attribute ID - @return ZB_TRUE if attribute is reported -*/ -zb_bool_t zcl_is_attr_reported(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id); - -/* TODO: Document */ -zb_ret_t zb_zcl_put_reporting_info(zb_zcl_reporting_info_t* rep_info_ptr, zb_bool_t override); - -/** @} */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#endif /* !(defined ZB_ZCL_DISABLE_REPORTING) || defined(DOXYGEN) */ - -#endif /* ZB_ZCL_REPORTING_H */ diff --git a/zboss/development/include/zcl/zb_zcl_scenes.h b/zboss/development/include/zcl/zb_zcl_scenes.h deleted file mode 100644 index 7b02a23b96..0000000000 --- a/zboss/development/include/zcl/zb_zcl_scenes.h +++ /dev/null @@ -1,2243 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Scenes cluster definitions -*/ - -#ifndef ZB_ZCL_SCENES_H -#define ZB_ZCL_SCENES_H 1 - -/** @cond DOXYGEN_ZCL_SECTION */ - -/*! @defgroup ZB_ZCL_SCENES ZCL Scenes cluster - @ingroup ZB_ZCL_CLUSTERS - @addtogroup ZB_ZCL_SCENES - ZCL Scenes cluster definitions - @{ -*/ - -/* ZB_ZCL_CLUSTER_ID_SCENES = 0x0005 */ - -/*! @name Scenes cluster attributes - @{ -*/ - -/*! @brief Scene cluster attribute identifiers - @see ZCL specification, subclause 3.7.2.2 - */ -enum zb_zcl_scene_attr_e -{ - /*! Number of scenes currently in the device's scene table */ - ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID = 0x0000, - /*! Scene ID of the scene last invoked */ - ZB_ZCL_ATTR_SCENES_CURRENT_SCENE_ID = 0x001, - /*! @brief Group ID of the scene last invoked - - Can hold 0x0000 if the scene last invoked is not associated with a group - */ - ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_ID = 0x002, - /*! @brief Indicates whether the state of the device corresponds to - that associated with the CurrentScene and CurrentGroup attributes - @li TRUE indicates that these attributes are valid - @li FALSE indicates that they are not valid - - SceneValid attribute has to be maintained by the application according to ZCL spec snippet below: - - > Before a scene has been stored or recalled, this attribute is set to FALSE. After a successful Store Scene or - > Recall Scene command it is set to TRUE. If, after a scene is stored or recalled, the state of the device is - > modified, this attribute is set to FALSE. - - */ - ZB_ZCL_ATTR_SCENES_SCENE_VALID_ID = 0x003, - /* TODO Remove default value for Name support attribute when scene name - support will be provided - */ - /*! @brief Indicates support for scene names - - The most significant bit of the NameSupport attribute indicates whether or - not scene names are supported - @li 1 indicates that they are supported - @li 0 indicates that they are not supported - @note Currently scene names are not supported - */ - ZB_ZCL_ATTR_SCENES_NAME_SUPPORT_ID = 0x004, - /*! @brief specifies the IEEE address of the device that last configured the - scene table - - The value 0xffffffffffffffff indicates that the device has not been - configured, or that the address of the device that last configured the - scenes cluster is not known - @attention The attribute is not supported! - */ - ZB_ZCL_ATTR_SCENES_LAST_CONFIGURED_BY_ID = 0x005 -}; - -/** @brief Default value for Scenes cluster revision global attribute */ -#define ZB_ZCL_SCENES_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/** @brief Maximal value for implemented Scenes cluster revision global attribute */ -#define ZB_ZCL_SCENES_CLUSTER_REVISION_MAX ZB_ZCL_SCENES_CLUSTER_REVISION_DEFAULT - -/** @brief Mask to extract Name support bit */ -#define ZB_ZCL_SCENES_NAME_SUPPORT_BIT_MASK 0x80 - -/*! Minimal permissible value for Current group attribute */ -#define ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_MIN_VALUE 0x0001 -/*! Maximal permissible value for Current group attribute */ -#define ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_MAX_VALUE 0xfff7 -/*! Maximal number of scene table records */ -#define ZB_ZCL_MAX_SCENE_TABLE_RECORDS 16 - -/** @brief Default value for Scene count attribute */ -#define ZB_ZCL_SCENES_SCENE_COUNT_DEFAULT_VALUE 0 - -/** @brief Default value for Current scene attribute */ -#define ZB_ZCL_SCENES_CURRENT_SCENE_DEFAULT_VALUE 0 - -/** @brief Default value for Current group attribute */ -#define ZB_ZCL_SCENES_CURRENT_GROUP_DEFAULT_VALUE 0 - -/** @brief Default value for Scene valid attribute */ -#define ZB_ZCL_SCENES_SCENE_VALID_DEFAULT_VALUE 0 - -/** @brief "Not used" value for Recall scene transition time */ -#define ZB_ZCL_RECALL_SCENES_TRANSITION_TIME_NOT_USED_VALUE 0xffff - -/* - * TODO: Remove default value for Scenes.NameSupport attribute when scene names - * will be supported. - */ -/** @brief Default value for Name support attribute - * The Stack does not support scene names, the default value for the attribute can be declared until name support will be added -*/ -#define ZB_ZCL_SCENES_NAME_SUPPORT_DEFAULT_VALUE 0 - -/** @brief Global Scene - group identifier - see ZLL spec 6.5.1.3.1*/ -#define ZB_ZCL_SCENE_GLOBAL_SCENE_GROUP_ID 0x00 - -/** @brief Global Scene - scene identifier - see ZLL spec 6.5.1.3.1*/ -#define ZB_ZCL_SCENE_GLOBAL_SCENE_ID 0x00 - - -/*! @brief Fixed-size part of the Scene table */ -typedef ZB_PACKED_PRE struct zb_zcl_scene_table_record_fixed_s -{ - /*! @brief Group identifier for the scene - - Can be zero if the scene is not associated with any group @attention Since - value of 0xffff is not appropriate as a group identifier, it is being used - as a free record marker in a form of @ref ZB_ZCL_SCENES_FREE_SCENE_TABLE_RECORD - macro - */ - zb_uint16_t group_id; - /*! @brief Scene transition time */ - zb_uint16_t transition_time; - /*! @brief Scene identifier */ - zb_uint8_t scene_id; - /*! @brief Field set length - - Actual length of the field sets. While the maximal length of the field - sets is known, its actual length should be figured out in order to finish reading at - a proper point. E. g.: as stated in ZCL spec, subclause 3.7.2.4.1.1, it is - not mandatory for a field set to be included in the command for every - cluster on the endpoint that has a defined field set. This field can provide - and actual length of the field sets thus being able to read - only the info required. - */ - zb_uint8_t field_sets_length; - zb_uint8_t transition_time_100ms; -} ZB_PACKED_STRUCT zb_zcl_scene_table_record_fixed_t; - -/*! @brief Declares a "free record" marker for a scene table - Used as a value of a group_id field in a corresponding table record -*/ -#define ZB_ZCL_SCENES_FREE_SCENE_TABLE_RECORD 0xffff - -/** @brief Default value for scene transition time */ -#define ZB_ZCL_SCENES_TRANSITION_TIME_DEFAULT_VALUE 0 - -/*! @brief Common part of the field set definition */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_fieldset_common_s -{ - zb_uint16_t cluster_id; /*!< Cluster identifier */ - zb_uint8_t fieldset_length; /*!< Length of the field set's variable part */ -} ZB_PACKED_STRUCT zb_zcl_scenes_fieldset_common_t; - -/*! @brief Declares Scenes attribute list - @param attr_list Attribute list name - @param scene_count @ref ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID placeholder - @param current_scene @ref ZB_ZCL_ATTR_SCENES_CURRENT_SCENE_ID placeholder - @param current_group @ref ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_ID placeholder - @param scene_valid @ref ZB_ZCL_ATTR_SCENES_SCENE_VALID_ID placeholder - @param name_support @ref ZB_ZCL_ATTR_SCENES_NAME_SUPPORT_ID placeholder -*/ -#define ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST( \ - attr_list, \ - scene_count, \ - current_scene, \ - current_group, \ - scene_valid, \ - name_support) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_SCENES) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID, (scene_count)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_SCENES_CURRENT_SCENE_ID, (current_scene)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_ID, (current_group)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_SCENES_SCENE_VALID_ID, (scene_valid)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_SCENES_NAME_SUPPORT_ID, (name_support)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @cond internals_doc */ -/** @brief Removes All scenes corresponding to a group identifiers in a whole device. - @param param - buffer to get data from. - @param group_id - group identifier for which all scenes must be removed. -*/ -void zb_zcl_scenes_remove_all_scenes_in_all_endpoints_by_group_id(zb_uint8_t param, zb_uint16_t group_id); -void zb_zcl_scenes_remove_all_scenes_in_all_endpoints(zb_uint8_t param); -/*! @} - * @endcond */ /* internals_doc */ - -/*! @} */ /* Scenes cluster attributes */ - -/** @cond internals_doc */ -/*! @name Scenes cluster internals - Internal structures for Scenes cluster - @internal - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_SCENES_CURRENT_SCENE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_SCENES_CURRENT_SCENE_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_SCENES_SCENE_VALID_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_SCENES_SCENE_VALID_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_SCENES_NAME_SUPPORT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_SCENES_NAME_SUPPORT_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/*! @} */ /* Scenes cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/*! @name Scenes cluster commands - @{ -*/ - -/*! @brief Command identifiers for Scenes Cluster - @see ZCL spec, subclause 3.7.2.4 -*/ -enum zb_zcl_scenes_cmd_e -{ - /** Add scene command */ - ZB_ZCL_CMD_SCENES_ADD_SCENE = 0x00, - /** View scene command */ - ZB_ZCL_CMD_SCENES_VIEW_SCENE = 0x01, - /** Remove scene command */ - ZB_ZCL_CMD_SCENES_REMOVE_SCENE = 0x02, - /** Remove all scenes command */ - ZB_ZCL_CMD_SCENES_REMOVE_ALL_SCENES = 0x03, - /** Store scene command */ - ZB_ZCL_CMD_SCENES_STORE_SCENE = 0x04, - /** Recall scene command */ - ZB_ZCL_CMD_SCENES_RECALL_SCENE = 0x05, - /** Get scene membership command */ - ZB_ZCL_CMD_SCENES_GET_SCENE_MEMBERSHIP = 0x06, - /** The Enhanced Add Scene command allows a scene to be added using a finer scene - * transition time than the Add Scene command. */ - ZB_ZCL_CMD_SCENES_ENHANCED_ADD_SCENE = 0x40, - /** The Enhanced View Scene command allows a scene to be retrieved using - * a finer scene transition time than the View Scene command. */ - ZB_ZCL_CMD_SCENES_ENHANCED_VIEW_SCENE = 0x41, - /** The Copy Scene command allows a device to efficiently copy scenes from - * one group/scene identifier pair to another group/scene identifier pair. */ - ZB_ZCL_CMD_SCENES_COPY_SCENE = 0x42, -}; - -/*! @brief Command response identifiers for Scenes Cluster - @see ZCL spec, subclause 3.7.2.5 -*/ -enum zb_zcl_scenes_cmd_resp_e -{ - /** Add scene response */ - ZB_ZCL_CMD_SCENES_ADD_SCENE_RESPONSE = 0x00, - /** View scene response */ - ZB_ZCL_CMD_SCENES_VIEW_SCENE_RESPONSE = 0x01, - /** Remove scene response */ - ZB_ZCL_CMD_SCENES_REMOVE_SCENE_RESPONSE = 0x02, - /** Remove all scenes response */ - ZB_ZCL_CMD_SCENES_REMOVE_ALL_SCENES_RESPONSE = 0x03, - /** Store scene response */ - ZB_ZCL_CMD_SCENES_STORE_SCENE_RESPONSE = 0x04, - /** Get scene membership response */ - ZB_ZCL_CMD_SCENES_GET_SCENE_MEMBERSHIP_RESPONSE = 0x06, - /** The Enhanced Add Scene Response command allows a device to respond - * to an Enhanced Add Scene command.*/ - ZB_ZCL_CMD_SCENES_ENHANCED_ADD_SCENE_RESPONSE = 0x40, - /** The Enhanced View Scene Response command allows a device to respond - * to an Enhanced View Scene command using a finer scene transition time - * that was available in the ZCL. */ - ZB_ZCL_CMD_SCENES_ENHANCED_VIEW_SCENE_RESPONSE = 0x41, - /** The Copy Scene Response command allows a device to respond - * to a Copy Scene command.*/ - ZB_ZCL_CMD_SCENES_COPY_SCENE_RESPONSE = 0x42, -}; - -/** @cond internals_doc */ -/* Scenes cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_SCENES_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_SCENES_ADD_SCENE_RESPONSE, \ - ZB_ZCL_CMD_SCENES_VIEW_SCENE_RESPONSE, \ - ZB_ZCL_CMD_SCENES_REMOVE_SCENE_RESPONSE, \ - ZB_ZCL_CMD_SCENES_REMOVE_ALL_SCENES_RESPONSE, \ - ZB_ZCL_CMD_SCENES_STORE_SCENE_RESPONSE, \ - ZB_ZCL_CMD_SCENES_GET_SCENE_MEMBERSHIP_RESPONSE - -#define ZB_ZCL_CLUSTER_ID_SCENES_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_SCENES_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_SCENES_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_SCENES_ADD_SCENE, \ - ZB_ZCL_CMD_SCENES_VIEW_SCENE, \ - ZB_ZCL_CMD_SCENES_REMOVE_SCENE, \ - ZB_ZCL_CMD_SCENES_REMOVE_ALL_SCENES, \ - ZB_ZCL_CMD_SCENES_STORE_SCENE, \ - ZB_ZCL_CMD_SCENES_RECALL_SCENE, \ - ZB_ZCL_CMD_SCENES_GET_SCENE_MEMBERSHIP - -#define ZB_ZCL_CLUSTER_ID_SCENES_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_SCENES_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/** - * Inform User App about Scene cluster Add Scene command. - * - */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_add_scene_req_s -{ - zb_uint16_t group_id; /**< Scene group identifier */ - zb_uint8_t scene_id; /**< Scene identifier */ - zb_uint16_t transition_time; /**< Scene transition time */ - /*! @brief Scene name - - Has zero length (for compatibility) as unsupported attribute. - */ - zb_uint8_t scene_name[1]; -} ZB_PACKED_STRUCT zb_zcl_scenes_add_scene_req_t; - - -/*! @brief Common macro to start filling Add scene command frame - - Fills the constant-structure part of the command payload only. - - Command can contain no fieldsets defining empty scene. The new scene can be - used, for example, for storing fieldsets with Store scene command. - @note According to a 3.7.2.4.2. subclause of ZCL spec, the command shall be - addressed to a single device (not a group). - @param buffer to put packet to - @param cmd_struct_ptr - pointer to the place variable-structure part of the - command payload (fieldsets) should be placed. - @param dis_default_resp - enable/disable default response - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store - @param transition_time - scene transition time - @param add_scene_cmd_id - a scene cmd ID (Add Scene or Enh Add Scene) -*/ -#define ZB_ZCL_SCENES_INIT_ADD_SCENE_REQ_COMMON( \ - buffer, \ - cmd_struct_ptr, \ - dis_default_resp, \ - group_id, \ - scene_id, \ - transition_time, \ - add_scene_cmd_id) \ - { \ - cmd_struct_ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL( \ - cmd_struct_ptr, \ - dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - cmd_struct_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - add_scene_cmd_id); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_struct_ptr, (group_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_struct_ptr, (scene_id)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_struct_ptr, (transition_time)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_struct_ptr, 0); \ - } - -/*! @brief Start filling Add scene command frame - - Fills the constant-structure part of the command payload only. - - Command can contain no fieldsets defining empty scene. The new scene can be - used, for example, for storing fieldsets with Store scene command. - @note According to a 3.7.2.4.2. subclause of ZCL spec, the command shall be - addressed to a single device (not a group). - @param buffer to put packet to - @param cmd_struct_ptr - pointer to the place variable-structure part of the - command payload (fieldsets) should be placed. - @param dis_default_resp - enable/disable default response - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store - @param transition_time - scene transition time (in seconds) -*/ -#define ZB_ZCL_SCENES_INIT_ADD_SCENE_REQ( \ - buffer, \ - cmd_struct_ptr, \ - dis_default_resp, \ - group_id, \ - scene_id, \ - transition_time) \ - ZB_ZCL_SCENES_INIT_ADD_SCENE_REQ_COMMON( \ - (buffer), \ - (cmd_struct_ptr), \ - (dis_default_resp), \ - (group_id), \ - (scene_id), \ - (transition_time), \ - (ZB_ZCL_CMD_SCENES_ADD_SCENE)) - -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - -/*! @brief Start filling Enhanced Add scene command frame - - Fills the constant-structure part of the command payload only. - - Command can contain no fieldsets defining empty scene. The new scene can be - used, for example, for storing fieldsets with Store scene command. - @note According to a 3.7.2.4.2. subclause of ZCL spec, the command shall be - addressed to a single device (not a group). - @param buffer to put packet to - @param cmd_struct_ptr - pointer to the place variable-structure part of the - command payload (fieldsets) should be placed. - @param dis_default_resp - enable/disable default response - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store - @param transition_time - scene transition time (in tenths of a second) -*/ -#define ZB_ZCL_SCENES_INIT_ENHANCED_ADD_SCENE_REQ( \ - buffer, \ - cmd_struct_ptr, \ - dis_default_resp, \ - group_id, \ - scene_id, \ - transition_time) \ - ZB_ZCL_SCENES_INIT_ADD_SCENE_REQ_COMMON( \ - (buffer), \ - (cmd_struct_ptr), \ - (dis_default_resp), \ - (group_id), \ - (scene_id), \ - (transition_time), \ - (ZB_ZCL_CMD_SCENES_ENHANCED_ADD_SCENE)) - -#endif /* !ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - -/*! @brief Sends Add scene command - - @note According to a 3.7.2.4.2. subclause of ZCL spec, the command shall be - addressed to a single device (not a group). - @param buffer - with prepared command payload - @param cmd_struct_ptr - pointer to the place variable-structure part of the - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param callback for getting command send status -*/ -#define ZB_ZCL_SCENES_SEND_ADD_SCENE_REQ( \ - buffer, \ - cmd_struct_ptr, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback) \ - { \ - ZB_ZCL_FINISH_PACKET(buffer, cmd_struct_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/** @brief Adds fieldset into the buffer for sending command - @param cmd_struct_ptr - pointer to the place in the buffer to put data to - @param cluster identifier the fieldset under consideration belongs to - @param fs_length - summary length of the attributes in the fieldset - @attention The order of the attribute values in the fieldset is significant -*/ -#define ZB_ZCL_SCENES_INIT_FIELDSET(cmd_struct_ptr, cluster, fs_length) \ - { \ - ZB_ZCL_PACKET_PUT_DATA16_VAL((cmd_struct_ptr), (cluster)); \ - ZB_ZCL_PACKET_PUT_DATA8((cmd_struct_ptr), (fs_length)); \ - } - - -/** @brief Parse common part of Add Scene command - @param buffer containing Store scene command payload - @param cmd_struct_ptr - pointer to the request representation structure of type zb_zcl_scenes_add_scene_req_t or NULL pointer if payload size is - too small - @attention The macro changes content of the buffer - @note The macro ignores scene name in the buffer, and, if it has non-zero - size, skips it and directly sets length of the scene name to zero in the - command representation structure -*/ -#define ZB_ZCL_SCENES_GET_ADD_SCENE_REQ_COMMON(buffer, cmd_struct_ptr) \ - { \ - if (sizeof(zb_zcl_scenes_add_scene_req_t) > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_add_scene_req_t*)zb_buf_begin(buffer); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->transition_time); \ - (void)zb_buf_cut_left( \ - (buffer), \ - sizeof(zb_zcl_scenes_add_scene_req_t) + \ - (cmd_struct_ptr)->scene_name[0]); \ - (cmd_struct_ptr)->scene_name[0] = 0; \ - } \ - } - -/** @brief Parses fieldset description - @param buffer containing fieldset - @param cmd_struct_ptr - pointer to the fieldset description representation - structure (of type @ref zb_zcl_scenes_fieldset_common_s) or NULL pointer if - payload size is too small - @param content_length - variable to contain size of the fieldset content - left unprocessed - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_ADD_SCENE_REQ_NEXT_FIELDSET_DESC( \ - buffer, \ - cmd_struct_ptr, \ - content_length) \ - { \ - if (sizeof(zb_zcl_scenes_fieldset_common_t) > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = (zb_zcl_scenes_fieldset_common_t *)zb_buf_begin(buffer); \ - (content_length) = sizeof(zb_zcl_scenes_fieldset_common_t) + \ - ( (zb_zcl_scenes_fieldset_common_t*) \ - (cmd_struct_ptr))->fieldset_length; \ - if ((content_length) > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - (content_length) = 0; \ - } \ - else \ - { \ - /* Cludgy: decoding cluster_id in the fieldset directly */ \ - ZB_ZCL_HTOLE16_INPLACE((cmd_struct_ptr)); \ - (void)zb_buf_cut_left((buffer), (content_length)); \ - } \ - } \ - } - -/** @brief Copies parsed fieldset description into designated memory area - @param src_data_ptr - pointer to the memory area containing parsed fieldset - description - @param dst_data_ptr - pointer to the memory area to put fieldset description - to - @param content_length - remaining length of the unprocessed fieldset content -*/ -#define ZB_ZCL_SCENES_GET_ADD_SCENE_REQ_STORE_FIELDSET_COMMON( \ - src_data_ptr, \ - dst_data_ptr, \ - content_length) \ - { \ - ZB_MEMCPY( \ - (dst_data_ptr), \ - (src_data_ptr), \ - sizeof(zb_zcl_scenes_fieldset_common_t)); \ - ((zb_zcl_scenes_fieldset_common_t*)(dst_data_ptr))->fieldset_length = 0; \ - content_length -= sizeof(zb_zcl_scenes_fieldset_common_t); \ - } - -/*! @brief View scene command payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_view_scene_req_s -{ - zb_uint16_t group_id; /*!< Scene group identifier */ - zb_uint8_t scene_id; /*!< Scene identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_view_scene_req_t; - -/*! @brief Common macro to send View Scene commands - - @note According to a 3.7.2.4.2. subclause of ZCL spec, the command shall be - addressed to a single device (not a group). - The command can be sent to device or group of devices either - @param buffer to put packet to - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param dis_default_resp - enable/disable default response - @param callback for getting command send status - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store - @param view_scene_cmd_id - command ID (View Scene or Enhanced View Scene) -*/ -#define ZB_ZCL_SCENES_SEND_VIEW_SCENE_REQ_COMMON( \ - buffer, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id, \ - view_scene_cmd_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL( \ - ptr, \ - dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - view_scene_cmd_id); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (scene_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/*! @brief Send View Scene commands - - @note According to a 3.7.2.4.2. subclause of ZCL spec, the command shall be - addressed to a single device (not a group). - The command can be sent to device or group of devices either - @param buffer to put packet to - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param dis_default_resp - enable/disable default response - @param callback for getting command send status - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_VIEW_SCENE_REQ( \ - buffer, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id) \ - ZB_ZCL_SCENES_SEND_VIEW_SCENE_REQ_COMMON( \ - buffer, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id, \ - ZB_ZCL_CMD_SCENES_VIEW_SCENE) - -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - -/*! @brief Send Enhanced View Scene command - - @note According to a 3.7.2.4.2. subclause of ZCL spec, the command shall be - addressed to a single device (not a group). - The command can be sent to device or group of devices either - @param buffer to put packet to - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param dis_default_resp - enable/disable default response - @param callback for getting command send status - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_ENHANCED_VIEW_SCENE_REQ( \ - buffer, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id) \ - ZB_ZCL_SCENES_SEND_VIEW_SCENE_REQ_COMMON( \ - buffer, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id, \ - ZB_ZCL_CMD_SCENES_ENHANCED_VIEW_SCENE) - -#endif /* !ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - -/** @brief Parses Scenes.ViewScene command payload - @param buffer to get data from - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_view_scene_req_s) or NULL pointer if payload size is - too small - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_VIEW_SCENE_REQ(buffer, cmd_struct_ptr) \ - { \ - if (sizeof(zb_zcl_scenes_view_scene_req_t) > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_view_scene_req_t*)zb_buf_begin(buffer); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id); \ - } \ - } - -/*! @brief Remove scene command payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_remove_scene_req_s -{ - zb_uint16_t group_id; /*!< Scene group identifier */ - zb_uint8_t scene_id; /*!< Scene identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_remove_scene_req_t; - -/*! @brief Send Remove scene command - - The command can be sent to device or group of devices either - @param buffer to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode. Either @ref - ZB_APS_ADDR_MODE_16_ENDP_PRESENT or @ref - ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT will fit - @param dst_ep - destination endpoint (if sendting to a particular device) - @param ep - sending endpoint - @param prof_id - profile identifier - @param dis_default_resp - enable/disable default response - @param callback for getting command send status - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_REMOVE_SCENE_REQ( \ - buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL( \ - ptr, \ - dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_SCENES_REMOVE_SCENE); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (scene_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/** @brief Parses Scenes.RemoveScene command payload - @param buffer to get data from - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_remove_scene_req_s) or NULL pointer if payload size - is too small - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_REMOVE_SCENE_REQ(buffer, cmd_struct_ptr) \ - { \ - if (sizeof(zb_zcl_scenes_remove_scene_req_t) > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_remove_scene_req_t*)zb_buf_begin(buffer); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id); \ - } \ - } - -/*! @brief Remove all scenes command payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_remove_all_scenes_req_s -{ - zb_uint16_t group_id; /*!< Scene group identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_remove_all_scenes_req_t; - -/*! @brief Send Remove all scenes command - - The command can be sent to device or group of devices either - @param buffer to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode. Either @ref - ZB_APS_ADDR_MODE_16_ENDP_PRESENT or @ref - ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT will fit - @param dst_ep - destination endpoint (if sendting to a particular device) - @param ep - sending endpoint - @param prof_id - profile identifier - @param dis_default_resp - enable/disable default response - @param callback for getting command send status - @param group_id - group identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_REMOVE_ALL_SCENES_REQ( \ - buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL( \ - ptr, \ - dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_SCENES_REMOVE_ALL_SCENES); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/** @brief Parses Scenes.RemoveScene command payload - @param buffer to get data from - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_remove_scene_req_s) or NULL pointer if payload size - is too small - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_REMOVE_ALL_SCENES_REQ(buffer, cmd_struct_ptr) \ - { \ - if ( sizeof(zb_zcl_scenes_remove_all_scenes_req_t) \ - > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_remove_all_scenes_req_t*)zb_buf_begin(buffer); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id); \ - } \ - } - -/*! @brief Store scene command payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_store_scene_req_s -{ - zb_uint16_t group_id; /*!< Group identifier */ - zb_uint8_t scene_id; /*!< Scene identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_store_scene_req_t; - -/*! @brief Send Store Scene command - - The command can be sent to device or group of devices either - @param buffer to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode. Either @ref - ZB_APS_ADDR_MODE_16_ENDP_PRESENT or @ref - ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT will fit - @param dst_ep - destination endpoint (if sendting to a particular device) - @param ep - sending endpoint - @param prof_id - profile identifier - @param dis_default_resp - enable/disable default response - @param callback for getting command send status - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_STORE_SCENE_REQ( \ - buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL( \ - ptr, \ - dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_SCENES_STORE_SCENE); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (scene_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/** @brief Parse Store Scene command - @param buffer containing Store scene command payload - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_store_scene_req_s) or NULL pointer if payload size - is too small - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_STORE_SCENE_REQ(buffer, cmd_struct_ptr) \ - { \ - if (sizeof(zb_zcl_scenes_store_scene_req_t) > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - ZB_ZCL_HTOLE16_INPLACE(zb_buf_begin((buffer))); \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_store_scene_req_t*)zb_buf_begin(buffer); \ - (void)zb_buf_cut_left( \ - (buffer), \ - sizeof(zb_zcl_scenes_store_scene_req_t)); \ - } \ - } - -/*! @brief Recall scene command payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_recall_scene_req_s -{ - zb_uint16_t group_id; /*!< Scene group identifier */ - zb_uint8_t scene_id; /*!< Scene identifier */ - zb_uint16_t transition_time; /*!< Transition Time identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_recall_scene_req_t; - -/*! @brief Recall scene command transition_time payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_recall_scene_transition_time_req_s -{ - zb_uint16_t transition_time; /*!< Determines how long the transition takes from the old cluster state to the new cluster state */ -} ZB_PACKED_STRUCT zb_zcl_scenes_recall_scene_transition_time_req_t; - -/*! @brief Send Recall scene command - The command can be sent to device or group of devices either - @param buffer to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode. Either @ref - ZB_APS_ADDR_MODE_16_ENDP_PRESENT or @ref - ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT will fit - @param dst_ep - destination endpoint (if sendting to a particular device) - @param ep - sending endpoint - @param prof_id - profile identifier - @param dis_default_resp - enable/disable default response - @param callback for getting command send status - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store - @param transition_time - determines how long the transition takes from the old cluster state to the new cluster state -*/ -void zb_zcl_scenes_send_recall_scene_req_zcl8(zb_bufid_t buffer, - const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t ep, - zb_uint16_t prof_id, - zb_uint8_t dis_default_resp, - zb_callback_t callback, - zb_uint16_t group_id, - zb_uint8_t scene_id, - zb_uint16_t transition_time); - -/*! @brief Send Recall scene command (pre-ZCL8) - Use @ref zb_zcl_scenes_send_recall_scene_req_zcl8 for ZCL8 revision call. - The command can be sent to device or group of devices either - @param buffer to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode. Either @ref - ZB_APS_ADDR_MODE_16_ENDP_PRESENT or @ref - ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT will fit - @param dst_ep - destination endpoint (if sendting to a particular device) - @param ep - sending endpoint - @param prof_id - profile identifier - @param dis_default_resp - enable/disable default response - @param callback for getting command send status - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -void zb_zcl_scenes_send_recall_scene_req(zb_bufid_t buffer, - const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t ep, - zb_uint16_t prof_id, - zb_uint8_t dis_default_resp, - zb_callback_t callback, - zb_uint16_t group_id, - zb_uint8_t scene_id); - -/** Macro for call @ref zb_zcl_scenes_send_recall_scene_req_zcl8 function - */ -#define ZB_ZCL_SCENES_SEND_RECALL_SCENE_REQ_ZCL8( \ - buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id, \ - transition_time) \ - { \ - zb_zcl_scenes_send_recall_scene_req_zcl8( \ - buffer, \ - ZB_ADDR_U_CAST(dst_addr), \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id, \ - transition_time); \ - } - -/** Macro for calling @ref zb_zcl_scenes_send_recall_scene_req function - */ -#define ZB_ZCL_SCENES_SEND_RECALL_SCENE_REQ( \ - buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id) \ - { \ - zb_zcl_scenes_send_recall_scene_req( \ - buffer, \ - ZB_ADDR_U_CAST(dst_addr), \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id, \ - scene_id); \ - } - - -/** @brief Recall scene payload length macro */ -#define ZB_ZCL_SCENES_RECALL_SCENE_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_scenes_recall_scene_req_t) - -/** @brief Transition Time field of Recall scene payload length macro */ -#define ZB_ZCL_SCENES_RECALL_SCENE_REQ_TRANSITION_TIME_PAYLOAD_LEN \ - sizeof(zb_uint16_t) - -/** @brief Transition Time field invalid value */ -#define ZB_ZCL_SCENES_RECALL_SCENE_REQ_TRANSITION_TIME_INVALID_VALUE \ - (zb_uint16_t)0xFFFF - -/** @brief Parse Recall Scene command - @param buffer containing Store scene command payload - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_recall_scene_req_s) or NULL pointer if payload size - is too small - @param req_len - length of ZCL command - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_RECALL_SCENE_REQ(buffer, cmd_struct_ptr, req_len) \ -{ \ - zb_zcl_scenes_recall_scene_req_t *recall_scene_req_ptr; \ - req_len = zb_buf_len(buffer); \ - (recall_scene_req_ptr) = (req_len) >= \ - (ZB_ZCL_SCENES_RECALL_SCENE_REQ_PAYLOAD_LEN - ZB_ZCL_SCENES_RECALL_SCENE_REQ_TRANSITION_TIME_PAYLOAD_LEN) ? \ - (zb_zcl_scenes_recall_scene_req_t*)zb_buf_begin(buffer) : NULL; \ - if (recall_scene_req_ptr) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(zb_buf_begin((buffer))); \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_recall_scene_req_t*)zb_buf_begin(buffer); \ - (void)zb_buf_cut_left( \ - (buffer), \ - (req_len)); \ - } \ - else \ - { \ - cmd_struct_ptr = NULL; \ - } \ -} - -/*! @brief Get scene membership command payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_get_scene_membership_req_s -{ - zb_uint16_t group_id; /*!< Scene group identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_get_scene_membership_req_t; - -/*! @brief Send Remove all scenes command - - The command can be sent to device or group of devices either - @param buffer to put packet to - @param dst_addr - address to send packet to - @param dst_addr_mode - addressing mode. Either @ref - ZB_APS_ADDR_MODE_16_ENDP_PRESENT or @ref - ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT will fit - @param dst_ep - destination endpoint (if sendting to a particular device) - @param ep - sending endpoint - @param prof_id - profile identifier - @param dis_default_resp - enable/disable default response - @param callback for getting command send status - @param group_id - group identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_GET_SCENE_MEMBERSHIP_REQ( \ - buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - group_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL( \ - ptr, \ - dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_SCENES_GET_SCENE_MEMBERSHIP); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - dst_addr_mode, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - -/*! @brief Send Copy scene command - - The command can be sent to device or group of devices either - @param buffer to put packet to - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint (if sendting to a particular device) - @param ep - sending endpoint - @param prof_id - profile identifier - @param dis_default_resp - enable/disable default response - @param callback for getting command send status - @param mode - a scene copying mode - @param group_id_from - group identifier for the scene to copy from - @param scene_id_from - scene identifier to copy from - @param group_id_to - group identifier for the scene to copy to - @param scene_id_to - scene identifier to copy to -*/ -#define ZB_ZCL_SCENES_SEND_COPY_SCENE_REQ( \ - buffer, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - dis_default_resp, \ - callback, \ - mode, \ - group_id_from, \ - scene_id_from, \ - group_id_to, \ - scene_id_to) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL( \ - ptr, \ - dis_default_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \ - ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_SCENES_COPY_SCENE); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (mode)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id_from)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (scene_id_from)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id_to)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (scene_id_to)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/*! @brief Send Copy scene Response command - - The command can be sent to device or group of devices either - - @attention - Application must send reply for this command. - - @param buffer to put packet to - @param cmd_struct_ptr - pointer to the place variable-structure part of the - command payload (fieldsets) should be placed. - @param seq_num - ZCL sequence number - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint (if sendting to a particular device) - @param ep - sending endpoint - @param prof_id - profile identifier - @param callback - for getting command send status - @param status - copying status - @param group_id_from - a group ID to copy from - @param scene_id_from - a scene ID to copy from -*/ -#define ZB_ZCL_SCENES_SEND_COPY_SCENE_RES( \ - buffer, \ - cmd_struct_ptr, \ - seq_num, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback, \ - status, \ - group_id_from, \ - scene_id_from) \ - { \ - cmd_struct_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL( \ - cmd_struct_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - cmd_struct_ptr, \ - seq_num, \ - ZB_ZCL_CMD_SCENES_COPY_SCENE_RESPONSE); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_struct_ptr, (status)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_struct_ptr, (group_id_from)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_struct_ptr, (scene_id_from)); \ - ZB_ZCL_FINISH_PACKET(buffer, cmd_struct_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -#endif /* !ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - -/** @brief Parses Scenes.GetSceneMembership command payload - @param buffer to get data from - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_get_scene_membership_req_s) or NULL pointer if payload size - is too small - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_GET_SCENE_MEMBERSHIP_REQ(buffer, cmd_struct_ptr) \ - { \ - if ( sizeof(zb_zcl_scenes_get_scene_membership_req_t) \ - > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_get_scene_membership_req_t*)zb_buf_begin(buffer); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id); \ - } \ - } - -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - -#define ZB_ZCL_COPY_ALL_SCENES_ENABLED 0x01U -#define ZB_ZCL_COPY_ALL_SCENES_DISABLED 0x00U - -/*! @brief Scene copying mode bitfield */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_copy_scene_mode_s -{ - zb_bitfield_t copy_all_scenes:1; /*!< The Copy All Scenes subfield is 1-bit in length and - indicates whether all scenes are to be copied. If this value - is set to 1, all scenes are to be copied and the Scene Identifier From - and Scene Identifier To fields SHALL be ignored. - Otherwise this field is set to 0. */ - zb_bitfield_t reserved:7; /*!< Reserved field */ -} ZB_PACKED_STRUCT zb_zcl_scenes_copy_scene_mode_t; - -/*! @brief Copy scene command payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_copy_scene_req_s -{ - zb_zcl_scenes_copy_scene_mode_t mode; /*!< The mode field is 8-bits in length and contains - information of how the scene copy is to proceed. - See @ref zb_zcl_scenes_copy_scene_mode_s */ - zb_uint16_t group_id_from; /*!< Scene group identifier from */ - zb_uint8_t scene_id_from; /*!< Scene identifier from */ - zb_uint16_t group_id_to; /*!< Scene group identifier to */ - zb_uint8_t scene_id_to; /*!< Scene identifier to */ -} ZB_PACKED_STRUCT zb_zcl_scenes_copy_scene_req_t; - -#define ZB_ZCL_SCENES_GET_COPY_SCENE_REQ(buffer, cmd_struct_ptr) \ - { \ - if (sizeof(zb_zcl_scenes_copy_scene_req_t) > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_copy_scene_req_t*)zb_buf_begin(buffer); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id_from); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id_to); \ - } \ - } - -#endif /* !ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - -/*! @brief Add scene response payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_add_scene_res_s -{ - zb_uint8_t status; /*!< Add scene status */ - zb_uint16_t group_id; /*!< Scene group identifier */ - zb_uint8_t scene_id; /*!< Scene identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_add_scene_res_t; - -/*! @brief Common macro to send Add Scene response - - @param buffer to put packet to - @param seq_num - ZCL sequence number - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param callback for getting command send status - @param status of the corresponding Add scene command execution. Appropriate - values (defined in @ref zcl_status enumeration)are: - @li @ref ZB_ZCL_STATUS_SUCCESS for successful result - @li @ref ZB_ZCL_STATUS_INSUFF_SPACE if the scene table is full - @li @ref ZB_ZCL_STATUS_INVALID_FIELD if the group is not present in the - Group Table - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store - @param cmd_id - a response cmd ID (Add Scene or Enh Add Scene) -*/ -#define ZB_ZCL_SCENES_SEND_ADD_SCENE_RES_COMMON( \ - buffer, \ - seq_num, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback, \ - status, \ - group_id, \ - scene_id, \ - cmd_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - ptr, \ - seq_num, \ - cmd_id); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (status)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (scene_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/*! @brief Send Add Scene response - - @param buffer to put packet to - @param seq_num - ZCL sequence number - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param callback for getting command send status - @param status of the corresponding Add scene command execution. Appropriate - values (defined in @ref zcl_status enumeration)are: - @li @ref ZB_ZCL_STATUS_SUCCESS for successful result - @li @ref ZB_ZCL_STATUS_INSUFF_SPACE if the scene table is full - @li @ref ZB_ZCL_STATUS_INVALID_FIELD if the group is not present in the - Group Table - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_ADD_SCENE_RES( \ - buffer, \ - seq_num, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback, \ - status, \ - group_id, \ - scene_id) \ - ZB_ZCL_SCENES_SEND_ADD_SCENE_RES_COMMON( \ - buffer, \ - seq_num, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback, \ - status, \ - group_id, \ - scene_id, \ - ZB_ZCL_CMD_SCENES_ADD_SCENE_RESPONSE) - -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - -/*! @brief Send Enhanced Add Scene response - - @param buffer to put packet to - @param seq_num - ZCL sequence number - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param callback for getting command send status - @param status of the corresponding Add scene command execution. Appropriate - values (defined in @ref zcl_status enumeration)are: - @li @ref ZB_ZCL_STATUS_SUCCESS for successful result - @li @ref ZB_ZCL_STATUS_INSUFF_SPACE if the scene table is full - @li @ref ZB_ZCL_STATUS_INVALID_FIELD if the group is not present in the - Group Table - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_ENHANCED_ADD_SCENE_RES( \ - buffer, \ - seq_num, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback, \ - status, \ - group_id, \ - scene_id) \ - ZB_ZCL_SCENES_SEND_ADD_SCENE_RES_COMMON( \ - buffer, \ - seq_num, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback, \ - status, \ - group_id, \ - scene_id, \ - ZB_ZCL_CMD_SCENES_ENHANCED_ADD_SCENE_RESPONSE) - -#endif /* !ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - -/** @brief Parses Scenes.AddSceneResponse command payload - @param buffer to get data from - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_add_scene_res_s) or NULL pointer if payload size is - too small - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_ADD_SCENE_RES(buffer, cmd_struct_ptr) \ - { \ - if (sizeof(zb_zcl_scenes_add_scene_res_t) > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_add_scene_res_t*)zb_buf_begin(buffer); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id); \ - } \ - } - -/** @brief Mandatory part of the Scenes.ViewSceneResponse payload */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_view_scene_res_fixed_size_s -{ - zb_uint8_t status; /*!< Command execution status */ - zb_uint16_t group_id; /*!< Scene group identifier */ - zb_uint8_t scene_id; /*!< Scene identifier */ - /** @brief Scene transition time - @attention Valid if status is @ref ZB_ZCL_STATUS_SUCCESS only - */ - zb_uint16_t transition_time; - /** @brief Scene name field. - - Since scene names are not supported, will contain only zero length byte on - formation. If received packet with scene name filled from some other - stack, the fields will be skipped during packet parsing, and length byte - will be set to zero. - @attention Valid if status is @ref ZB_ZCL_STATUS_SUCCESS only - */ - zb_uint8_t scene_name[1]; -} ZB_PACKED_STRUCT zb_zcl_scenes_view_scene_res_fixed_size_t; - -/*! @brief Common macro to start filling View scene response frame - - Fills the mandatory part of the View scene response payload. - - @param buffer to put packet to - @param cmd_struct_ptr - pointer to the place variable-structure part of the - command payload (fieldsets) should be placed. - @param seq_num - ZCL sequence number - @param status of the command execution. Appropriate values (defined in @ref - zcl_status enumeration) are: - @li ZB_ZCL_STATUS_SUCCESS for successful result - @li ZB_ZCL_STATUS_INSUFF_SPACE if fieldsets don't fit into packet - @li ZB_ZCL_STATUS_INVALID_FIELD if the group is not present in the - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store - @param view_res_cmd_id - a command ID (View Response or Enh View Response) -*/ -#define ZB_ZCL_SCENES_INIT_VIEW_SCENE_RES_COMMON( \ - buffer, \ - cmd_struct_ptr, \ - seq_num, \ - status, \ - group_id, \ - scene_id, \ - view_res_cmd_id) \ - { \ - cmd_struct_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL( \ - cmd_struct_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - cmd_struct_ptr, \ - seq_num, \ - view_res_cmd_id); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_struct_ptr, (status)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_struct_ptr, (group_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_struct_ptr, (scene_id)); \ - } - -/*! @brief Start filling View scene response frame - - Fills the mandatory part of the View scene response payload. - - @param buffer to put packet to - @param cmd_struct_ptr - pointer to the place variable-structure part of the - command payload (fieldsets) should be placed. - @param seq_num - ZCL sequence number - @param status of the command execution. Appropriate values (defined in @ref - zcl_status enumeration) are: - @li ZB_ZCL_STATUS_SUCCESS for successful result - @li ZB_ZCL_STATUS_INSUFF_SPACE if fieldsets don't fit into packet - @li ZB_ZCL_STATUS_INVALID_FIELD if the group is not present in the - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_INIT_VIEW_SCENE_RES( \ - buffer, \ - cmd_struct_ptr, \ - seq_num, \ - status, \ - group_id, \ - scene_id) \ - ZB_ZCL_SCENES_INIT_VIEW_SCENE_RES_COMMON( \ - buffer, \ - cmd_struct_ptr, \ - seq_num, \ - status, \ - group_id, \ - scene_id, \ - ZB_ZCL_CMD_SCENES_VIEW_SCENE_RESPONSE) - - -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - -/*! @brief Start filling Enhanced View scene response frame - - Fills the mandatory part of the View scene response payload. - - @param buffer to put packet to - @param cmd_struct_ptr - pointer to the place variable-structure part of the - command payload (fieldsets) should be placed. - @param seq_num - ZCL sequence number - @param status of the command execution. Appropriate values (defined in @ref - zcl_status enumeration) are: - @li ZB_ZCL_STATUS_SUCCESS for successful result - @li ZB_ZCL_STATUS_INSUFF_SPACE if fieldsets don't fit into packet - @li ZB_ZCL_STATUS_INVALID_FIELD if the group is not present in the - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_INIT_ENHANCED_VIEW_SCENE_RES( \ - buffer, \ - cmd_struct_ptr, \ - seq_num, \ - status, \ - group_id, \ - scene_id) \ - ZB_ZCL_SCENES_INIT_VIEW_SCENE_RES_COMMON( \ - buffer, \ - cmd_struct_ptr, \ - seq_num, \ - status, \ - group_id, \ - scene_id, \ - ZB_ZCL_CMD_SCENES_ENHANCED_VIEW_SCENE_RESPONSE) - -#endif /* !ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - -/*! @brief Sends View scene response - - @param buffer with prepared command payload - @param cmd_struct_ptr - pointer to the place variable-structure part of the - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param callback for getting command send status -*/ -#define ZB_ZCL_SCENES_SEND_VIEW_SCENE_RES( \ - buffer, \ - cmd_struct_ptr, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback) \ - { \ - ZB_ZCL_FINISH_PACKET(buffer, cmd_struct_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/** @brief Adds transition time into Scenes.ViewSceneResponse payload. - @param cmd_struct_ptr - pointer to the place in buffer to put data to - @param trans_time - transition time to put -*/ -#define ZB_ZCL_SCENES_ADD_TRANSITION_TIME_VIEW_SCENE_RES( \ - cmd_struct_ptr, \ - trans_time) \ - ZB_ZCL_PACKET_PUT_DATA16((cmd_struct_ptr), &(trans_time)) - -/** @brief Adds scene name into Scenes.ViewSceneResponse payload. - - Since the Stack does not support scene names, the define puts only zero scene name length byte - to preserve payload format. - @param cmd_struct_ptr - pointer to the place in buffer to put data to - @param scene_name - scene name to put (currently ignored) -*/ -#define ZB_ZCL_SCENES_ADD_SCENE_NAME_VIEW_SCENE_RES( \ - cmd_struct_ptr, \ - scene_name) \ - ZB_ZCL_PACKET_PUT_DATA8((cmd_struct_ptr), 0) - -/* TODO Fix possible issue with buffer length */ - -/** @brief Parses common part of the Scenes.ViewSceneResponse - @param buffer containing data - @param response_ptr - pointer to the extracted data -*/ -#define ZB_ZCL_SCENES_GET_VIEW_SCENE_RES_COMMON(buffer, response_ptr) \ - { \ - if (zb_buf_len((buffer)) < \ - (2 * sizeof(zb_uint8_t) + sizeof(zb_uint16_t))) \ - { \ - (response_ptr) = NULL; \ - } \ - else \ - { \ - (response_ptr) = \ - (zb_zcl_scenes_view_scene_res_fixed_size_t*) \ - zb_buf_begin((buffer)); \ - ZB_ZCL_HTOLE16_INPLACE(&((response_ptr)->group_id)); \ - if ((response_ptr)->status == ZB_ZCL_STATUS_SUCCESS) \ - { \ - ZB_ZCL_HTOLE16_INPLACE(&((response_ptr)->transition_time)); \ - (void)zb_buf_cut_left((buffer), sizeof(zb_zcl_scenes_view_scene_res_fixed_size_t) + \ - (response_ptr)->scene_name[0]); \ - (response_ptr)->scene_name[0] = 0; \ - } \ - else \ - { \ - (void)zb_buf_cut_left( \ - (buffer), \ - (2 * sizeof(zb_uint8_t) + sizeof(zb_uint16_t))); \ - } \ - } \ - } - - -/*! @brief Remove scene response payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_remove_scene_res_s -{ - zb_uint8_t status; /** Command execution status */ - zb_uint16_t group_id; /** Scene group identifier */ - zb_uint8_t scene_id; /** Scene identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_remove_scene_res_t; - -/*! @brief Send Remove Scene response - - @param buffer to put packet to - @param seq_num - ZCL sequence number - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param callback for getting command send status - @param status of the corresponding Add scene command execution. Appropriate - values (defined in @ref zcl_status enumeration)are: - @li @ref ZB_ZCL_STATUS_SUCCESS for successful result - @li @ref ZB_ZCL_STATUS_NOT_FOUND if the scene is not present in the scene table - @li @ref ZB_ZCL_STATUS_INVALID_FIELD if the group is not present in the - Group Table - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_REMOVE_SCENE_RES( \ - buffer, \ - seq_num, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback, \ - status, \ - group_id, \ - scene_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - ptr, \ - seq_num, \ - ZB_ZCL_CMD_SCENES_REMOVE_SCENE_RESPONSE); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (status)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (scene_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/** @brief Parses Scenes.RemoveSceneResponse command payload - @param buffer to get data from - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_remove_scene_res_s) or NULL pointer if payload - size is too small - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_REMOVE_SCENE_RES(buffer, cmd_struct_ptr) \ - { \ - if (sizeof(zb_zcl_scenes_remove_scene_res_t) > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_remove_scene_res_t*)zb_buf_begin(buffer); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id); \ - } \ - } - -/** @brief Remove all scenes response payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_remove_all_scenes_res_s -{ - zb_uint8_t status; /** Command execution status */ - zb_uint16_t group_id; /** Group identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_remove_all_scenes_res_t; - -/*! @brief Send Remove all scenes response - - @param buffer to put packet to - @param seq_num - ZCL sequence number - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param callback for getting command send status - @param status of the corresponding Add scene command execution. Appropriate - values (defined in @ref zcl_status enumeration)are: - @li @ref ZB_ZCL_STATUS_SUCCESS for successful result - @li @ref ZB_ZCL_STATUS_INVALID_FIELD if the group is not present in the - Group Table - @param group_id - group identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_REMOVE_ALL_SCENES_RES( \ - buffer, \ - seq_num, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback, \ - status, \ - group_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - ptr, \ - seq_num, \ - ZB_ZCL_CMD_SCENES_REMOVE_ALL_SCENES_RESPONSE); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (status)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/** @brief Parses Scenes.RemoveAllScenesResponse command payload - @param buffer to get data from - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_remove_all_scenes_res_s) or NULL pointer if payload - size is too small - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_REMOVE_ALL_SCENES_RES(buffer, cmd_struct_ptr) \ - { \ - if ( sizeof(zb_zcl_scenes_remove_all_scenes_res_t) \ - > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_remove_all_scenes_res_t*)zb_buf_begin(buffer); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id); \ - } \ - } - -/** @brief Store scene response payload structure */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_store_scene_res_s -{ - zb_uint8_t status; /*!< Command execution status */ - zb_uint16_t group_id; /*!< Scene group identifier */ - zb_uint8_t scene_id; /*!< Scene identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_store_scene_res_t; - -/*! @brief Send Store scene response - - @param buffer to put packet to - @param seq_num - ZCL sequence number - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param callback for getting command send status - @param status of the corresponding Add scene command execution. Appropriate - values (defined in @ref zcl_status enumeration)are: - @li @ref ZB_ZCL_STATUS_SUCCESS for successful result - @li ZB_ZCL_STATUS_INSUFF_SPACE if fieldsets don't fit into packet - @li @ref ZB_ZCL_STATUS_INVALID_FIELD if the group is not present in the - Group Table - @param group_id - group identifier for the scene to store - @param scene_id - scene identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_SEND_STORE_SCENE_RES( \ - buffer, \ - seq_num, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback, \ - status, \ - group_id, \ - scene_id) \ - { \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - ptr, \ - seq_num, \ - ZB_ZCL_CMD_SCENES_STORE_SCENE_RESPONSE); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (status)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (scene_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/** @brief Parses Scenes.StoreScene command payload - @param buffer to get data from - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_store_scene_res_s) or NULL pointer if payload size - is too small - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_STORE_SCENE_RES(buffer, cmd_struct_ptr) \ - { \ - if (sizeof(zb_zcl_scenes_store_scene_res_t) > zb_buf_len((buffer))) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_store_scene_res_t*)zb_buf_begin(buffer); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->group_id); \ - } \ - } - -/** @brief Scene table capacity: at least one scene can be added - - Exact number is unknown -*/ -#define ZB_ZCL_SCENES_CAPACITY_ONE_MORE ((zb_uint8_t)0xfe) - -/** @brief Scene table capacity unknown */ -#define ZB_ZCL_SCENES_CAPACITY_UNKNOWN ((zb_uint8_t)0xff) - -/** @brief Get scene membership response fixed-structure payload part - representation */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_get_scene_membership_res_mandatory_s -{ - /** @brief Command execution status - - Appropriate values are: - @li ZB_ZCL_STATUS_SUCCESS - successfully executed - @li ZB_ZCL_STATUS_INVALID_FIELD - group is not present in the Group Table - see @ref zcl_status enumeration - */ - zb_uint8_t status; - /** @brief Scene table capacity - - Permitted values are: - @li 0..0xfd direct scene table capacity - @li @ref ZB_ZCL_SCENES_CAPACITY_ONE_MORE at least one more scene can be added - @li @ref ZB_ZCL_SCENES_CAPACITY_UNKNOWN scene table capacity is unknown - */ - zb_uint8_t capacity; - zb_uint16_t group_id; /**< Group identifier */ -} ZB_PACKED_STRUCT zb_zcl_scenes_get_scene_membership_res_mandatory_t; - -/** @brief Get scene membership response optional payload part - representation */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_get_scene_membership_res_optional_s -{ - /** @brief Number of scenes in the response. - @note Valid if status has ZB_ZCL_STATUS_SUCCESS value only. - */ - zb_uint8_t scene_count; - /** @brief Array of scenes corresponding to the group identifier. - - Array contains strictly @ref scene_count elements. - @note Valid if status has ZB_ZCL_STATUS_SUCCESS value only. - */ - zb_uint8_t scene_list[1]; -} ZB_PACKED_STRUCT zb_zcl_scenes_get_scene_membership_res_optional_t; - -/** @brief Get scene membership response */ -typedef ZB_PACKED_PRE struct zb_zcl_scenes_get_scene_membership_res_s -{ - /** @brief Mandatory payload part */ - zb_zcl_scenes_get_scene_membership_res_mandatory_t mandatory; - /** @brief Optional payload part */ - zb_zcl_scenes_get_scene_membership_res_optional_t optional; -} ZB_PACKED_STRUCT zb_zcl_scenes_get_scene_membership_res_t; - -/** @brief Start filling Get scene membership response frame - - Fills the mandatory part of the Get scene membership scene response payload. - - @param buffer to put packet to - @param cmd_struct_ptr - pointer to the place variable-structure part of the - command payload (fieldsets) should be placed. - @param seq_num - ZCL sequence number - @param cap_ptr - pointer to the capacity fields of the response - @param status of the command execution. Appropriate values (defined in @ref - zcl_status enumeration) are: - @li ZB_ZCL_STATUS_SUCCESS for successful result - @li ZB_ZCL_STATUS_INVALID_FIELD if the group is not present in the - @param capacity of the scene table - @param group_id - group identifier for the scene to store -*/ -#define ZB_ZCL_SCENES_INIT_GET_SCENE_MEMBERSHIP_RES( \ - buffer, \ - cmd_struct_ptr, \ - seq_num, \ - cap_ptr, \ - status, \ - capacity, \ - group_id) \ - { \ - cmd_struct_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL( \ - cmd_struct_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - cmd_struct_ptr, \ - seq_num, \ - ZB_ZCL_CMD_SCENES_GET_SCENE_MEMBERSHIP_RESPONSE); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_struct_ptr, (status)); \ - (cap_ptr) = (cmd_struct_ptr); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_struct_ptr, (capacity)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_struct_ptr, (group_id)); \ - } - -/** @brief Appends Scene count value to Get scene membership response - constant-structure payload part - @note Should not be used if command status is not ZB_ZCL_STATUS_SUCCESS - @param cmd_struct_ptr - pointer to the memory area SceneCount value should be put to - @param scene_count - number of scenes in the scene list -*/ -#define ZB_ZCL_SCENES_ADD_SCENE_COUNT_GET_SCENE_MEMBERSHIP_RES( \ - cmd_struct_ptr, \ - scene_count) \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_struct_ptr, (scene_count)) - -/** @brief Appends a scene identifier to the Scene list in Get scene membership - response payload - @note Should be preceded with @ref - ZB_ZCL_SCENES_ADD_SCENE_COUNT_GET_SCENE_MEMBERSHIP_RES macro invocation. - @param cmd_struct_ptr - pointer to the memory area scene identifier should - be put to - @param scene_id - scene identifier -*/ -#define ZB_ZCL_SCENES_ADD_SCENE_ID_GET_SCENE_MEMBERSHIP_RES( \ - cmd_struct_ptr, \ - scene_id) \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_struct_ptr, (scene_id)) - -/*! @brief Sends Get scene membership response - - @param buffer with prepared command payload - @param cmd_struct_ptr - pointer to the place directly after the payload - @param dst_addr - address to send packet to - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prof_id - profile identifier - @param callback for getting command send status -*/ -#define ZB_ZCL_SCENES_SEND_GET_SCENE_MEMBERSHIP_RES( \ - buffer, \ - cmd_struct_ptr, \ - dst_addr, \ - dst_ep, \ - ep, \ - prof_id, \ - callback) \ - { \ - ZB_ZCL_FINISH_PACKET(buffer, cmd_struct_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - prof_id, \ - ZB_ZCL_CLUSTER_ID_SCENES, \ - callback); \ - } - -/** @brief Parses Scenes.RemoveAllScenesResponse command payload - @param buffer to get data from - @param cmd_struct_ptr - pointer to the request representation structure (of - type @ref zb_zcl_scenes_get_scene_membership_res_s) or NULL pointer if - payload size is too small to contain mandatory part - @attention The macro changes content of the buffer -*/ -#define ZB_ZCL_SCENES_GET_GET_SCENE_MEMBERSHIP_RES(buffer, cmd_struct_ptr) \ - { \ - if (zb_buf_len((buffer)) < \ - sizeof(zb_zcl_scenes_get_scene_membership_res_t)) \ - { \ - (cmd_struct_ptr) = NULL; \ - } \ - else \ - { \ - (cmd_struct_ptr) = \ - (zb_zcl_scenes_get_scene_membership_res_t*)zb_buf_begin((buffer)); \ - ZB_ZCL_HTOLE16_INPLACE(&(cmd_struct_ptr)->mandatory.group_id); \ - } \ - } - -/** @cond internals_doc */ - -zb_uint8_t zb_zcl_scenes_process_store_scene(zb_uint8_t param, zb_zcl_scenes_store_scene_req_t* req, const zb_zcl_parsed_hdr_t *cmd_info); - -zb_uint8_t zb_zcl_scenes_process_recall_scene(zb_uint8_t param, zb_zcl_scenes_recall_scene_req_t* req, const zb_zcl_parsed_hdr_t *cmd_info); - -zb_uint8_t zb_zcl_scenes_process_remove_all_scenes(zb_uint8_t param, zb_zcl_scenes_remove_all_scenes_req_t* req, const zb_zcl_parsed_hdr_t *cmd_info); - -/** @endcond */ - -/*! @} */ /* Scenes cluster commands */ - -/*! @} */ /* ZCL Scenes cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_scenes_init_server(void); -void zb_zcl_scenes_init_client(void); -#define ZB_ZCL_CLUSTER_ID_SCENES_SERVER_ROLE_INIT zb_zcl_scenes_init_server -#define ZB_ZCL_CLUSTER_ID_SCENES_CLIENT_ROLE_INIT zb_zcl_scenes_init_client - -#endif /* ZB_ZCL_SCENES_H */ diff --git a/zboss/development/include/zcl/zb_zcl_shade_config.h b/zboss/development/include/zcl/zb_zcl_shade_config.h deleted file mode 100644 index baa43937a0..0000000000 --- a/zboss/development/include/zcl/zb_zcl_shade_config.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Shade Configuration cluster definitions -*/ - -#ifndef ZB_ZCL_SHADE_CONFIG_H -#define ZB_ZCL_SHADE_CONFIG_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond DOXYGEN_ZCL_SECTION */ - -/* Logically most opened value */ -#define ZB_ZCL_SHADE_CONFIG_LOGICALLY_MOST_OPENED 0 - -/* Logically most closed value */ -#define ZB_ZCL_SHADE_CONFIG_LOGICALLY_MOST_CLOSED 0xffff - -/** @defgroup ZB_ZCL_SHADE_CONFIG ZCL Shade Configuration cluster - @ingroup ZB_ZCL_CLUSTERS - @addtogroup ZB_ZCL_SHADE_CONFIG - @{ -*/ - -/** @name Shade Configuration cluster attributes - @{ -*/ - -/** @brief Shade Configuration cluster information attribute set identifiers - @see ZCL spec, subclause 7.2.2.2.1 -*/ -enum zb_zcl_shade_config_info_attr_e -{ - /** The PhysicalClosedLimit attribute indicates the most closed (numerically lowest) - * position that the shade can physically move to. */ - ZB_ZCL_ATTR_SHADE_CONFIG_PHYSICAL_CLOSED_LIMIT_ID = 0x0000, - /** The MotorStepSize attribute indicates the angle the shade motor moves for one step, - * measured in 1/10th of a degree. */ - ZB_ZCL_ATTR_SHADE_CONFIG_MOTOR_STEP_SIZE_ID = 0x0001, - /** @brief Status attribute */ - ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_ID = 0x0002 -}; - -/** @brief Bit values for Status attribute - * @see ZCL spec, subclause 7.2.2.2.1.3 - */ -enum zb_zcl_shade_config_status_type_e -{ - /** Shade operational value */ - ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_SHADE_OPERATIONAL = 0x00, - /** Shade Adjusting value */ - ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_SHADE_ADJUSTING = 0x01, - /** Shade Direction value */ - ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_SHADE_DIRECTION = 0x02, - /** Forward Direction of Motor value */ - ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_FORWARD_DIRECTION_OF_MOTOR = 0x03, - /** Reserved values */ - ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_RESERVED = 0x04 -}; - -/** @cond internals_doc */ -/** @internal Set bits from conf_var variable to type_value */ -#define ZB_ZCL_SET_BIT(conf_var, type_value) \ -{ \ - (conf_var) = (conf_var) | (type_value); \ -} - -/** @internal Get type_value bits from conf_var variable */ -#define ZB_ZCL_GET_BIT(conf_var, type_value) ((conf_var) & (type_value)) - -/** @internal Clear type_value bits in conf_var variable */ -#define ZB_ZCL_CLR_BIT(conf_var, type_value) \ -{ \ - (conf_var) = (conf_var) & ~(type_value); \ -} -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Sets bits of Status parameter - @param type_value - bit to set - @param conf_var - config variable -*/ -#define ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_SET(conf_var, type_value) \ - ZB_ZCL_SET_BIT(conf_var, type_value) - -/** @brief Gets bit value of Status parameter - @param type_value - bit value to check - @param conf_var - config variable -*/ -#define ZB_ZCL_ATTR_SHADE_CONFIG_GET_STATUS_BIT_VAL(conf_var, type_value) \ - ZB_ZCL_GET_BIT(conf_var, type_value) - - -/** @brief Clear bit of Status parameter - @param type_value - bit to clear - @param conf_var - config variable -*/ -#define ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_CLEAR(conf_var, type_value) \ - ZB_ZCL_CLR_BIT(conf_var, type_value) - - -/** @brief Shade cluster settings attribute set identifiers - @see ZCL spec, subclause 7.2.2.2.2 -*/ -enum zb_zcl_shade_config_settings_attr_e -{ - /** @brief ClosedLimit attribute */ - ZB_ZCL_ATTR_SHADE_CONFIG_CLOSED_LIMIT_ID = 0x0010, - /** @brief Mode attribute */ - ZB_ZCL_ATTR_SHADE_CONFIG_MODE_ID = 0x0011 -}; - -/** @brief Permissible values for Mode attribute - @see ZCL spec, subclause 7.2.2.2.2.2 */ -enum zb_zcl_shade_config_mode_e -{ - /** Normal value */ - ZB_ZCL_ATTR_SHADE_CONFIG_MODE_NORMAL = 0x00, - /** Configure value */ - ZB_ZCL_ATTR_SHADE_CONFIG_MODE_CONFIGURE = 0x01, - /** Reserved values */ - ZB_ZCL_ATTR_SHADE_CONFIG_MODE_RESERVED = 0x02 -}; - -/** @cond internals_doc */ -typedef struct zb_zcl_shade_set_value_param_s -{ - zb_uint16_t new_value; - zb_bool_t is_config; -} zb_zcl_shade_set_value_param_t; - -typedef struct zb_zcl_shade_get_value_param_s -{ - zb_uint16_t ret_value; -} zb_zcl_shade_get_value_param_t; -/*! @} - * @endcond */ /* internals_doc */ - - /** @brief Default value for Shade Configuration cluster revision global attribute */ -#define ZB_ZCL_SHADE_CONFIG_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/** @brief Shade Configuration Status attribute default value */ -#define ZB_ZCL_SHADE_CONFIG_STATUS_DEFAULT_VALUE 0x00 - -/** @brief ClosedLimit attribute default value */ -#define ZB_ZCL_SHADE_CONFIG_CLOSED_LIMIT_DEFAULT_VALUE 0x0001 - -/** @brief Zero Point attribute default value */ -#define ZB_ZCL_SHADE_CONFIG_ZERO_POINT_DEFAULT_VALUE 0x0000 - -/** @brief Mode attribute default value */ -#define ZB_ZCL_SHADE_CONFIG_MODE_DEFAULT_VALUE ZB_ZCL_ATTR_SHADE_CONFIG_MODE_NORMAL - -/** @brief Declare attribute list for Shade Configuration cluster - @param attr_list - attribute list name - @param status - pointer to variable to store Status attribute value - @param closed_limit - pointer to variable to store ClosedLimit attribute value - @param mode - pointer to variable to store Mode attribute value -*/ -#define ZB_ZCL_DECLARE_SHADE_CONFIG_ATTRIB_LIST(attr_list, status, closed_limit, mode) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_SHADE_CONFIG) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_ID, (status)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_SHADE_CONFIG_CLOSED_LIMIT_ID, (closed_limit)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_SHADE_CONFIG_MODE_ID, (mode)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ /* Shade Configuration cluster attributes */ - -/* Descriptors for server side */ - -/** @cond internals_doc */ -/** @name Shade Configuration cluster internals - Internal structures for Shade Configuration cluster - @internal - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_SHADE_CONFIG_STATUS_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_SHADE_CONFIG_CLOSED_LIMIT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_SHADE_CONFIG_CLOSED_LIMIT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_SHADE_CONFIG_MODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_SHADE_CONFIG_MODE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/** Number of attributes mandatory for reporting in Shade Configuration cluster */ -#define ZB_ZCL_SHADE_CONFIG_REPORT_ATTR_COUNT 0 - - -/** Macro for setting Mode attribute - @param ep - endpoint id - @param mode_val - mode value -*/ - -/** @brief Shade Configuration cluster command identifiers - @see ZCL spec, subclause ? -*/ -/*enum zb_zcl_shade_config_cmd_e -{ - -};*/ - -/** Mandatory commands defines */ - -/*! @internal Setting Shade Mode value macro: - @param ep - endpoint where setting - @param mode_val - Shade Mode value -*/ - -#define ZB_ZCL_SHADE_SET_MODE(ep, mode_val) \ -{ \ - zb_uint8_t mode = (mode_val); \ - ZB_ZCL_SET_ATTRIBUTE((ep), \ - ZB_ZCL_CLUSTER_ID_SHADE_CONFIG, \ - ZB_ZCL_ATTR_SHADE_CONFIG_MODE_ID, \ - &mode, \ - ZB_FALSE); \ -} - -/** @} */ /* Shade Configuration cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/** @name Shade Configuration cluster commands - @{ -*/ - - -/** @} */ /* Shade Configuration cluster commands */ - -/** @} */ /* ZCL Shade Configuration cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_shade_config_init_server(void); -void zb_zcl_shade_config_init_client(void); -#define ZB_ZCL_CLUSTER_ID_SHADE_CONFIG_SERVER_ROLE_INIT zb_zcl_shade_config_init_server -#define ZB_ZCL_CLUSTER_ID_SHADE_CONFIG_CLIENT_ROLE_INIT zb_zcl_shade_config_init_client - -#endif /* ZB_ZCL_SHADE_CONFIG_H */ diff --git a/zboss/development/include/zcl/zb_zcl_temp_measurement.h b/zboss/development/include/zcl/zb_zcl_temp_measurement.h deleted file mode 100644 index 25cb92bc96..0000000000 --- a/zboss/development/include/zcl/zb_zcl_temp_measurement.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Temperature Measurement cluster definitions -*/ - -#ifndef ZB_ZCL_TEMP_MEASUREMENT_H -#define ZB_ZCL_TEMP_MEASUREMENT_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_TEMP_MEASUREMENT - * @{ - * @details - * All commands in the cluster have only request form, and carry no payload. - */ - - -/* Cluster ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT */ - -/*! @name Temperature Measurement cluster attributes - @{ -*/ - -/*! @brief Temperature Measurement cluster attribute identifiers - @see ZCL spec, Temperature Measurement Cluster 4.4.2.2.1 -*/ -enum zb_zcl_temp_measurement_attr_e -{ - /*! @brief MeasuredValue, ZCL spec 4.4.2.2.1.1 */ - ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID = 0x0000, - /*! @brief MinMeasuredValue, ZCL spec 4.4.2.2.1.2 */ - ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID = 0x0001, - /*! @brief MaxMeasuredValue, ZCL spec 4.4.2.2.1.3 */ - ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID = 0x0002, - /*! @brief Tolerance, ZCL spec 4.4.2.2.1.4 */ -#ifndef ZB_DISABLE_TEMP_MEASUREMENT_TOLERANCE_ID - ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID = 0x0003, -#else - ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID = 0xF003, -#endif -}; - -/** @brief Default value for Temperature Measurement cluster revision global attribute */ -#define ZB_ZCL_TEMP_MEASUREMENT_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/** @brief MeasuredValue attribute unknown value */ -#define ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_UNKNOWN ((zb_int16_t)0x8000) - -/** @brief MinMeasuredValue attribute minimum value */ -#define ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_MIN_VALUE ((zb_int16_t)0x954d) - -/** @brief MinMeasuredValue attribute maximum value */ -#define ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_MAX_VALUE 0x7ffe - -/** @brief MinMeasuredValue attribute invalid value */ -#define ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_INVALID ((zb_int16_t)0x8000) - -/** @brief MaxMeasuredValue attribute minimum value */ -#define ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_MIN_VALUE ((zb_int16_t)0x954e) - -/** @brief MaxMeasuredValue attribute maximum value */ -#define ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_MAX_VALUE 0x7fff - -/** @brief MaxMeasuredValue attribute invalid value */ -#define ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_INVALID ((zb_int16_t)0x8000) - - - /* (See: Table 4-13 Temperature Measurement Information Attribute Set) */ - -/** @brief Tolerance attribute minimum value */ -#define ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_MIN_VALUE 0x0000 - -/** @brief Tolerance attribute maximum value */ -#define ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_MAX_VALUE 0x0800 - -/** @brief Default value for Value attribute */ -#define ZB_ZCL_TEMP_MEASUREMENT_VALUE_DEFAULT_VALUE ZB_ZCL_NON_VALUE_INT16 - -/** @brief Default value for MinValue attribute */ -#define ZB_ZCL_TEMP_MEASUREMENT_MIN_VALUE_DEFAULT_VALUE ZB_ZCL_NON_VALUE_INT16 - -/** @brief Default value for MaxValue attribute */ -#define ZB_ZCL_TEMP_MEASUREMENT_MAX_VALUE_DEFAULT_VALUE ZB_ZCL_NON_VALUE_INT16 - -/** @cond internals_doc */ -/*! @internal @name Temperature Measurement cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in Temperature Measurement cluster */ -#define ZB_ZCL_TEMP_MEASUREMENT_REPORT_ATTR_COUNT 1 - -/*! Write attribute hook is used to set min/max temperature values */ -void zb_zcl_temp_measurement_write_attr_hook( - zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -/*! @} */ /* Temperature Measurement cluster internals */ -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief Declare attribute list for Temperature Measurement cluster - server side - @param attr_list - attribute list name - @param value - pointer to variable to store MeasuredValue attribute - @param min_value - pointer to variable to store MinMeasuredValue attribute - @param max_value - pointer to variable to store MAxMeasuredValue attribute - @param tolerance - pointer to variable to store Tolerance attribute -*/ -#define ZB_ZCL_DECLARE_TEMP_MEASUREMENT_ATTRIB_LIST(attr_list, \ - value, min_value, max_value, tolerance) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_TEMP_MEASUREMENT) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, (value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, (min_value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, (max_value)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID, (tolerance)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Temperature Measurement cluster attributes */ - -/*! @name Temperature Measurement cluster commands - @{ -*/ - -/*! @} */ /* Temperature Measurement cluster commands */ - -/*! @} */ /* ZCL Temperature Measurement cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_temp_measurement_init_server(void); -void zb_zcl_temp_measurement_init_client(void); -#define ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT_SERVER_ROLE_INIT zb_zcl_temp_measurement_init_server -#define ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT_CLIENT_ROLE_INIT zb_zcl_temp_measurement_init_client - - -#endif /* ZB_ZCL_TEMP_MEASUREMENT_H */ diff --git a/zboss/development/include/zcl/zb_zcl_thermostat.h b/zboss/development/include/zcl/zb_zcl_thermostat.h deleted file mode 100644 index 50d0035faf..0000000000 --- a/zboss/development/include/zcl/zb_zcl_thermostat.h +++ /dev/null @@ -1,1875 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Thermostat cluster definitions -*/ - -#ifndef ZB_ZCL_THERMOSTAT_H -#define ZB_ZCL_THERMOSTAT_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond DOXYGEN_ZCL_SECTION */ - -/* Cluster ZB_ZCL_CLUSTER_ID_THERMOSTAT */ - -/** @addtogroup ZB_ZCL_THERMOSTAT - * @{ - */ - -/* <31.07.13> Tokarev CR function prototype moved from C file into header for public access */ -/** - * Thermostat initialization function - * initialize setpoint mode, schedule table - */ -void zb_zcl_thermostat_init(void); -/* <31.07.13> Tokarev CR function prototype moved from C file into header for public access */ - -/*! @name Thermostat cluster attributes - @{ -*/ - -/*! @brief Thermostat cluster attribute identifiers - @see ZCL spec, subclause 6.3.2.2 -*/ -enum zb_zcl_thermostat_attr_e -{ - /** @brief Local Temperature attribute */ - ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_ID = 0x0000, - /** @brief OutdoorTemperature represents the outdoor temperature in degrees Celsius, - * as measured locally or remotely (over the network). */ - ZB_ZCL_ATTR_THERMOSTAT_OUTDOOR_TEMPERATURE_ID = 0x0001, - /** @brief Occupancy specifies whether the heated/cooled space is occupied or not, - * as measured locally or remotely (over the network). */ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPANCY_ID = 0x0002, - /** @brief The AbsMinHeatSetpointLimit attribute specifies the absolute minimum level - * that the heating setpoint MAY be set to. */ - ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_HEAT_SETPOINT_LIMIT_ID = 0x0003, - /** @brief The AbsMaxHeatSetpointLimit attribute specifies the absolute maximum level - * that the heating setpoint MAY be set to. */ - ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_HEAT_SETPOINT_LIMIT_ID = 0x0004, - /** @brief The AbsMinCoolSetpointLimit attribute specifies the absolute minimum level - * that the cooling setpoint MAY be set to. */ - ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_COOL_SETPOINT_LIMIT_ID = 0x0005, - /** @brief The AbsMaxCoolSetpointLimit attribute specifies the absolute maximum level - * that the cooling setpoint MAY be set to. */ - ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_COOL_SETPOINT_LIMIT_ID = 0x0006, - /** @brief The PICoolingDemand attribute is 8 bits in length and specifies the level - * of cooling demanded by the PI (proportional integral) control loop in use - * by the thermostat (if any), in percent. */ - ZB_ZCL_ATTR_THERMOSTAT_PI_COOLING_DEMAND_ID = 0x0007, - /** @brief The PIHeatingDemand attribute is 8 bits in length and specifies the level - * of heating demanded by the PI loop in percent. */ - ZB_ZCL_ATTR_THERMOSTAT_PI_HEATING_DEMAND_ID = 0x0008, - /** @brief The HVACSystemTypeConfiguration attribute specifies the HVAC system type - * controlled by the thermostat. */ - ZB_ZCL_ATTR_THERMOSTAT_HVAC_SYSTEM_TYPE_CONFIGURATION_ID = 0x0009, - /** @brief Local Temperature Calibration */ - ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_ID = 0x0010, - /** @brief Occupied Cooling Setpoint attribute */ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID = 0x0011, - /** @brief Occupied Heating Setpoint attribute */ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID = 0x0012, - /** @brief Unoccupied Cooling Setpoint attribute */ - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_COOLING_SETPOINT_ID = 0x0013, - /** @brief Unoccupied Heating Setpoint attribute */ - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_ID = 0x0014, - /** @brief The MinHeatSetpointLimit attribute specifies the minimum level that the heating - * setpoint MAY be set to. */ - ZB_ZCL_ATTR_THERMOSTAT_MIN_HEAT_SETPOINT_LIMIT_ID = 0x0015, - /** @brief The MaxHeatSetpointLimit attribute specifies the maximum level that the heating - * setpoint MAY be set to. */ - ZB_ZCL_ATTR_THERMOSTAT_MAX_HEAT_SETPOINT_LIMIT_ID = 0x0016, - /** @brief The MinCoolSetpointLimit attribute specifies the minimum level that the cooling - * setpoint MAY be set to. */ - ZB_ZCL_ATTR_THERMOSTAT_MIN_COOL_SETPOINT_LIMIT_ID = 0x0017, - /** @brief The MaxCoolSetpointLimit attribute specifies the maximum level that the cooling - * setpoint MAY be set to. */ - ZB_ZCL_ATTR_THERMOSTAT_MAX_COOL_SETPOINT_LIMIT_ID = 0x0018, - /** @brief The MinSetpointDeadBand attribute specifies the minimum difference between the - * Heat Setpoint and the Cool SetPoint, in steps of 0.1C. */ - ZB_ZCL_ATTR_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_ID = 0x0019, - /** @brief The RemoteSensing attribute is an 8-bit bitmap that specifies whether the local - * temperature, outdoor temperature and occupancy are being sensed by internal sensors - * or remote networked sensors. */ - ZB_ZCL_ATTR_THERMOSTAT_REMOTE_SENSING_ID = 0x001a, - /** @brief Control Sequence Of Operation attribute */ - ZB_ZCL_ATTR_THERMOSTAT_CONTROL_SEQUENCE_OF_OPERATION_ID = 0x001b, - /** @brief System Mode attribute */ - ZB_ZCL_ATTR_THERMOSTAT_SYSTEM_MODE_ID = 0x001c, - /** The AlarmMask attribute specifies whether each of the alarms is enabled. */ - ZB_ZCL_ATTR_THERMOSTAT_ALARM_MASK_ID = 0x001d, - /** @brief Thermostat Running Mode attribute */ - ZB_ZCL_ATTR_THERMOSTAT_RUNNING_MODE_ID = 0x001e, - /*! @brief Start of Week attribute */ - ZB_ZCL_ATTR_THERMOSTAT_START_OF_WEEK_ID = 0x0020, - /** @brief NumberOfWeeklyTransitions attribute determines how many weekly schedule - * transitions the thermostat is capable of handling. */ - ZB_ZCL_ATTR_THERMOSTAT_NUMBER_OF_WEEKLY_TRANSITIONS_ID = 0x0021, - /** @brief NumberOfDailyTransitions attribute determines how many daily schedule - * transitions the thermostat is capable of handling. */ - ZB_ZCL_ATTR_THERMOSTAT_NUMBER_OF_DAILY_TRANSITIONS_ID = 0x0022, - /** @brief TemperatureSetpointHold specifies the temperature hold status on the thermostat. */ - ZB_ZCL_ATTR_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_ID = 0x0023, - /** @brief TemperatureSetpointHoldDuration sets the period in minutes for which a setpoint - * hold is active. */ - ZB_ZCL_ATTR_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_DURATION_ID = 0x0024, - /** @brief The ThermostatProgrammingOperationMode attribute determines the operational state - * of the thermostats programming. */ - ZB_ZCL_ATTR_THERMOSTAT_THERMOSTAT_PROGRAMMING_OPERATION_MODE_ID = 0x0025, - /** @brief ThermostatRunningState represents the current relay state of the heat, cool, - * and fan relays. */ - ZB_ZCL_ATTR_THERMOSTAT_THERMOSTAT_RUNNING_STATE_ID = 0x0029, - /** @brief The SetpointChangeSource attribute specifies the source of the current active - * OccupiedCoolingSetpoint or OccupiedHeatingSetpoint (i.e., who or what determined - * the current setpoint). */ - ZB_ZCL_ATTR_THERMOSTAT_SETPOINT_CHANGE_SOURCE_ID = 0x0030, - /** @brief The SetpointChangeAmount attribute specifies the delta between the current active - * OccupiedCoolingSetpoint or OccupiedHeatingSetpoint and the previous active - * setpoint. */ - ZB_ZCL_ATTR_THERMOSTAT_SETPOINT_CHANGE_AMOUNT_ID = 0x0031, - /** @brief The SetpointChangeSourceTimestamp attribute specifies the time in UTC at which - * the SetpointChangeSourceAmount attribute change was recorded. */ - ZB_ZCL_ATTR_THERMOSTAT_SETPOINT_CHANGE_SOURCE_TIMESTAMP_ID = 0x0032, - /** @brief Specifies the degrees Celsius, in 0.1 degree increments, the Thermostat server - * will allow the LocalTemperature attribute to float above the OccupiedCooling - * setpoint (i.e., OccupiedCooling + OccupiedSetback) or below the OccupiedHeating - * setpoint (i.e., occupiedHeating, OccupiedSetback) before initiating a state change - * to bring the temperature back to the users desired setpoint. */ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_ID = 0x0034, - /** @brief Specifies the minimum degrees Celsius, in 0.1 degree increments, - * the Thermostat server will allow the OccupiedSetback attribute - * to be configured by a user. */ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MIN_ID = 0x0035, - /** @brief Specifies the maximum degrees Celsius, in 0.1 degree increments, - * the Thermostat server will allow the OccupiedSetback attribute - * to be configured by a user. */ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MAX_ID = 0x0036, - /** @brief Specifies the degrees Celsius, in 0.1 degree increments, the Thermostat server - * will allow the LocalTemperature attribute to float above the UnoccupiedCooling - * setpoint (i.e., UnoccupiedCooling + UnoccupiedSetback) or below the - * UnoccupiedHeating setpoint (i.e., UnoccupiedHeating - UnoccupiedSetback) - * before initiating a state change to bring the temperature back - * to the users desired setpoint. */ - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_ID = 0x0037, - /** @brief Specifies the minimum degrees Celsius, in 0.1 degree increments, the Thermostat - * server will allow the UnoccupiedSetback attribute to be configured by a user. */ - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MIN_ID = 0x0038, - /** @brief Specifies the maximum degrees Celsius, in 0.1 degree increments, the Thermostat - * server will allow the UnoccupiedSetback attribute to be configured by a user. */ - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MAX_ID = 0x0039, - /** @brief Specifies the delta, in 0.1 degrees Celsius, between LocalTemperature and - * the OccupiedHeatingSetpoint or UnoccupiedHeatingSetpoint attributes at which - * the Thermostat server will operate in emergency heat mode. */ - ZB_ZCL_ATTR_THERMOSTAT_EMERGENCY_HEAT_DELTA_ID = 0x003a, - /** @brief Indicates the type of Mini Split ACType of Mini Split AC is defined depending - * on how Cooling and Heating condition is achieved by Mini Split AC. */ - ZB_ZCL_ATTR_THERMOSTAT_AC_TYPE_ID = 0x0040, - /** @brief Indicates capacity of Mini Split AC in terms of the format defined by - * the ACCapacityFormat attribute. */ - ZB_ZCL_ATTR_THERMOSTAT_AC_CAPACITY_ID = 0x0041, - /** @brief Indicates type of refrigerant used within the Mini Split AC. */ - ZB_ZCL_ATTR_THERMOSTAT_AC_REFRIGERANT_TYPE_ID = 0x0042, - /** @brief This indicates type of Compressor used within the Mini Split AC. */ - ZB_ZCL_ATTR_THERMOSTAT_AC_COMPRESSOR_TYPE_ID = 0x0043, - /** @brief This indicates the type of errors encountered within the Mini Split AC. */ - ZB_ZCL_ATTR_THERMOSTAT_AC_ERROR_CODE_ID = 0x0044, - /** @brief AC Louver position attribute */ - ZB_ZCL_ATTR_THERMOSTAT_AC_LOUVER_POSITION_ID = 0x0045, - /** @brief ACCoilTemperature represents the temperature in degrees Celsius, as measured - * locally or remotely (over the network). */ - ZB_ZCL_ATTR_THERMOSTAT_AC_COIL_TEMPERATURE_ID = 0x0046, - /** @brief This is the format for the ACCapacity attribute. */ - ZB_ZCL_ATTR_THERMOSTAT_AC_CAPACITY_FORMAT_ID = 0x0047, -}; - -/*! @brief Values for Control Sequence Of Operation attribute, - @see ZCL spec, subclause 6.3.2.2.2.12 */ -enum zb_zcl_thermostat_control_sequence_of_operation_e -{ - /*! Cooling Only value */ - ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_COOLING_ONLY = 0x00, - /*! Cooling With Reheat value */ - ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_COOLING_WITH_REHEAT = 0x01, - /*! Heating Only value */ - ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_HEATING_ONLY = 0x02, - /*! Heating With Reheat value */ - ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_HEATING_WITH_REHEAT = 0x03, - /*! Cooling and Heating 4-pipes value */ - ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_COOLING_AND_HEATING_4_PIPES = 0x04, - /*! Cooling and Heating 4-pipes with Reheat value */ - ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_COOLING_AND_HEATING_4_PIPES_WITH_REHEAT = 0x05, - - ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_RESERVED = 0x06 -}; - -/*! @brief Values for System Mode attribute, - @see ZCL spec, subclause 6.3.2.2.2.13 */ -enum zb_zcl_thermostat_system_mode_e -{ - /*! Off value */ - ZB_ZCL_THERMOSTAT_SYSTEM_MODE_OFF = 0x00, - /*! Auto value */ - ZB_ZCL_THERMOSTAT_SYSTEM_MODE_AUTO = 0x01, - /*! Cool value */ - ZB_ZCL_THERMOSTAT_SYSTEM_MODE_COOL = 0x03, - /*! Heat value */ - ZB_ZCL_THERMOSTAT_SYSTEM_MODE_HEAT = 0x04, - /*! Emergency Heating value */ - ZB_ZCL_THERMOSTAT_SYSTEM_MODE_EMERGENCY_HEATING = 0x05, - /*! Precooling value */ - ZB_ZCL_THERMOSTAT_SYSTEM_MODE_PRECOOLING = 0x06, - /*! Fan Only value */ - ZB_ZCL_THERMOSTAT_SYSTEM_MODE_FAN_ONLY = 0x07, - /*! Dry value */ - ZB_ZCL_THERMOSTAT_SYSTEM_MODE_DRY = 0x08, - /*! Sleep value */ - ZB_ZCL_THERMOSTAT_SYSTEM_MODE_SLEEP = 0x09, - /* 07/02/2015 CR [AV] */ - /*! Unknown system mode value */ - ZB_ZCL_THERMOSTAT_SYSTEM_MODE_RESERVED = 0x0a -}; - - -/*! @brief Values for AC Louver position attribute */ -enum zb_zcl_thermostat_ac_louver_position_e -{ - ZB_ZCL_THERMOSTAT_LOUVER_FULLY_CLOSED = 0x01, - ZB_ZCL_THERMOSTAT_LOUVER_FULLY_OPENED = 0x02, - ZB_ZCL_THERMOSTAT_LOUVER_QUARTER_OPEN = 0x03, - ZB_ZCL_THERMOSTAT_LOUVER_HALF_OPEN = 0x04, - ZB_ZCL_THERMOSTAT_LOUVER_THREE_QUARTERS_OPEN = 0x05, -}; - -/*! @brief Values for Start of Week attribute, - @see ZCL spec, subclause 6.3.2.2.3.1 */ -enum zb_zcl_thermostat_start_of_week_e -{ - /*! Sunday value */ - ZB_ZCL_THERMOSTAT_START_OF_WEEK_SUNDAY = 0x00, - /*! Monday value */ - ZB_ZCL_THERMOSTAT_START_OF_WEEK_MONDAY = 0x01, - /*! Tuesday value */ - ZB_ZCL_THERMOSTAT_START_OF_WEEK_TUESDAY = 0x02, - /*! Wednesday value */ - ZB_ZCL_THERMOSTAT_START_OF_WEEK_WEDNESDAY = 0x03, - /*! Thursday value */ - ZB_ZCL_THERMOSTAT_START_OF_WEEK_THURSDAY = 0x04, - /*! Friday value */ - ZB_ZCL_THERMOSTAT_START_OF_WEEK_FRIDAY = 0x05, - /*! Saturday value */ - ZB_ZCL_THERMOSTAT_START_OF_WEEK_SATURDAY = 0x06, -}; - -/*! @brief Values for Temperature Setpoint Hold attribute, - @see ZCL spec, subclause 6.3.2.2.3.4 */ -enum zb_zcl_thermostat_temperature_setpoint_hold_e -{ - /*! Off value */ - ZB_ZCL_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_OFF = 0x00, - /*! On value */ - ZB_ZCL_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_ON = 0x01, -}; - -/*! @brief Thermostat Alarm Code for Alarming - @see ZCL spec 6.3.2.2.2.14, Table 6-18 -*/ -enum zb_zcl_thermostat_alarm_code_e -{ - /** @brief MainsVoltageAlarmCode - MainsVoltageMinThreshold reached for Mains Voltage**/ - ZB_ZCL_THERMOSTAT_ALARM_CODE_INITIALIZATION_FAILURE = 0x00, - /** @brief MainsVoltageAlarmCode - MainsVoltageMaxThreshold reached for Mains Voltage**/ - ZB_ZCL_THERMOSTAT_ALARM_CODE_HARDWARE_FAILURE = 0x01, - /** @brief BatteryAlarmCode - BatteryVoltageMinThreshold or - * BatteryPercentageMinThreshold reached for Battery Source 1 */ - ZB_ZCL_THERMOSTAT_ALARM_CODE_SELFCALIBRATION_FAILURE = 0x02, -}; - -/** @brief Default value for Thermostat cluster revision global attribute */ -#define ZB_ZCL_THERMOSTAT_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/* Default value for Start Of Week attribute */ -#define ZB_ZCL_THERMOSTAT_START_OF_WEEK_DEFAULT_VALUE ZB_ZCL_THERMOSTAT_START_OF_WEEK_SUNDAY - -/** @brief Min value for Local Temperature attribute */ -#define ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_MIN_VALUE 0x954d - -/** @brief Max value for Local Temperature attribute */ -#define ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_MAX_VALUE 0x7fff - -/** @brief Min value for Outdoor Temperature attribute */ -#define ZB_ZCL_THERMOSTAT_OUTDOOR_TEMPERATURE_MIN_VALUE 0x954d - -/** @brief Max value for Outdoor Temperature attribute */ -#define ZB_ZCL_THERMOSTAT_OUTDOOR_TEMPERATURE_MAX_VALUE 0x7fff - -/** @brief Invalid value for Local Temperature attribute */ -#define ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_INVALID ZB_ZCL_NON_VALUE_INT16 - -/** @brief Default value for Local Temperature attribute */ -#define ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_DEFAULT_VALUE 0xffff - -/** @brief Min value for Local Temperature Calibration attribute */ -#define ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_MIN_VALUE 0xe7 - -/** @brief Max value for Local Temperature Calibration attribute */ -#define ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_MAX_VALUE 0x19 - -/** @brief Default value for Occupied Cooling Setpoint attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_DEFAULT_VALUE 0x0a28 - -/** @brief Min value for Occupied Cooling Setpoint attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_MIN_VALUE 0x954d - -/** @brief Max value for Occupied Cooling Setpoint attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_MAX_VALUE 0x7fff - -/** @brief Default value for Occupied Heating Setpoint attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_DEFAULT_VALUE 0x07d0 - -/** @brief Min value for Occupied Heating Setpoint attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_MIN_VALUE 0x954d - -/** @brief Max value for Occupied Heating Setpoint attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_MAX_VALUE 0x7fff - -/** @brief Min value for Min Setpoint Dead Band attribute */ -#define ZB_ZCL_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_MIN_VALUE 0x0a - -/** @brief Max value for Min Setpoint Dead Band attribute */ -#define ZB_ZCL_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_MAX_VALUE 0x19 - -/** @brief Local Temperature Sensed Remotely bit of Remote Sensing attribute */ -#define ZB_ZCL_THERMOSTAT_REMOTE_SENSING_LOCAL_TEMPERATURE_SENSED_REMOTELY_BIT (1<<0) - -/** @brief Outdoor Temperature Sensed Remotely bit of Remote Sensing attribute */ -#define ZB_ZCL_THERMOSTAT_REMOTE_SENSING_OUTDOOR_TEMPERATURE_SENSED_REMOTELY_BIT (1<<1) - -/** @brief Occupancy Sensed Sensed Remotely bit of Remote Sensing attribute */ -#define ZB_ZCL_THERMOSTAT_REMOTE_SENSING_OCCUPANCY_SENSED_REMOTELY_BIT (1<<2) - -/** @brief Default value for Control Sequence Of Operation attribute */ -#define ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_DEFAULT_VALUE 0x04 - -/** @brief Default value for System Mode attribute */ -#define ZB_ZCL_THERMOSTAT_CONTROL_SYSTEM_MODE_DEFAULT_VALUE 0x01 - -/** @brief Default value for Occupancy attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPANCY_DEFAULT_VALUE ((zb_uint8_t)1U) - -/** @brief Bitmask for Occupancy attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPANCY_BITMASK ((zb_uint8_t)0x01) - -/** @brief Default value for AbsMinHeatSetpointLimit attribute */ -#define ZB_ZCL_THERMOSTAT_ABS_MIN_HEAT_SETPOINT_LIMIT_DEFAULT_VALUE ((zb_int16_t)0x02BC) - -/** @brief Default value for AbsMaxHeatSetpointLimit attribute */ -#define ZB_ZCL_THERMOSTAT_ABS_MAX_HEAT_SETPOINT_LIMIT_DEFAULT_VALUE ((zb_int16_t)0x0BB8) - -/** @brief Default value for AbsMinCoolSetpointLimit attribute */ -#define ZB_ZCL_THERMOSTAT_ABS_MIN_COOL_SETPOINT_LIMIT_DEFAULT_VALUE ((zb_int16_t)0x0640) - -/** @brief Default value for AbsMaxCoolSetpointLimit attribute */ -#define ZB_ZCL_THERMOSTAT_ABS_MAX_COOL_SETPOINT_LIMIT_DEFAULT_VALUE ((zb_int16_t)0x0C80) - -/** @brief Min value for PICoolingDemand attribute */ -#define ZB_ZCL_THERMOSTAT_PI_COOLING_DEMAND_MIN_VALUE ((zb_uint8_t)0x00) - -/** @brief Max value for PICoolingDemand attribute */ -#define ZB_ZCL_THERMOSTAT_PI_COOLING_DEMAND_MAX_VALUE ((zb_uint8_t)0x64) - -/** @brief Min value for PIHeatingDemand attribute */ -#define ZB_ZCL_THERMOSTAT_PI_HEATING_DEMAND_MIN_VALUE ((zb_uint8_t)0x00) - -/** @brief Max value for PIHeatingDemand attribute */ -#define ZB_ZCL_THERMOSTAT_PI_HEATING_DEMAND_MAX_VALUE ((zb_uint8_t)0x64) - -/** @brief Default value for HVACSystemTypeConfiguration attribute */ -#define ZB_ZCL_THERMOSTAT_HVAC_SYSTEM_TYPE_CONFIGURATION_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for LocalTemperatureCalibration attribute */ -#define ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_DEFAULT_VALUE ((zb_int8_t)0x00) - -/** @brief Default value for UnoccupiedCoolingSetpoint attribute */ -#define ZB_ZCL_THERMOSTAT_UNOCCUPIED_COOLING_SETPOINT_DEFAULT_VALUE ((zb_int16_t)0x0A28) - -/** @brief Default value for UnoccupiedHeatingSetpoint attribute */ -#define ZB_ZCL_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_DEFAULT_VALUE ((zb_int16_t)0x07D0) - -/** @brief Default value for MinHeatSetpointLimit attribute */ -#define ZB_ZCL_THERMOSTAT_MIN_HEAT_SETPOINT_LIMIT_DEFAULT_VALUE ((zb_int16_t)0x02BC) - -/** @brief Default value for MaxHeatSetpointLimit attribute */ -#define ZB_ZCL_THERMOSTAT_MAX_HEAT_SETPOINT_LIMIT_DEFAULT_VALUE ((zb_int16_t)0x0BB8) - -/** @brief Default value for MinCoolSetpointLimit attribute */ -#define ZB_ZCL_THERMOSTAT_MIN_COOL_SETPOINT_LIMIT_DEFAULT_VALUE ((zb_int16_t)0x0640) - -/** @brief Default value for MaxCoolSetpointLimit attribute */ -#define ZB_ZCL_THERMOSTAT_MAX_COOL_SETPOINT_LIMIT_DEFAULT_VALUE ((zb_int16_t)0x0C80) - -/** @brief Default value for MinSetpointDeadBand attribute */ -#define ZB_ZCL_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_DEFAULT_VALUE ((zb_int8_t)0x19) - -/** @brief Default value for RemoteSensing attribute */ -#define ZB_ZCL_THERMOSTAT_REMOTE_SENSING_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for ControlSequenceOfOperation attribute */ -#define ZB_ZCL_THERMOSTAT_CONTROL_SEQUENCE_OF_OPERATION_DEFAULT_VALUE ((zb_uint8_t)0x04) - -/** @brief Default value for SystemMode attribute */ -#define ZB_ZCL_THERMOSTAT_SYSTEM_MODE_DEFAULT_VALUE ((zb_uint8_t)0x01) - -/** @brief Default value for AlarmMask attribute */ -#define ZB_ZCL_THERMOSTAT_ALARM_MASK_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for RunningMode attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNING_MODE_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Off value for RunningMode attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNING_MODE_OFF_VALUE ((zb_uint8_t)0x00) - -/** @brief Cool value for RunningMode attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNING_MODE_COOL_VALUE ((zb_uint8_t)0x03) - -/** @brief Heat value for RunningMode attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNING_MODE_HEAT_VALUE ((zb_uint8_t)0x04) - -/** @brief Default value for TemperatureSetpointHold attribute */ -#define ZB_ZCL_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for TemperatureSetpointHoldDuration attribute */ -#define ZB_ZCL_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_DURATION_DEFAULT_VALUE ((zb_uint16_t)0xFFFF) - -/** @brief Min value for TemperatureSetpointHoldDuration attribute */ -#define ZB_ZCL_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_DURATION_MIN_VALUE ((zb_uint16_t)0x0000) - -/** @brief Max value for TemperatureSetpointHoldDuration attribute */ -#define ZB_ZCL_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_DURATION_MAX_VALUE ((zb_uint16_t)0x05a0) - -/** @brief Default value for ThermostatProgrammingOperationMode attribute */ -#define ZB_ZCL_THERMOSTAT_THERMOSTAT_PROGRAMMING_OPERATION_MODE_DEFAULT_VALUE ((zb_uint8_t)0) - -/** @brief Default value for SetpointChangeSource attribute */ -#define ZB_ZCL_THERMOSTAT_SETPOINT_CHANGE_SOURCE_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Default value for SetpointChangeAmount attribute */ -#define ZB_ZCL_THERMOSTAT_SETPOINT_CHANGE_AMOUNT_DEFAULT_VALUE ((zb_int16_t)0x8000) - -/** @brief Default value for SetpointChangeSourceTimestamp attribute */ -#define ZB_ZCL_THERMOSTAT_SETPOINT_CHANGE_SOURCE_TIMESTAMP_DEFAULT_VALUE ((zb_time_t)0x00000000) - -/** @brief Default value for OccupiedSetback attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPIED_SETBACK_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for OccupiedSetbackMin attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPIED_SETBACK_MIN_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for OccupiedSetbackMax attribute */ -#define ZB_ZCL_THERMOSTAT_OCCUPIED_SETBACK_MAX_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for UnoccupiedSetback attribute */ -#define ZB_ZCL_THERMOSTAT_UNOCCUPIED_SETBACK_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for UnoccupiedSetbackMin attribute */ -#define ZB_ZCL_THERMOSTAT_UNOCCUPIED_SETBACK_MIN_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for UnoccupiedSetbackMax attribute */ -#define ZB_ZCL_THERMOSTAT_UNOCCUPIED_SETBACK_MAX_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for EmergencyHeatDelta attribute */ -#define ZB_ZCL_THERMOSTAT_EMERGENCY_HEAT_DELTA_DEFAULT_VALUE ((zb_uint8_t)0xFF) - -/** @brief Default value for ACType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_TYPE_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Unknown value for ACType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_TYPE_UNKNOWN_VALUE ZB_ZCL_THERMOSTAT_AC_TYPE_DEFAULT_VALUE - -/** @brief Cooling and Fixed Speed value for ACType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_TYPE_COOLING_AND_FIXED_SPEED_VALUE ((zb_uint8_t)0x01) - -/** @brief Heat Pump and Fixed Speed value for ACType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_TYPE_HEAT_PUMP_AND_FIXED_SPEED_VALUE ((zb_uint8_t)0x02) - -/** @brief Cooling and Inverter value for ACType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_TYPE_COOLING_AND_INVERTER_VALUE ((zb_uint8_t)0x03) - -/** @brief Heat Pump and Inverter value value for ACType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_TYPE_HEAT_PUMP_AND_INVERTER_VALUE ((zb_uint8_t)0x04) - -/** @brief Default value for ACCapacity attribute */ -#define ZB_ZCL_THERMOSTAT_AC_CAPACITY_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for ACRefrigerantType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_REFRIGERANT_TYPE_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Unknown value for ACRefrigerantType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_REFRIGERANT_TYPE_UNKNOWN_VALUE ZB_ZCL_THERMOSTAT_AC_REFRIGERANT_TYPE_DEFAULT_VALUE - -/** @brief R22 value for ACRefrigerantType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_REFRIGERANT_TYPE_R22_VALUE ((zb_uint8_t)0x01) - -/** @brief R410a value for ACRefrigerantType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_REFRIGERANT_TYPE_R410A_VALUE ((zb_uint8_t)0x02) - -/** @brief R407c value for ACRefrigerantType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_REFRIGERANT_TYPE_R407C_VALUE ((zb_uint8_t)0x03) - -/** @brief Default value for ACCompressorType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_COMPRESSOR_TYPE_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Unknown value for ACCompressorType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_COMPRESSOR_TYPE_UNKNOWN_VALUE ZB_ZCL_THERMOSTAT_AC_COMPRESSOR_TYPE_DEFAULT_VALUE - -/** @brief T1(Max working ambient 43 ºC) value for ACCompressorType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_COMPRESSOR_TYPE_T1_VALUE ((zb_uint8_t)0x01) - -/** @brief T2(Max working ambient 35 ºC) value for ACCompressorType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_COMPRESSOR_TYPE_T2_VALUE ((zb_uint8_t)0x02) - -/** @brief T3(Max working ambient 52 ºC) value for ACCompressorType attribute */ -#define ZB_ZCL_THERMOSTAT_AC_COMPRESSOR_TYPE_T3_VALUE ((zb_uint8_t)0x03) - -/** @brief Default value for ACErrorCode attribute */ -#define ZB_ZCL_THERMOSTAT_AC_ERROR_CODE_DEFAULT_VALUE ((zb_uint32_t)0x00000000) - -/** @brief Compressor Failure or Refrigerant Leakage bit of AC Error Code attribute */ -#define ZB_ZCL_THERMOSTAT_AC_ERROR_CODE_COMPRESSOR_FAILURE_OR_REFRIGERANT_LEAKAGE_BIT (1<<0) - -/** @brief Room Temperature Sensor Failure bit of AC Error Code attribute */ -#define ZB_ZCL_THERMOSTAT_AC_ERROR_CODE_ROOM_TEMPERATURE_SENSOR_FAILURE_BIT (1<<1) - -/** @brief Outdoor Temperature Sensor Failure bit of AC Error Code attribute */ -#define ZB_ZCL_THERMOSTAT_AC_ERROR_CODE_OUTDOOR_TEMPERATURE_SENSOR_FAILURE_BIT (1<<2) - -/** @brief Indoor Coil Temperature Sensor Failure bit of AC Error Code attribute */ -#define ZB_ZCL_THERMOSTAT_AC_ERROR_CODE_INDOOR_COIL_TEMPERATURE_SENSOR_FAILURE_BIT (1<<3) - -/** @brief Fan Failure bit of AC Error Code attribute */ -#define ZB_ZCL_THERMOSTAT_AC_ERROR_CODE_FAN_FAILURE_BIT (1<<4) - -/** @brief Default value for ACLouverPosition attribute */ -#define ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Fully Closed value for ACLouverPosition attribute */ -#define ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_FULLY_CLOSED_VALUE ((zb_uint8_t)0x01) - -/** @brief Fully Open value for ACLouverPosition attribute */ -#define ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_FULLY_OPEN_VALUE ((zb_uint8_t)0x02) - -/** @brief Quarter Open value for ACLouverPosition attribute */ -#define ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_QUARTER_OPEN_VALUE ((zb_uint8_t)0x03) - -/** @brief Three Quarters Open value for ACLouverPosition attribute */ -#define ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_THREE_QUARTERS_OPEN_VALUE ((zb_uint8_t)0x05) - -/** @brief Half Open value for ACLouverPosition attribute */ -#define ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_HALF_OPEN_VALUE ((zb_uint8_t)0x04) - -/** @brief Min value for AC Coil Temperature attribute */ -#define ZB_ZCL_THERMOSTAT_AC_COIL_TEMPERATURE_MIN_VALUE 0x954d - -/** @brief Max value for AC Coil Temperature attribute */ -#define ZB_ZCL_THERMOSTAT_AC_COIL_TEMPERATURE_MAX_VALUE 0x7fff - -/** @brief Default value for AC Capacity Format attribute */ -#define ZB_ZCL_THERMOSTAT_AC_CAPACITY_FORMAT_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief BTUh value for AC Capacity Format attribute */ -#define ZB_ZCL_THERMOSTAT_AC_CAPACITY_FORMAT_BTUH_VALUE ZB_ZCL_THERMOSTAT_AC_CAPACITY_FORMAT_DEFAULT_VALUE - -/** @brief Default value for ACCapacityFormat attribute */ -#define ZB_ZCL_THERMOSTAT_AC_CAPACITY_FORMAT_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Initialization failure bit of Alarm Mask attribute */ -#define ZB_ZCL_THERMOSTAT_ALARM_MASK_INITIALIZATION_FAILURE_BIT (1<<0) - -/** @brief Hardware Failure bit of Alarm Mask attribute */ -#define ZB_ZCL_THERMOSTAT_ALARM_MASK_HARDWARE_FAILURE_BIT (1<<1) - -/** @brief Self-Calibration Failure bit of Alarm Mask attribute */ -#define ZB_ZCL_THERMOSTAT_ALARM_MASK_SELFCALIBRATION_FAILURE_BIT (1<<2) - -/** @brief Simple/Setpoint(0) or Schedule_Programming(1) mode bit of Thermostat Programming Operation Mode attribute */ -#define ZB_ZCL_THERMOSTAT_PROGRAMMING_OPERATION_MODE_SIMPLE_SETPOINT_OR_PROGRAMMING_MODE_BIT (1<<0) - -/** @brief Auto/recovery mode bit of Thermostat Programming Operation Mode attribute */ -#define ZB_ZCL_THERMOSTAT_PROGRAMMING_OPERATION_MODE_AUTO_RECOVERY_MODE_BIT (1<<1) - -/** @brief Economy/EnergyStar mode bit of Thermostat Programming Operation Mode attribute */ -#define ZB_ZCL_THERMOSTAT_PROGRAMMING_OPERATION_MODE_ECONOMY_ENERGY_STAR_MODE_BIT (1<<2) - -/** @brief Heat State On bit of Thermostat Running State attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNNING_STATE_HEAT_STATE_ON_BIT (1<<0) - -/** @brief Cool State On bit of Thermostat Running State attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNNING_STATE_COOL_STATE_ON_BIT (1<<1) - -/** @brief Fan State On bit of Thermostat Running State attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNNING_STATE_FAN_STATE_ON_BIT (1<<2) - -/** @brief Heat 2nd Stage State On bit of Thermostat Running State attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNNING_STATE_HEAT_2ND_STAGE_STATE_ON_BIT (1<<3) - -/** @brief Cool 2nd Stage State On bit of Thermostat Running State attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNNING_STATE_COOL_2ND_STAGE_STATE_ON_BIT (1<<4) - -/** @brief Fan 2nd Stage State On bit of Thermostat Running State attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNNING_STATE_FAN_2ND_STAGE_STATE_ON_BIT (1<<5) - -/** @brief Fan 3rd Stage State On bit of Thermostat Running State attribute */ -#define ZB_ZCL_THERMOSTAT_RUNNNING_STATE_FAN_3RD_STAGE_STATE_ON_BIT (1<<6) - -/** @brief Declare attribute list for Thermostat cluster - @param attr_list - attribute list name - @param local_temperature - pointer to variable to store Local Temperature attribute value - @param local_temperature_calibration - pointer to variable to store Local Temperature Calibration attribute value - @param occupied_cooling_setpoint - pointer to variable to store Occupied Cooling Setpoint attribute value - @param occupied_heating_setpoint - pointer to variable to store Occupied Heating Setpoint attribute value - @param control_seq_of_operation - pointer to variable to store Control Sequence Of Operation attribute value - @param system_mode - pointer to variable to store System Mode attribute value - @param start_of_week - pointer to variable to store Start of Week attribute value -*/ -#define ZB_ZCL_DECLARE_THERMOSTAT_ATTRIB_LIST(attr_list, \ - local_temperature, local_temperature_calibration, occupied_cooling_setpoint, \ - occupied_heating_setpoint, control_seq_of_operation, system_mode, start_of_week) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_THERMOSTAT) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_ID, (local_temperature)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_ID, (local_temperature_calibration)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID, (occupied_cooling_setpoint)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID, (occupied_heating_setpoint)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_CONTROL_SEQUENCE_OF_OPERATION_ID, (control_seq_of_operation)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_SYSTEM_MODE_ID, (system_mode)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_START_OF_WEEK_ID, (start_of_week)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @brief Declare attribute list for Thermostat cluster - @param attr_list - attribute list name - @param local_temperature - pointer to variable to store Local Temperature attribute value - @param abs_min_heat_setpoint_limit - pointer to variable to store Abs Min Heat Setpoint Limit attribute value - @param abs_max_heat_setpoint_limit - pointer to variable to store Abs Max Heat Setpoint Limit attribute value - @param abs_min_cool_setpoint_limit - pointer to variable to store Abs Min Cool Setpoint Limit attribute value - @param abs_max_cool_setpoint_limit - pointer to variable to store Abs Max Cool Setpoint Limit attribute value - @param PI_cooling_demand - pointer to variable to store PI Cooling Demand attribute value - @param PI_heating_demand - pointer to variable to store PI Heating Demand attribute value - @param HVAC_system_type_configuration - pointer to variable to store HVAC system type - configuration attribute value; write-optional access according to ZCL8 specification, be careful - when redefining its handling - @param local_temperature_calibration - pointer to variable to store Local Temperature - Calibration attribute value - @param occupied_cooling_setpoint - pointer to variable to store Occupied Cooling Setpoint attribute value - @param occupied_heating_setpoint - pointer to variable to store Occupied Heating Setpoint attribute value - @param unoccupied_cooling_setpoint - pointer to variable to store Unoccupied Cooling Setpoint attribute value - @param unoccupied_heating_setpoint - pointer to variable to store Unoccupied Heating Setpoint attribute value - @param min_heat_setpoint_limit - pointer to variable to store Min Heat Setpoint Limit attribute value - @param max_heat_setpoint_limit - pointer to variable to store Max Heat Setpoint Limit attribute value - @param min_cool_setpoint_limit - pointer to variable to store Min Cool Setpoint Limit attribute value - @param max_cool_setpoint_limit - pointer to variable to store Max Cool Setpoint Limit attribute value - @param min_setpoint_dead_band - pointer to variable to store Min Setpoint Dead Band attribute - value; write-optional access according to ZCL8 specification, be careful - when redefining its handling - @param remote_sensing - pointer to variable to store remote Sensing attribute value - @param control_seq_of_operation - pointer to variable to store Control Sequence Of Operation attribute value - @param system_mode - pointer to variable to store System Mode attribute value - @param start_of_week - pointer to variable to store Start of Week attribute value -*/ -#define ZB_ZCL_DECLARE_THERMOSTAT_ATTRIB_LIST_EXT(attr_list, \ - local_temperature, abs_min_heat_setpoint_limit, abs_max_heat_setpoint_limit, abs_min_cool_setpoint_limit, \ - abs_max_cool_setpoint_limit, PI_cooling_demand, PI_heating_demand, HVAC_system_type_configuration, \ - local_temperature_calibration, occupied_cooling_setpoint, occupied_heating_setpoint, unoccupied_cooling_setpoint, \ - unoccupied_heating_setpoint, min_heat_setpoint_limit, max_heat_setpoint_limit, min_cool_setpoint_limit, \ - max_cool_setpoint_limit, min_setpoint_dead_band, remote_sensing, control_seq_of_operation, system_mode, start_of_week) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_THERMOSTAT) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_ID, (local_temperature)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_HEAT_SETPOINT_LIMIT_ID, (abs_min_heat_setpoint_limit)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_HEAT_SETPOINT_LIMIT_ID, (abs_max_heat_setpoint_limit)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_COOL_SETPOINT_LIMIT_ID, (abs_min_cool_setpoint_limit)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_COOL_SETPOINT_LIMIT_ID, (abs_max_cool_setpoint_limit)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_PI_COOLING_DEMAND_ID, (PI_cooling_demand)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_PI_HEATING_DEMAND_ID, (PI_heating_demand)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_HVAC_SYSTEM_TYPE_CONFIGURATION_ID, (HVAC_system_type_configuration)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_ID, (local_temperature_calibration)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID, (occupied_cooling_setpoint)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID, (occupied_heating_setpoint)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_COOLING_SETPOINT_ID, (unoccupied_cooling_setpoint)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_ID, (unoccupied_heating_setpoint)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_MIN_HEAT_SETPOINT_LIMIT_ID, (min_heat_setpoint_limit)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_MAX_HEAT_SETPOINT_LIMIT_ID, (max_heat_setpoint_limit)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_MIN_COOL_SETPOINT_LIMIT_ID, (min_cool_setpoint_limit)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_MAX_COOL_SETPOINT_LIMIT_ID, (max_cool_setpoint_limit)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_ID, (min_setpoint_dead_band)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_REMOTE_SENSING_ID, (remote_sensing)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_CONTROL_SEQUENCE_OF_OPERATION_ID, (control_seq_of_operation)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_SYSTEM_MODE_ID, (system_mode)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_START_OF_WEEK_ID, (start_of_week)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @brief Bits of ThermostatProgrammingOperationMode */ -enum zb_zcl_thermostat_programming_operation_mode_bit_e -{ - /*! Schedule programming bit */ - ZB_ZCL_THERMOSTAT_SCHEDULE_PROGRAMMING_MODE_BIT = 0x01, - /*! Auto/recovery bit */ - ZB_ZCL_THERMOSTAT_AUTO_RECOVERY_PROGRAMMING_MODE_BIT = 0x02, - /*! Economy/energy star bit */ - ZB_ZCL_THERMOSTAT_ECONOMY_ENERGY_START_PROGRAMMING_MODE_BIT = 0x04, -}; - -/*! @} */ /* Thermostat cluster attributes */ - -/*! @name Thermostat cluster commands - @{ -*/ - -/*! @brief Thermostat cluster command identifiers - @see ZCL spec, subclause 6.3.2.3 -*/ -enum zb_zcl_thermostat_cmd_e -{ - /** Setpoint Raise/Lower command */ - ZB_ZCL_CMD_THERMOSTAT_SETPOINT_RAISE_LOWER = 0x00, - /** Set Weekly Schedule command */ - ZB_ZCL_CMD_THERMOSTAT_SET_WEEKLY_SCHEDULE = 0x01, - /** Get Weekly Schedule command */ - ZB_ZCL_CMD_THERMOSTAT_GET_WEEKLY_SCHEDULE = 0x02, - /** Clear Weekly Schedule command */ - ZB_ZCL_CMD_THERMOSTAT_CLEAR_WEEKLY_SCHEDULE = 0x03, - /** Get Relay Status Log command */ - ZB_ZCL_CMD_THERMOSTAT_GET_RELAY_STATUS_LOG = 0x04 -}; - -/*! @brief Thermostat cluster command identifiers - @see ZCL spec, subclause 6.3.2.4 -*/ -enum zb_zcl_thermostat_cmd_resp_ha_e -{ - /** Get Weekly Schedule response command */ - ZB_ZCL_CMD_THERMOSTAT_GET_WEEKLY_SCHEDULE_RESP = 0x00, - /** Get Relay Status Log response command */ - ZB_ZCL_CMD_THERMOSTAT_GET_RELAY_STATUS_LOG_RESP = 0x01 -}; - -/** @cond internals_doc */ -/* Thermostat cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_THERMOSTAT_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_THERMOSTAT_GET_WEEKLY_SCHEDULE_RESP, \ - ZB_ZCL_CMD_THERMOSTAT_GET_RELAY_STATUS_LOG_RESP - -#define ZB_ZCL_CLUSTER_ID_THERMOSTAT_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_THERMOSTAT_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_THERMOSTAT_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_THERMOSTAT_SETPOINT_RAISE_LOWER, \ - ZB_ZCL_CMD_THERMOSTAT_SET_WEEKLY_SCHEDULE, \ - ZB_ZCL_CMD_THERMOSTAT_GET_WEEKLY_SCHEDULE, \ - ZB_ZCL_CMD_THERMOSTAT_CLEAR_WEEKLY_SCHEDULE, \ - ZB_ZCL_CMD_THERMOSTAT_GET_RELAY_STATUS_LOG - -#define ZB_ZCL_CLUSTER_ID_THERMOSTAT_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_THERMOSTAT_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/*! @} */ /* Thermostat cluster commands */ - -/*! - @cond internals_doc - @internal @name Thermostat cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_OUTDOOR_TEMPERATURE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_OUTDOOR_TEMPERATURE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_OCCUPANCY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPANCY_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_HEAT_SETPOINT_LIMIT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_HEAT_SETPOINT_LIMIT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_HEAT_SETPOINT_LIMIT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_HEAT_SETPOINT_LIMIT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_COOL_SETPOINT_LIMIT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_COOL_SETPOINT_LIMIT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_COOL_SETPOINT_LIMIT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_COOL_SETPOINT_LIMIT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_PI_COOLING_DEMAND_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_PI_COOLING_DEMAND_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_PI_HEATING_DEMAND_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_PI_HEATING_DEMAND_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_THERMOSTAT_PROGRAMMING_OPERATION_MODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_THERMOSTAT_PROGRAMMING_OPERATION_MODE_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_THERMOSTAT_RUNNING_STATE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_THERMOSTAT_RUNNING_STATE_ID, \ - ZB_ZCL_ATTR_TYPE_16BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/** According to ZCL8, Table 6-11. Attributes of the Thermostat Information Attribute Set, - * ZB_ZCL_ATTR_THERMOSTAT_HVAC_SYSTEM_TYPE_CONFIGURATION_ID attribute access was changed to Read and Write - * Optional. For compatibility reasons access rights in the following constructor were not changed. - * - * If it is needed to change access rights to this attribute, this macros should be modified. */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_HVAC_SYSTEM_TYPE_CONFIGURATION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_HVAC_SYSTEM_TYPE_CONFIGURATION_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_ID, \ - ZB_ZCL_ATTR_TYPE_S8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_COOLING_SETPOINT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_COOLING_SETPOINT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_MIN_HEAT_SETPOINT_LIMIT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_MIN_HEAT_SETPOINT_LIMIT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_MAX_HEAT_SETPOINT_LIMIT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_MAX_HEAT_SETPOINT_LIMIT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_MIN_COOL_SETPOINT_LIMIT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_MIN_COOL_SETPOINT_LIMIT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_MAX_COOL_SETPOINT_LIMIT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_MAX_COOL_SETPOINT_LIMIT_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/** According to ZCL8, Table 6-13. Attributes of the Thermostat Settings Attribute Set, - * ZB_ZCL_ATTR_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_ID attribute access was changed to Read and Write - * Optional. For compatibility reasons access rights in the following constructor were not changed. - * - * If it is needed to change access rights to this attribute, this macros should be modified. */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_ID, \ - ZB_ZCL_ATTR_TYPE_S8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_REMOTE_SENSING_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_REMOTE_SENSING_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_CONTROL_SEQUENCE_OF_OPERATION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_CONTROL_SEQUENCE_OF_OPERATION_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_SYSTEM_MODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_SYSTEM_MODE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE | ZB_ZCL_ATTR_ACCESS_SCENE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_ALARM_MASK_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_ALARM_MASK_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_RUNNING_MODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_RUNNING_MODE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_START_OF_WEEK_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_START_OF_WEEK_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_NUMBER_OF_WEEKLY_TRANSITIONS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_NUMBER_OF_WEEKLY_TRANSITIONS_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_NUMBER_OF_DAILY_TRANSITIONS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_NUMBER_OF_DAILY_TRANSITIONS_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_DURATION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_DURATION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_SETPOINT_CHANGE_SOURCE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_SETPOINT_CHANGE_SOURCE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_SETPOINT_CHANGE_AMOUNT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_SETPOINT_CHANGE_AMOUNT_TIMESTAMP_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_SETPOINT_CHANGE_SOURCE_TIMESTAMP_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_SETPOINT_CHANGE_SOURCE_TIMESTAMP_ID, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MIN_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MIN_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MAX_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MAX_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MIN_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MIN_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MAX_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MAX_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_EMERGENCY_HEAT_DELTA_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_EMERGENCY_HEAT_DELTA_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_AC_TYPE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_AC_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_AC_CAPACITY_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_AC_CAPACITY_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_AC_REFRIGERANT_TYPE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_AC_REFRIGERANT_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_AC_COMPRESSOR_TYPE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_AC_COMPRESSOR_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_AC_ERROR_CODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_AC_ERROR_CODE_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_AC_LOUVER_POSITION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_AC_LOUVER_POSITION_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_AC_COIL_TEMPERATURE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_AC_COIL_TEMPERATURE_ID, \ - ZB_ZCL_ATTR_TYPE_S16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_AC_CAPACITY_FORMAT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_AC_CAPACITY_FORMAT_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in Thermostat cluster */ -#define ZB_ZCL_THERMOSTAT_REPORT_ATTR_COUNT 1 - -/***************************** commands *****************************/ - -/* Setpoint is defined in 0.01C, while amount is defined in 0.1C */ -#define ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_AMOUNT_MUL 10 - -/** @internal Structure for Setpoint Raise/Lower command - */ -typedef ZB_PACKED_PRE struct zb_zcl_thermostat_setpoint_raise_lower_req_s -{ - zb_uint8_t mode; - zb_int8_t amount; -} ZB_PACKED_STRUCT zb_zcl_thermostat_setpoint_raise_lower_req_t; - -/*! @brief Values for Mode field, - @see ZCL spec, subclause 6.3.2.3.1.2 */ -enum zb_zcl_thermostat_setpoint_raise_lower_mode_e -{ - /*! Heat value */ - ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_MODE_HEAT = 0x00, - /*! Cool value */ - ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_MODE_COOL = 0x01, - /*! Both (Heat and Cool) value */ - ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_MODE_BOTH = 0x02, - - ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_MODE_RESERVED = 0x03 -}; - -#define ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_thermostat_setpoint_raise_lower_req_t) - -/*! @brief Send Setpoint Raise/Lower command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param mode - Mode value - @param amount - Amount value -*/ -#define ZB_ZCL_THERMOSTAT_SEND_SETPOINT_RAISE_LOWER_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, mode, amount) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_THERMOSTAT_SETPOINT_RAISE_LOWER); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (mode)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (amount)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_THERMOSTAT, cb);\ -} - -/*! - @brief Parses Get Setpoint Raise/Lower command and fills data request - structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param setpoint_raise_lower_req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_THERMOSTAT_GET_SETPOINT_RAISE_LOWER_REQ(data_buf, req, status) \ -{ \ - zb_zcl_thermostat_setpoint_raise_lower_req_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_REQ_PAYLOAD_LEN ? \ - (zb_zcl_thermostat_setpoint_raise_lower_req_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr != NULL) \ - { \ - ZB_MEMCPY(&(req), req_ptr, sizeof(zb_zcl_thermostat_setpoint_raise_lower_req_t)); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/* Add/Get Weekly Schedule record for Set/Get Weekly Schedule commands */ - -/** @internal Structure for Weekly Schedule record - */ -typedef ZB_PACKED_PRE struct zb_zcl_thermostat_weekly_schedule_point_pair_s -{ - zb_uint16_t transition_time; - zb_uint16_t heat_set_point; - zb_uint16_t cool_set_point; -} ZB_PACKED_STRUCT zb_zcl_thermostat_weekly_schedule_point_pair_t; - -#define ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_POINT_PAIR_FULL_SIZE \ - sizeof(zb_zcl_thermostat_weekly_schedule_point_pair_t) - -#define ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_POINT_PAIR_ONE_SIZE \ - sizeof(zb_zcl_thermostat_weekly_schedule_point_pair_t) - sizeof(zb_uint16_t) - -#define ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MAX_NUM_OF_TRANSITIONS 10 - -/*! @brief Values for Mode for Sequence field, - @see ZCL spec, subclause 10.1.3.3.1.4 */ -enum zb_zcl_thermostat_weekly_schedule_mode_for_seq_e -{ - /*! Heat value */ - ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_HEAT = 0x01, - /*! Cool value */ - ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_COOL = 0x02, - /*! Both (Heat and Cool) value */ - ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_BOTH = 0x03, - - ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_RESERVED = 0x04 -}; - -/** @brief Add attribute value to command payload - @param cmd_ptr - pointer to a command data memory - @param mode_for_seq - Mode For Sequence value (from header) - @param transition_time - Transition Time value - @param heat_set_point - Heat Set Point value - @param cool_set_point - Cool Set Point value -*/ -#define ZB_ZCL_THERMOSTAT_ADD_VALUE_WEEKLY_SCHEDULE(cmd_ptr, \ - mode_for_seq, transition_time, heat_set_point, cool_set_point) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (transition_time)); \ - if (mode_for_seq & ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_HEAT) \ - { \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (heat_set_point)); \ - } \ - if (mode_for_seq & ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_COOL) \ - { \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (cool_set_point)); \ - } \ -} - -/** @brief Parses Set Weekly Schedule request and returns next Set point pair record or NULL if there - * is no more data. - - If request contains invalid data, NULL is returned. - @param data_buf - pointer to zb_buf_t buffer containing write attribute request data - @param mode_for_seq - Mode For Sequence value (from Set Weekly Schedule header) - @param pair_req - out pointer to Set Point Pair record - */ -#define ZB_ZCL_THERMOSTAT_GET_NEXT_WEEKLY_SCHEDULE_POINT_PAIR_REQ(data_buf, mode_for_seq, pair_req, status) \ -{ \ - zb_zcl_thermostat_weekly_schedule_point_pair_t *pair_req_ptr; \ - zb_uint8_t req_size; \ - \ - if (mode_for_seq == ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_BOTH) \ - { \ - req_size = ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_POINT_PAIR_FULL_SIZE; \ - } \ - else \ - { \ - req_size = ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_POINT_PAIR_ONE_SIZE; \ - } \ - \ - pair_req_ptr = (zb_buf_len(data_buf) >= req_size) ? \ - (zb_zcl_thermostat_weekly_schedule_point_pair_t*)zb_buf_begin(data_buf) : NULL; \ - if (pair_req_ptr) \ - { \ - ZB_MEMCPY(&(pair_req), pair_req_ptr, req_size); \ - \ - ZB_ZCL_HTOLE16_INPLACE(&(pair_req.transition_time)); \ - ZB_ZCL_HTOLE16_INPLACE(&(pair_req.heat_set_point)); \ - if (mode_for_seq == ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_COOL) \ - { \ - (pair_req).cool_set_point = (pair_req).heat_set_point; \ - } \ - \ - (void)zb_buf_cut_left((data_buf), req_size); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/* Set Weekly Schedule command */ - -typedef ZB_PACKED_PRE struct zb_zcl_thermostat_set_weekly_schedule_req_s -{ - zb_uint8_t num_of_transitions; - zb_uint8_t day_of_week; - zb_uint8_t mode_for_seq; -} ZB_PACKED_STRUCT zb_zcl_thermostat_set_weekly_schedule_req_t; - -#define ZB_ZCL_THERMOSTAT_SET_WEEKLY_SCHEDULE_REQ_SIZE \ - sizeof(zb_zcl_thermostat_set_weekly_schedule_req_t) - -/* 2018/08/10 CR:MAJOR (rev. 39327): According to the spec, one Set Weekly Schedule pkt may contain up to 10 df - * transitions, but we support only one. */ - -/** @brief Initialize Set Weekly Schedule command - @param buffer - buffer to store command data - @param cmd_ptr - pointer to a command data memory - @param def_resp - enable/disable default response - @param num_of_transition - Number Of Transition value - @param day_of_week - Day Of Week value - @param mode_for_seq - Mode For Sequence value - @param transition - Transition Time value - @param heat_set - Heat Set value - @param cool_set - Cool Set value -*/ -#define ZB_ZCL_THERMOSTAT_INIT_SET_WEEKLY_SCHEDULE_REQ(buffer, \ - cmd_ptr, def_resp, num_of_transition, day_of_week, mode_for_seq, \ - transition, heat_set, cool_set) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(cmd_ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(cmd_ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_THERMOSTAT_SET_WEEKLY_SCHEDULE); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (num_of_transition)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (day_of_week)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (mode_for_seq)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (transition)); \ - if (ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_HEAT == (mode_for_seq)) \ - { \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (heat_set)); \ - } \ - else \ - if (ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_COOL == (mode_for_seq)) \ - { \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (cool_set)); \ - } \ - else \ - if (ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MODE_FOR_SEQ_BOTH == (mode_for_seq)) \ - { \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (heat_set)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_ptr, (cool_set)); \ - } \ -} - - -/** @brief Send Set Weekly Schedule command - @param buffer - buffer to store command data - @param cmd_ptr - pointer to a command data memory - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param profile_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_THERMOSTAT_SEND_SET_WEEKLY_SCHEDULE_REQ( \ - buffer, cmd_ptr, addr, dst_addr_mode, dst_ep, ep, profile_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, profile_id, \ - ZB_ZCL_CLUSTER_ID_THERMOSTAT, cb); \ -} - -/** @brief Parses Set Weekly Schedule request header - - If request contains invalid data, status is ZB_FALSE. - @param data_buf - pointer to zb_buf_t buffer containing write attribute request data - @param req - record of type @ref zb_zcl_thermostat_set_weekly_schedule_req_t - @param status - result of parsing - */ -#define ZB_ZCL_THERMOSTAT_GET_SET_WEEKLY_SCHEDULE_REQ(data_buf, req, status) \ -{ \ - zb_zcl_thermostat_set_weekly_schedule_req_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_THERMOSTAT_SET_WEEKLY_SCHEDULE_REQ_SIZE ? \ - (zb_zcl_thermostat_set_weekly_schedule_req_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, sizeof(zb_zcl_thermostat_set_weekly_schedule_req_t)); \ - ZB_ASSERT(req.num_of_transitions <= ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MAX_NUM_OF_TRANSITIONS);\ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - \ - (void)zb_buf_cut_left((data_buf), sizeof(zb_zcl_thermostat_set_weekly_schedule_req_t)); \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/* Get Weekly Schedule command */ - -typedef ZB_PACKED_PRE struct zb_zcl_thermostat_get_weekly_schedule_req_s -{ - zb_uint8_t days_to_return; - zb_uint8_t mode_to_return; -} ZB_PACKED_STRUCT zb_zcl_thermostat_get_weekly_schedule_req_t; - -#define ZB_ZCL_THERMOSTAT_GET_WEEKLY_SCHEDULE_REQ_PAYLOAD_LEN \ - sizeof(zb_zcl_thermostat_get_weekly_schedule_req_t) - -/*! @brief Send Get Weekly Schedule command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param days_to_return - Days To Return value - @param mode_to_return - Mode To Return value -*/ -#define ZB_ZCL_THERMOSTAT_SEND_GET_WEEKLY_SCHEDULE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - days_to_return, mode_to_return) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_THERMOSTAT_GET_WEEKLY_SCHEDULE); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (days_to_return)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (mode_to_return)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT((buffer), (addr), (dst_addr_mode), \ - (dst_ep), (ep), (prfl_id), ZB_ZCL_CLUSTER_ID_THERMOSTAT, (cb)); \ -} - -/*! - @brief Parses Get Weekly Schedule command and fills data request - structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - record of type @ref zb_zcl_thermostat_set_weekly_schedule_req_t - @param status - success or not read parameters - ZB_ZCL_PARSE_STATUS_SUCCESS or - ZB_ZCL_PARSE_STATUS_FAILURE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_THERMOSTAT_GET_GET_WEEKLY_SCHEDULE_REQ(data_buf, req, status) \ -{ \ - zb_zcl_thermostat_get_weekly_schedule_req_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_THERMOSTAT_GET_WEEKLY_SCHEDULE_REQ_PAYLOAD_LEN ? \ - (zb_zcl_thermostat_get_weekly_schedule_req_t*)zb_buf_begin(data_buf) : NULL;\ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, sizeof(zb_zcl_thermostat_get_weekly_schedule_req_t)); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/* Get Weekly Schedule response command */ - -/** Structure for Get Weekly Schedule resp command - */ -typedef ZB_PACKED_PRE struct zb_zcl_thermostat_get_weekly_schedule_resp_s -{ - zb_uint8_t num_of_transitions; - zb_uint8_t day_of_week; - zb_uint8_t mode_for_seq; -} ZB_PACKED_STRUCT zb_zcl_thermostat_get_weekly_schedule_resp_t; - -/** @brief Initialize Get Weekly Schedule resp command - @param buffer - buffer to store command data - @param cmd_ptr - pointer to a command data memory - @param seq - sequency - @param num_of_transitions - Number Of Transition value - @param day_of_week - Day Of Week value - @param mode_for_seq - Mode For Sequence value -*/ -#define ZB_ZCL_THERMOSTAT_INIT_GET_WEEKLY_SCHEDULE_RESP(buffer, cmd_ptr, seq, \ - num_of_transitions, day_of_week, mode_for_seq) \ -{ \ - cmd_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(cmd_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(cmd_ptr, (seq), \ - ZB_ZCL_CMD_THERMOSTAT_GET_WEEKLY_SCHEDULE_RESP); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (num_of_transitions)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (day_of_week)); \ - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, (mode_for_seq)); \ -} - -/** @brief Send Get Weekly Schedule resp command - @param buffer - buffer to store command data - @param cmd_ptr - pointer to a command data memory - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param profile_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_THERMOSTAT_SEND_GET_WEEKLY_SCHEDULE_RESP( \ - buffer, cmd_ptr, addr, dst_addr_mode, dst_ep, ep, profile_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, cmd_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, profile_id,\ - ZB_ZCL_CLUSTER_ID_THERMOSTAT, cb); \ -} - -/** @brief Parses Get Weekly Schedule response header - - If request contains invalid data, status is ZB_FALSE. - @param data_buf - pointer to zb_buf_t buffer containing write attribute request data - @param resp - record of type @ref zb_zcl_thermostat_get_weekly_schedule_resp_t - @param status - result of parsing - */ -#define ZB_ZCL_THERMOSTAT_GET_GET_WEEKLY_SCHEDULE_RESP(data_buf, resp, status) \ -{ \ - zb_zcl_thermostat_get_weekly_schedule_resp_t *resp_ptr = \ - zb_buf_len(data_buf) >= sizeof(zb_zcl_thermostat_get_weekly_schedule_resp_t) ? \ - (zb_zcl_thermostat_get_weekly_schedule_resp_t*)zb_buf_begin(data_buf) : NULL; \ - if (resp_ptr) \ - { \ - ZB_MEMCPY(&(resp), resp_ptr, sizeof(zb_zcl_thermostat_get_weekly_schedule_resp_t)); \ - ZB_ASSERT(resp.num_of_transitions <= \ - ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_MAX_NUM_OF_TRANSITIONS); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - \ - (void)zb_buf_cut_left((data_buf), sizeof(zb_zcl_thermostat_get_weekly_schedule_resp_t)); \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/* Clear Weekly Schedule command */ -/*! @brief Clear Weekly Schedule command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_THERMOSTAT_SEND_CLEAR_WEEKLY_SCHEDULE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_THERMOSTAT_CLEAR_WEEKLY_SCHEDULE); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT((buffer), (addr), (dst_addr_mode), (dst_ep), \ - (ep), (prfl_id), ZB_ZCL_CLUSTER_ID_THERMOSTAT, (cb)); \ -} - -/* Get Relay Status Log command */ -/*! @brief Send Get Relay Status Log req command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_THERMOSTAT_SEND_GET_RELAY_STATUS_LOG_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_THERMOSTAT_GET_RELAY_STATUS_LOG); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT((buffer), (addr), (dst_addr_mode), (dst_ep), \ - (ep), (prfl_id), ZB_ZCL_CLUSTER_ID_THERMOSTAT, (cb)); \ -} - -/* Get Relay Status Log response */ - -typedef ZB_PACKED_PRE struct zb_zcl_thermostat_get_relay_status_log_resp_s -{ - zb_uint16_t time_of_day; - zb_uint8_t relay_status; - zb_int16_t local_temperature; - zb_uint8_t humidity_in_percentage; - zb_int16_t set_point; - zb_uint16_t unread_entries; -} ZB_PACKED_STRUCT zb_zcl_thermostat_get_relay_status_log_resp_t; - -#define ZB_ZCL_THERMOSTAT_GET_RELAY_STATUS_LOG_RESP_SIZE \ - sizeof(zb_zcl_thermostat_get_relay_status_log_resp_t) - -/*! @brief Send Get Relay Status Log resp command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param seq - sequency - @param cb - callback for getting command send status - @param time_of_day - Time Of Day value - @param relay_status - Relay Status value - @param local_temperature - Local Temperature value - @param humidity_in_percentage - Humidity In Percentage value - @param set_point - Set Point value - @param unread_entries - Unread Entries value -*/ -#define ZB_ZCL_THERMOSTAT_SEND_GET_RELAY_STATUS_LOG_RESP( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq, cb, time_of_day, relay_status, \ - local_temperature, humidity_in_percentage, set_point, unread_entries) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq, ZB_ZCL_CMD_THERMOSTAT_GET_RELAY_STATUS_LOG_RESP); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (time_of_day)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (relay_status)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (local_temperature)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (humidity_in_percentage)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (set_point)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (unread_entries)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_THERMOSTAT, cb); \ -} - -/*! - @brief Parses Get Relay Status Log command and fills data request - structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param resp - variable to save command request - @param status - success or not read parameters - ZB_ZCL_PARSE_STATUS_SUCCESS or - ZB_ZCL_PARSE_STATUS_FAILURE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_THERMOSTAT_GET_GET_RELAY_STATUS_LOG_RESP(data_buf, resp, status) \ -{ \ - zb_zcl_thermostat_get_relay_status_log_resp_t *resp_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_THERMOSTAT_GET_RELAY_STATUS_LOG_RESP_SIZE ? \ - (zb_zcl_thermostat_get_relay_status_log_resp_t*)zb_buf_begin(data_buf) : NULL; \ - if (resp_ptr) \ - { \ - ZB_MEMCPY(&(resp), resp_ptr, sizeof(zb_zcl_thermostat_get_relay_status_log_resp_t));\ - ZB_ZCL_HTOLE16_INPLACE(&(resp)->time_of_day); \ - /* FIXME: Can we use it with signed 16-bit int? */ \ - ZB_ZCL_HTOLE16_INPLACE(&(resp)->local_temperature); \ - ZB_ZCL_HTOLE16_INPLACE(&(resp)->set_point); \ - ZB_ZCL_HTOLE16_INPLACE(&(resp)->unread_entries); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/*! @} - * @endcond */ /* Thermostat cluster internals */ - -/*! @cond internals_doc - @name Thermostat cluster command internals - Internal structures and defines for execute cluster command handlers. - @{ -*/ - -/** @brief Size of table with Weekly Schedule records */ -#define ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_TABLE_SIZE 20 - -/** @brief Flag days field "record is free" */ -#define ZB_ZCL_THERMOSTAT_WEEKLY_FREE_RECORD 0 - -/** @brief Bit set "All days" */ -#define ZB_ZCL_THERMOSTAT_WEEKLY_ALL 0x7f - -/** @brief Bit "Weekly vacation" */ -#define ZB_ZCL_THERMOSTAT_WEEKLY_VACATION (1<<7) - -/** @brief Parameter - Thermostat will be schedule - * without any specific record*/ -#define ZB_ZCL_THERMOSTAT_PROCESS_NONE 0xff - -/** @brief Second per week */ -#define ZB_SECOND_PER_WEEK (60*60*24*7) - -/** @brief Second per day */ -#define ZB_SECOND_PER_DAY (60*60*24) - -/** @brief Second per minutes */ -#define ZB_SECOND_PER_MINUTE 60 - -/** @brief Days per week */ -#define ZB_DAYS_PER_WEEK 7 - -/** @brief Time delta for using setpoint: skip setpoint if it expired - * more then this value */ -#define ZB_ZCL_THERMOSTAT_SETPOINT_TIME_DELTA (10 * 60) /* 10 minutes */ - -/** @brief Subtract time in seconds round week */ -#define ZB_WEEK_TIME_SUBTRACT(a, b) ((a) > (b)) ? ((a) - (b)) : ((a) + ZB_SECOND_PER_WEEK - (b)) - -#ifdef ZB_TIMER_32 - // 1 day (24h) -/** @brief Maximum period of Thermostat process loop */ - #define ZB_ZCL_THERMOSTAT_TIMER_MAX (24*60*60) -#else - // 5 min -/** @brief Maximum period of Thermostat process loop */ - #define ZB_ZCL_THERMOSTAT_TIMER_MAX (5*60) -#endif - - -/** @brief Struct with one Weekly Schedule attribute */ -typedef struct zb_zcl_thermostat_weekly_schedule_record_s -{ - zb_uint8_t days; /*< days, ZB_ZCL_THERMOSTAT_WEEKLY_FREE_RECORD (0) - free record */ - zb_uint32_t start_time; /*< seconds after midnight */ - zb_uint8_t mode; /*< Mode for Sequence */ - zb_uint16_t heat_setpoint; /*< Heat Set Point */ - zb_uint16_t cool_setpoint; /*< Cool Set Point */ -} -zb_zcl_thermostat_weekly_schedule_record_t; - -/*! @} - @endcond */ /* Thermostat cluster internals */ - -/*! @} */ /* ZCL HA Thermostat cluster definitions */ - -/** @cond internals_doc */ -/** @brief Struct with Context Thermostat cluster */ -typedef struct zb_zcl_thermostat_context_s -{ - zb_zcl_thermostat_weekly_schedule_record_t schedule_table[ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_TABLE_SIZE]; - zb_uint8_t setpoint_mode; -} -zb_zcl_thermostat_context_t; - -/** @brief Declare run Thermostat command for User Application -*/ -typedef ZB_PACKED_PRE struct zb_zcl_thermostat_value_param_s -{ - zb_uint8_t mode; /*!< Mode for Sequence */ - zb_uint16_t heat_setpoint; /*!< Heat Set Point */ - zb_uint16_t cool_setpoint; /*!< Cool Set Point */ -} zb_zcl_thermostat_value_param_t; -/*! @} - * @endcond */ /* internals_doc */ -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_thermostat_init(void); -zb_uint8_t zb_zcl_thermostat_get_current_day_of_week(zb_uint8_t start_of_week); - -void zb_zcl_thermostat_init_server(void); -void zb_zcl_thermostat_init_client(void); -#define ZB_ZCL_CLUSTER_ID_THERMOSTAT_SERVER_ROLE_INIT zb_zcl_thermostat_init_server -#define ZB_ZCL_CLUSTER_ID_THERMOSTAT_CLIENT_ROLE_INIT zb_zcl_thermostat_init_client - -#endif /* ZB_ZCL_THERMOSTAT_H */ diff --git a/zboss/development/include/zcl/zb_zcl_thermostat_ui_config.h b/zboss/development/include/zcl/zb_zcl_thermostat_ui_config.h deleted file mode 100644 index b4584d0909..0000000000 --- a/zboss/development/include/zcl/zb_zcl_thermostat_ui_config.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Thermostat UI Configuration cluster definitions -*/ - -#ifndef ZB_ZCL_THERMOSTAT_UI_CONFIG_H -#define ZB_ZCL_THERMOSTAT_UI_CONFIG_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond DOXYGEN_ZCL_SECTION */ - -/* Cluster ZB_ZCL_CLUSTER_ID_THERMOSTAT_UI_CONFIG */ - -/*! @addtogroup ZB_ZCL_THERMOSTAT_UI_CONFIG - @{ - @name Thermostat UI Configuration cluster attributes - @{ -*/ - -/*! @brief Thermostat UI Configuration cluster attribute identifiers - @see ZCL spec, subclause 6.6.2.2 -*/ -enum zb_zcl_thermostat_ui_config_attr_e -{ - /** @brief Temperature Display Mode attribute */ - ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_TEMPERATURE_DISPLAY_MODE_ID = 0x0000, - /** @brief Keypad Lockout attribute */ - ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_ID = 0x0001, - /** The ScheduleProgrammingVisibility attribute is used to hide the weekly - * schedule programming functionality or menu on a thermostat from a user - * to prevent local user programming of the weekly schedule. */ - ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_SCHEDULE_PROGRAMMING_VISIBILITY_ID = 0x0002, -}; - -/*! @brief Values for Temperature Display Mode attribute, - @see ZCL spec, subclause 6.6.2.2.1 */ -enum zb_zcl_thermostat_ui_config_temperature_display_mode_e -{ - /*! Temperature in C value */ - ZB_ZCL_THERMOSTAT_UI_CONFIG_TEMPERATURE_DISPLAY_MODE_IN_C = 0x00, - /*! Temperature in F value */ - ZB_ZCL_THERMOSTAT_UI_CONFIG_TEMPERATURE_DISPLAY_MODE_IN_F = 0x01, - - ZB_ZCL_THERMOSTAT_UI_CONFIG_TEMPERATURE_DISPLAY_MODE_RESERVED = 0x02 -}; - -/*! @brief Values for Keypad Lockout attribute, - @see ZCL spec, subclause 6.6.2.2.2 */ -enum zb_zcl_thermostat_ui_config_keypad_lockout_e -{ - /*! No Lockout value */ - ZB_ZCL_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_NO_LOCKOUT = 0x00, - /*! Level 1 Lockout value */ - ZB_ZCL_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_LEVEL_1 = 0x01, - /*! Level 2 Lockout value */ - ZB_ZCL_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_LEVEL_2 = 0x02, - /*! Level 3 Lockout value */ - ZB_ZCL_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_LEVEL_3 = 0x03, - /*! Level 4 Lockout value */ - ZB_ZCL_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_LEVEL_4 = 0x04, - /*! Level 5 Lockout value */ - ZB_ZCL_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_LEVEL_5 = 0x05, - - ZB_ZCL_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_RESERVED = 0x06 -}; - -/** @brief Default value for Thermostat UI Configuration cluster revision global attribute */ -#define ZB_ZCL_THERMOSTAT_UI_CONFIG_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0001u) - -/** @brief Default value for Temperature Display Mode attribute */ -#define ZB_ZCL_THERMOSTAT_UI_CONFIG_TEMPERATURE_DISPLAY_MODE_DEFAULT_VALUE 0x00 - -/** @brief Default value for Keypad Lockout attribute */ -#define ZB_ZCL_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_DEFAULT_VALUE 0x00 - -/** @brief Default value for ScheduleProgrammingVisibility attribute */ -#define ZB_ZCL_THERMOSTAT_UI_CONFIG_SCHEDULE_PROGRAMMING_VISIBILITY_DEFAULT_VALUE ((zb_uint8_t)0x00) - -/** @brief Declare attribute list for Thermostat UI Configuration cluster - @param attr_list - attribute list name - @param temperature_display_mode - pointer to variable to store Temperature Display Mode attribute value - @param keypad_lockout - pointer to variable to store Keypad Lockout attribute value -*/ -#define ZB_ZCL_DECLARE_THERMOSTAT_UI_CONFIG_ATTRIB_LIST(attr_list, temperature_display_mode, keypad_lockout) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_THERMOSTAT) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_TEMPERATURE_DISPLAY_MODE_ID, (temperature_display_mode)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_ID, (keypad_lockout)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/*! @} */ /* Thermostat UI Configuration cluster attributes */ - -/*! @name Thermostat UI Configuration cluster commands - @{ -*/ - -/*! @} */ /* Thermostat UI Configuration cluster commands */ - -/*! @cond internals_doc - @internal @name Thermostat UI Configuration cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_TEMPERATURE_DISPLAY_MODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_TEMPERATURE_DISPLAY_MODE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in Thermostat UI Configuration cluster */ -#define ZB_ZCL_THERMOSTAT_UI_CONFIG_REPORT_ATTR_COUNT 0 - -/*! @} - @endcond */ /* Thermostat UI Configuration cluster internals */ - -/*! @} */ /* ZCL HA Thermostat UI Configuration cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_thermostat_ui_config_init_server(void); -void zb_zcl_thermostat_ui_config_init_client(void); -#define ZB_ZCL_CLUSTER_ID_THERMOSTAT_UI_CONFIG_SERVER_ROLE_INIT zb_zcl_thermostat_ui_config_init_server -#define ZB_ZCL_CLUSTER_ID_THERMOSTAT_UI_CONFIG_CLIENT_ROLE_INIT zb_zcl_thermostat_ui_config_init_client - -#endif /* ZB_ZCL_THERMOSTAT_UI_CONFIG_H */ diff --git a/zboss/development/include/zcl/zb_zcl_time.h b/zboss/development/include/zcl/zb_zcl_time.h deleted file mode 100644 index c08ca2807b..0000000000 --- a/zboss/development/include/zcl/zb_zcl_time.h +++ /dev/null @@ -1,484 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Time cluster definitions -*/ - -#ifndef ZB_ZCL_TIME_H -#define ZB_ZCL_TIME_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_TIME ZCL Time cluster - * @{ - * @details - */ - -/* Cluster ZB_ZCL_CLUSTER_ID_TIME */ - -/** - * @brief Set real time clock callback - * @param[in] time - UTC time at which real time clock will be set - * @return ZB_TRUE if real time clock was set to new value and ZB_FALSE otherwise - * - */ -typedef zb_bool_t (*zb_zcl_time_set_real_time_clock_t)(zb_uint32_t time); - -/** @cond internals_doc */ - -/** - * @brief Set user's callback that will be initialize real time clock on device by - * specified value. - * @param[in] cb - Callback function - * @see zb_zcl_time_set_real_time_clock_t - * - */ -void zb_zcl_set_real_time_clock_callback(zb_zcl_time_set_real_time_clock_t cb); - -/* typedef struct */ - -/** This enum defines possible authoritative levels of time server */ -enum time_server_authoritative_level_e -{ - ZB_ZCL_TIME_SERVER_NOT_CHOSEN = 0, - ZB_ZCL_TIME_HAS_SYNCHRONIZED_BIT, - ZB_ZCL_TIME_HAS_MASTER_BIT, - ZB_ZCL_TIME_HAS_MASTER_AND_SUPERSEDING_BITS, - ZB_ZCL_TIME_COORDINATOR_WITH_MASTER_AND_SUPERSEDING_BITS -}; - -/** Time synchronization payload */ -typedef struct zb_zcl_time_sync_payload_s -{ - /** Network time received from the most authoritative Time server */ - zb_uint32_t time; - /** Source address of the most authoritative Time server */ - zb_uint16_t addr; - /** Source endpoint of the most authoritative Time server */ - zb_uint8_t endpoint; - /** Authoritative level of Time source server. - * @see @ref time_server_authoritative_level_e - */ - zb_uint8_t level; -} zb_zcl_time_sync_payload_t; - -/** @endcond */ /* internals_doc */ - -/** - * @brief Set user's callback that will be initialize real time clock on device by - * specified value. - * "If the Master bit of the @ref ZB_ZCL_ATTR_TIME_TIME_STATUS_ID "TimeStatus" attribute has a value of 0, - * writing to @ref ZB_ZCL_ATTR_TIME_TIME_ID "Time" attribute SHALL set the real time clock to the written value, - * otherwise it cannot be written." - * @see ZCL spec, subclause 3.12.2.2.1 - * - */ -#define ZB_ZCL_TIME_SET_REAL_TIME_CLOCK_CB(func_ptr) (zb_zcl_set_real_time_clock_callback((func_ptr))) - - -#define ZB_TIME_COMPARE_AUTH_LEVEL(new_level, new_short_addr, old_level, old_short_addr) \ - (((new_level) > (old_level)) || \ - (((old_level) > ZB_ZCL_TIME_SERVER_NOT_CHOSEN) && \ - ((new_level) == (old_level)) && \ - ((new_short_addr) < (old_short_addr)))) - - -/** - * @brief Callback to call when new time server found during synchronization. - */ -typedef void (*zb_zcl_time_sync_time_server_found_cb_t)(zb_ret_t status, zb_uint32_t auth_level, zb_uint16_t short_addr, - zb_uint8_t ep, zb_uint32_t nw_time); - - -/** - * @brief Start time synchronization. - * @param endpoint endpoint for each time server synchronization shall be started. - * @param cb callback that will be called on each successful time server discovery. - * @details Start time synchronization process. If device doesn't have master bit set in Time Status attribute of Time Cluster - * then starts to search available time server in Zigbee network and tries to read status and time attributes. - * After time server successfully found and gathered attributes their values will be passed to application - * to take further actions. - */ -void zb_zcl_time_server_synchronize(zb_uint8_t endpoint, zb_zcl_time_sync_time_server_found_cb_t cb); - - -/** - * @brief Handle read attribute response for time cluster. - * @details Handles read attribute response while time synchronization process running. - * If time synchronization process is not started or finished there will be no processing. - */ -zb_bool_t zb_zcl_time_server_read_attr_handle(zb_uint8_t param); - - -/** @defgroup ZB_ZCL_TIME_ATTRS Time cluster attributes - @{ -*/ - -/*! @brief Time cluster attribute identifiers - @see ZCL spec, subclause 3.12.2.2 -*/ -enum zb_zcl_time_attr_e -{ - /*! @brief Time attribute */ - ZB_ZCL_ATTR_TIME_TIME_ID = 0x0000, - /*! @brief Time Status attribute */ - ZB_ZCL_ATTR_TIME_TIME_STATUS_ID = 0x0001, - /*! @brief Time Zone attribute */ - ZB_ZCL_ATTR_TIME_TIME_ZONE_ID = 0x0002, - /*! @brief Dst Start attribute */ - ZB_ZCL_ATTR_TIME_DST_START_ID = 0x0003, - /*! @brief Dst End attribute */ - ZB_ZCL_ATTR_TIME_DST_END_ID = 0x0004, - /*! @brief Dst Shift attribute */ - ZB_ZCL_ATTR_TIME_DST_SHIFT_ID = 0x0005, - /*! @brief Standard Time attribute */ - ZB_ZCL_ATTR_TIME_STANDARD_TIME_ID = 0x0006, - /*! @brief Local Time attribute */ - ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID = 0x0007, - /*! @brief Last Set Time attribute */ - ZB_ZCL_ATTR_TIME_LAST_SET_TIME_ID = 0x0008, - /*! @brief Valid Until Time attribute */ - ZB_ZCL_ATTR_TIME_VALID_UNTIL_TIME_ID = 0x0009 -}; - -/*! @brief Permissible values for Time Status attribute, - @see ZCL spec, subclause 3.12.2.2.2 */ -enum zb_zcl_time_time_status_e -{ - /*! Master value */ - ZB_ZCL_TIME_MASTER = 0, - /*! Synchronized value */ - ZB_ZCL_TIME_SYNCHRONIZED = 1, - /*! Master Zone Dst value */ - ZB_ZCL_TIME_MASTER_ZONE_DST = 2, - /*! Superseding value */ - ZB_ZCL_TIME_SUPERSEDING = 3 -}; - - -/** Check if @e Master bit of @ref zb_zcl_time_attr_e::ZB_ZCL_ATTR_TIME_TIME_STATUS_ID "TimeStatus" attribute is set. - * @param val - 8-bit that contains value of @e TimeStatus attribute - * @return zb_uint8_t value greater then 0 if @e Master bit is set, and return 0 otherwise. - * @see @ref zb_zcl_time_time_status_e -*/ -#define ZB_ZCL_TIME_TIME_STATUS_MASTER_BIT_IS_SET(val) ((val) & (1 << ZB_ZCL_TIME_MASTER)) -/** Check if @e Synchronized bit of @ref zb_zcl_time_attr_e::ZB_ZCL_ATTR_TIME_TIME_STATUS_ID "TimeStatus" attribute is set. - * @param val - 8-bit that contains value of @e TimeStatus attribute - * @return zb_uint8_t value greater then 0 if @e Synchronized bit is set, and return 0 otherwise. - * @see @ref zb_zcl_time_time_status_e -*/ -#define ZB_ZCL_TIME_TIME_STATUS_SYNCHRONIZED_BIT_IS_SET(val) ((val) & (1 << ZB_ZCL_TIME_SYNCHRONIZED)) -/** Check if MasterZoneDST bit of @ref zb_zcl_time_attr_e::ZB_ZCL_ATTR_TIME_TIME_STATUS_ID "TimeStatus" attribute is set. - * @param val - 8-bit that contains value of @e TimeStatus attribute - * @return zb_uint8_t value greater then 0 if @e MasterZoneDST bit is set, and return 0 otherwise. - * @see @ref zb_zcl_time_time_status_e -*/ -#define ZB_ZCL_TIME_TIME_STATUS_MASTER_ZONE_DST_BIT_IS_SET(val) ((val) & (1 << ZB_ZCL_TIME_MASTER_ZONE_DST)) -/** Check if Superseding bit of @ref zb_zcl_time_attr_e::ZB_ZCL_ATTR_TIME_TIME_STATUS_ID "TimeStatus" attribute is set. - * @param val - 8-bit that contains value of @e TimeStatus attribute - * @return zb_uint8_t value greater then 0 if @e Superseding bit is set, and return 0 otherwise. - * @see @ref zb_zcl_time_time_status_e -*/ -#define ZB_ZCL_TIME_TIME_STATUS_SUPERSEDING_BIT_IS_SET(val) ((val) & (1 << ZB_ZCL_TIME_SUPERSEDING)) - -/** @brief Default value for Time cluster revision global attribute */ -#define ZB_ZCL_TIME_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief Invalid value of Time attribute */ -#define ZB_ZCL_TIME_TIME_INVALID_VALUE ((zb_time_t)0xFFFFFFFF) - -/** @brief Default value for Time attribute */ -#define ZB_ZCL_TIME_TIME_DEFAULT_VALUE ZB_ZCL_TIME_TIME_INVALID_VALUE - -/** @brief Minimum value for Time attribute */ -#define ZB_ZCL_TIME_TIME_MIN_VALUE ((zb_time_t)0x0) - -/** @brief Maximum value for Time attribute */ -#define ZB_ZCL_TIME_TIME_MAX_VALUE ((zb_time_t)0xFFFFFFFE) - -/** @brief Default value for Time Status attribute */ -#define ZB_ZCL_TIME_TIME_STATUS_DEFAULT_VALUE 0x00 - -/** @brief Default value for Time Zone attribute */ -#define ZB_ZCL_TIME_TIME_ZONE_DEFAULT_VALUE 0x00000000 - -/** @brief Default value for DstStart attribute */ -#define ZB_ZCL_TIME_DST_START_DEFAULT_VALUE ((zb_uint32_t)0xFFFFFFFF) - -/** @brief Default value for DstEnd attribute */ -#define ZB_ZCL_TIME_DST_END_DEFAULT_VALUE ((zb_uint32_t)0xFFFFFFFF) - -/** @brief Default value for Dst Shift attribute */ -#define ZB_ZCL_TIME_DST_SHIFT_DEFAULT_VALUE 0x00000000 - -/** @brief Default value for StandardTime attribute */ -#define ZB_ZCL_TIME_STANDARD_TIME_DEFAULT_VALUE ((zb_uint32_t)0xFFFFFFFF) - -/** @brief Default value for LocalTime attribute */ -#define ZB_ZCL_TIME_LOCAL_TIME_DEFAULT_VALUE ((zb_uint32_t)0xFFFFFFFF) - -/** @brief Default value for Last Set Time attribute */ -#define ZB_ZCL_TIME_LAST_SET_TIME_DEFAULT_VALUE 0xffffffff - -/** @brief Default value for Valid Until Time attribute */ -#define ZB_ZCL_TIME_VALID_UNTIL_TIME_DEFAULT_VALUE 0xffffffff - -/** @brief Declare attribute list for Time cluster - @param attr_list - attribute list name - @param time - pointer to variable to store Time attribute value; write-optional acc.to ZCL8, be careful when redefining its handling - @param time_status - pointer to variable to store Time Status attribute value; write-optional acc.to ZCL8, be careful when redefining its handling - @param time_zone - pointer to variable to store Time Zone attribute value - @param dst_start - pointer to variable to store Dst Start attribute value - @param dst_end - pointer to variable to store Dst End attribute value - @param dst_shift - pointer to variable to store Dst Shift attribute value - @param standard_time - pointer to variable to store Standard Time attribute value - @param local_time - pointer to variable to store Local Time attribute value - @param last_set_time - pointer to variable to store Last Set Time attribute value - @param valid_until_time - pointer to variable to store Valid Until Time attribute value - - Time and TimeStatus attributes are Read & Write-Optional acc. to ZCL8 spec. - Due to internal implementation specifics Read-Write access mode is used for - declaring the attributes, while optional writability is blocked by the stack - in runtime automatically according to conditions from ZCL8 spec sections 3.12.2.2.1-3.12.2.2.2. -*/ -#define ZB_ZCL_DECLARE_TIME_ATTRIB_LIST(attr_list, time, time_status, time_zone, \ - dst_start, dst_end, dst_shift, standard_time, local_time, last_set_time, valid_until_time) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_TIME) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TIME_TIME_ID, (time)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TIME_TIME_STATUS_ID, (time_status)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, (time_zone)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TIME_DST_START_ID, (dst_start)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TIME_DST_END_ID, (dst_end)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TIME_DST_SHIFT_ID, (dst_shift)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TIME_STANDARD_TIME_ID, (standard_time)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID, (local_time)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TIME_LAST_SET_TIME_ID, (last_set_time)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TIME_VALID_UNTIL_TIME_ID, (valid_until_time)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ /* ZB_ZCL_TIME_ATTRS */ - -/** @defgroup ZB_ZCL_TIME_COMMANDS Time cluster commands - * @{ - */ - -/** @} */ /* ZB_ZCL_TIME_COMMANDS */ - - -/** @cond internals_doc */ -/** Acc. to ZCL8 Table 3-69 and section 3.12.2.2.1 "Time Attribute" Time attribute is write-optional. - * The corresponding conditions are checked in the stack, but be careful when redefining - * processing of the attribute in applications. - */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TIME_TIME_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TIME_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/** Acc. to ZCL8 Table 3-69 and section 3.12.2.2.2 "TimeStatus Attribute" TimeStatus attribute is write-optional. - * The corresponding conditions are checked in the stack, but be careful when redefining - * processing of the attribute in applications. - */ -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TIME_TIME_STATUS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TIME_TIME_STATUS_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, \ - ZB_ZCL_ATTR_TYPE_S32, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TIME_DST_START_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TIME_DST_START_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TIME_DST_END_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TIME_DST_END_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TIME_DST_SHIFT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TIME_DST_SHIFT_ID, \ - ZB_ZCL_ATTR_TYPE_S32, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TIME_STANDARD_TIME_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TIME_STANDARD_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_U32, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TIME_LAST_SET_TIME_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TIME_LAST_SET_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TIME_VALID_UNTIL_TIME_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TIME_VALID_UNTIL_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_UTC_TIME, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/*! @internal Number of attributes mandatory for reporting in Time cluster */ -#define ZB_ZCL_TIME_REPORT_ATTR_COUNT 0 - -/** @endcond */ /* Time cluster internals */ - - -/** @struct zb_zcl_time_attrs_s - * @brief Time cluster attributes - */ -typedef struct zb_zcl_time_attrs_s -{ - - /** @copydoc ZB_ZCL_ATTR_TIME_TIME_ID - * @see ZB_ZCL_ATTR_TIME_TIME_ID - */ - zb_uint32_t time; - - /** @copydoc ZB_ZCL_ATTR_TIME_TIME_STATUS_ID - * @see ZB_ZCL_ATTR_TIME_TIME_STATUS_ID - */ - zb_uint8_t time_status; - - /** @copydoc ZB_ZCL_ATTR_TIME_TIME_ZONE_ID - * @see ZB_ZCL_ATTR_TIME_TIME_ZONE_ID - */ - zb_int32_t time_zone; - - /** @copydoc ZB_ZCL_ATTR_TIME_DST_START_ID - * @see ZB_ZCL_ATTR_TIME_DST_START_ID - */ - zb_uint32_t dst_start; - - /** @copydoc ZB_ZCL_ATTR_TIME_DST_END_ID - * @see ZB_ZCL_ATTR_TIME_DST_END_ID - */ - zb_uint32_t dst_end; - - /** @copydoc ZB_ZCL_ATTR_TIME_DST_SHIFT_ID - * @see ZB_ZCL_ATTR_TIME_DST_SHIFT_ID - */ - zb_uint32_t dst_shift; - - /** @copydoc ZB_ZCL_ATTR_TIME_STANDARD_TIME_ID - * @see ZB_ZCL_ATTR_TIME_STANDARD_TIME_ID - */ - zb_uint32_t standard_time; - - /** @copydoc ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID - * @see ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID - */ - zb_uint32_t local_time; - - /** @copydoc ZB_ZCL_ATTR_TIME_LAST_SET_TIME_ID - * @see ZB_ZCL_ATTR_TIME_LAST_SET_TIME_ID - */ - zb_uint32_t last_set_time; - - /** @copydoc ZB_ZCL_ATTR_TIME_VALID_UNTIL_TIME_ID - * @see ZB_ZCL_ATTR_TIME_VALID_UNTIL_TIME_ID - */ - zb_uint32_t valid_until_time; -} zb_zcl_time_attrs_t; - - -/** @brief Declare attribute list for Time cluster - * @param[in] attr_list - attribute list variable name - * @param[in] attrs - variable of @ref zb_zcl_time_attrs_s type (containing Time cluster attributes) - */ -#define ZB_ZCL_DECLARE_TIME_ATTR_LIST(attr_list, attrs) \ - ZB_ZCL_DECLARE_TIME_ATTRIB_LIST(attr_list, \ - &attrs.time, &attrs.time_status, &attrs.time_zone, \ - &attrs.dst_start, &attrs.dst_end, &attrs.dst_shift, \ - &attrs.standard_time, &attrs.local_time, \ - &attrs.last_set_time, &attrs.valid_until_time ) - -/** @} */ /** ZB_ZCL_TIME */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_time_update_current_time(zb_uint8_t endpoint); - -void zb_zcl_time_init_server(void); -void zb_zcl_time_init_client(void); -#define ZB_ZCL_CLUSTER_ID_TIME_SERVER_ROLE_INIT zb_zcl_time_init_server -#define ZB_ZCL_CLUSTER_ID_TIME_CLIENT_ROLE_INIT zb_zcl_time_init_client - -#endif /* ZB_ZCL_TIME_H */ diff --git a/zboss/development/include/zcl/zb_zcl_touchlink_commissioning.h b/zboss/development/include/zcl/zb_zcl_touchlink_commissioning.h deleted file mode 100644 index 31807b5108..0000000000 --- a/zboss/development/include/zcl/zb_zcl_touchlink_commissioning.h +++ /dev/null @@ -1,2072 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Touchlink Commissioning cluster -*/ - -#if !defined (ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING_H) -#define ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING_H 1 - -#include /* int types, zb_bufid_t */ - -/** @cond (DOXYGEN_ZCL_SECTION && DOXYGEN_TOUCHLINK_FEATURE) */ - -/** @addtogroup ZB_ZCL_TOUCHLINK_COMMISSIONING - Touchlink Commissioning cluster - @{ -*/ - -/** @brief Default value for Touchlink Commissioning cluster revision global attribute */ -#define ZB_ZCL_TOUCHLINK_COMMISSIONING_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/*! - @brief Declare attribute list for Touchlink Commissioning cluster (only cluster revision attribute) - @param attr_list - attribute list name -*/ -#define ZB_ZCL_DECLARE_TOUCHLINK_COMMISSIONING_ATTR_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_TOUCHLINK_COMMISSIONING) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @brief First primary Touchlink channels mask. */ -#define ZB_ZLL_PRIMARY_CHANNEL_MASK ((1l << 11) | (1l << 15) | (1l << 20) | (1l << 25)) - -/** @brief Configurable parameters: minimum address range that maybe assigned during commissioning */ -#define ZB_ZLL_MIN_ADDR_RANGE 100 -/** @brief Configurable parameters: default address range that is assigned during commissioning */ -#define ZB_ZLL_DEFAULT_ADDR_RANGE 1000 - -/** @brief Configurable parameters: minimum group id range that maybe assigned during commissioning */ -#define ZB_ZLL_MIN_GROUP_ID_RANGE 100 -/** @brief Configurable parameters: default group id range that is assigned during commissioning */ -#define ZB_ZLL_DEFAULT_GROUP_ID_RANGE 1000 - -/** @brief aplcInterPANTransIdLifetime constant value. - * @see ZCL spec, subclause 13.3.4.2. - */ -#define ZB_ZLL_APLC_INTRP_TRANSID_LIFETIME ( ZB_MILLISECONDS_TO_BEACON_INTERVAL(8000)) - -/** @brief aplcScanTimeBaseDuration constant value. - * @see ZCL spec, subclause 13.3.4.2. - */ -#define ZB_ZLL_APLC_SCAN_TIME_BASE_DURATION ( ZB_MILLISECONDS_TO_BEACON_INTERVAL(250)) - -/** @brief aplcRxWindowDuration constant value. - * @see ZCL spec, subclause 13.3.4.2. - */ -#define ZB_ZLL_APLC_RX_WINDOW_DURATION (ZB_MILLISECONDS_TO_BEACON_INTERVAL(5000)) - -/** - * @brief aplcMinStartupDelayTime constant value. - * @see ZCL spec, subclause 13.3.4.2. - */ -#define ZB_ZLL_APLC_MIN_STARTUP_DELAY_TIME (ZB_MILLISECONDS_TO_BEACON_INTERVAL(2000)) - -/** No attributes for reporting in Touchlink profile. */ -#define ZB_ZLL_REPORT_ATTR_COUNT 0 - -/*! @name Touchlink Commissioning cluster internals - Internal structures for Touchlink Commissioning cluster - @internal - @{ -*/ - -/** @brief Touchlink commissioning general status is used in different commissioning - * response command frames. */ -typedef enum zb_zll_general_status_e -{ - ZB_ZLL_GENERAL_STATUS_SUCCESS, /**< Status: OK. */ - ZB_ZLL_GENERAL_STATUS_FAILURE /**< Status: Error. */ -} zb_zll_general_status_t; - -/** - * @brief Finish packet and send it to the designated IEEE address. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer containing packet. - * @param data_ptr [IN] - pointer to the packet tail. - * @param dst_addr_long [IN] - destination device's IEEE address. - * @param callback [IN] - callback to call upon send packet confirmation. - * @return packet send schedule status (see @ref zb_ret_t). - */ -zb_ret_t zb_zll_send_packet(zb_bufid_t buffer, zb_uint8_t* data_ptr, zb_ieee_addr_t dst_addr_long, zb_callback_t callback); -#define ZB_ZLL_SEND_PACKET(buffer, data_ptr, dst_addr_long, callback) \ - zb_zll_send_packet(buffer, data_ptr, dst_addr_long, callback) - -/* TODO Provide normal battle-time implementation */ -/** @brief Provides new response identifier. */ -#define ZB_ZLL_GET_NEW_RESPONSE_ID() 0x01 - -/* TODO Provide normal battle-time implementation */ -/** @brief Provides new inter-PAN transaction identifier. */ -#define ZB_ZLL_GET_NEW_TRANS_ID() 0x01 - -/* TODO Remove internal API function calling */ -/** @brief Get NIB Ext Pan ID */ -zb_uint8_t* zb_zll_get_nib_ext_pan_id(void); - -/* TODO Remove internal API function calling */ -/** @brief Get NIB Update ID */ -zb_uint8_t zb_zll_get_nib_update_id(void); - -/*! @} */ /* Commissioning cluster internals */ - -/*! @name Touchlink Commissioning cluster commands - @{ -*/ - -/*! @brief Touchlink commissioning cluster command identifiers - @see ZCL spec, subclauses 13.3.2.1 -*/ -enum zb_zll_commissioning_touchlink_cmd_e -{ - ZB_ZLL_CMD_COMMISSIONING_SCAN_REQ = 0x00, - ZB_ZLL_CMD_COMMISSIONING_DEVICE_INFORMATION_REQ = 0x02, - ZB_ZLL_CMD_COMMISSIONING_IDENTIFY_REQ = 0x06, - ZB_ZLL_CMD_COMMISSIONING_RESET_TO_FACTORY_NEW_REQ = 0x07, - ZB_ZLL_CMD_COMMISSIONING_NETWORK_START_REQ = 0x10, - ZB_ZLL_CMD_COMMISSIONING_NETWORK_JOIN_ROUTER_REQ = 0x12, - ZB_ZLL_CMD_COMMISSIONING_NETWORK_JOIN_END_DEVICE_REQ = 0x14, - ZB_ZLL_CMD_COMMISSIONING_NETWORK_UPDATE_REQ = 0x16 -}; - -/*! @brief Touchlink commissioning cluster utility command identifiers - @see ZCL spec, subclauses 13.3.2.1 -*/ -enum zb_zll_commissioning_utility_cmd_e -{ - ZB_ZLL_CMD_COMMISSIONING_GET_GROUP_IDENTIFIERS_REQUEST = 0x41, - ZB_ZLL_CMD_COMMISSIONING_GET_ENDPOINT_LIST_REQUEST = 0x42 -}; - -/*! @brief Touchlink commissioning cluster response command identifiers - @see ZCL spec, subclause 13.3.2.2 -*/ -enum zb_zll_commissioning_touchlink_cmd_resp_e -{ - ZB_ZLL_CMD_COMMISSIONING_SCAN_RES = 0x01, - ZB_ZLL_CMD_COMMISSIONING_DEVICE_INFORMATION_RES = 0x03, - ZB_ZLL_CMD_COMMISSIONING_NETWORK_START_RES = 0x11, - ZB_ZLL_CMD_COMMISSIONING_NETWORK_JOIN_ROUTER_RES = 0x13, - ZB_ZLL_CMD_COMMISSIONING_NETWORK_JOIN_END_DEVICE_RES = 0x15 -}; - -/*! @brief Touchlink commissioning cluster utility response command identifiers - @see ZCL spec, subclause 13.3.2.2 -*/ -enum zb_zll_commissioning_utility_cmd_resp_e -{ - ZB_ZLL_CMD_COMMISSIONING_ENDPOINT_INFORMATION = 0x40, - ZB_ZLL_CMD_COMMISSIONING_GET_GROUP_IDENTIFIERS_RESPONSE = 0x41, - ZB_ZLL_CMD_COMMISSIONING_GET_ENDPOINT_LIST_RESPONSE = 0x42 -}; - -/************************** Scan request command definitions ****************************/ - -/** @brief Parsed Scan request payload representation. - * @see ZCL spec, subclause 13.3.2.1.1. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_scan_req_s -{ - /** @brief Inter-PAN transaction identifier - * @see ZCL spec, subclause 13.3.2.1.1.1. - */ - zb_uint32_t trans_id; - /** @brief Zigbee information - * @see ZCL spec, subclause 13.3.2.1.1.2. - */ - zb_uint8_t zb_info; - /** @brief Touchlink information - * @see ZCL spec, subclause 13.3.2.1.1.3. - */ - zb_uint8_t zll_info; -} ZB_PACKED_STRUCT zb_zll_commissioning_scan_req_t; - -/** @brief Touchlink information bit values. - * @see ZCL spec, subclause 13.3.2.1.1.3. - */ -enum zb_zll_info_e -{ - ZB_ZLL_INFO_FACTORY_NEW = 0x01, - ZB_ZLL_INFO_ADDR_ASSIGNMENT = 0x02, - ZB_ZLL_INFO_TOUCHLINK_INITIATOR = 0x10, - ZB_ZLL_INFO_TOUCHLINK_PRIOR = 0x20 -}; - -/** @brief Get Touchlink Info current value */ -zb_uint8_t zb_zll_get_info_current_value(void); -#define ZB_ZLL_ZB_INFO_CURRENT_VALUE() zb_zll_get_info_current_value() - -/** @brief Check is Touchlink device factory new */ -#define ZB_ZLL_DEVICE_INFO_GET_FACTORY_NEW(zll_info) ((zll_info) & ZB_ZLL_INFO_FACTORY_NEW) - -/** @brief Check is current Touchlink device factory new */ -#define ZB_ZLL_IS_FACTORY_NEW() (ZB_ZLL_DEVICE_INFO_GET_FACTORY_NEW(ZLL_DEVICE_INFO().zll_info)) - -/** @brief Set current Touchlink device is factory new */ -#define ZB_ZLL_SET_FACTORY_NEW() (ZLL_DEVICE_INFO().zll_info |= ZB_ZLL_INFO_FACTORY_NEW) - -/** @brief Set current Touchlink device is not factory new */ -#define ZB_ZLL_CLEAR_FACTORY_NEW() (ZLL_DEVICE_INFO().zll_info &= ~ZB_ZLL_INFO_FACTORY_NEW) - -/** @brief Check is Touchlink device capable of address assignment */ -#define ZB_ZLL_DEVICE_INFO_GET_ADDR_ASSIGNMENT(zll_info) ((zll_info) & ZB_ZLL_INFO_ADDR_ASSIGNMENT) - -/** @brief Check is current Touchlink device capable of address assignment */ -#define ZB_ZLL_IS_ADDR_ASSIGNMENT() \ - (ZB_ZLL_DEVICE_INFO_GET_ADDR_ASSIGNMENT(ZLL_DEVICE_INFO().zll_info)) - -/** @brief Check is Touchlink device a link initiator */ -#define ZB_ZLL_DEVICE_INFO_GET_LINK_INITIATOR(zll_info) \ - ((zll_info) & ZB_ZLL_INFO_TOUCHLINK_INITIATOR) - -/** @brief Check is current Touchlink device a link initiator */ -#define ZB_ZLL_IS_LINK_INITIATOR() \ - (ZB_ZLL_DEVICE_INFO_GET_LINK_INITIATOR(ZLL_DEVICE_INFO().zll_info)) - -/** @brief Schedules Commissioning.ScanRequest sending. - * @param buffer to use for packet creation. - * @param callback to call upon packet confirmation. - */ -void zb_zll_commissioning_send_scan_req(zb_bufid_t buffer, zb_callback_t callback); -#define ZB_ZLL_COMMISSIONING_SEND_SCAN_REQ(buffer, callback) \ - zb_zll_commissioning_send_scan_req(buffer, callback) - -/** @brief Parses Commissioning.ScanRequest payload. - * @attention Assumes that ZCL header was already cut. - * @param data_ptr - pointer to a variable of type @ref zb_zll_commissioning_scan_req_s. - * @param buffer with the Commissioning.ScanRequest payload. - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_SCAN_REQ(data_ptr, buffer, status) \ -{ \ - zb_uint8_t* src_ptr = zb_buf_begin((buffer)); \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_scan_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH32(&((data_ptr)->trans_id), src_ptr); \ - src_ptr += sizeof(zb_uint32_t); \ - (data_ptr)->zb_info = *(src_ptr++); \ - (data_ptr)->zll_info = *(src_ptr); \ - } \ -} - -/** - * @brief Endpoint information for parsed Commissioning.ScanResponse representation. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_ep_info_s -{ - /** @brief Endpoint identifier. - * - * This field shall only be present when the number of sub-devices field is equal to 1. - */ - zb_uint8_t endpoint_id; - /** @brief Profile identifier. - * - * This field shall only be present when the number of sub-devices field is equal to 1. - */ - zb_uint16_t profile_id; - /** @brief Device identifier. - * - * This field shall only be present when the number of sub-devices field is equal to 1. - */ - zb_uint16_t device_id; - /** @brief Version. - * - * This field shall only be present when the number of sub-devices field is equal to 1. - */ - zb_uint8_t version; - /** @brief Group identifiers count. - * - * This field shall only be present when the number of sub-devices field is equal to 1. - */ - zb_uint8_t n_group_ids; -} ZB_PACKED_STRUCT zb_zll_commissioning_ep_info_t; - -/** @brief Parsed Commissioning.ScanResponse structure. - * @see ZCL spec, subclause 13.3.2.2.1. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_scan_res_s -{ - /** @brief Inter-PAN transaction identifier. */ - zb_uint32_t trans_id; - /** @brief RSSI correction. */ - zb_uint8_t rssi_correction; - /** @brief Zigbee device information. */ - zb_uint8_t zb_info; - /** @brief Touchlink information. */ - zb_uint8_t zll_info; - /** @brief Key bitmask. */ - zb_uint16_t key_bitmask; - /** @brief Response identifier. */ - zb_uint32_t resp_id; - /** @brief Extended Pan ID. */ - zb_ext_pan_id_t ext_pan_id; - /** @brief Network update identifier. */ - zb_uint8_t nwk_upd_id; - /** @brief Logical channel. */ - zb_uint8_t channel; - /** @brief Pan ID. */ - zb_uint16_t pan_id; - /** @brief Network address. */ - zb_uint16_t nwk_addr; - /** @brief Number of sub-devices. */ - zb_uint8_t n_subdevs; - /** @brief Total group identifiers. */ - zb_uint8_t group_ids_total; - - /** - * @brief Endpoint information. - * Shall be present if device has only single endpoint. - */ - zb_zll_commissioning_ep_info_t endpoint_info; -} ZB_PACKED_STRUCT zb_zll_commissioning_scan_res_t; - -/** - * @brief Schedules Commissioning.ScanResponse sending. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param seq_num [IN] - ZCL sequence number. - * @param callback [IN] - callback to call upon packet confirm. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ - -/* - AT: looks like that is a error, it completely breaks security subsystem for Touchlink commissioning, - so i remove this code from ZB_ZLL_COMMISSIONING_SEND_SCAN_RES macro - ZLL_DEVICE_INFO().response_id = ZLL_TRAN_CTX().transaction_id; - TRACE_MSG(TRACE_ZLL1, "resp id %d", (FMT__P, ZLL_DEVICE_INFO().transaction_id)); - replaced by: - ZLL_DEVICE_INFO().response_id = ZB_ZLL_GET_NEW_RESPONSE_ID(); - ZB_HTOLE32_VAL(&(scan_data->resp_id), ZLL_DEVICE_INFO().response_id); -*/ - -#define ZB_ZLL_COMMISSIONING_SEND_SCAN_RES( \ - buffer, \ - seq_num, \ - callback, \ - status) \ -{ \ - zb_zll_commissioning_scan_res_t *scan_data; \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(data_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(data_ptr, (seq_num), ZB_ZLL_CMD_COMMISSIONING_SCAN_RES); \ - scan_data = (zb_zll_commissioning_scan_res_t *)data_ptr; \ - ZB_HTOLE32(&(scan_data->trans_id), &(ZLL_TRAN_CTX().transaction_id)); \ - scan_data->rssi_correction = ZLL_DEVICE_INFO().rssi_correction; \ - scan_data->zb_info = ZB_ZLL_ZB_INFO_CURRENT_VALUE(); \ - scan_data->zll_info = ZLL_DEVICE_INFO().zll_info; \ - ZB_HTOLE16(&(scan_data->key_bitmask), &(ZLL_DEVICE_INFO().key_info)); \ - ZLL_DEVICE_INFO().response_id = ZB_ZLL_GET_NEW_RESPONSE_ID(); \ - ZB_HTOLE32_VAL(&(scan_data->resp_id), ZLL_DEVICE_INFO().response_id); \ - ZB_IEEE_ADDR_COPY(scan_data->ext_pan_id, zb_zll_get_nib_ext_pan_id()); \ - scan_data->nwk_upd_id = (ZB_ZLL_IS_FACTORY_NEW() ? 0x00 : zb_zll_get_nib_update_id()); \ - scan_data->channel = ZB_PIBCACHE_CURRENT_CHANNEL(); \ - ZB_HTOLE16_VAL(&(scan_data->pan_id), ZB_PIBCACHE_PAN_ID()); \ - ZB_HTOLE16_VAL(&(scan_data->nwk_addr), ZB_PIBCACHE_NETWORK_ADDRESS()); \ - scan_data->n_subdevs = ZCL_CTX().device_ctx->ep_count; \ - scan_data->group_ids_total = ZLL_DEVICE_INFO().total_group_id_count; \ - if (ZCL_CTX().device_ctx->ep_count == 1) \ - { \ - zb_af_endpoint_desc_t* descriptor = ZCL_CTX().device_ctx->ep_desc_list[0]; \ - scan_data->endpoint_info.endpoint_id = descriptor->ep_id; \ - ZB_HTOLE16(&(scan_data->endpoint_info.profile_id), &(descriptor->profile_id)); \ - ZB_HTOLE16(&(scan_data->endpoint_info.device_id), &(descriptor->simple_desc->app_device_id)); \ - scan_data->endpoint_info.version = descriptor->simple_desc->app_device_version; \ - scan_data->endpoint_info.n_group_ids = descriptor->group_id_count; \ - } \ - data_ptr += sizeof(zb_zll_commissioning_scan_res_t) - \ - (ZCL_CTX().device_ctx->ep_count == 1 ? 0 : sizeof(zb_zll_commissioning_ep_info_t)); \ - (status) = ZB_ZLL_SEND_PACKET((buffer), data_ptr, ZLL_TRAN_CTX().src_addr, (callback)); \ -} - -/** @brief Parses Commissioning.ScanResponse. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref zb_zll_commissioning_scan_res_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_SCAN_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_scan_res_t) && \ - zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_scan_res_t)-sizeof(zb_zll_commissioning_ep_info_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_scan_res_t *scan_data = \ - (zb_zll_commissioning_scan_res_t *)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH32(&((data_ptr)->trans_id), &(scan_data->trans_id)); \ - (data_ptr)->rssi_correction = scan_data->rssi_correction; \ - (data_ptr)->zb_info = scan_data->zb_info; \ - (data_ptr)->zll_info = scan_data->zll_info; \ - ZB_LETOH16(&((data_ptr)->key_bitmask), &(scan_data->key_bitmask)); \ - ZB_LETOH32(&((data_ptr)->resp_id), &(scan_data->resp_id)); \ - ZB_IEEE_ADDR_COPY((data_ptr)->ext_pan_id, scan_data->ext_pan_id); \ - (data_ptr)->nwk_upd_id = scan_data->nwk_upd_id; \ - (data_ptr)->channel = scan_data->channel; \ - ZB_LETOH16(&((data_ptr)->pan_id), &(scan_data->pan_id)); \ - ZB_LETOH16(&((data_ptr)->nwk_addr), &(scan_data->nwk_addr)); \ - (data_ptr)->n_subdevs = scan_data->n_subdevs; \ - (data_ptr)->group_ids_total = scan_data->group_ids_total; \ - if ((data_ptr)->n_subdevs == 1) \ - { \ - (data_ptr)->endpoint_info.endpoint_id = scan_data->endpoint_info.endpoint_id; \ - ZB_LETOH16(&((data_ptr)->endpoint_info.profile_id), &(scan_data->endpoint_info.profile_id)); \ - ZB_LETOH16(&((data_ptr)->endpoint_info.device_id), &(scan_data->endpoint_info.device_id)); \ - (data_ptr)->endpoint_info.version = scan_data->endpoint_info.version; \ - (data_ptr)->endpoint_info.n_group_ids = scan_data->endpoint_info.n_group_ids; \ - \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_scan_res_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - } \ - else \ - { \ - if (zb_buf_len((buffer)) != \ - sizeof(zb_zll_commissioning_scan_res_t)-sizeof(zb_zll_commissioning_ep_info_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - } \ - } \ -} - -/************************** Device information command definitions ****************************/ - -/** @brief Parsed Commissioning.DeviceInformationRequest payload. - * @see ZCL spec, subclause 13.3.2.1.2. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_device_information_req_s -{ - /** @brief Inter-PAN transaction identifier. */ - zb_uint32_t trans_id; - /** @brief Start index. */ - zb_uint8_t start_idx; -} ZB_PACKED_STRUCT zb_zll_commissioning_device_information_req_t; - -/** @brief Schedules sending Commissioning.DeviceInformationRequest command. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param start_index [IN] - device index to start reporting with. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status [OUT] - packet schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_DEVICE_INFO_REQ( \ - buffer, \ - start_index, \ - dst_addr, \ - callback, \ - status) \ -{ \ - zb_zll_commissioning_device_information_req_t *req; \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_A(data_ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZLL_CMD_COMMISSIONING_DEVICE_INFORMATION_REQ); \ - req = (zb_zll_commissioning_device_information_req_t*)data_ptr; \ - ZB_HTOLE32(&(req->trans_id), &(ZLL_TRAN_CTX().transaction_id)); \ - req->start_idx= (start_index); \ - data_ptr += sizeof(zb_zll_commissioning_device_information_req_t); \ - status = ZB_ZLL_SEND_PACKET((buffer), data_ptr, (dst_addr), (callback)); \ -} - -/** @brief Parses Commissioning.DeviceInformationRequest. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_device_information_req_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_DEVICE_INFO_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_device_information_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_device_information_req_t *req_data = \ - (zb_zll_commissioning_device_information_req_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH32(&((data_ptr)->trans_id), &(req_data->trans_id)); \ - (data_ptr)->start_idx = req_data->start_idx; \ - } \ -} - -/** @brief Parsed permanent part of the Commissioning.DeviceInformationResponse payload. - * @see ZCL spec, subclause 13.3.2.2.2. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_device_information_common_res_s -{ - /** @brief Inter-PAN transaction identifier. */ - zb_uint32_t trans_id; - /** @brief Number of sub-devices. */ - zb_uint8_t n_subdevs; - /** @brief Start index. */ - zb_uint8_t start_idx; - /** @brief Device information record count. */ - zb_uint8_t n_records; -} ZB_PACKED_STRUCT zb_zll_commissioning_device_information_common_res_t; - -/** @brief Maximum number of device information records in the response. */ -#define ZB_ZLL_COMMISSIONING_DEVICE_INFO_MAX_RECORDS 0x05 - -/** @brief Parsed device information record from the Commissioning.DeviceInformationResponse - * payload. - * @see ZCL spec, subclause 13.3.2.2.2. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_device_information_ep_info_res_s -{ - zb_ieee_addr_t ieee_addr; /**< IEEE address of the sub-device. */ - zb_uint8_t ep_id; /**< Device's endpoint identifier. */ - zb_uint16_t profile_id; /**< Profile identifier. */ - zb_uint16_t device_id; /**< Device identifier. */ - zb_uint8_t version; /**< Device version. */ - zb_uint8_t group_id_count; /**< Group identifier count. */ - zb_uint8_t sort; /**< Sort. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_device_information_ep_info_res_t; - -/** @brief Starts filling in Commissioning.DeviceInformationResponse command. - * @param buffer to put packet to (by pointer). - * @param data_ptr - pointer to contain address right after the response's permanent part's tail. - * @param tsn - ZCL transaction sequence number. - * @param start_index - index of the first reported device. - * @param n_devs_reported - number of reported devices. - */ -#define ZB_ZLL_COMMISSIONING_INIT_DEVICE_INFO_RES( \ - buffer, \ - data_ptr, \ - tsn, \ - start_index, \ - n_devs_reported) \ -{ \ - zb_zll_commissioning_device_information_common_res_t *req_data; \ - data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL((data_ptr)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - (data_ptr), \ - (tsn), \ - ZB_ZLL_CMD_COMMISSIONING_DEVICE_INFORMATION_RES); \ - req_data = (zb_zll_commissioning_device_information_common_res_t*)data_ptr; \ - ZB_HTOLE32(&(req_data->trans_id), &(ZLL_TRAN_CTX().transaction_id)); \ - req_data->n_subdevs = ZCL_CTX().device_ctx->ep_count; \ - req_data->start_idx = (start_index); \ - req_data->n_records = (n_devs_reported); \ - data_ptr += sizeof(zb_zll_commissioning_device_information_common_res_t); \ -} - -/** - * @brief Add next device information record into Commissioning.DeviceInformationResponse. - * @param data_ptr [IN] - pointer to contain address right after the added record's tail. - * @param ep_id_ [IN] - endpoint identifier of the sub-device. - * @param profile [IN] - profile identifier of the sub-device. - * @param device [IN] - device identifier. - * @param version_ [IN] of the device. - * @param n_group_ids [IN] - group identifier count. - * @param sort_ [IN] - endpoint info sort flag. - * @attention According to ZCL spec, Device Information Response frame can contain not more than - * 5 device information records. Caller should check this condition. - */ -#define ZB_ZLL_COMMISSIONING_ADD_EP_INFO_DEVICE_INFO_RES( \ - data_ptr, \ - ep_id_, \ - profile, \ - device, \ - version_, \ - n_group_ids, \ - sort_) \ -{ \ - zb_zll_commissioning_device_information_ep_info_res_t *req_data = \ - (zb_zll_commissioning_device_information_ep_info_res_t*)data_ptr; \ - ZB_IEEE_ADDR_COPY(req_data->ieee_addr, ZB_PIBCACHE_EXTENDED_ADDRESS()); \ - req_data->ep_id = (ep_id_); \ - ZB_HTOLE16_VAL(&(req_data->profile_id), (profile)); \ - ZB_HTOLE16_VAL(&(req_data->device_id), (device)); \ - req_data->version = (version_); \ - req_data->group_id_count = (n_group_ids); \ - req_data->sort = (sort_); \ - data_ptr += sizeof(zb_zll_commissioning_device_information_ep_info_res_t);\ -} - -/** - * @brief Schedules Commissioning.DeviceInformationResponse for sending. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer containing payload. - * @param data_ptr [IN] - pointer to the payload's tail. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to call upon packet confirm. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_DEVICE_INFO_RES(buffer, data_ptr, dst_addr, callback, status) \ - (status) = ZB_ZLL_SEND_PACKET(buffer, data_ptr, dst_addr, callback) - -/** @brief Parses Commissioning.DeviceInformationResponse permanent part. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_device_information_common_res_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_DEVICE_INFO_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zll_commissioning_device_information_common_res_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_device_information_common_res_t* src_ptr = \ - (zb_zll_commissioning_device_information_common_res_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH32(&((data_ptr)->trans_id), &(src_ptr->trans_id)); \ - (data_ptr)->n_subdevs = src_ptr->n_subdevs; \ - (data_ptr)->start_idx = src_ptr->start_idx; \ - (data_ptr)->n_records = src_ptr->n_records; \ - (void)zb_buf_cut_left((buffer), sizeof(zb_zll_commissioning_device_information_common_res_t)); \ - } \ -} - -/** Parses next device description record in Commissioning.DeviceInformationResponse payload. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_device_information_ep_info_res_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_NEXT_EP_INFO_DEVICE_INFO_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) < sizeof(zb_zll_commissioning_device_information_ep_info_res_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_device_information_ep_info_res_t* src_ptr = \ - (zb_zll_commissioning_device_information_ep_info_res_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_ZCL_PACKET_GET_DATA_IEEE((data_ptr)->ieee_addr, (src_ptr)); \ - (data_ptr)->ep_id = src_ptr->ep_id; \ - ZB_LETOH16(&((data_ptr)->profile_id), &(src_ptr->profile_id)); \ - ZB_LETOH16(&((data_ptr)->device_id), &(src_ptr->device_id)); \ - (data_ptr)->version = src_ptr->version; \ - (data_ptr)->group_id_count = src_ptr->group_id_count; \ - (data_ptr)->sort = src_ptr->sort; \ - (void)zb_buf_cut_left((buffer), sizeof(zb_zll_commissioning_device_information_ep_info_res_t)); \ - } \ -} - -/************************** Identify request command definitions ****************************/ - -/** - * @brief Parsed Commissioning.IdentifyRequest payload. - * @see ZCL spec, subclause 13.3.2.1.3. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_identify_req_s -{ - /** @brief Inter-PAN transaction identifier. */ - zb_uint32_t trans_id; - /** @brief Identify duration. */ - zb_uint16_t duration; -} ZB_PACKED_STRUCT zb_zll_commissioning_identify_req_t; - -/** - * @brief Schedules sending Commissioning.IdentifyRequest command. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param p_identify_duration [IN] - period to identify. - * @param ieee_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_IDENTIFY_REQ( \ - buffer, \ - p_identify_duration, \ - ieee_addr, \ - callback, \ - status) \ -{ \ - zb_zll_commissioning_identify_req_t *req_data; \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_O(data_ptr, ZB_ZCL_DISABLE_DEFAULT_RESPONSE); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZLL_CMD_COMMISSIONING_IDENTIFY_REQ); \ - req_data = (zb_zll_commissioning_identify_req_t*)data_ptr; \ - ZB_HTOLE32(&(req_data->trans_id), &(ZLL_TRAN_CTX().transaction_id)); \ - ZB_HTOLE16(&(req_data->duration), (p_identify_duration)); \ - data_ptr += sizeof(zb_zll_commissioning_identify_req_t); \ - (status) = ZB_ZLL_SEND_PACKET((buffer), data_ptr, (ieee_addr), (callback)); \ -} - -/** @brief Parses Commissioning.IdentifyRequest. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref zb_zll_commissioning_identify_req_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_IDENTIFY_REQ(data_ptr, buffer, status) \ -{ \ - /* FIXED */ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_identify_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_identify_req_t* src_ptr = \ - (zb_zll_commissioning_identify_req_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH32(&((data_ptr)->trans_id), &(src_ptr->trans_id)); \ - ZB_LETOH16(&((data_ptr)->duration), &(src_ptr->duration)); \ - } \ -} - -/** - * @brief Identify request parameters. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_identify_req_param_s -{ - zb_ieee_addr_t dst_addr; /**< @brief Destination device address. */ - /** - * @brief Time to identify. - * Has special values: - * @li @ref ZB_ZLL_IDENTIFY_STOP - instructs target to exit identify mode. - * @li @ref ZB_ZLL_IDENTIFY_DEFAULT_TIME - instructs target to identify for a default period - * known by the receiver. - */ - zb_uint16_t identify_time; -} ZB_PACKED_STRUCT zb_zll_commissioning_identify_req_param_t; - -/** - * @brief "Exit identify mode" constant for @ref - * zb_zll_commissioning_identify_req_param_s "Identify request." - */ -#define ZB_ZLL_IDENTIFY_STOP 0 - -/** - * @brief "Identify for default period" constant for @ref - * zb_zll_commissioning_identify_req_param_s "Identify request." - */ -#define ZB_ZLL_IDENTIFY_DEFAULT_TIME 0xffff - -/** - * @brief Fills in appropriate structures and starts identify request sending process. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param address [IN] - IEEE address of the target device. - * @param period [IN] - time to identify. - * @param status [OUT] - status of the operation. - */ -#define ZB_ZLL_COMMISSIONING_FILL_IDENTIFY_REQ(buffer, address, period, status) \ -{ \ - zb_zll_commissioning_identify_req_param_t* request = \ - ZB_BUF_GET_PARAM((buffer), zb_zll_commissioning_identify_req_param_t); \ - ZB_IEEE_ADDR_COPY(request->dst_addr, (address)); \ - request->identify_time = (period); \ - (status) = zb_zll_identify(ZB_REF_FROM_BUF((buffer))); \ -} - -/** - * @brief Extract Identify request parameters from the buffer. - * @param data_ptr [OUT] - pointer to a memory region to put request parameters to. Must be - * capable of storing value of type @ref zb_zll_commissioning_identify_req_param_s. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer containing request parameters (as - * a tail parameter). - */ -#define ZB_ZLL_COMMISSIONING_GET_IDENTIFY_REQ_PARAM(data_ptr, buffer) \ -{ \ - zb_zll_commissioning_identify_req_param_t* tmp_ptr = \ - ZB_BUF_GET_PARAM((buffer), zb_zll_commissioning_identify_req_param_t); \ - ZB_MEMCPY((data_ptr), tmp_ptr, sizeof(zb_zll_commissioning_identify_req_param_t)); \ -} - -/** - * @brief Sets up Identify request and schedules it for sending. - * Checks transaction state, identify period acceptability, fills in and schedules for sending - * command packet. - * @param param [IN] - reference to the packet buffer containing @ref - * zb_zll_commissioning_identify_req_param_s structure as parameter. - * @returns - * @li RET_OK in case of success. In this case application will be notified on further status - * (packet received, timed out, etc.) via zboss_signal_handler(). - * @li RET_INVALID_STATE if identify time period doesn't correspond to the transaction state. I.e. - * either identify request was already sent, and identify period is non-zero, or request was not - * sent, and identify period is zero zus instructing the target to exit identify state. - * @li packet schedule error otherwise. - */ -zb_ret_t zb_zll_identify(zb_uint8_t param); - -/************************** Reset to factory new command definitions ****************************/ - -/** @brief Parsed Commissioning.ResetToFactoryNewRequest payload. - * @see ZCL spec, subclause 13.3.2.1.4. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_reset_to_fn_s -{ - /** @brief Inter-PAN transaction identifier. */ - zb_uint32_t trans_id; -} ZB_PACKED_STRUCT zb_zll_commissioning_reset_to_fn_t; - -/** - * @brief Schedules sending Commissioning.ResetToFactoryNewRequest command. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_RESET_TO_FN_REQ( \ - buffer, \ - dst_addr, \ - callback, \ - status) \ -{ \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_O(data_ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZLL_CMD_COMMISSIONING_RESET_TO_FACTORY_NEW_REQ); \ - ZB_ZCL_PACKET_PUT_DATA32_VAL(data_ptr, ZLL_TRAN_CTX().transaction_id); \ - (status) = ZB_ZLL_SEND_PACKET((buffer), data_ptr, (dst_addr), (callback)); \ -} - -/** @brief Parses Commissioning.ResetToFactoryNewRequest. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref zb_zll_commissioning_reset_to_fn_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_RESET_TO_FN_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_reset_to_fn_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_uint8_t* src_ptr = zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_ZCL_PACKET_GET_DATA32(&((data_ptr)->trans_id), (src_ptr)); \ - } \ -} - -/************************** Network start command definitions ****************************/ - -/** - * @brief Parsed Commissioning.NetworkStartRequest payload. - * @see ZCL spec, subclause 13.3.2.1.5. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_network_start_req_s -{ - zb_uint32_t trans_id; /**< Inter-PAN transaction identifier. */ - zb_ext_pan_id_t ext_pan_id; /**< Extended Pan ID. */ - zb_uint8_t key_idx; /**< Key index. */ - zb_uint8_t encr_nwk_key[16]; /**< Encrypted network key. */ - zb_uint8_t channel; /**< Logical channel. */ - zb_uint16_t pan_id; /**< Pan ID. */ - zb_uint16_t short_addr; /**< Network address. */ - zb_uint16_t group_ids_begin; /**< Group identifiers begin. */ - zb_uint16_t group_ids_end; /**< Group identifiers end. */ - zb_uint16_t free_nwk_addrs_begin; /**< Free network address range begin. */ - zb_uint16_t free_nwk_addrs_end; /**< Free network address range end. */ - zb_uint16_t free_group_ids_begin; /**< Free group identifiers range begin. */ - zb_uint16_t free_group_ids_end; /**< Free group identifiers range end. */ - zb_ieee_addr_t initiator_ieee; /**< Initiator IEEE address. */ - zb_uint16_t initiator_short; /**< Initiator network address. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_network_start_req_t; - -/** - * @brief Schedules sending Commissioning.NetworkStartRequest command. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param ext_pan_id_ [IN] - extended Pan ID of the new network. - * @param key_index [IN] - index of the field to be used in the encrypted network key field. - * @param encrypted_nwk_key [IN] - encrypted network key. - * @param logical_channel [IN] - Touchlink channel to be used for the new network. - * @param pan_id_ [IN] - new network Pan ID. - * @param nwk_addr [IN] - short network address for the recipient. - * @param grp_ids_begin [IN] - group identifiers begin field. - * @param grp_ids_end [IN] - group identifiers end field. - * @param free_nwk_addrs_begin_ [IN] - free network addresses begin field. - * @param free_nwk_addrs_end_ [IN] - free network addresses end field. - * @param free_group_ids_begin_ [IN] - free group identifiers begin field. - * @param free_group_ids_end_ [IN] - free group identifiers end field. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_NETWORK_START_REQ( \ - buffer, \ - ext_pan_id_, \ - key_index, \ - encrypted_nwk_key, \ - logical_channel, \ - pan_id_, \ - nwk_addr, \ - grp_ids_begin, \ - grp_ids_end, \ - free_nwk_addrs_begin_, \ - free_nwk_addrs_end_, \ - free_group_ids_begin_, \ - free_group_ids_end_, \ - dst_addr, \ - callback, \ - status) \ -{ \ - zb_zll_commissioning_network_start_req_t *req_data; \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A( \ - data_ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_DISABLE_DEFAULT_RESPONSE); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZLL_CMD_COMMISSIONING_NETWORK_START_REQ); \ - /* do not use PACKET_PUT... define, get memory from buffer \ - * once for type zb_zll_commissioning_network_start_req_t, use struct->field to fill in all the values \ - * use this approach for ALL the cases */ \ - req_data = (zb_zll_commissioning_network_start_req_t*)data_ptr; \ - ZB_HTOLE32(&(req_data->trans_id), &(ZLL_TRAN_CTX().transaction_id)); \ - ZB_IEEE_ADDR_COPY(req_data->ext_pan_id, (ext_pan_id_)); \ - req_data->key_idx = (key_index); \ - ZB_MEMCPY(req_data->encr_nwk_key, (encrypted_nwk_key), 16); \ - req_data->channel = (logical_channel); \ - ZB_HTOLE16_VAL(&(req_data->pan_id), (pan_id_)); \ - ZB_HTOLE16_VAL(&(req_data->short_addr), (nwk_addr)); \ - ZB_HTOLE16_VAL(&(req_data->group_ids_begin), (grp_ids_begin)); \ - ZB_HTOLE16_VAL(&(req_data->group_ids_end), (grp_ids_end)); \ - ZB_HTOLE16_VAL(&(req_data->free_nwk_addrs_begin), (free_nwk_addrs_begin_)); \ - ZB_HTOLE16_VAL(&(req_data->free_nwk_addrs_end), (free_nwk_addrs_end_)); \ - ZB_HTOLE16_VAL(&(req_data->free_group_ids_begin), (free_group_ids_begin_)); \ - ZB_HTOLE16_VAL(&(req_data->free_group_ids_end), (free_group_ids_end_)); \ - ZB_IEEE_ADDR_COPY(req_data->initiator_ieee, ZB_PIBCACHE_EXTENDED_ADDRESS()); \ - ZB_HTOLE16_VAL(&(req_data->initiator_short), ZB_PIBCACHE_NETWORK_ADDRESS()); \ - data_ptr += sizeof(zb_zll_commissioning_network_start_req_t); \ - (status) = ZB_ZLL_SEND_PACKET((buffer), data_ptr, (dst_addr), (callback)); \ -} - -/** - * @brief Parses Commissioning.NetworkStartRequest. - * @attention Assumes that ZCL header already cut. - * @param data_ptr [OUT] - pointer to a variable of type @ref - * zb_zll_commissioning_network_start_req_s. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer containing the packet. - * @param status [OUT] - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_NETWORK_START_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_network_start_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_network_start_req_t *src_ptr = \ - (zb_zll_commissioning_network_start_req_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH32(&((data_ptr)->trans_id), &(src_ptr->trans_id)); \ - ZB_IEEE_ADDR_COPY((data_ptr)->ext_pan_id, src_ptr->ext_pan_id); \ - (data_ptr)->key_idx = src_ptr->key_idx; \ - ZB_MEMCPY((data_ptr)->encr_nwk_key, src_ptr->encr_nwk_key, 16); \ - (data_ptr)->channel = src_ptr->channel; \ - ZB_LETOH16(&((data_ptr)->pan_id), &(src_ptr->pan_id)); \ - ZB_LETOH16(&((data_ptr)->short_addr), &(src_ptr->short_addr)); \ - ZB_LETOH16(&((data_ptr)->group_ids_begin), &(src_ptr->group_ids_begin)); \ - ZB_LETOH16(&((data_ptr)->group_ids_end), &(src_ptr->group_ids_end)); \ - ZB_LETOH16(&((data_ptr)->free_nwk_addrs_begin), &(src_ptr->free_nwk_addrs_begin)); \ - ZB_LETOH16(&((data_ptr)->free_nwk_addrs_end), &(src_ptr->free_nwk_addrs_end)); \ - ZB_LETOH16(&((data_ptr)->free_group_ids_begin), &(src_ptr->free_group_ids_begin)); \ - ZB_LETOH16(&((data_ptr)->free_group_ids_end), &(src_ptr->free_group_ids_end)); \ - ZB_IEEE_ADDR_COPY((data_ptr)->initiator_ieee, (src_ptr->initiator_ieee)); \ - ZB_LETOH16(&((data_ptr)->initiator_short), &(src_ptr->initiator_short)); \ - } \ -} - -/** - * @brief Parsed Commissioning.NetworkStartResponse payload. - * @see ZLL spec, subclause 13.3.2.2.3. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_network_start_res_s -{ - zb_uint32_t trans_id; /**< Inter-PAN transaction identifier. */ - zb_uint8_t status; /**< Status. */ - zb_ext_pan_id_t ext_pan_id; /**< Extended Pan ID. */ - zb_uint8_t nwk_upd_id; /**< Network update identifier. */ - zb_uint8_t channel; /**< Logical channel. */ - zb_uint16_t pan_id; /**< Pqn ID. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_network_start_res_t; - -/** - * @brief The only acceptable value for network update identifier field in the network start - * response. - * @see ZCL spec, subclause 13.3.2.2.3.4. - */ -#define ZB_ZLL_NETWORK_UPDATE_ID ((zb_uint8_t)0) - -/** - * @brief Schedules Commissioning.NetworkStartResponse sending. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer containing payload. - * @param seq_num [IN] - ZCL transaction sequence number. - * @param nwk_status [IN] - network start request result. - * @param ext_pan_id_ [IN] - extended Pan ID of the network to be started. - * @param pan_id_ [IN] - Pan ID of the network to be started. - * @param channel_ [IN] - channel number network will be started on. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status_ [OUT] - packet send schedule status. - */ -#define ZB_ZLL_COMMISSIONING_SEND_NETWORK_START_RES( \ - buffer, \ - seq_num, \ - nwk_status, \ - ext_pan_id_, \ - pan_id_, \ - channel_, \ - dst_addr, \ - callback, \ - status_) \ -{ \ - zb_zll_commissioning_network_start_res_t *req_data; \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(data_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(data_ptr, (seq_num), \ - ZB_ZLL_CMD_COMMISSIONING_NETWORK_START_RES); \ - req_data = (zb_zll_commissioning_network_start_res_t*)data_ptr; \ - ZB_HTOLE32(&(req_data->trans_id), &(ZLL_TRAN_CTX().transaction_id)); \ - req_data->status = (nwk_status); \ - ZB_IEEE_ADDR_COPY(req_data->ext_pan_id, (ext_pan_id_)); \ - req_data->nwk_upd_id = ZB_ZLL_NETWORK_UPDATE_ID; \ - req_data->channel = (channel_); \ - ZB_HTOLE16_VAL(&(req_data->pan_id), (pan_id_)); \ - data_ptr += sizeof(zb_zll_commissioning_network_start_res_t); \ - (status_) = ZB_ZLL_SEND_PACKET((buffer), data_ptr, (dst_addr), (callback)); \ -} - -/** - * @brief Parses Commissioning.NetworkStartResponse. - * @attention Assumes that ZCL header already cut. - * @param data_ptr [OUT] - pointer to a variable of type @ref - * zb_zll_commissioning_network_start_res_s that will contain parsed information. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer containing the packet. - * @param op_status [OUT] - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_NETWORK_START_RES(data_ptr, buffer, op_status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_network_start_res_t)) \ - { \ - (op_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_network_start_res_t *src_ptr = \ - (zb_zll_commissioning_network_start_res_t*)zb_buf_begin((buffer)); \ - (op_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH32(&((data_ptr)->trans_id), &(src_ptr->trans_id)); \ - (data_ptr)->status = src_ptr->status; \ - ZB_IEEE_ADDR_COPY((data_ptr)->ext_pan_id, src_ptr->ext_pan_id); \ - (data_ptr)->nwk_upd_id = src_ptr->nwk_upd_id; \ - (data_ptr)->channel = src_ptr->channel; \ - ZB_LETOH16(&((data_ptr)->pan_id), &(src_ptr->pan_id)); \ - } \ -} - -/************************** Network join router command definitions ****************************/ - -/** - * @brief Parsed Commissioning.NetworkJoinRouterRequest payload. - * @see ZCL spec, subclause 13.3.2.1.6. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_network_join_router_req_s -{ - zb_uint32_t trans_id; /**< Inter-PAN transaction identifier. */ - zb_ext_pan_id_t ext_pan_id; /**< Extended Pan ID. */ - zb_uint8_t key_idx; /**< Key index. */ - zb_uint8_t encr_nwk_key[16]; /**< Encrypted network key. */ - zb_uint8_t nwk_upd_id; /**< Network update identifier. */ - zb_uint8_t channel; /**< Logical channel. */ - zb_uint16_t pan_id; /**< Pan ID. */ - zb_uint16_t short_addr; /**< Network address. */ - zb_uint16_t group_ids_begin; /**< Group identifiers begin. */ - zb_uint16_t group_ids_end; /**< Group identifiers end. */ - zb_uint16_t free_nwk_addrs_begin; /**< Free network address range begin. */ - zb_uint16_t free_nwk_addrs_end; /**< Free network address range end. */ - zb_uint16_t free_group_ids_begin; /**< Free group identifiers range begin. */ - zb_uint16_t free_group_ids_end; /**< Free group identifiers range end. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_network_join_router_req_t; - -/** - * @brief Schedules sending Commissioning.NetworkJoinRouterRequest command. - * @param buffer to put packet to (by pointer). - * @param key_index [IN] - index of the field to be used in the encrypted network key field. - * @param encrypted_nwk_key [IN] - encrypted network key. - * @param nwk_addr [IN] - short network address for the recipient. - * @param grp_ids_begin [IN] - group identifiers begin field. - * @param grp_ids_end [IN] - group identifiers end field. - * @param free_nwk_addrs_begin_ [IN] - free network addresses begin field. - * @param free_nwk_addrs_end_ [IN] - free network addresses end field. - * @param free_group_ids_begin_ [IN] - free group identifiers begin field. - * @param free_group_ids_end_ [IN] - free group identifiers end field. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_NETWORK_JOIN_ROUTER_REQ( \ - buffer, \ - key_index, \ - encrypted_nwk_key, \ - nwk_addr, \ - grp_ids_begin, \ - grp_ids_end, \ - free_nwk_addrs_begin_, \ - free_nwk_addrs_end_, \ - free_group_ids_begin_, \ - free_group_ids_end_, \ - dst_addr, \ - callback, \ - status) \ -{ \ - zb_zll_commissioning_network_join_router_req_t* req_data; \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(data_ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_NOT_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZLL_CMD_COMMISSIONING_NETWORK_JOIN_ROUTER_REQ); \ - req_data = (zb_zll_commissioning_network_join_router_req_t*)data_ptr; \ - ZB_HTOLE32(&(req_data->trans_id), &(ZLL_TRAN_CTX().transaction_id)); \ - ZB_IEEE_ADDR_COPY(req_data->ext_pan_id, zb_zll_get_nib_ext_pan_id()); \ - req_data->key_idx = (key_index); \ - ZB_MEMCPY(req_data->encr_nwk_key, (encrypted_nwk_key), 16); \ - req_data->nwk_upd_id = zb_zll_get_nib_update_id(); \ - req_data->channel = (ZLL_DEVICE_INFO().nwk_channel) ? \ - ZLL_DEVICE_INFO().nwk_channel : ZB_PIBCACHE_CURRENT_CHANNEL(); \ - ZB_HTOLE16_VAL(&(req_data->pan_id), ZB_PIBCACHE_PAN_ID()); \ - ZB_HTOLE16_VAL(&(req_data->short_addr), (nwk_addr)); \ - ZB_HTOLE16_VAL(&(req_data->group_ids_begin), (grp_ids_begin)); \ - ZB_HTOLE16_VAL(&(req_data->group_ids_end), (grp_ids_end)); \ - ZB_HTOLE16_VAL(&(req_data->free_nwk_addrs_begin), (free_nwk_addrs_begin_)); \ - ZB_HTOLE16_VAL(&(req_data->free_nwk_addrs_end), (free_nwk_addrs_end_)); \ - ZB_HTOLE16_VAL(&(req_data->free_group_ids_begin), (free_group_ids_begin_)); \ - ZB_HTOLE16_VAL(&(req_data->free_group_ids_end), (free_group_ids_end_)); \ - data_ptr += sizeof(zb_zll_commissioning_network_join_router_req_t); \ - (status) = ZB_ZLL_SEND_PACKET((buffer), data_ptr, (dst_addr), (callback)); \ -} - -/** @brief Parses Commissioning.NetworkJoinRouterRequest. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_network_join_router_req_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_NETWORK_JOIN_ROUTER_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_network_join_router_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_network_join_router_req_t *src_ptr = \ - (zb_zll_commissioning_network_join_router_req_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH32(&((data_ptr)->trans_id), &(src_ptr->trans_id)); \ - ZB_IEEE_ADDR_COPY((data_ptr)->ext_pan_id, src_ptr->ext_pan_id); \ - (data_ptr)->key_idx = src_ptr->key_idx; \ - ZB_MEMCPY((data_ptr)->encr_nwk_key, src_ptr->encr_nwk_key, 16); \ - (data_ptr)->nwk_upd_id = src_ptr->nwk_upd_id; \ - (data_ptr)->channel = src_ptr->channel; \ - ZB_LETOH16(&((data_ptr)->pan_id), &(src_ptr->pan_id)); \ - ZB_LETOH16(&((data_ptr)->short_addr), &(src_ptr->short_addr)); \ - ZB_LETOH16(&((data_ptr)->group_ids_begin), &(src_ptr->group_ids_begin)); \ - ZB_LETOH16(&((data_ptr)->group_ids_end), &(src_ptr->group_ids_end)); \ - ZB_LETOH16(&((data_ptr)->free_nwk_addrs_begin), &(src_ptr->free_nwk_addrs_begin)); \ - ZB_LETOH16(&((data_ptr)->free_nwk_addrs_end), &(src_ptr->free_nwk_addrs_end)); \ - ZB_LETOH16(&((data_ptr)->free_group_ids_begin), &(src_ptr->free_group_ids_begin)); \ - ZB_LETOH16(&((data_ptr)->free_group_ids_end), &(src_ptr->free_group_ids_end)); \ - } \ -} - -/** - * @brief Parsed Commissioning.NetworkJoinRouterResponse payload. - * @see ZLL spec, subclause 13.3.2.2.4. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_network_join_router_res_s -{ - zb_uint32_t trans_id; /**< Inter-PAN transaction identifier. */ - zb_uint8_t status; /**< Status. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_network_join_router_res_t; - -/** - * @brief Schedules sending Commissioning.NetworkJoinRouterResponse command. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param nwk_status [IN] - network join router operation status. - * @param tsn [IN] - ZCL transaction sequence number. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_NETWORK_JOIN_ROUTER_RES( \ - buffer, \ - nwk_status, \ - tsn, \ - dst_addr, \ - callback, \ - status) \ -{ \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(data_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - (tsn), \ - ZB_ZLL_CMD_COMMISSIONING_NETWORK_JOIN_ROUTER_RES); \ - ZB_ZCL_PACKET_PUT_DATA32_VAL(data_ptr, ZLL_TRAN_CTX().transaction_id); \ - ZB_ZCL_PACKET_PUT_DATA8(data_ptr, (nwk_status)); \ - (status) = ZB_ZLL_SEND_PACKET((buffer), data_ptr, (dst_addr), (callback)); \ -} - -/** @brief Parses Commissioning.NetworkJoinRouterResponse. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_network_join_router_res_s. - * @param buffer containing the packet (by pointer). - * @param op_status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_NETWORK_JOIN_ROUTER_RES(data_ptr, buffer, op_status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_network_join_router_res_t)) \ - { \ - (op_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_uint8_t* src_ptr = zb_buf_begin((buffer)); \ - (op_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_ZCL_PACKET_GET_DATA32(&((data_ptr)->trans_id), (src_ptr)); \ - ZB_ZCL_PACKET_GET_DATA8(&((data_ptr)->status), (src_ptr)); \ - } \ -} - -/************************* Network join end device command definitions ***************************/ - -/** @brief Parsed Commissioning.NetworkJoinEndDeviceRequest payload. - * @see ZCL spec, subclause 13.3.2.1.7. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_network_join_end_device_req_s -{ - zb_uint32_t trans_id; /**< Inter-PAN transaction identifier. */ - zb_ext_pan_id_t ext_pan_id; /**< Extended Pan ID. */ - zb_uint8_t key_idx; /**< Key index. */ - zb_uint8_t encr_nwk_key[16]; /**< Encrypted network key. */ - zb_uint8_t nwk_upd_id; /**< Network update identifier. */ - zb_uint8_t channel; /**< Logical channel. */ - zb_uint16_t pan_id; /**< Pan ID. */ - zb_uint16_t short_addr; /**< Network address. */ - zb_uint16_t group_ids_begin; /**< Group identifiers begin. */ - zb_uint16_t group_ids_end; /**< Group identifiers end. */ - zb_uint16_t free_nwk_addrs_begin; /**< Free network address range begin. */ - zb_uint16_t free_nwk_addrs_end; /**< Free network address range end. */ - zb_uint16_t free_group_ids_begin; /**< Free group identifiers range begin. */ - zb_uint16_t free_group_ids_end; /**< Free group identifiers range end. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_network_join_end_device_req_t; - -/** - * @brief Schedules sending Commissioning.NetworkJoinEndDeviceRequest command. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param key_index [IN] - index of the field to be used in the encrypted network key field. - * @param encrypted_nwk_key [IN] - encrypted network key. - * @param logical_channel [IN] - Touchlink channel to be used for the new network. - * @param nwk_addr [IN] - short network address for the recipient. - * @param grp_ids_begin [IN] - group identifiers begin field. - * @param grp_ids_end [IN] - group identifiers end field. - * @param free_nwk_addrs_begin_ [IN] - free network addresses begin field. - * @param free_nwk_addrs_end_ [IN] - free network addresses end field. - * @param free_group_ids_begin_ [IN] - free group identifiers begin field. - * @param free_group_ids_end_ [IN] - free group identifiers end field. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_NETWORK_JOIN_ED_REQ( \ - buffer, \ - key_index, \ - encrypted_nwk_key, \ - logical_channel, \ - nwk_addr, \ - grp_ids_begin, \ - grp_ids_end, \ - free_nwk_addrs_begin_, \ - free_nwk_addrs_end_, \ - free_group_ids_begin_, \ - free_group_ids_end_, \ - dst_addr, \ - callback, \ - status) \ -{ \ - zb_zll_commissioning_network_join_end_device_req_t *req_data; \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(data_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZLL_CMD_COMMISSIONING_NETWORK_JOIN_END_DEVICE_REQ); \ - req_data = (zb_zll_commissioning_network_join_end_device_req_t*)data_ptr; \ - ZB_HTOLE32(&(req_data->trans_id), &(ZLL_TRAN_CTX().transaction_id)); \ - ZB_IEEE_ADDR_COPY(req_data->ext_pan_id, zb_zll_get_nib_ext_pan_id()); \ - req_data->key_idx = (key_index); \ - ZB_MEMCPY(req_data->encr_nwk_key, (encrypted_nwk_key), 16); \ - req_data->nwk_upd_id = zb_zll_get_nib_update_id(); \ - req_data->channel = (logical_channel); \ - ZB_HTOLE16_VAL(&(req_data->pan_id), ZB_PIBCACHE_PAN_ID()); \ - ZB_HTOLE16_VAL(&(req_data->short_addr), (nwk_addr)); \ - ZB_HTOLE16_VAL(&(req_data->group_ids_begin), (grp_ids_begin)); \ - ZB_HTOLE16_VAL(&(req_data->group_ids_end), (grp_ids_end)); \ - ZB_HTOLE16_VAL(&(req_data->free_nwk_addrs_begin), (free_nwk_addrs_begin_)); \ - ZB_HTOLE16_VAL(&(req_data->free_nwk_addrs_end), (free_nwk_addrs_end_)); \ - ZB_HTOLE16_VAL(&(req_data->free_group_ids_begin), (free_group_ids_begin_)); \ - ZB_HTOLE16_VAL(&(req_data->free_group_ids_end), (free_group_ids_end_)); \ - data_ptr += sizeof(zb_zll_commissioning_network_join_end_device_req_t); \ - (status) = ZB_ZLL_SEND_PACKET((buffer), data_ptr, (dst_addr), (callback)); \ -} - -/** @brief Parses Commissioning.NetworkJoinEndDeviceRequest. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_network_join_end_device_req_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_NETWORK_JOIN_ED_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_network_join_end_device_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_network_join_end_device_req_t *src_ptr = \ - (zb_zll_commissioning_network_join_end_device_req_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH32(&((data_ptr)->trans_id), &(src_ptr->trans_id)); \ - ZB_IEEE_ADDR_COPY((data_ptr)->ext_pan_id, src_ptr->ext_pan_id); \ - (data_ptr)->key_idx = src_ptr->key_idx; \ - ZB_MEMCPY((data_ptr)->encr_nwk_key, src_ptr->encr_nwk_key, 16); \ - (data_ptr)->nwk_upd_id = src_ptr->nwk_upd_id; \ - (data_ptr)->channel = src_ptr->channel; \ - ZB_LETOH16(&((data_ptr)->pan_id), &(src_ptr->pan_id)); \ - ZB_LETOH16(&((data_ptr)->short_addr), &(src_ptr->short_addr)); \ - ZB_LETOH16(&((data_ptr)->group_ids_begin), &(src_ptr->group_ids_begin)); \ - ZB_LETOH16(&((data_ptr)->group_ids_end), &(src_ptr->group_ids_end)); \ - ZB_LETOH16(&((data_ptr)->free_nwk_addrs_begin), &(src_ptr->free_nwk_addrs_begin)); \ - ZB_LETOH16(&((data_ptr)->free_nwk_addrs_end), &(src_ptr->free_nwk_addrs_end)); \ - ZB_LETOH16(&((data_ptr)->free_group_ids_begin), &(src_ptr->free_group_ids_begin)); \ - ZB_LETOH16(&((data_ptr)->free_group_ids_end), &(src_ptr->free_group_ids_end)); \ - } \ -} - -/** - * @brief Parsed Commissioning.NetworkJoinEndDeviceResponse payload. - * @see ZLL spec, subclause 13.3.2.2.5. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_network_join_end_device_res_s -{ - zb_uint32_t trans_id; /**< Inter-PAN transaction identifier. */ - zb_uint8_t status; /**< Status. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_network_join_end_device_res_t; - -/** - * @brief Schedules sending Commissioning.NetworkJoinEndDeviceResponse command. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param nwk_status [IN] - network join end device result. - * @param tsn [IN] - ZCL transaction sequence number. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_NETWORK_JOIN_ED_RES( \ - buffer, \ - nwk_status, \ - tsn, \ - dst_addr, \ - callback, \ - status) \ -{ \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(data_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - (tsn), \ - ZB_ZLL_CMD_COMMISSIONING_NETWORK_JOIN_END_DEVICE_RES); \ - ZB_ZCL_PACKET_PUT_DATA32_VAL(data_ptr, ZLL_TRAN_CTX().transaction_id); \ - ZB_ZCL_PACKET_PUT_DATA8(data_ptr, (nwk_status)); \ - (status) = ZB_ZLL_SEND_PACKET((buffer), data_ptr, (dst_addr), (callback)); \ -} - -/** @brief Parses Commissioning.NetworkJoinEndDeviceResponse. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_network_join_end_device_res_s. - * @param buffer containing the packet (by pointer). - * @param op_status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_NETWORK_JOIN_ED_RES(data_ptr, buffer, op_status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_network_join_end_device_res_t)) \ - { \ - (op_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_uint8_t* src_ptr = zb_buf_begin((buffer)); \ - (op_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_ZCL_PACKET_GET_DATA32(&((data_ptr)->trans_id), (src_ptr)); \ - ZB_ZCL_PACKET_GET_DATA8(&((data_ptr)->status), (src_ptr)); \ - } \ -} - -/************************** Network update command definitions ****************************/ - -/** - * @brief Parsed Commissioning.NetworkUpdateRequest payload. - * @see ZCL spec, subclause 13.3.2.2.5. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_network_update_req_s -{ - zb_uint32_t trans_id; /**< Inter-PAN transaction identifier. */ - zb_ext_pan_id_t ext_pan_id; /**< Extended Pan ID. */ - zb_uint8_t nwk_upd_id; /**< Network update identifier. */ - zb_uint8_t channel; /**< Logical channel. */ - zb_uint16_t pan_id; /**< Pan ID. */ - zb_uint16_t short_addr; /**< Network address. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_network_update_req_t; - -/** - * @brief Schedules sending Commissioning.NetworkUpdateRequest command. - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param nwk_addr [IN] - network address assigned to the target. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param logical_channel [IN] - channel number. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_NETWORK_UPDATE_REQ_WITH_CHANNEL( \ - buffer, \ - nwk_addr, \ - dst_addr, \ - logical_channel, \ - callback, \ - status) \ -{ \ - zb_zll_commissioning_network_update_req_t *req_data; \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_O(data_ptr, ZB_ZCL_DISABLE_DEFAULT_RESPONSE); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZLL_CMD_COMMISSIONING_NETWORK_UPDATE_REQ); \ - req_data = (zb_zll_commissioning_network_update_req_t*)data_ptr; \ - ZB_HTOLE32(&(req_data->trans_id), &(ZLL_TRAN_CTX().transaction_id)); \ - ZB_IEEE_ADDR_COPY(req_data->ext_pan_id, zb_zll_get_nib_ext_pan_id()); \ - req_data->nwk_upd_id = zb_zll_get_nib_update_id(); \ - req_data->channel = (logical_channel); \ - ZB_HTOLE16_VAL(&(req_data->pan_id), ZB_PIBCACHE_PAN_ID()); \ - ZB_HTOLE16_VAL(&(req_data->short_addr), (nwk_addr)); \ - data_ptr += sizeof(zb_zll_commissioning_network_update_req_t); \ - (status) = ZB_ZLL_SEND_PACKET((buffer), data_ptr, (dst_addr), (callback)); \ -} - -/** - * @brief Schedules sending Commissioning.NetworkUpdateRequest command. - * (send command with current value of channel from pib cache) - * @param buffer [IN] - index @ref zb_bufid_t of the buffer to put packet to. - * @param nwk_addr [IN] - network address assigned to the target. - * @param dst_addr [IN] - IEEE device address to send packet to. - * @param callback [IN] - callback to schedule on packet send confirmation. - * @param status [OUT] - packet send schedule status (see @ref zb_ret_t). - */ -#define ZB_ZLL_COMMISSIONING_SEND_NETWORK_UPDATE_REQ( \ - buffer, \ - nwk_addr, \ - dst_addr, \ - callback, \ - status) \ -{ \ - ZB_ZLL_COMMISSIONING_SEND_NETWORK_UPDATE_REQ_WITH_CHANNEL( \ - buffer, \ - nwk_addr, \ - dst_addr, \ - ZB_PIBCACHE_CURRENT_CHANNEL(), \ - callback, \ - status); \ -} - -/** @brief Parses Commissioning.NetworkUpdateRequest. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref zb_zll_commissioning_network_update_req_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_NETWORK_UPDATE_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_network_update_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_network_update_req_t *src_ptr = \ - (zb_zll_commissioning_network_update_req_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH32(&((data_ptr)->trans_id), &(src_ptr->trans_id)); \ - ZB_IEEE_ADDR_COPY((data_ptr)->ext_pan_id, src_ptr->ext_pan_id); \ - (data_ptr)->nwk_upd_id = src_ptr->nwk_upd_id; \ - (data_ptr)->channel = src_ptr->channel; \ - ZB_LETOH16(&((data_ptr)->pan_id), &(src_ptr->pan_id)); \ - ZB_LETOH16(&((data_ptr)->short_addr), &(src_ptr->short_addr)); \ - } \ -} - -/************************** Get group identifiers command definitions ****************************/ - -/** @brief Parsed Commissioning.GetGroupIdentifiersRequest payload. - * @see ZCL spec, subclause 13.3.2.1.9. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_get_group_ids_req_s -{ - zb_uint8_t start_idx; /**< Start index. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_get_group_ids_req_t; - -/** @brief Schedules sending Commissioning.GetGroupIdentifiersRequest command. - * @param buffer to put packet to (by pointer). - * @param start_index - Rindex at which to start returning group identifiers. - * @param dst_addr - IEEE device address to send packet to. - * @param dst_ep - endpoint of device to send packet to. - * @param ep - endpoint of target device. - * @param callback to schedule on packet send confirmation. - */ -#define ZB_ZLL_COMMISSIONING_SEND_GET_GROUP_ID_REQ( \ - buffer, \ - start_index, \ - dst_addr, \ - dst_ep, \ - ep, \ - callback) \ -{ \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(data_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZLL_CMD_COMMISSIONING_NETWORK_UPDATE_REQ); \ - ZB_ZCL_PACKET_PUT_DATA8(data_ptr, (start_index)); \ - ZB_ZCL_FINISH_PACKET((buffer), data_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (buffer), \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - ZB_AF_ZLL_PROFILE_ID, \ - ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING, \ - callback); \ -} - -/** @brief Parses Commissioning.GetGroupIdentifiersRequest. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref zb_zll_commissioning_get_group_ids_req_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_GET_GROUP_ID_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_get_group_ids_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_uint8_t* src_ptr = zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_ZCL_PACKET_GET_DATA8(&((data_ptr)->start_idx), (src_ptr)); \ - } \ -} - -/** @brief Parsed Commissioning.GetGroupIdentifiersResponse payload. - * @see ZCL spec, subclause 13.3.2.2.7. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_get_group_ids_res_permanent_s -{ - zb_uint8_t total; /**< Total. */ - zb_uint8_t start_idx; /**< Start index. */ - zb_uint8_t count; /**< Count. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_get_group_ids_res_permanent_t; - -/** @brief Group information record for Commissioning.GetGroupIdentifiersResponse command. - * @see ZCL spec, subclause 13.3.2.2.7.4. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_group_info_record_s -{ - zb_uint16_t group_id; /**< Group identifier. */ - zb_uint8_t group_type; /**< Group type. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_group_info_record_t; - -/** @brief Group type value for group_type field of @ref zb_zll_commissioning_group_info_record_s. - * @see ZCL spec, subclause 13.3.2.2.7.4. - */ -#define ZB_ZLL_COMMISSIONING_GROUP_INFO_GROUP_TYPE_VALUE 0x00 - -/** @brief Fills in mandatory part of Commissioning.GetGroupIdentifiersResponse payload. - * @param buffer to put packet to (by pointer). - * @param data_ptr - pointer to contain address right after the response's permanent part's tail. - * @param total_ - all count group identifiers - * @param start_index - Index at which to start returning group identifiers. - * @param count_ - count of identifiers in this payload. - * @param tsn [IN] - ZCL transaction sequence number. - */ -#define ZB_ZLL_COMMISSIONING_INIT_GET_GROUP_ID_RES( \ - buffer, \ - data_ptr, \ - total_, \ - start_index, \ - count_, \ - tsn) \ -{ \ - (data_ptr) = ZB_ZCL_START_PACKET((buffer)); \ - zb_zll_commissioning_get_group_ids_res_permanent_t *req_data; \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(data_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - (tsn), \ - ZB_ZLL_CMD_COMMISSIONING_GET_GROUP_IDENTIFIERS_RESPONSE); \ - req_data = (zb_zll_commissioning_get_group_ids_res_permanent_t*)data_ptr; \ - req_data->total = (total_); \ - req_data->start_idx = (start_index); \ - req_data->count = (count_); \ - data_ptr += sizeof(zb_zll_commissioning_get_group_ids_res_permanent_t); \ -} - -#define ZB_ZLL_COMMISSIONING_ADD_GROUP_INFO_GET_GROUP_ID_RES(data_ptr, grp_id, grp_type) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16((data_ptr), (grp_id)); \ - ZB_ZCL_PACKET_PUT_DATA8((data_ptr), (grp_type)); \ -} - -#define ZB_ZLL_COMMISSIONING_SEND_GET_GROUP_ID_RES( \ - buffer, \ - data_ptr, \ - addr, \ - dst_ep, \ - ep, \ - callback) \ -{ \ - ZB_ZCL_FINISH_PACKET((buffer), (data_ptr)) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (buffer), \ - addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - ZB_AF_ZLL_PROFILE_ID, \ - ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING, \ - callback); \ -} - -/** @brief Parses permanent part of Commissioning.GetGroupIdentifiersResponse. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_get_group_ids_res_permanent_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_GET_GROUP_ID_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_get_group_ids_res_permanent_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_get_group_ids_res_permanent_t* src_ptr = \ - (zb_zll_commissioning_get_group_ids_res_permanent_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_MEMCPY((data_ptr), src_ptr,sizeof(zb_zll_commissioning_get_group_ids_res_permanent_t)); \ - (void)zb_buf_cut_left((buffer), sizeof(zb_zll_commissioning_get_group_ids_res_permanent_t)); \ - } \ -} - -/** @brief Extracts next group information record from - * Commissioning.GetGroupIdentifiersResponse. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref zb_zll_commissioning_group_info_record_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_NEXT_GROUP_INFO_GET_GROUP_ID_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_group_info_record_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_uint8_t* src_ptr = zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_ZCL_PACKET_GET_DATA16(&((data_ptr)->group_id), (src_ptr)); \ - ZB_ZCL_PACKET_GET_DATA8(&((data_ptr)->group_type), (src_ptr)); \ - (void)zb_buf_cut_left((buffer), sizeof(zb_zll_commissioning_group_info_record_t)); \ - } \ -} - -/************************** Get endpoint list command definitions ****************************/ - -/** @brief Parsed Commissioning.GetEndpointListRequest payload. - * @see ZCL spec, subclause 13.3.2.1.10. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_get_endpoint_list_req_s -{ - zb_uint8_t start_idx; /**< Start index. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_get_endpoint_list_req_t; - -/** @brief Schedules sending Commissioning.GetEndpointListRequest command. - * @param buffer to put packet to (by pointer). - * @param start_index - Index at which to start returning group identifiers. - * @param addr - IEEE device address to send packet to. - * @param dst_ep - endpoint of device to send packet to. - * @param ep - endpoint of target device. - * @param callback to schedule on packet send confirmation. - */ -#define ZB_ZLL_COMMISSIONING_SEND_GET_EP_LIST_REQ( \ - buffer, \ - start_index, \ - addr, \ - dst_ep, \ - ep, \ - callback) \ -{ \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(data_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZLL_CMD_COMMISSIONING_GET_ENDPOINT_LIST_REQUEST); \ - ZB_ZCL_PACKET_PUT_DATA8(data_ptr, (start_index)); \ - ZB_ZCL_FINISH_PACKET((buffer), data_ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (buffer), \ - addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - ZB_AF_ZLL_PROFILE_ID, \ - ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING, \ - callback); \ -} - -/** @brief Parses Commissioning.GetEndpointListRequest. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_get_endpoint_list_req_s. - * @param status - status read parameters - see @ref zb_zcl_parse_status_e - * @param buffer containing the packet (by pointer). - */ -#define ZB_ZLL_COMMISSIONING_GET_GET_EP_LIST_REQ(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_get_endpoint_list_req_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_uint8_t* src_ptr = zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_ZCL_PACKET_GET_DATA8(&((data_ptr)->start_idx), (src_ptr)); \ - } \ -} - -/** @brief Parsed Commissioning.GetEndpointListResponse payload. - * @see ZCL spec, subclause 13.3.2.2.8. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_get_endpoint_list_res_s -{ - zb_uint8_t total; /**< Total. */ - zb_uint8_t start_idx; /**< Start index. */ - zb_uint8_t count; /**< Count. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_get_endpoint_list_res_t; - -/** @brief Endpoint information record for Commissioning.GetEndpointListResponse command. - * @see ZCL spec, subclause 13.3.2.2.8. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_endpoint_info_record_s -{ - zb_uint16_t addr_short; /**< Network address. */ - zb_uint8_t endpoint; /**< Endpoint identifier. */ - zb_uint16_t profile_id; /**< Profile identifier. */ - zb_uint16_t device_id; /**< Device identifier. */ - zb_uint8_t version; /**< Version. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_endpoint_info_record_t; - -/** @brief Fills in mandatory part of Commissioning.GetGroupIdentifiersResponse payload. - * @param buffer to put packet to (by pointer). - * @param total_ - all count endpoint list - * @param start_index - Index at which to start returning endpoint list. - * @param count_ - count of endpoints in this payload. - * @param tsn [IN] - ZCL transaction sequence number. - * @param data_ptr - pointer to contain address right after the response's permanent part's tail. - */ -#define ZB_ZLL_COMMISSIONING_INIT_GET_EP_LIST_RES( \ - buffer, \ - total_, \ - start_index, \ - count_, \ - tsn, \ - data_ptr) \ -{ \ - zb_zll_commissioning_get_endpoint_list_res_t *res_data; \ - (data_ptr) = ZB_ZCL_START_PACKET((buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL((data_ptr)); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - (data_ptr), \ - (tsn), \ - ZB_ZLL_CMD_COMMISSIONING_GET_ENDPOINT_LIST_RESPONSE); \ - res_data = (zb_zll_commissioning_get_endpoint_list_res_t*)(data_ptr); \ - res_data->total = (total_); \ - res_data->start_idx = (start_index); \ - res_data->count = (count_); \ - (data_ptr) += sizeof(zb_zll_commissioning_get_endpoint_list_res_t); \ -} - -#define ZB_ZLL_COMMISSIONING_ADD_EP_INFO_GET_EP_LIST_RES( \ - data_ptr, \ - addr, \ - ep, \ - profile, \ - device, \ - version_id) \ -{ \ - zb_zll_commissioning_endpoint_info_record_t *res_data = \ - (zb_zll_commissioning_endpoint_info_record_t*)data_ptr; \ - res_data = (zb_zll_commissioning_get_endpoint_list_res_t*)data_ptr; \ - ZB_HTOLE16_VAL(&(res_data->addr_short), (addr)); \ - res_data->endpoint = (ep); \ - ZB_HTOLE16_VAL(&(res_data->profile_id), (profile)); \ - ZB_HTOLE16_VAL(&(res_data->device_id), (device)); \ - res_data->version = (version_id); \ - (data_ptr) += sizeof(zb_zll_commissioning_endpoint_info_record_t); \ -} - -#define ZB_ZLL_COMMISSIONING_SEND_GET_EP_LIST_RES( \ - buffer, \ - data_ptr, \ - dst_addr, \ - dst_ep, \ - ep, \ - callback) \ -{ \ - ZB_ZCL_FINISH_PACKET((buffer), (data_ptr)) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (buffer), \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - ZB_AF_ZLL_PROFILE_ID, \ - ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING, \ - callback); \ -} - -/** @brief Parses permanent part of Commissioning.GetEndpointListResponse. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_get_endpoint_list_res_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_GET_EP_LIST_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_get_endpoint_list_res_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_get_endpoint_list_res_t* src_ptr = \ - (zb_zll_commissioning_get_endpoint_list_res_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_MEMCPY((data_ptr)), src_ptr, sizeof(zb_zll_commissioning_get_endpoint_list_res_t)); \ - (void)zb_buf_cut_left((buffer), sizeof(zb_zll_commissioning_get_endpoint_list_res_t)); \ - } \ -} - -/** @brief Extracts next endpoint information record from - * Commissioning.GetEndpointListResponse. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_endpoint_info_record_s. - * @param buffer containing the packet (by pointer). - * @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t). - */ -#define ZB_ZLL_COMMISSIONING_GET_NEXT_EP_INFO_GET_EP_LIST_RES(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_endpoint_info_record_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_endpoint_info_record_t* src_ptr = \ - (zb_zll_commissioning_endpoint_info_record_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_LETOH16(&((data_ptr)->addr_short), &(src_ptr->addr_short)); \ - (data_ptr)->endpoint = src_ptr->endpoint; \ - ZB_LETOH16(&((data_ptr)->profile_id), &(src_ptr->profile_id)); \ - ZB_LETOH16(&((data_ptr)->device_id), &(src_ptr_device_id)); \ - (data_ptr)->version = src_ptr->version; \ - (void)zb_buf_cut_left((buffer), sizeof(zb_zll_commissioning_endpoint_info_record_t)); \ - } \ -} - -/************************** Endpoint information command definitions ****************************/ - -/** @brief Parsed Commissioning.EndpointInformation payload. - * @see ZCL spec, subclause 13.3.2.2.6. - */ -typedef ZB_PACKED_PRE struct zb_zll_commissioning_endpoint_information_s -{ - zb_ieee_addr_t addr_long; /**< IEEE address. */ - zb_uint16_t addr_short; /**< Network address. */ - zb_uint8_t endpoint; /**< Endpoint identifier. */ - zb_uint16_t profile_id; /**< Profile identifier. */ - zb_uint16_t device_id; /**< Device identifier. */ - zb_uint8_t version; /**< Version. */ -} ZB_PACKED_STRUCT zb_zll_commissioning_endpoint_information_t; - -/** @brief Schedules sending Commissioning.EndpointInformation command. - * @param buffer to put packet to (by pointer). - * @param endpoint_id - endpoint identifier. - * @param profile - profile identifier. - * @param device - device identifier. - * @param version_ - device version. - * @param dst_addr - IEEE device address to send packet to. - * @param dst_ep - endpoint of device to send packet to. - * @param ep - endpoint of target device. - * @param callback to schedule on packet send confirmation. - */ -#define ZB_ZLL_COMMISSIONING_SEND_EP_INFO( \ - buffer, \ - endpoint_id, \ - profile, \ - device, \ - version_, \ - dst_addr, \ - dst_ep, \ - ep, \ - callback) \ -{ \ - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET((buffer)); \ - zb_zll_commissioning_endpoint_information_t *req_data; \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(data_ptr); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( \ - data_ptr, \ - ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZLL_CMD_COMMISSIONING_NETWORK_UPDATE_REQ); \ - req_data = (zb_zll_commissioning_endpoint_information_t*)(data_ptr); \ - ZB_IEEE_ADDR_COPY(req_data->addr_long, ZB_PIBCACHE_EXTENDED_ADDRESS());\ - ZB_HTOLE16_VAL(&(req_data->addr_short), ZB_PIBCACHE_NETWORK_ADDRESS());\ - req_data->endpoint = (endpoint_id); \ - ZB_HTOLE16_VAL(&(req_data->profile_id), (profile)); \ - ZB_HTOLE16_VAL(&(req_data->device_id), (device)); \ - req_data->version = (version_); \ - (data_ptr) += sizeof(zb_zll_commissioning_endpoint_information_t); \ - ZB_ZCL_FINISH_PACKET((buffer), (data_ptr)) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (buffer), \ - dst_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - dst_ep, \ - ep, \ - ZB_AF_ZLL_PROFILE_ID, \ - ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING, \ - callback); \ -} - -/** @brief Parses Commissioning.EndpointInformation. - * @attention Assumes that ZCL header already cut. - * @param data_ptr - pointer to a variable of type @ref - * zb_zll_commissioning_endpoint_information_s. - * @param buffer containing the packet (by pointer). - * @param status - status read parameters - see @ref zb_zcl_parse_status_e - */ -#define ZB_ZLL_COMMISSIONING_GET_EP_INFO(data_ptr, buffer, status) \ -{ \ - if (zb_buf_len((buffer)) != sizeof(zb_zll_commissioning_endpoint_information_t)) \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - zb_zll_commissioning_endpoint_information_t* src_ptr = \ - (zb_zll_commissioning_endpoint_information_t*)zb_buf_begin((buffer)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_IEEE_ADDR_COPY((data_ptr)->addr_long, src_ptr->addr_long); \ - ZB_LETOH16(&((data_ptr)->addr_short), &(src_ptr->addr_short)); \ - (data_ptr)->endpoint = src_ptr->endpoint; \ - ZB_LETOH16(&((data_ptr)->profile_id), &(src_ptr->profile_id)); \ - ZB_LETOH16(&((data_ptr)->device_id), &(src_ptr->device_id)); \ - (data_ptr)->version = src_ptr->version; \ - } \ -} - -/*! @} */ /* Touchlink Commissioning cluster commands */ - -/*! @} */ /* Touchlink Commissioning cluster */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION && DOXYGEN_TOUCHLINK_FEATURE */ - -#define ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING_SERVER_ROLE_INIT (zb_zcl_cluster_init_t)NULL -#define ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING_CLIENT_ROLE_INIT (zb_zcl_cluster_init_t)NULL - -#endif /* ZB_ZCL_CLUSTER_ID_TOUCHLINK_COMMISSIONING_H */ diff --git a/zboss/development/include/zcl/zb_zcl_tunneling.h b/zboss/development/include/zcl/zb_zcl_tunneling.h deleted file mode 100644 index 1d011e1444..0000000000 --- a/zboss/development/include/zcl/zb_zcl_tunneling.h +++ /dev/null @@ -1,1012 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Tunneling cluster definitions -*/ -#ifndef ZB_ZCL_TUNNELING_H -#define ZB_ZCL_TUNNELING_H 1 - -#define ZB_ZCL_TUNNELING_MAX_INCOMING_TRANSFER_SIZE (ZB_ASDU_MAX_FRAG_LEN - 3 /* ZCL cmd */ - 2 /* Tunnel_ID */) -#define ZB_ZCL_TUNNELING_SRV_TABLE_SIZE 10 - -#include "zcl/zb_zcl_common.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - - -/** @addtogroup ZB_ZCL_TUNNELING - * @{ - * @details - * The tunneling cluster provides an interface for tunneling protocols. It is - * comprised of commands and attributes required to transport any existing - * metering communication protocol within the payload of standard Zigbee - * frames (including the handling of issues such as addressing, fragmentation - * and flow control). Examples for such protocols are DLMS/COSEM, IEC61107, - * ANSI C12, M-Bus, ClimateTalk etc.\n - * This cluster transmits custom data between peers\n - * Model: One (client) to More (servers)\n - */ - - -/** @defgroup ZB_ZCL_TUNNELING_ATTRS Tunneling cluster attributes - * @{ - */ - -/** @brief Tunneling cluster attribute identifiers - * @see SE spec, subclause D.6.2.2 - */ -enum zb_zcl_tunneling_attr_e -{ - /*! @brief CloseTunnelTimeout defines the minimum number of seconds that the - * server waits on an inactive tunnel before closing it on its own and freeing - * its resources (without waiting for the CloseTunnel command from the client). - * Inactive means here that the timer is re-started with each new reception of - * a command.0x0000 is an invalid value. - * @see ZB_ZCL_TUNNELING_CLOSE_TUNNEL_TIMEOUT_MIN_VALUE - * @see ZB_ZCL_TUNNELING_CLOSE_TUNNEL_TIMEOUT_DEFAULT_VALUE - */ - ZB_ZCL_ATTR_TUNNELING_CLOSE_TUNNEL_TIMEOUT_ID = 0 -}; - -/** @brief Default value for Tunneling cluster revision global attribute */ -#define ZB_ZCL_TUNNELING_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u) - -/** @brief Min value for the @e CloseTunnelTimeout attribute - * @see ZB_ZCL_ATTR_TUNNELING_CLOSE_TUNNEL_TIMEOUT_ID */ -#define ZB_ZCL_TUNNELING_CLOSE_TUNNEL_TIMEOUT_MIN_VALUE 0x0001 - -/** @brief Default value for the @e CloseTunnelTimeout attribute - * @see ZB_ZCL_ATTR_TUNNELING_CLOSE_TUNNEL_TIMEOUT_ID */ -#define ZB_ZCL_TUNNELING_CLOSE_TUNNEL_TIMEOUT_DEFAULT_VALUE 0xFFFF - - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_TUNNELING_CLOSE_TUNNEL_TIMEOUT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_TUNNELING_CLOSE_TUNNEL_TIMEOUT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -/** @endcond */ /* internals_doc */ - -/** @def ZB_ZCL_DECLARE_TUNNELING_ATTRIB_LIST(attr_list, close_tunnel_timeout) - * @brief Declare attribute list for Tunneling cluster - * @param[in] attr_list - attribute list name - * @param[in] close_tunnel_timeout - pointer to variable to store On/Tunneling attribute value - */ -#define ZB_ZCL_DECLARE_TUNNELING_ATTRIB_LIST(attr_list, close_tunnel_timeout) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_TUNNELING) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_TUNNELING_CLOSE_TUNNEL_TIMEOUT_ID, (close_tunnel_timeout)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** - * @brief Tunneling cluster attributes - */ -typedef struct zb_zcl_tunneling_attrs_s -{ - /** @copydoc ZB_ZCL_ATTR_TUNNELING_CLOSE_TUNNEL_TIMEOUT_ID - * @see ZB_ZCL_ATTR_TUNNELING_CLOSE_TUNNEL_TIMEOUT_ID - */ - zb_uint16_t close_tunnel_timeout; -} zb_zcl_tunneling_attrs_t; - - -/** @brief Declare attribute list for Tunneling cluster cluster - * @param[in] attr_list - attribute list variable name - * @param[in] attrs - pointer to @ref zb_zcl_tunneling_attrs_s structure - */ -#define ZB_ZCL_DECLARE_TUNNELING_ATTR_LIST(attr_list, attrs) \ - ZB_ZCL_DECLARE_TUNNELING_ATTRIB_LIST(attr_list, &attrs.close_tunnel_timeout ) - -/** @cond internals_doc */ - -#define ZB_ZCL_TUNNELING_TUNNEL_ID_INVALID_VALUE 0xFFFF - -#define ZB_ZCL_TUNNELING_MANUFACTURER_CODE_NOT_USED 0xFFFF - -/** @endcond */ /* internals_doc */ - -/** @} */ /* ZB_ZCL_TUNNELING_ATTRS */ - - -/** @defgroup ZB_ZCL_TUNNELING_COMMANDS Tunneling cluster commands - * @{ - */ - -/** @brief Tunnel cluster commands received - * @see SE spec, subclause D.6.2.4 - */ -enum zb_zcl_tunneling_cli_cmd_e -{ - - ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL = 0x00, /**< @brief @e RequestTunnel is the client command used to setup a tunnel - * association with the server. The request payload specifies the protocol - * identifier for the requested tunnel, a manufacturer code in case of proprietary - * protocols and the use of flow control for streaming protocols. - * @see zb_zcl_tunneling_request_tunnel_s - */ - - ZB_ZCL_TUNNELING_CLI_CMD_CLOSE_TUNNEL = 0x01, /**< @brief Client command used to close the tunnel with the server. The parameter - * in the payload specifies the tunnel identifier of the tunnel that has to be - * closed. The server leaves the tunnel open and the assigned resources allocated - * until the client sends the @e CloseTunnel command or the @e CloseTunnelTimeout - * fires. - * @see zb_zcl_tunneling_close_tunnel_s - */ - - ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA = 0x02, /**< @brief Command that indicates (if received) that the client has sent data - * to the server. The data itself is contained within the payload. - * @see zb_zcl_tunneling_transfer_data_payload_s - */ - - ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA_ERROR = 0x03, /**< @brief This command is generated by the receiver of a @e TransferData command - * if the tunnel status indicates that something is wrong. - * @details There are three cases in which @e TransferDataError is sent:\n - *
    - *
  • The @e TransferData received contains a TunnelID that does not match to any - * of the active tunnels of the receiving device. This could happen if a - * (sleeping) device sends a @e TransferData command to a tunnel that has been - * closed by the server after the @e CloseTunnelTimeout. - *
  • - *
  • The @e TransferData received contains a proper TunnelID of an active - * tunnel, but the device sending the data does not match to it. - *
  • - *
  • The @e TransferData received contains more data - * @e MaximumIncomingTransferSize of the receiving device. - *
  • - *
- * @see zb_zcl_tunneling_transfer_data_error_s - */ - - ZB_ZCL_TUNNELING_CLI_CMD_ACK_TRANSFER_DATA = 0x04, /**< Command sent in response to each TransferData command - * in case – and only in case – flow control has been - * requested by the client in the TunnelRequest command and - * is supported by both tunnel endpoints. The response - * payload indicates the number of octets that may still be - * received by the receiver. - * @see zb_zcl_tunneling_ack_transfer_data_s - */ - - ZB_ZCL_TUNNELING_CLI_CMD_READY_DATA = 0x05, /**< The ReadyData command is generated – after a receiver - * had to stop the dataflow using the AckTransferData(0) - * command – to indicate that the device is now ready to - * continue receiving data. The parameter NumberOfOctetsLeft - * gives a hint on how much space is left for the next - * data transfer. The ReadyData command is only issued if - * flow control is enabled. - * @see zb_zcl_tunneling_ready_data_s - */ - - ZB_ZCL_TUNNELING_CLI_CMD_GET_SUPPORTED_TUNNEL_PROTOCOLS = 0x06, /**< Get Supported Tunnel Protocols is the client command - * used to determine the tunnel protocols supported on another device. - * @see zb_zcl_tunneling_get_supported_tunnel_protocols_s - */ -}; - - -/** @brief Tunnel cluster commands generated - * @see SE spec, subclause D.6.2.5 - */ -enum zb_zcl_tunneling_srv_cmd_e -{ - ZB_ZCL_TUNNELING_SRV_CMD_REQUEST_TUNNEL_RESPONSE = 0x00, /**< @brief @e RequestTunnelResponse is sent by the server in response to a @e RequestTunnel - * command previously received from the client. The response contains the - * status of the @e RequestTunnel command and a tunnel identifier corresponding - * to the tunnel that has been set-up in the server in case of success. - * @see zb_zcl_tunneling_request_tunnel_response_s - */ - - ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA = 0x01, /**< @brief Command that transfers data from server to the client. The data - * itself has to be placed within the payload. - * @see zb_zcl_tunneling_transfer_data_payload_s - */ - - ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA_ERROR = 0x02, /**< @copydoc ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA_ERROR */ - - ZB_ZCL_TUNNELING_SRV_CMD_ACK_TRANSFER_DATA = 0x03, /**< @copydoc ZB_ZCL_TUNNELING_CLI_CMD_ACK_TRANSFER_DATA */ - - ZB_ZCL_TUNNELING_SRV_CMD_READY_DATA = 0x04, /**< @copydoc ZB_ZCL_TUNNELING_CLI_CMD_READY_DATA */ - - ZB_ZCL_TUNNELING_SRV_CMD_SUPPORTED_TUNNEL_PROTOCOLS_RESPONSE = 0x05, /**< Supported Tunnel Protocols Response is sent - * in response to a Get Supported Tunnel Protocols - * command previously received. The response contains - * a list of tunnel protocols supported by the device; - * the payload of the response should be capable of - * holding up to 16 protocols. - * @see zb_zcl_tunneling_supported_tunnel_protocols_response_s - */ - - ZB_ZCL_TUNNELING_SRV_CMD_TUNNEL_CLOSURE_NOTIFICATION = 0x06, /**< TunnelClosureNotification is sent by the server - * to indicate that a tunnel has been closed due to - * expiration of a CloseTunnelTimeout. - * @see zb_zcl_tunneling_tunnel_closure_notification_s - */ -}; - -/** @cond internals_doc */ -/* TUNNELING cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_TUNNELING_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_TUNNELING_SRV_CMD_REQUEST_TUNNEL_RESPONSE, \ - ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA, \ - ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA_ERROR - -#define ZB_ZCL_CLUSTER_ID_TUNNELING_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_TUNNELING_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_TUNNELING_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL, \ - ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA, \ - ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA_ERROR, \ - ZB_ZCL_TUNNELING_CLI_CMD_CLOSE_TUNNEL - -#define ZB_ZCL_CLUSTER_ID_TUNNELING_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_TUNNELING_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/** @brief @e TunnelStatus parameter values. - * @see SE spec, Table D-127 - * @see @ref ZB_ZCL_TUNNELING_SRV_CMD_REQUEST_TUNNEL_RESPONSE "RequestTunnelResponse" - * @see zb_zcl_tunneling_request_tunnel_response_s::tunnel_status - */ -enum zb_zcl_tunneling_tunnel_status_e -{ - - ZB_ZCL_TUNNELING_STATUS_SUCCESS = 0, /**< The tunnel has been opened and may now be used to transfer data in - * both directions. - */ - - ZB_ZCL_TUNNELING_STATUS_BUSY = 1, /**< The server is busy and cannot create a new tunnel at the moment. - * The client may try again after a recommended timeout of 3 minutes. - */ - - ZB_ZCL_TUNNELING_STATUS_NO_MORE_IDS = 2, /**< The server has no more resources to setup requested tunnel. Clients - * should close any open tunnels before retrying. - */ - - ZB_ZCL_TUNNELING_STATUS_PROTOCOL_NOT_SUPPORTED = 3, /**< The server does not support the protocol that has been requested - * in the ProtocolID parameter of the RequestTunnel command. - */ - - ZB_ZCL_TUNNELING_STATUS_FLOW_CONTROL_NOT_SUPPORTED = 4, /**< Flow control has been requested by the client in the RequestTunnel - * command but cannot be provided by the server (missing resources or no - * support). - */ -}; - - -/** @brief @e TransferDataStatus parameter values. - * @see SE spec, Table D-125 - * @see zb_zcl_tunneling_transfer_data_error_t::transfer_data_status - */ -enum zb_zcl_tunneling_transfer_data_status_e -{ - - /** @brief The @e TransferData command contains a @e TunnelID of a non-existent - * tunnel. - */ - ZB_ZCL_TUNNELING_TRANSFER_DATA_STATUS_NO_SUCH_TUNNEL = 0x00, - - /** @brief The @e TransferData command contains a @e TunnelID that does not match the - * device sending the data. - */ - ZB_ZCL_TUNNELING_TRANSFER_DATA_STATUS_WRONG_DEVICE = 0x01, - - /** @brief The @e TransferData command contains more data than indicated by the - * @e MaximumIncomingTransferSize of the receiving device - */ - ZB_ZCL_TUNNELING_TRANSFER_DATA_STATUS_DATA_OVERFLOW = 0x02, - - /* Custom Internal Error status */ - ZB_ZCL_TUNNELING_TRANSFER_DATA_INTERNAL_ERROR = 0xFE, - - /* Custom OK status (does not sent in pkt) */ - ZB_ZCL_TUNNELING_TRANSFER_DATA_STATUS_OK = 0xFF, -}; - -/** @brief Tunneling @e ProtocolID Enumerations - * @see SE spec, subclause D.6.2.4.1.2, Table D-124 - * @see @ref ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL "RequestTunnel" - * @see zb_zcl_tunneling_request_tunnel_s::protocol_id - */ -typedef enum zb_zcl_tunneling_protocol_id_e -{ - ZB_ZCL_TUNNELING_PROTOCOL_DLMS_COSEM = 0, /**< DLMS/COSEM (IEC 62056) */ - ZB_ZCL_TUNNELING_PROTOCOL_IEC_61107 = 1, /**< IEC 61107 */ - ZB_ZCL_TUNNELING_PROTOCOL_ANSI_C12 = 2, /**< ANSI C12 */ - ZB_ZCL_TUNNELING_PROTOCOL_M_BUS = 3, /**< M-BUS */ - ZB_ZCL_TUNNELING_PROTOCOL_SML = 4, /**< SML */ - ZB_ZCL_TUNNELING_PROTOCOL_CLIMATE_TALK = 5, /**< ClimateTalk */ - ZB_ZCL_TUNNELING_PROTOCOL_GB_HRGP = 6, /**< GB-HRGP */ - ZB_ZCL_TUNNELING_PROTOCOL_IPv4 = 7, /**< IP v4 */ - ZB_ZCL_TUNNELING_PROTOCOL_IPv6 = 8, /**< IP v6 */ - /* 9 to 199 reserved for future growth */ - ZB_ZCL_TUNNELING_PROTOCOL_MANUFACTURER_DEFINED = 200, /**< 200 to 254 manufacturer-defined protocols */ - ZB_ZCL_TUNNELING_PROTOCOL_RESERVED = 255 /**< reserved value */ -} zb_zcl_tunneling_protocol_id_t; - -/************* Tunnel cluster command structures **************/ - -/** @brief @ref ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL "RequestTunnel" command payload - * @see SE spec, subclause D.6.2.4.1.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_request_tunnel_s -{ - - /** @brief An enumeration representing the identifier of the metering - * communication protocol for which the tunnel is requested. - * @see zb_zcl_tunneling_protocol_id_e - */ - zb_uint8_t protocol_id; /* (M) */ - - /** @brief A code that is allocated by the Zigbee Alliance, relating the - * manufacturer to a device and – for the tunneling - a manufacturer specific - * protocol. The parameter is ignored when the @e ProtocolID value is less than 200. - * This allows for 55 manufacturer-defined protocols for each manufacturer to - * be defined. A value of 0xFFFF indicates that the Manufacturer Code is not used. - */ - zb_uint16_t manufacturer_code; /* (M) */ - - /** @brief A boolean type parameter that indicates whether flow control support - * is requested from the tunnel (ZB_TRUE) or not (ZB_FALSE). The default value is - * FALSE (no flow control). - */ - zb_bool_t flow_control_support; /* (M) */ - - /** @brief A value that defines the size, in octets, of the maximum data packet - * that can be transferred to the client in the payload of a single - * @e TransferData command. - */ - zb_uint16_t max_incoming_transfer_size; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_tunneling_request_tunnel_t; - - -void zb_zcl_tunneling_set_max_incoming_to_cli_transfer_size(zb_uint16_t transfer_size); - - -/** @def ZB_ZCL_TUNNELING_SEND_REQUEST_TUNNEL - * @brief Send @ref ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL "RequestTunnel" command - * @param _param - Reference to buffer. - * @param _addr - Address of the device to send command to. - * @param _dst_addr_mode - Address mode for _dst_addr. - * @param _dst_ep - Destination endpoint. - * @param _ep - Current endpoint. - * @param _prfl_id - profile identifier - * @param _def_resp - enable/disable default zcl response - * @param _cb - Callback which should be called when the ZCL stack receives - * APS ack. - * @param _protocol_id - @ref zb_zcl_tunneling_request_tunnel_t::protocol_id value - * @param _manufacturer_code - @ref zb_zcl_tunneling_request_tunnel_t::manufacturer_code value - * @param _flow_control_support - @ref zb_zcl_tunneling_request_tunnel_t::flow_control_support value - * @param _max_incoming_transfer_size - @ref zb_zcl_tunneling_request_tunnel_t::max_incoming_transfer_size value - * @par Usage - * @n Example of sending @ref ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL "RequestTunnel" command - */ -#define ZB_ZCL_TUNNELING_SEND_REQUEST_TUNNEL( \ - _param, _addr, _dst_addr_mode, _dst_ep, _ep, _prfl_id, _def_resp, _cb, \ - _protocol_id, _manufacturer_code, _flow_control_support, \ - _max_incoming_transfer_size) \ -{ \ - zb_zcl_tunneling_set_max_incoming_to_cli_transfer_size( \ - _max_incoming_transfer_size); \ - { \ - zb_bufid_t _buffer = _param; \ - zb_uint8_t* __ptr = zb_zcl_start_command_header(_buffer, \ - ZB_ZCL_CONSTRUCT_FRAME_CONTROL(ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, (_def_resp)), \ - 0, /* No manuf_code */ \ - ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL, NULL); \ - ZB_ZCL_PACKET_PUT_DATA8(__ptr, (_protocol_id)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(__ptr, (_manufacturer_code)); \ - ZB_ZCL_PACKET_PUT_DATA8(__ptr, (_flow_control_support)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(__ptr, (_max_incoming_transfer_size)); \ - ZB_ZCL_FINISH_PACKET(_buffer, __ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - _buffer, (_addr), (_dst_addr_mode), (_dst_ep), (_ep), (_prfl_id), \ - ZB_ZCL_CLUSTER_ID_TUNNELING, (_cb)); \ - } \ -} - - -/** @brief Macro for parsing payload of @ref ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL "RequestTunnel" command - * @param _data_ptr - pointer to @ref zb_zcl_tunneling_request_tunnel_t structure - * @param _buffer - pointer to buffer where @e RequestTunnel command's payload is stored. - * @param _status - status of payload parsing - */ -#define ZB_ZCL_TUNNELING_GET_REQUEST_TUNNEL(_data_ptr, _buffer, _status) \ -{ \ - zb_zcl_tunneling_request_tunnel_t *src_ptr = \ - (zb_zcl_tunneling_request_tunnel_t*)zb_buf_begin((_buffer)); \ - \ - if (zb_buf_len((_buffer)) < sizeof(zb_zcl_tunneling_request_tunnel_t)) \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - (_data_ptr)->protocol_id = src_ptr->protocol_id; \ - ZB_HTOLE16(&(_data_ptr)->manufacturer_code, &(src_ptr->manufacturer_code)); \ - (_data_ptr)->flow_control_support = src_ptr->flow_control_support; \ - ZB_HTOLE16(&(_data_ptr)->max_incoming_transfer_size, \ - &(src_ptr->max_incoming_transfer_size)); \ - } \ -} - - -/** - * @brief @ref ZB_ZCL_TUNNELING_CLI_CMD_CLOSE_TUNNEL "CloseTunnel" command payload - * @see SE spec, subclause D.6.2.4.2.2. - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_close_tunnel_s -{ - /** @brief The identifier of the tunnel that shall be closed. It is the same number - * that has been previously returned in the response to a @ref ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL "RequestTunnel" command. - * Valid numbers range between 0..65535 and must correspond to a tunnel that is - * still active and maintained by the server. - */ - zb_uint16_t tunnel_id; -} -ZB_PACKED_STRUCT -zb_zcl_tunneling_close_tunnel_t; - - -/** @brief @ref ZB_ZCL_TUNNELING_CLI_CMD_CLOSE_TUNNEL "CloseTunnel" command - * @param _param - Reference to buffer. - * @param _addr - Address of the device to send command to. - * @param _dst_addr_mode - Address mode for _dst_addr. - * @param _dst_ep - Destination endpoint. - * @param _ep - Current endpoint. - * @param _prfl_id - profile identifier - * @param _def_resp - enable/disable default zcl response - * @param _cb - Callback which should be called when the ZCL stack receives - * APS ack. - * @param _tunnel_id - @ref zb_zcl_tunneling_close_tunnel_t::tunnel_id value - * @par Usage - * @n Example of sending @ref ZB_ZCL_TUNNELING_CLI_CMD_CLOSE_TUNNEL "CloseTunnel" command - */ -#define ZB_ZCL_TUNNELING_SEND_CLOSE_TUNNEL( \ - _param, _addr, _dst_addr_mode, _dst_ep, _ep, _prfl_id, _def_resp, _cb, \ - _tunnel_id) \ -{ \ - zb_bufid_t _buffer = _param; \ - zb_uint8_t* __ptr = zb_zcl_start_command_header(_buffer, \ - ZB_ZCL_CONSTRUCT_FRAME_CONTROL(ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, (_def_resp)), \ - 0, /* No manuf_code */ \ - ZB_ZCL_TUNNELING_CLI_CMD_CLOSE_TUNNEL, NULL); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(__ptr, (_tunnel_id)); \ - ZB_ZCL_FINISH_PACKET(_buffer, __ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - _buffer, (_addr), (_dst_addr_mode), (_dst_ep), (_ep), (_prfl_id), \ - ZB_ZCL_CLUSTER_ID_TUNNELING, (_cb)); \ -} - - -/** @brief Macro for parsing payload of @ref ZB_ZCL_TUNNELING_CLI_CMD_CLOSE_TUNNEL "CloseTunnel" command - * @param _data_ptr - pointer to @ref zb_zcl_tunneling_close_tunnel_t structure - * @param _buffer - pointer to buffer where @e CloseTunnel command's payload is stored. - * @param _status - status of payload parsing - */ -#define ZB_ZCL_TUNNELING_GET_CLOSE_TUNNEL(_data_ptr, _buffer, _status) \ -{ \ - zb_zcl_tunneling_close_tunnel_t *src_ptr = \ - (zb_zcl_tunneling_close_tunnel_t*)zb_buf_begin((_buffer)); \ - \ - if (zb_buf_len((_buffer)) < sizeof(zb_zcl_tunneling_close_tunnel_t)) \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&(_data_ptr)->tunnel_id, &(src_ptr->tunnel_id)); \ - } \ -} - - -/** - * @brief @e TransferData commands header data. - * @see SE spec, subclause D.6.2.4.3.2 - * @see @ref zb_zcl_tunneling_transfer_data_payload_t::hdr - * @see @ref ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA "TransferData" client command - * @see @ref ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA "TransferData" server command - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_transfer_data_hdr_s -{ - /** @brief number between 0..65535 that uniquely identifies the tunnel that has - * been allocated in the server triggered through the RequestTunnel command. - * This ID must be used to send data through the tunnel or passed with any - * commands concerning that specific tunnel. - */ - zb_uint16_t tunnel_id; -} -ZB_PACKED_STRUCT -zb_zcl_tunneling_transfer_data_hdr_t; - - -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_srv_rec_s -{ - zb_uint16_t dst_addr; - zb_uint8_t dst_ep; - zb_uint8_t src_ep; - /** */ - zb_zcl_tunneling_request_tunnel_t tunnel_options; - zb_uint16_t close_tunnel_timeout; - zb_uint16_t max_incoming_to_srv_transfer_size; -} -ZB_PACKED_STRUCT zb_zcl_tunneling_srv_rec_t; - - -typedef ZB_PACKED_PRE struct zb_zcl_tunnel_request_params_out_s -{ - zb_uint8_t tunnel_status; - zb_uint16_t max_incoming_to_srv_transfer_size; -} ZB_PACKED_STRUCT zb_zcl_tunnel_request_params_out_t; - - -/** @brief @e TransferData payload. - * This structure presents custom implementation of Transfer Data command payload defined in SE spec. - * @see SE spec, subclause D.6.2.4.3.2 and D.6.2.5.2 - * @see @ref ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA "TransferData" client command - * @see @ref ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA "TransferData" server command - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_transfer_data_payload_s -{ - - /** @ref zb_zcl_tunneling_transfer_data_hdr_t - */ - zb_zcl_tunneling_transfer_data_hdr_t hdr; - - /** Size of @ref tun_data */ - zb_uint8_t data_size; - - /** @brief Octet containing the data to be transferred through the tunnel in - * the format of the communication protocol for which the tunnel has been - * requested and opened. The payload contains the assembled data exactly as it - * was sent by the client. Theoretically, its length is solely limited through - * the fragmentation algorithm and the RX/TX transfer buffer sizes within the - * communication partners. The content of the payload is up to the application - * sending the data. It is neither guaranteed, that it contains a complete PDU - * nor is any other assumption on its internal format made. This is left up to - * the implementer of the specific protocol tunnel behavior. - */ - zb_uint8_t *tun_data; -} -ZB_PACKED_STRUCT -zb_zcl_tunneling_transfer_data_payload_t; - -/** @cond internals_doc */ -zb_ret_t zb_zcl_tunneling_client_send_transfer_data(zb_uint8_t param, zb_uint8_t ep, zb_uint16_t prfl_id, - zb_uint8_t def_resp, zb_callback_t cb, zb_uint16_t tunnel_id, - zb_uint16_t data_size, zb_uint8_t *image_data); -zb_ret_t zb_zcl_tunneling_server_send_transfer_data(zb_uint8_t param, zb_uint8_t ep, zb_uint16_t prfl_id, - zb_uint8_t def_resp, zb_callback_t cb, zb_uint16_t tunnel_id, - zb_uint16_t data_size, zb_uint8_t *image_data); - -/** @endcond */ /* internal_doc */ - -/*! Send @e TransferData command from Tunneling server to client - * @param _param - Reference to buffer. - * @param _ep - Current endpoint. - * @param _prfl_id - profile identifier - * @param _def_resp - enable/disable default zcl response - * @param _cb - Callback which should be called when the ZCL stack receives - * APS ack. - * @param _tunnel_id - @ref zb_zcl_tunneling_transfer_data_hdr_t::tunnel_id value - * @param _data_size - @ref zb_zcl_tunneling_transfer_data_payload_t::data_size value - * @param _image_data - tun_data from @ref zb_zcl_tunneling_transfer_data_payload_t::tun_data value - * @par Usage - * @n Example of sending @e TransferData command - * @see @ref ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA "TransferData" server command - */ -#define ZB_ZCL_TUNNELING_SERVER_SEND_TRANSFER_DATA( \ - _param, _ep, _prfl_id, _def_resp, _cb, \ - _tunnel_id, _data_size, _image_data) \ - zb_zcl_tunneling_server_send_transfer_data(_param, _ep, _prfl_id, _def_resp, _cb, \ - _tunnel_id, _data_size, _image_data) - -/*! Send @e TransferData command from Tunneling client to server - * @param _param - Reference to buffer. - * @param _ep - Current endpoint. - * @param _prfl_id - profile identifier - * @param _def_resp - enable/disable default zcl response - * @param _cb - Callback which should be called when the ZCL stack receives - * APS ack. - * @param _tunnel_id - @ref zb_zcl_tunneling_transfer_data_hdr_t::tunnel_id value - * @param _data_size - @ref zb_zcl_tunneling_transfer_data_payload_t::data_size value - * @param _image_data - tun_data from @ref zb_zcl_tunneling_transfer_data_payload_t::tun_data value - * @par Usage - * @n Example of sending @e TransferData command - * @see @ref ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA "TransferData" client command - */ -#define ZB_ZCL_TUNNELING_CLIENT_SEND_TRANSFER_DATA( \ - _param, _ep, _prfl_id, _def_resp, _cb, \ - _tunnel_id, _data_size, _image_data) \ - zb_zcl_tunneling_client_send_transfer_data(_param, _ep, _prfl_id, _def_resp, _cb, \ - _tunnel_id, _data_size, _image_data) - -/** @brief Macro for parsing payload of @e TransferData command - * @param _data_ptr - pointer to @ref zb_zcl_tunneling_transfer_data_payload_t structure - * @param _buffer - pointer to buffer where @e TransferData command's payload is stored. - * @param _status - status of payload parsing - * @see @ref ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA "TransferData" client command - * @see @ref ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA "TransferData" server command - */ -#define ZB_ZCL_TUNNELING_GET_TRANSFER_DATA(_data_ptr, _buffer, _status) \ -{ \ - zb_uint8_t *src_ptr = (zb_uint8_t*)zb_buf_begin((_buffer)); \ - \ - if (zb_buf_len((_buffer)) < sizeof(zb_zcl_tunneling_transfer_data_hdr_t)) \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&(_data_ptr)->hdr.tunnel_id, src_ptr); \ - (_data_ptr)->data_size = zb_buf_len((_buffer)) - \ - sizeof(zb_zcl_tunneling_transfer_data_hdr_t); \ - (_data_ptr)->tun_data = (zb_uint8_t*)(src_ptr + \ - sizeof(zb_zcl_tunneling_transfer_data_hdr_t)); \ - } \ -} - - -/** @brief @e TransferDataError command payload - * @see SE spec, subclause D.6.2.4.4.2 - * @see Client @ref ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA_ERROR "TransferDataError" command - * @see Server @ref ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA_ERROR "TransferDataError" command - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_transfer_data_error_s -{ - - /** @brief A number between 0..65535 that uniquely identifies the tunnel that - * has been allocated in the server triggered through the RequestTunnel command. - * This ID must be used for the data transfer through the tunnel or passed with - * any commands concerning that specific tunnel. - */ - zb_uint16_t tunnel_id; - - /** @brief The @e TransferDataStatus parameter indicates the error that occurred - * within the receiver after the last @e TransferData command. - * @see zb_zcl_tunneling_transfer_data_status_e - */ - zb_uint8_t transfer_data_status; -} -ZB_PACKED_STRUCT zb_zcl_tunneling_transfer_data_error_t; - - -/*! @brief Send client @ref ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA_ERROR "TransferDataError" command and - * server @ref ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA_ERROR "TransferDataError" command - * @param _buffer - pointer to buffer. - * @param _addr - Address of the device to send command to. - * @param _dst_addr_mode - Address mode for _dst_addr. - * @param _dst_ep - Destination endpoint. - * @param _ep - Current endpoint. - * @param _prfl_id - profile identifier - * @param _def_resp - enable/disable default zcl response - * @param _cb - Callback which should be called when the ZCL stack receives - * APS ack. - * @param _seq_num - ZCL transaction sequence number - * @param _tunnel_id - @ref zb_zcl_tunneling_transfer_data_error_t::tunnel_id value - * @param _transfer_data_status - @ref zb_zcl_tunneling_transfer_data_error_t::transfer_data_status value - * @param _command_id - Tunneling cluster's command identifier. - * @param _direction - command direction. - */ -#define ZB_ZCL_TUNNELING_SEND_TRANSFER_DATA_ERROR( \ - _buffer, _addr, _dst_addr_mode, _dst_ep, _ep, _prfl_id, _def_resp, _cb, _seq_num, \ - _tunnel_id, _transfer_data_status, _command_id, _direction) \ -{ \ - zb_uint8_t* __ptr = ZB_ZCL_START_PACKET((_buffer)); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(__ptr, \ - _direction, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(__ptr, _seq_num, _command_id); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(__ptr, (_tunnel_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(__ptr, (_transfer_data_status)); \ - ZB_ZCL_FINISH_PACKET((_buffer), __ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - (_buffer), (_addr), (_dst_addr_mode), (_dst_ep), (_ep), (_prfl_id), \ - ZB_ZCL_CLUSTER_ID_TUNNELING, (_cb)); \ -} - - -/** @brief Macro for parsing payload of @e TransferDataError command - * @param _data_ptr - pointer to @ref zb_zcl_tunneling_transfer_data_error_t structure - * @param _buffer - pointer to buffer where @e TransferDataError command's payload is stored. - * @param _status - status of payload parsing - * @see @ref ZB_ZCL_TUNNELING_CLI_CMD_TRANSFER_DATA_ERROR "TransferDataError" client command - * @see @ref ZB_ZCL_TUNNELING_SRV_CMD_TRANSFER_DATA_ERROR "TransferDataError" server command - */ -#define ZB_ZCL_TUNNELING_GET_TRANSFER_DATA_ERROR(_data_ptr, _buffer, _status) \ -{ \ - zb_zcl_tunneling_transfer_data_error_t *src_ptr = \ - (zb_zcl_tunneling_transfer_data_error_t*)zb_buf_begin((_buffer)); \ - \ - if (zb_buf_len((_buffer)) < sizeof(zb_zcl_tunneling_transfer_data_error_t)) \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&(_data_ptr)->tunnel_id, &(src_ptr->tunnel_id)); \ - (_data_ptr)->transfer_data_status = src_ptr->transfer_data_status; \ - } \ -} - - -/** @brief @ref ZB_ZCL_TUNNELING_SRV_CMD_REQUEST_TUNNEL_RESPONSE "RequestTunnelResponse" command payload - * @see SE spec, subclause D.6.2.5.1.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_request_tunnel_response_s -{ - - /** @brief A number between 0..65535 that uniquely identifies the tunnel that - * has been allocated in the server triggered through the @ref ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL "RequestTunnel" - * command. - * This ID must now be used to send data through this tunnel (@e TunnelID, - * @e TransferData) and is also required to close the tunnel again (@ref ZB_ZCL_TUNNELING_CLI_CMD_CLOSE_TUNNEL "CloseTunnel"). - * If the command has failed, the @e TunnelStatus contains the reason of the error - * and the @e TunnelID is set to 0xFFFF. - */ - zb_uint16_t tunnel_id; - - /** @brief The @e TunnelStatus parameter indicates the server’s internal status - * after the execution of a @ref ZB_ZCL_TUNNELING_CLI_CMD_REQUEST_TUNNEL "RequestTunnel" command. - * @see @ref zb_zcl_tunneling_tunnel_status_e - */ - zb_uint8_t tunnel_status; - - /** @brief A value that defines the size, in octets, of the maximum data packet - * that can be transferred to the server in the payload of a single @e TransferData command. - */ - zb_uint16_t max_incoming_transfer_size; -} -ZB_PACKED_STRUCT zb_zcl_tunneling_request_tunnel_response_t; - - -/** @brief Macro for sending @ref ZB_ZCL_TUNNELING_SRV_CMD_REQUEST_TUNNEL_RESPONSE "RequestTunnelResponse" command - * @param _param - Reference to buffer. - * @param _addr - Address of the device to send command to. - * @param _dst_addr_mode - Address mode for _dst_addr. - * @param _dst_ep - Destination endpoint. - * @param _ep - Current endpoint. - * @param _prfl_id - profile identifier - * @param _def_resp - enable/disable default zcl response - * @param _seq_num - ZCL transaction sequence number - * @param _cb - Callback which should be called when the ZCL stack receives - * APS ack. - * @param _tunnel_id - @ref zb_zcl_tunneling_request_tunnel_response_t::tunnel_id value - * @param _tunnel_status - @ref zb_zcl_tunneling_request_tunnel_response_t::tunnel_status value - * @param _max_incoming_transfer_size - @ref zb_zcl_tunneling_request_tunnel_response_t::max_incoming_transfer_size value - * - */ -#define ZB_ZCL_TUNNELING_SEND_REQUEST_TUNNEL_RESPONSE( \ - _param, _addr, _dst_addr_mode, _dst_ep, _ep, _prfl_id, _def_resp, _seq_num, _cb, \ - _tunnel_id, _tunnel_status, _max_incoming_transfer_size) \ -{ \ - zb_bufid_t _buffer = _param; \ - zb_uint8_t* __ptr = ZB_ZCL_START_PACKET(_buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(__ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, \ - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(__ptr, _seq_num, ZB_ZCL_TUNNELING_SRV_CMD_REQUEST_TUNNEL_RESPONSE); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(__ptr, (_tunnel_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(__ptr, (_tunnel_status)); \ - ZB_ZCL_PACKET_PUT_DATA16_VAL(__ptr, (_max_incoming_transfer_size)); \ - ZB_ZCL_FINISH_PACKET(_buffer, __ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - _buffer, (_addr), (_dst_addr_mode), (_dst_ep), (_ep), (_prfl_id), \ - ZB_ZCL_CLUSTER_ID_TUNNELING, (_cb)); \ -} - - -/** @brief Macro for parsing payload of @ref ZB_ZCL_TUNNELING_SRV_CMD_REQUEST_TUNNEL_RESPONSE "RequestTunnelResponse" command - * @param _data_ptr - pointer to @ref zb_zcl_tunneling_request_tunnel_response_t structure - * @param _buffer - pointer to buffer where @e RequestTunnelResponse command's payload is stored. - * @param _status - status of payload parsing - */ -#define ZB_ZCL_TUNNELING_GET_REQUEST_TUNNEL_RESPONSE(_data_ptr, _buffer, _status) \ -{ \ - zb_zcl_tunneling_request_tunnel_response_t *src_ptr = \ - (zb_zcl_tunneling_request_tunnel_response_t*)zb_buf_begin((_buffer)); \ - \ - if (zb_buf_len((_buffer)) < sizeof(zb_zcl_tunneling_request_tunnel_response_t)) \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ - else \ - { \ - (_status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - ZB_HTOLE16(&(_data_ptr)->tunnel_id, &(src_ptr->tunnel_id)); \ - (_data_ptr)->tunnel_status = src_ptr->tunnel_status; \ - ZB_HTOLE16(&(_data_ptr)->max_incoming_transfer_size, \ - &(src_ptr->max_incoming_transfer_size)); \ - } \ -} - - -/** @e AckTransferData command payload. - * @see SE spec, subclause D.6.2.4.5.2. - * @see Client @ref ZB_ZCL_TUNNELING_CLI_CMD_ACK_TRANSFER_DATA "AckTransferData" command - * @see Server @ref ZB_ZCL_TUNNELING_SRV_CMD_ACK_TRANSFER_DATA "AckTransferData" command - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_ack_transfer_data_s -{ - - /** A number between 0..65535 that uniquely identifies the tunnel that has been allocated - * in the server triggered through the @e RequestTunnel command. - */ - zb_uint16_t tunnel_id; /* (M) */ - - /** Indicates the number of bytes that may still be received by the initiator of this command. - */ - zb_uint16_t number_of_bytes_left; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_tunneling_ack_transfer_data_t; - - -/** @e ReadyData command payload - * @see SE spec, subclause D.6.2.4.6.2 - * @see Client @ref ZB_ZCL_TUNNELING_CLI_CMD_READY_DATA "ReadyData" command - * @see Server @ref ZB_ZCL_TUNNELING_CLI_CMD_READY_DATA "ReadyData" command - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_ready_data_s -{ - - /** A number between 0..65535 that uniquely identifies the tunnel that has - * been allocated in the server triggered through the @e RequestTunnel command. - */ - zb_uint16_t tunnel_id; /* (M) */ - - /** Indicates the number of octets that may be received by the initiator of this - * command (receiver). It is most likely the remaining size of the buffer holding - * the data that is sent over @e TransferData. - */ - zb_uint16_t number_of_octets_left; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_tunneling_ready_data_t; - - -/** @ref ZB_ZCL_TUNNELING_CLI_CMD_GET_SUPPORTED_TUNNEL_PROTOCOLS "GetSupportedTunnelProtocols" command payload - * @see SE spec, subclause D.6.2.4.7.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_get_supported_tunnel_protocols_s -{ - /** Where there are more protocols supported than can be returned in a single - * Supported @e TunnelProtocolsResponse command, this field allows an offset - * to be specified on subsequent @e GetSupportedTunnelProtocols commands - */ - zb_uint8_t protocol_offset; /* (O) */ -} ZB_PACKED_STRUCT zb_zcl_tunneling_get_supported_tunnel_protocols_t; - - -/** Supported Tunnel Protocols Response Command Protocol Fields - * @see SE spec, Figure D-112 - * @see zb_zcl_tunneling_supported_tunnel_protocols_response_t::protocols - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_protocol_field_s -{ - - /** A code that is allocated by the Zigbee Alliance, relating the manufacturer - * to a device and - for tunneling - a manufacturer specific protocol. - */ - zb_uint16_t manufacturer_code; - - /** An enumeration representing the identifier of the metering communication protocol - * for the supported tunnel. - * @see SE spec, Table D-124 - * @see zb_zcl_tunneling_protocol_id_t - */ - zb_uint8_t protocol_id; -} ZB_PACKED_STRUCT zb_zcl_tunneling_protocol_field_t; - - -/** @ref ZB_ZCL_TUNNELING_SRV_CMD_SUPPORTED_TUNNEL_PROTOCOLS_RESPONSE "SupportedTunnelProtocolResponse" - * command payload. - * @see SE spec, subclause D.6.2.5.6.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_supported_tunnel_protocols_response_s -{ - /** The Protocol List Complete field is a Boolean; a value of 0(ZB_FALSE) indicates that - * there are more supported protocols available (if more than 16 protocols are supported). - * A value of 1(ZB_TRUE) indicates that the list of supported protocols is complete. - */ - zb_uint8_t protocol_list_complete; - - /** The number of Protocol fields contained in the response. - */ - zb_uint8_t protocol_count; - - /** The payload of the response should be capable of holding up to 16 protocols. - * @see zb_zcl_tunneling_protocol_field_s - */ - zb_zcl_tunneling_protocol_field_t protocol_list[16]; -} ZB_PACKED_STRUCT zb_zcl_tunneling_supported_tunnel_protocols_response_t; - - -/** @ref ZB_ZCL_TUNNELING_SRV_CMD_TUNNEL_CLOSURE_NOTIFICATION "TunnelClosureNotification" - * command payload - * @see SE spec, subclause D.6.2.5.7.2 - */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_tunnel_closure_notification_s -{ - /** The identifier of the tunnel that has been closed. It is the same number - * that has been previously returned in the response to a @e RequestTunnel command. - */ - zb_uint16_t tunnel_id; /* (M) */ -} ZB_PACKED_STRUCT zb_zcl_tunneling_tunnel_closure_notification_t; - - -/*********************** Tunnel API **************************/ - -/** @cond internal_doc */ -typedef ZB_PACKED_PRE struct zb_zcl_tunneling_cli_s -{ - zb_uint16_t tunnel_id; - zb_uint16_t dst_addr; - zb_uint8_t dst_ep; - zb_uint16_t max_incoming_to_cli_transfer_size; - zb_uint16_t max_outgoing_to_srv_transfer_size; -} -ZB_PACKED_STRUCT -zb_zcl_tunneling_cli_t; - -extern zb_zcl_tunneling_cli_t tunneling_cli; - -/** @endcond */ /* internal_doc */ - -/*! @} */ /* ZB_ZCL_TUNNELING_COMMANDS */ - -/** @} */ /* addtogroup */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -/**************************** Tunnel internal **********************************/ - -void zb_zcl_tunneling_init_server(void); -void zb_zcl_tunneling_init_client(void); -#define ZB_ZCL_CLUSTER_ID_TUNNELING_SERVER_ROLE_INIT zb_zcl_tunneling_init_server -#define ZB_ZCL_CLUSTER_ID_TUNNELING_CLIENT_ROLE_INIT zb_zcl_tunneling_init_client - -#endif /* ZB_ZCL_TUNNELING_H */ diff --git a/zboss/development/include/zcl/zb_zcl_window_covering.h b/zboss/development/include/zcl/zb_zcl_window_covering.h deleted file mode 100644 index 1e4eb3497b..0000000000 --- a/zboss/development/include/zcl/zb_zcl_window_covering.h +++ /dev/null @@ -1,728 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Window Covering cluster definitions -*/ - -#ifndef ZB_ZCL_WINDOW_COVERING_H -#define ZB_ZCL_WINDOW_COVERING_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_WINDOW_COVERING - * @{ - * @details - * All commands in the cluster have request form only, and could be responded with Default - * Response command, if not disabled explicitly. - * - */ - -/** @name Window Covering cluster attributes - @{ -*/ - -/** @brief Window Covering Attribute Sets Identifiers - @see ZCL8 spec, Table 7-39 -*/ -enum zb_zcl_window_covering_attribute_sets_e -{ - /** @brief Window Covering Information attribute set */ - ZB_ZCL_WINDOW_COVERING_INFORMATION = 0x000, - /** @brief Window Covering Settings attribute set */ - ZB_ZCL_WINDOW_COVERING_SETTINGS = 0x001 -}; - -/** @brief Window Covering cluster information attribute set identifiers - @see ZCL8 spec, subclause 7.4.2.1.1 -*/ -enum zb_zcl_window_covering_info_attr_e -{ - /** @brief Window Covering Type attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_WINDOW_COVERING_TYPE_ID = 0x0000, - /** @brief PhysicalClosedLimit Lift attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_PHYSICAL_CLOSED_LIMIT_LIFT_ID = 0x0001, - /** @brief PhysicalClosedLimit Tilt attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_PHY_CLOSED_LIMIT_TILT_ID = 0x0002, - /** @brief CurrentPosition Lift attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID = 0x0003, - /** @brief CurrentPosition Tilt attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_ID = 0x0004, - /** @brief Number of Actuations Lift attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_NUMBER_OF_ACTUATIONS_LIFT_ID = 0x0005, - /** @brief Number of Actuations Tilt attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_NUMBER_OF_ACTUATIONS_TILT_ID = 0x0006, - /** @brief Config/Status attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID = 0x0007, - /** @brief Current Position Lift Percentage attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID = 0x0008, - /** @brief Current Position Tilt Percentage attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID = 0x0009 -}; - -/** @brief Permissible values for Type attribute - * @see ZCL8 spec, subclause 7.4.2.1.2 - */ -enum zb_zcl_window_covering_window_covering_type_e -{ - /** Rollershade value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_ROLLERSHADE = 0x00, - /** Rollershade - 2 Motor value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_ROLLERSHADE_2_MOTOR = 0x01, - /** Rollershade - Exterior value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_ROLLERSHADE_EXTERIOR = 0x02, - /** Rollershade - Exterior - 2 Motor value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_ROLLERSHADE_EXTERIOR_2_MOTOR = 0x03, - /** Drapery value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_DRAPERY = 0x04, - /** Awning value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_AWNING = 0x05, - /** Shutter value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_SHUTTER = 0x06, - /** Tilt Blind - Tilt Only value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_TILT_BLIND_TILT_ONLY = 0x07, - /** Tilt Blind - Lift and Tilt value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_TILT_BLIND_LIFT_AND_TILT = 0x08, - /** Projector screen value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_PROJECTOR_SCREEN = 0x09 -}; - -/** @brief Permissible values for Config/Status attribute - @see ZCL8 spec, subclause 7.4.2.1.2.7*/ -enum zb_zcl_window_covering_config_status_e -{ - /** Operational value */ - ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_OPERATIONAL = 0x01, - /** Online value */ - ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_ONLINE = 0x02, - /** Open/Up Commands have been reversed value */ - ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_REVERSE_COMMANDS = 0x04, - /** Lift control is Closed Loop value */ - ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_LIFT_CONTROL_IS_CLOSED_LOOP = 0x08, - /** Tilt control is Closed Loop value */ - ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_TILT_CONTROL_IS_CLOSED_LOOP = 0x10, - /** Lift Encoder Controlled value */ - ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_LIFT_ENCODER_CONTROLLED = 0x20, - /** Tilt Encoder Controlled value */ - ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_TILT_ENCODER_CONTROLLED = 0x40 -}; - -/** @brief Window covering cluster settings attribute set identifiers - @see ZCL8 spec, subclause 7.4.2.1.3 -*/ -enum zb_zcl_window_covering_settings_attr_e -{ - /** @brief InstalledOpenLimit - Lift attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID = 0x0010, - /** @brief InstalledClosedLimit - Lift attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_ID = 0x0011, - /** @brief InstalledOpenLimit - Tilt attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_TILT_ID = 0x0012, - /** @brief InstalledClosedLimit - Tilt attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_TILT_ID = 0x0013, - /** @brief Velocity - Lift attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_VELOCITY_ID = 0x0014, - /** @brief Acceleration Time - Lift attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_ACCELERATION_TIME_ID = 0x0015, - /** @brief Deceleration Time - Lift attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_DECELERATION_TIME_ID = 0x0016, - /** @brief Mode attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_MODE_ID = 0x0017, - /** @brief Intermediate Setpoints - Lift attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_INTERMEDIATE_SETPOINTS_LIFT_ID = 0x0018, - /** @brief Intermediate Setpoints - Tilt attribute */ - ZB_ZCL_ATTR_WINDOW_COVERING_INTERMEDIATE_SETPOINTS_TILT_ID = 0x0019 -}; - -/** @brief Permissible values for Mode attribute - @see ZCL8 spec, subclause 7.4.2.1.3.8*/ -enum zb_zcl_window_covering_mode_e -{ - /** Reversed motor direction value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_REVERSED_MOTOR_DIRECTION = 0x01, - /** Run in calibration mode value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_RUN_IN_CALIBRATION_MODE = 0x02, - /** Motor is running in maintenance mode value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_MOTOR_IS_RUNNING_IN_MAINTENANCE_MODE = 0x04, - /** LEDs will display feedback value */ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_LEDS_WILL_DISPLAY_FEEDBACK = 0x08 -}; - -/** @brief Default value for Window Covering cluster revision global attribute */ -#define ZB_ZCL_WINDOW_COVERING_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0003u) - -/** @brief Default value for PhysicalClosedLimitLift attribute */ -#define ZB_ZCL_WINDOW_COVERING_PHYSICAL_CLOSED_LIMIT_LIFT_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for PhyClosedLimitTilt attribute */ -#define ZB_ZCL_WINDOW_COVERING_PHY_CLOSED_LIMIT_TILT_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for CurrentPositionLift attribute */ -#define ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_LIFT_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for CurrentPositionTilt attribute */ -#define ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_TILT_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for NumberOfActuationsLift attribute */ -#define ZB_ZCL_WINDOW_COVERING_NUMBER_OF_ACTUATIONS_LIFT_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for NumberOfActuationsTilt attribute */ -#define ZB_ZCL_WINDOW_COVERING_NUMBER_OF_ACTUATIONS_TILT_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Window covering type attribute default value */ -#define ZB_ZCL_WINDOW_COVERING_WINDOW_COVERING_TYPE_DEFAULT_VALUE 0x00 - - -/** @brief Config/status attribute default value */ -#define ZB_ZCL_WINDOW_COVERING_CONFIG_STATUS_DEFAULT_VALUE \ - ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_OPERATIONAL \ - | ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_ONLINE - -/** @brief Current position lift percentage attribute default value */ -#define ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_DEFAULT_VALUE 0xff - -/** @brief Current position lift percentage attribute max value */ -#define ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_MAX_VALUE 0x64 - -/** @brief Current position tilt percentage attribute default value */ -#define ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_DEFAULT_VALUE 0xff - -/** @brief Current position tilt percentage attribute max value */ -#define ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_MAX_VALUE 0x64 - -/** @brief Installed open limit lift attribute default value */ -#define ZB_ZCL_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_DEFAULT_VALUE 0x0000 - -/** @brief Installed closed limit lift attribute default value */ -#define ZB_ZCL_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_DEFAULT_VALUE 0xffff - -/** @brief Installed open limit tilt attribute default value */ -#define ZB_ZCL_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_TILT_DEFAULT_VALUE 0x0000 - -/** @brief Installed closed limit tilt attribute default value */ -#define ZB_ZCL_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_TILT_DEFAULT_VALUE 0xffff - -/** @brief Default value for Velocity attribute */ -#define ZB_ZCL_WINDOW_COVERING_VELOCITY_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for AccelerationTime attribute */ -#define ZB_ZCL_WINDOW_COVERING_ACCELERATION_TIME_DEFAULT_VALUE ((zb_uint16_t)0x0000) - -/** @brief Default value for DecelerationTime attribute */ -#define ZB_ZCL_WINDOW_COVERING_DECELERATION_TIME_DEFAULT_VALUE ((zb_uint16_t)0x0000) - - -/** @brief Mode attribute default value */ -#define ZB_ZCL_WINDOW_COVERING_MODE_DEFAULT_VALUE \ - ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_MOTOR_IS_RUNNING_IN_MAINTENANCE_MODE - -/** @brief Default value for IntermediateSetpointsLift attribute */ -#define ZB_ZCL_WINDOW_COVERING_INTERMEDIATE_SETPOINTS_LIFT_DEFAULT_VALUE {0x31, 0x2C, 0x30, 0x78, 0x30, 0x30, 0x30, 0x30, 0x00} - -/** @brief Default value for IntermediateSetpointsTilt attribute */ -#define ZB_ZCL_WINDOW_COVERING_INTERMEDIATE_SETPOINTS_TILT_DEFAULT_VALUE {0x31, 0x2C, 0x30, 0x78, 0x30, 0x30, 0x30, 0x30, 0x00} - -/** @brief Declare attribute list for Window Covering cluster - @param attr_list - attribute list name - @param window_covering_type - pointer to variable to store Window Covering Type attribute value - @param config_status - pointer to variable to store Config/Status attribute value - @param current_position_lift_percentage - pointer to variable to store - Current Position Lift Percentage attribute value - @param current_position_tilt_percentage - pointer to variable to store - Current Position Tilt Percentage attribute value - @param installed_open_limit_lift - pointer to variable to store Installed Open Limit Lift - attribute value - @param installed_closed_limit_lift - pointer to variable to store Installed Closed Limit Lift - attribute value - @param installed_open_limit_tilt - pointer to variable to store Installed Open Limit Tilt - attribute value - @param installed_closed_limit_tilt - pointer to variable to store Installed Closed Limit Tilt - attribute value - @param mode - pointer to variable to store Mode attribute value -*/ -#define ZB_ZCL_DECLARE_WINDOW_COVERING_CLUSTER_ATTRIB_LIST(attr_list, window_covering_type, \ - config_status, current_position_lift_percentage, current_position_tilt_percentage, \ - installed_open_limit_lift, installed_closed_limit_lift, installed_open_limit_tilt, \ - installed_closed_limit_tilt, mode) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_WINDOW_COVERING) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WINDOW_COVERING_WINDOW_COVERING_TYPE_ID, \ - (window_covering_type)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID, \ - (config_status)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID, \ - (current_position_lift_percentage)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID, \ - (current_position_tilt_percentage)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID, \ - (installed_open_limit_lift)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_ID, \ - (installed_closed_limit_lift)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_TILT_ID, \ - (installed_open_limit_tilt)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_TILT_ID, \ - (installed_closed_limit_tilt)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WINDOW_COVERING_MODE_ID, (mode)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - -/** @} */ /* Window Covering cluster attributes */ - -/** - * @name Attribute value manipulation API - * @{ - */ - -/** @internal Set bits from conf_var variable to type_value */ -#define ZB_ZCL_SET_BIT(conf_var, type_value) \ -{ \ - (conf_var) = (conf_var) | (type_value); \ -} - -/** @internal Get type_value bits from conf_var variable */ -#define ZB_ZCL_GET_BIT(conf_var, type_value) ((conf_var) & (type_value)) - -/** @internal Clear type_value bits in conf_var variable */ -#define ZB_ZCL_CLR_BIT(conf_var, type_value) \ -{ \ - (conf_var) = (conf_var) & ~(type_value); \ -} - -/** - * @brief Sets bits of Config/Status parameter. - * @param type_value - bit to set. - * @param conf_var - config variable. - * @hideinitializer - */ -#define ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_SET(conf_var, type_value) \ - ZB_ZCL_SET_BIT(conf_var, type_value) - -/** @brief Gets bit value of Config/Status parameter - @param type_value - bit value to check - @param conf_var - config variable - * @hideinitializer -*/ -#define ZB_ZCL_ATTR_WINDOW_COVERING_GET_CONFIG_STATUS_BIT_VAL(conf_var, type_value) \ - ZB_ZCL_GET_BIT(conf_var, type_value) - -/** @brief Clear bit of Config/Status parameter - @param type_value - bit to clear - @param conf_var - config variable - * @hideinitializer -*/ -#define ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_CLEAR(conf_var, type_value) \ - ZB_ZCL_CLR_BIT(conf_var, type_value) - -/** @brief Sets bits of Mode parameter - @param type_value - type which need to set - @param mode_var - mode variable - * @hideinitializer -*/ -#define ZB_ZCL_ATTR_WINDOW_COVERING_MODE_SET(mode_var, type_value) \ - ZB_ZCL_SET_BIT(mode_var, type_value) - -/** @brief Gets bits of Mode parameter - @param type_value - type which need to set - @param mode_var - mode variable - * @hideinitializer -*/ -#define ZB_ZCL_ATTR_WINDOW_COVERING_MODE_GET(mode_var, type_value) \ - ZB_ZCL_GET_BIT(mode_var, type_value) - -/** @brief Clear bytes of Mode parameter - @param type_value - type which need to set - @param mode_var - mode variable -*/ -#define ZB_ZCL_ATTR_WINDOW_COVERING_MODE_CLEAR(mode_var, type_value) \ - ZB_ZCL_CLR_BIT(mode_var, type_value) - -/** @cond internals_doc */ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_WINDOW_COVERING_TYPE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_WINDOW_COVERING_TYPE_ID, \ - ZB_ZCL_ATTR_TYPE_8BIT_ENUM, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_SCENE | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_SCENE | ZB_ZCL_ATTR_ACCESS_REPORTING, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_ID( \ - data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_TILT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_TILT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_TILT_ID( \ - data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_TILT_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WINDOW_COVERING_MODE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WINDOW_COVERING_MODE_ID, \ - ZB_ZCL_ATTR_TYPE_8BITMAP, \ - ZB_ZCL_ATTR_ACCESS_READ_WRITE, \ - (void*) data_ptr \ -} - -/** @internal Number of attributes mandatory for reporting in window covering cluster */ -#define ZB_ZCL_WINDOW_COVERING_REPORT_ATTR_COUNT 2 - -/** @endcond */ /* internals_doc */ - -/** @} */ /* Attribute value manipulation API */ - -/** @name Window Covering cluster commands - @{ -*/ - -/** @brief Window Covering cluster command identifiers - @see ZCL8 spec, subclause 7.4.2.2 -*/ -enum zb_zcl_window_covering_cmd_e -{ - /** Up/Open command */ - ZB_ZCL_CMD_WINDOW_COVERING_UP_OPEN = 0x00, - /** Down/Close command */ - ZB_ZCL_CMD_WINDOW_COVERING_DOWN_CLOSE = 0x01, - /** Stop command */ - ZB_ZCL_CMD_WINDOW_COVERING_STOP = 0x02, - /** Go to Lift Value command */ - ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_LIFT_VALUE = 0x04, - /** Go to Lift Percentage command */ - ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_LIFT_PERCENTAGE = 0x05, - /** Go to Tilt Value command */ - ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_TILT_VALUE = 0x07, - /** Go to Tilt Percentage command */ - ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_TILT_PERCENTAGE = 0x08 -}; - -/** @cond internals_doc */ -/* Window covering cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_WINDOW_COVERING_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_WINDOW_COVERING_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_WINDOW_COVERING_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_WINDOW_COVERING_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_WINDOW_COVERING_UP_OPEN, \ - ZB_ZCL_CMD_WINDOW_COVERING_DOWN_CLOSE, \ - ZB_ZCL_CMD_WINDOW_COVERING_STOP, \ - ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_LIFT_PERCENTAGE, \ - ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_TILT_PERCENTAGE - -#define ZB_ZCL_CLUSTER_ID_WINDOW_COVERING_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_WINDOW_COVERING_CLIENT_ROLE_GENERATED_CMD_LIST -/*! @} - * @endcond */ /* internals_doc */ - -/** Mandatory commands defines */ - -/** @brief Structured representation of GO_TO_LIFT_VALUE command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_go_to_lift_value_req_s -{ - /** Lift Value */ - zb_uint16_t lift_value; -} ZB_PACKED_STRUCT zb_zcl_go_to_lift_value_req_t; - -/** @brief Structured representation of GO_TO_LIFT_PERCENTAGE command payload - @see ZCL8 spec, subclause 7.4.2.2.5.1*/ -typedef ZB_PACKED_PRE struct zb_zcl_go_to_lift_percentage_req_s -{ - /** Percentage Lift Value */ - zb_uint8_t percentage_lift_value; -} ZB_PACKED_STRUCT zb_zcl_go_to_lift_percentage_req_t; - -/** @brief Structured representation of GO_TO_TILT_VALUE command payload */ -typedef ZB_PACKED_PRE struct zb_zcl_go_to_tilt_value_req_s -{ - /** Tilt Value */ - zb_uint16_t tilt_value; -} ZB_PACKED_STRUCT zb_zcl_go_to_tilt_value_req_t; - -/** @brief Structured representation of GO_TO_TILT_PERCENTAGE command payload - @see ZCL8 spec, subclause 7.4.2.2.7.1*/ -typedef ZB_PACKED_PRE struct zb_zcl_go_to_tilt_percentage_req_s -{ - /** Percentage Tilt Value */ - zb_uint8_t percentage_tilt_value; -} ZB_PACKED_STRUCT zb_zcl_go_to_tilt_percentage_req_t; - -/** @brief Send Up/Open command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WINDOW_COVERING_SEND_UP_OPEN_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_WINDOW_COVERING_UP_OPEN); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, \ - prfl_id, ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, cb); \ -} - -/** @brief Send Down/Close command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WINDOW_COVERING_SEND_DOWN_CLOSE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_WINDOW_COVERING_DOWN_CLOSE); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, \ - prfl_id, ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, cb); \ -} - -/** @brief Send Stop command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WINDOW_COVERING_SEND_STOP_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_WINDOW_COVERING_STOP); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, \ - prfl_id, ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, cb); \ -} - -/** @brief Send Go to Lift Percentage command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param percentage_lift_value - Percentage Lift value -*/ -#define ZB_ZCL_WINDOW_COVERING_SEND_GO_TO_LIFT_PERCENTAGE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, percentage_lift_value) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_LIFT_PERCENTAGE); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, percentage_lift_value); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, \ - prfl_id, ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, cb); \ -} - -/** @brief Parses Get Go to Lift Percentage command and fills data request - structure. If request contains invalid data, status parameter is ZB_FALSE - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param lift_percentage_req - pointer to a variable to save command request to - @param status - return ZB_ZCL_PARSE_STATUS_SUCCESS if request contains valid data, - else ZB_ZCL_PARSE_STATUS_FAILURE - @note data_buf buffer should contain command request payload without ZCL header. - */ -#define ZB_ZCL_WINDOW_COVERING_GET_GO_TO_LIFT_PERCENTAGE_REQ( \ - data_buf, lift_percentage_req, status) \ -{ \ - zb_zcl_go_to_lift_percentage_req_t *lift_percentage_req_ptr; \ - (lift_percentage_req_ptr) = zb_buf_len(data_buf) >= \ - sizeof(zb_zcl_go_to_lift_percentage_req_t) ? \ - (zb_zcl_go_to_lift_percentage_req_t*)zb_buf_begin(data_buf) : NULL; \ - if (lift_percentage_req_ptr != NULL) \ - { \ - (lift_percentage_req)->percentage_lift_value = \ - lift_percentage_req_ptr->percentage_lift_value; \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @brief Send Go to Tilt Percentage command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param percentage_tilt_value - Percentage Tilt value -*/ -#define ZB_ZCL_WINDOW_COVERING_SEND_GO_TO_TILT_PERCENTAGE_REQ( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, percentage_tilt_value) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_TILT_PERCENTAGE); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, percentage_tilt_value); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT(buffer, addr, dst_addr_mode, dst_ep, ep, \ - prfl_id, ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, cb); \ -} - -/** @brief Parses Get Go to Tilt Percentage command and fills to data request - structure. If request contains invalid data, -1 is returned as Percentage Tilt Value - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param tilt_percentage_req - variable to save command request - @param status - return ZB_ZCL_PARSE_STATUS_SUCCESS if request contains valid data, - else ZB_ZCL_PARSE_STATUS_FAILURE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WINDOW_COVERING_GET_GO_TO_TILT_PERCENTAGE_REQ( \ - data_buf, tilt_percentage_req, status) \ -{ \ - zb_zcl_go_to_tilt_percentage_req_t *tilt_percentage_req_ptr; \ - (tilt_percentage_req_ptr) = zb_buf_len(data_buf) >= \ - sizeof(zb_zcl_go_to_tilt_percentage_req_t) ? \ - (zb_zcl_go_to_tilt_percentage_req_t*)zb_buf_begin(data_buf) : NULL; \ - if (tilt_percentage_req_ptr != NULL) \ - { \ - (tilt_percentage_req)->percentage_tilt_value = \ - tilt_percentage_req_ptr->percentage_tilt_value; \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @} */ /* Window Covering cluster commands */ - -/** @} */ /* ZCL Window Covering cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -void zb_zcl_window_covering_init_server(void); -void zb_zcl_window_covering_init_client(void); -#define ZB_ZCL_CLUSTER_ID_WINDOW_COVERING_SERVER_ROLE_INIT zb_zcl_window_covering_init_server -#define ZB_ZCL_CLUSTER_ID_WINDOW_COVERING_CLIENT_ROLE_INIT zb_zcl_window_covering_init_client - -#endif /* ZB_ZCL_WINDOW_COVERING_H */ diff --git a/zboss/development/include/zcl/zb_zcl_wwah.h b/zboss/development/include/zcl/zb_zcl_wwah.h deleted file mode 100644 index fe2ceb3c6d..0000000000 --- a/zboss/development/include/zcl/zb_zcl_wwah.h +++ /dev/null @@ -1,2617 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: WWAH cluster definitions -*/ - -#ifndef ZB_ZCL_WWAH_H -#define ZB_ZCL_WWAH_H 1 - -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_commands.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/* Cluster ZB_ZCL_CLUSTER_ID_WWAH */ - -/** @addtogroup ZB_ZCL_WWAH - * @{ - * @details - * This cluster provides an opportunity to use various features - * of the Work With All Hubs cluster. - * - * The WWAH cluster shall exist on only 1 endpoint of the Zigbee node, - * it should be identified using cluster ID 0xfc57 and manufacturer ID 0x1217. - * - * All configurations/command settings in this cluster shall be persisted across power cycles - * and rejoins. Only a device factory reset can reset this cluster and put it back to default - * settings. - * - * For more information see Zigbee WWAH Cluster definition (document number in Zigbee Alliance - * 17-01067-022). - * - */ - - -/*! @defgroup ZB_ZCL_WWAH_ATTR WWAH cluster attributes - @{ -*/ - -/* Amazon Lab 126 manufacturer code */ -#define WWAH_MANUFACTURER_CODE 0x1217 - -/*! @brief WWAH cluster attribute identifiers - @see WWAH spec, subclause 6.3.2.2 -*/ -enum zb_zcl_wwah_attr_e -{ - /** If set to TRUE, the device SHALL disallow downgrades of it's firmware. */ - ZB_ZCL_ATTR_WWAH_DISABLE_OTA_DOWNGRADES_ID = 0x0002, - /** If set to FALSE, the node SHALL ignore MGMT Leave Without Rejoin commands. */ - ZB_ZCL_ATTR_WWAH_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED_ID = 0x0003, - /** This attribute is a fixed value containing the number of Network Level Retries - * the device performs when sending a unicast command, not including APS retries. */ - ZB_ZCL_ATTR_WWAH_NWK_RETRY_COUNT_ID = 0x0004, - /** This attribute is a fixed value containing the number of MAC Level Retries the - * device performs when sending a unicast command, not including APS retries. */ - ZB_ZCL_ATTR_WWAH_MAC_RETRY_COUNT_ID = 0x0005, - /** This attribute is set to TRUE if the router's check-in algorithm has been enabled - * through the 'Enable Periodic Router Check-Ins' command detailed below. */ - ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID = 0x0006, - /** This attribute is set to FALSE if support for Touchlink Interpan messages has been - * disabled on the device. */ - ZB_ZCL_ATTR_WWAH_TOUCHLINK_INTERPAN_ENABLED_ID = 0x0007, - /** If set to TRUE, the device SHALL enable the WWAH Parent Classification - * Advertisements feature. */ - ZB_ZCL_ATTR_WWAH_WWAH_PARENT_CLASSIFICATION_ENABLED_ID = 0x0008, - /** This attribute is TRUE if the WWAH Application Event Retry Algorithm is enabled. */ - ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_ENABLED_ID = 0x0009, - /** This attribute is the queue size for re-delivery attempts in the WWAH Application - * Event Retry Algorithm. */ - ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_QUEUE_SIZE_ID = 0x000A, - /** This attribute is set to TRUE if the WWAH Rejoin Algorithm is enabled. */ - ZB_ZCL_ATTR_WWAH_WWAH_REJOIN_ENABLED_ID = 0x000B, - /** This attribute is the time in seconds the device waits before retrying a data poll - * when a MAC level data poll fails for any reason. */ - ZB_ZCL_ATTR_WWAH_MAC_POLL_FAILURE_WAIT_TIME_ID = 0x000C, - /** This attribute indicates whether the device is able to be configured using ZDO - * commands that are not encrypted using the Trust Center Link Key. */ - ZB_ZCL_ATTR_WWAH_CONFIGURATION_MODE_ENABLED_ID = 0x000D, - /** This attribute contains the ID of the current debug report stored on the node. */ - ZB_ZCL_ATTR_WWAH_CURRENT_DEBUG_REPORT_ID_ID = 0x000E, - /** If this attribute is set to TRUE, the node SHALL only process network - * key rotation commands which are sent via unicast and are encrypted by - * the Trust Center Link Key. */ - ZB_ZCL_ATTR_WWAH_TC_SECURITY_ON_NWK_KEY_ROTATION_ENABLED_ID = 0x000F, - /** If this attribute is set to TRUE, the endpoint device SHALL enable - * the WWAH Bad Parent Recovery feature. */ - ZB_ZCL_ATTR_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_ID = 0x0010, - /** This attribute contains the channel number of the only channel the device - * SHALL accept in a ZDO Mgmt Network Update command. */ - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_ID = 0x0011, - /** This attribute contains the only short PAN ID the device SHALL accept in - * a NLME Network Update command. */ - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_PANID_ID = 0x0012, - /** This attribute contains the maximum time in seconds the device may be unavailable - * after completing its OTA download (while restarting, etc). */ - ZB_ZCL_ATTR_WWAH_OTA_MAX_OFFLINE_DURATION_ID = 0x0013, -}; - -/** @brief Minimum value for Cluster Revision attribute */ -#define ZB_ZCL_WWAH_CLUSTER_REVISION_MIN_VALUE 0x0001 - -/** @brief Default value for WWAH cluster revision global attribute */ -#define ZB_ZCL_WWAH_CLUSTER_REVISION_DEFAULT ZB_ZCL_WWAH_CLUSTER_REVISION_MIN_VALUE - -/** @brief Default value for MGMTLeaveWithoutRejoinEnabled attribute */ -#define ZB_ZCL_WWAH_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED_DEFAULT_VALUE ZB_TRUE - -/** @brief Minimum value for NWKRetryCount attribute */ -#define ZB_ZCL_WWAH_NWK_RETRY_COUNT_MIN_VALUE 0x03 - -/** @brief Maximum value for NWKRetryCount attribute */ -#define ZB_ZCL_WWAH_NWK_RETRY_COUNT_MAX_VALUE 0xFF - -/** @brief Minimum value for MACRetryCount attribute */ -#define ZB_ZCL_WWAH_MAC_RETRY_COUNT_MIN_VALUE 0x03 - -/** @brief Maximum value for MACRetryCount attribute */ -#define ZB_ZCL_WWAH_MAC_RETRY_COUNT_MAX_VALUE 0xFF - -/** @brief Default value for RouterCheckInEnabled attribute */ -#define ZB_ZCL_WWAH_ROUTER_CHECK_IN_ENABLED_DEFAULT_VALUE ZB_FALSE - -/** @brief Default value for WWAHParentClassificationEnabled attribute */ -#define ZB_ZCL_WWAH_WWAH_PARENT_CLASSIFICATION_ENABLED_DEFAULT_VALUE ZB_FALSE - -/** @brief Default value for WWAHAppEventRetryEnabled attribute */ -#define ZB_ZCL_WWAH_WWAH_APP_EVENT_RETRY_ENABLED_DEFAULT_VALUE ZB_TRUE - -/** @brief Minimum value for WWAHAppEventRetryQueueSize attribute */ -#define ZB_ZCL_WWAH_WWAH_APP_EVENT_RETRY_QUEUE_SIZE_MIN_VALUE 10 - -/** @brief Maximum value for WWAHAppEventRetryQueueSize attribute */ -#define ZB_ZCL_WWAH_WWAH_APP_EVENT_RETRY_QUEUE_SIZE_MAX_VALUE 0xFF - -/** @brief Default value for WWAHAppEventRetryQueueSize attribute */ -#define ZB_ZCL_WWAH_WWAH_APP_EVENT_RETRY_QUEUE_SIZE_DEFAULT_VALUE 10 - -/** @brief Default value for WWAHRejoinEnabled attribute */ -#define ZB_ZCL_WWAH_WWAH_REJOIN_ENABLED_DEFAULT_VALUE ZB_FALSE - -/** @brief Minimum value for MACPollFailureWaitTime attribute */ -#define ZB_ZCL_WWAH_MAC_POLL_FAILURE_WAIT_TIME_MIN_VALUE 0x00 - -/** @brief Maximum value for MACPollFailureWaitTime attribute */ -#define ZB_ZCL_WWAH_MAC_POLL_FAILURE_WAIT_TIME_MAX_VALUE 0xFF - -/** @brief Default value for MACPollFailureWaitTime attribute */ -#define ZB_ZCL_WWAH_MAC_POLL_FAILURE_WAIT_TIME_DEFAULT_VALUE 3 - -/** @brief Default value for ConfigurationModeEnabled attribute */ -#define ZB_ZCL_WWAH_CONFIGURATION_MODE_ENABLED_DEFAULT_VALUE ZB_TRUE - -/** @brief Minimum value for CurrentDebugReportID attribute */ -#define ZB_ZCL_WWAH_CURRENT_DEBUG_REPORT_ID_MIN_VALUE 0x00 - -/** @brief Maximum value for CurrentDebugReportID attribute */ -#define ZB_ZCL_WWAH_CURRENT_DEBUG_REPORT_ID_MAX_VALUE 0xFF - -/** @brief Default value for TCSecurityOnNwkKeyRotationEnabled attribute */ -#define ZB_ZCL_WWAH_TC_SECURITY_ON_NWK_KEY_ROTATION_ENABLED_DEFAULT_VALUE ZB_FALSE - -/** @brief Default value for WWAHBadParentRecoveryEnabled attribute */ -#define ZB_ZCL_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_DEFAULT_VALUE ZB_FALSE - -/** @brief Minimum value for PendingNetworkUpdateChannel attribute */ -#define ZB_ZCL_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_MIN_VALUE 0x00 - -/** @brief Maximum value for PendingNetworkUpdateChannel attribute */ -#define ZB_ZCL_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_MAX_VALUE 0xFF - -/** @brief Default value for PendingNetworkUpdateChannel attribute */ -#define ZB_ZCL_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_DEFAULT_VALUE 0xFF - -/** @brief Minimum value for PendingNetworkUpdatePANID attribute */ -#define ZB_ZCL_WWAH_PENDING_NETWORK_UPDATE_PANID_MIN_VALUE 0x0000 - -/** @brief Maximum value for PendingNetworkUpdatePANID attribute */ -#define ZB_ZCL_WWAH_PENDING_NETWORK_UPDATE_PANID_MAX_VALUE 0xFFFF - -/** @brief Default value for PendingNetworkUpdatePANID attribute */ -#define ZB_ZCL_WWAH_PENDING_NETWORK_UPDATE_PANID_DEFAULT_VALUE 0xFFFF - -/** @brief Minimum value for OTAMaxOfflineDuration attribute */ -#define ZB_ZCL_WWAH_OTA_MAX_OFFLINE_DURATION_MIN_VALUE 0x0000 - -/** @brief Maximum value for OTAMaxOfflineDuration attribute */ -#define ZB_ZCL_WWAH_OTA_MAX_OFFLINE_DURATION_MAX_VALUE 0xFFFF - -/** @brief Additional MAC Poll retry count */ -#define ZB_ZCL_WWAH_MAC_POLL_RETRY_COUNT 2 - -/*! @} */ /* WWAH cluster attributes */ - -/*! @defgroup ZB_ZCL_WWAH_COMMANDS WWAH cluster commands - @{ -*/ - -/*! @brief WWAH cluster command identifiers - @see WWAH spec -*/ -enum zb_zcl_wwah_cmd_e -{ - /** Enable APS Link Key Authorization command */ - ZB_ZCL_CMD_WWAH_ENABLE_APS_LINK_KEY_AUTHORIZATION_ID = 0x00, - /** Disable APS Link Key Authorization command */ - ZB_ZCL_CMD_WWAH_DISABLE_APS_LINK_KEY_AUTHORIZATION_ID = 0x01, - /** APS Link Key Authorization Query command */ - ZB_ZCL_CMD_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_ID = 0x02, - /** Request New APS Link Key command */ - ZB_ZCL_CMD_WWAH_REQUEST_NEW_APS_LINK_KEY_ID = 0x03, - /** Enable WWAH App Event Retry Algorithm command */ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_ID = 0x04, - /** Disable WWAH App Event Retry Algorithm command */ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_ID = 0x05, - /** Request Time command */ - ZB_ZCL_CMD_WWAH_REQUEST_TIME_ID = 0x06, - /** Enable WWAH Rejoin Algorithm command */ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_REJOIN_ALGORITHM_ID = 0x07, - /** Disable WWAH Rejoin Algorithm command */ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_REJOIN_ALGORITHM_ID = 0x08, - /** Set IAS Zone Enrollment Method command */ - ZB_ZCL_CMD_WWAH_SET_IAS_ZONE_ENROLLMENT_METHOD_ID = 0x09, - /** Clear Binding Table command */ - ZB_ZCL_CMD_WWAH_CLEAR_BINDING_TABLE_ID = 0x0A, - /** Enable Periodic Router Check Ins command */ - ZB_ZCL_CMD_WWAH_ENABLE_PERIODIC_ROUTER_CHECK_INS_ID = 0x0B, - /** Disable Periodic Router Check Ins command */ - ZB_ZCL_CMD_WWAH_DISABLE_PERIODIC_ROUTER_CHECK_INS_ID = 0x0C, - /** Set MAC Poll CCA Wait Time command */ - ZB_ZCL_CMD_WWAH_SET_MAC_POLL_CCA_WAIT_TIME_ID = 0x0D, - /** Set Pending Network Update command */ - ZB_ZCL_CMD_WWAH_SET_PENDING_NETWORK_UPDATE_ID = 0x0E, - /** Require APS ACKs on Unicasts command */ - ZB_ZCL_CMD_WWAH_REQUIRE_APS_ACKS_ON_UNICASTS_ID = 0x0F, - /** Remove APS ACKs on Unicasts Requirement command */ - ZB_ZCL_CMD_WWAH_REMOVE_APS_ACKS_ON_UNICASTS_REQUIREMENT_ID = 0x10, - /** APS ACK Requirement Query command */ - ZB_ZCL_CMD_WWAH_APS_ACK_REQUIREMENT_QUERY_ID = 0x11, - /** Debug Report Query command */ - ZB_ZCL_CMD_WWAH_DEBUG_REPORT_QUERY_ID = 0x12, - /** Survey Beacons command */ - ZB_ZCL_CMD_WWAH_SURVEY_BEACONS_ID = 0x13, - /** Disable OTA Downgrades command */ - ZB_ZCL_CMD_WWAH_DISABLE_OTA_DOWNGRADES_ID = 0x14, - /** Disable MGMT Leave Without Rejoin command */ - ZB_ZCL_CMD_WWAH_DISABLE_MGMT_LEAVE_WITHOUT_REJOIN_ID = 0x15, - /** Disable Touchlink Interpan Message Support command */ - ZB_ZCL_CMD_WWAH_DISABLE_TOUCHLINK_INTERPAN_MESSAGE_SUPPORT_ID = 0x16, - /** Enable WWAH Parent Classification command */ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_PARENT_CLASSIFICATION_ID = 0x17, - /** Disable WWAH Parent Classification command */ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_PARENT_CLASSIFICATION_ID = 0x18, - /** Enable TC Security On Nwk Key Rotation command */ - ZB_ZCL_CMD_WWAH_ENABLE_TC_SECURITY_ON_NWK_KEY_ROTATION_ID = 0x19, - /** Enable WWAH Bad Parent Recovery command */ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_BAD_PARENT_RECOVERY_ID = 0x1A, - /** Disable WWAH Bad Parent Recovery command */ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_BAD_PARENT_RECOVERY_ID = 0x1B, - /** Enable Configuration Mode command */ - ZB_ZCL_CMD_WWAH_ENABLE_CONFIGURATION_MODE_ID = 0x1C, - /** Disable Configuration Mode command */ - ZB_ZCL_CMD_WWAH_DISABLE_CONFIGURATION_MODE_ID = 0x1D, - /** Use Trust Center for Cluster command */ - ZB_ZCL_CMD_WWAH_USE_TRUST_CENTER_FOR_CLUSTER_ID = 0x1E, - /** Trust Center for Cluster Server Query command */ - ZB_ZCL_CMD_WWAH_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_ID = 0x1F, -}; - -enum zb_zcl_wwah_cmd_resp_e -{ - /** APS Link Key Authorization Query Response command */ - ZB_ZCL_CMD_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_RESPONSE_ID = 0x00, - /** Powering Off Notification command */ - ZB_ZCL_CMD_WWAH_POWERING_OFF_NOTIFICATION_ID = 0x01, - /** Powering On Notification command */ - ZB_ZCL_CMD_WWAH_POWERING_ON_NOTIFICATION_ID = 0x02, - /** Short Address Change command */ - ZB_ZCL_CMD_WWAH_SHORT_ADDRESS_CHANGE_ID = 0x03, - /** APS ACK Requirement Query Response command */ - ZB_ZCL_CMD_WWAH_APS_ACK_REQUIREMENT_QUERY_RESPONSE_ID = 0x04, - /** Power Descriptor Change command */ - ZB_ZCL_CMD_WWAH_POWER_DESCRIPTOR_CHANGE_ID = 0x05, - /** New Debug Report Notification command */ - ZB_ZCL_CMD_WWAH_NEW_DEBUG_REPORT_NOTIFICATION_ID = 0x06, - /** Debug Report Query Response command */ - ZB_ZCL_CMD_WWAH_DEBUG_REPORT_QUERY_RESPONSE_ID = 0x07, - /** Trust Center for Cluster Server Query Response command */ - ZB_ZCL_CMD_WWAH_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_RESPONSE_ID = 0x08, - /** Survey Beacons Response command */ - ZB_ZCL_CMD_WWAH_SURVEY_BEACONS_RESPONSE_ID = 0x09, -}; - - -/* WWAH control cluster commands list : only for information - do not modify */ -#define ZB_ZCL_CLUSTER_ID_WWAH_SERVER_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_RESPONSE_ID, \ - ZB_ZCL_CMD_WWAH_POWERING_OFF_NOTIFICATION_ID, \ - ZB_ZCL_CMD_WWAH_POWERING_ON_NOTIFICATION_ID, \ - ZB_ZCL_CMD_WWAH_SHORT_ADDRESS_CHANGE_ID, \ - ZB_ZCL_CMD_WWAH_APS_ACK_REQUIREMENT_QUERY_RESPONSE_ID, \ - ZB_ZCL_CMD_WWAH_POWER_DESCRIPTOR_CHANGE_ID, \ - ZB_ZCL_CMD_WWAH_NEW_DEBUG_REPORT_NOTIFICATION_ID, \ - ZB_ZCL_CMD_WWAH_DEBUG_REPORT_QUERY_RESPONSE_ID, \ - ZB_ZCL_CMD_WWAH_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_RESPONSE_ID, \ - ZB_ZCL_CMD_WWAH_SURVEY_BEACONS_RESPONSE_ID - -#define ZB_ZCL_CLUSTER_ID_WWAH_CLIENT_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_WWAH_SERVER_ROLE_GENERATED_CMD_LIST - -#define ZB_ZCL_CLUSTER_ID_WWAH_CLIENT_ROLE_GENERATED_CMD_LIST \ - ZB_ZCL_CMD_WWAH_ENABLE_APS_LINK_KEY_AUTHORIZATION_ID, \ - ZB_ZCL_CMD_WWAH_DISABLE_APS_LINK_KEY_AUTHORIZATION_ID, \ - ZB_ZCL_CMD_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_ID, \ - ZB_ZCL_CMD_WWAH_REQUEST_NEW_APS_LINK_KEY_ID, \ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_ID, \ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_ID, \ - ZB_ZCL_CMD_WWAH_REQUEST_TIME_ID, \ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_REJOIN_ALGORITHM_ID, \ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_REJOIN_ALGORITHM_ID, \ - ZB_ZCL_CMD_WWAH_SET_IAS_ZONE_ENROLLMENT_METHOD_ID, \ - ZB_ZCL_CMD_WWAH_CLEAR_BINDING_TABLE_ID, \ - ZB_ZCL_CMD_WWAH_ENABLE_PERIODIC_ROUTER_CHECK_INS_ID, \ - ZB_ZCL_CMD_WWAH_DISABLE_PERIODIC_ROUTER_CHECK_INS_ID, \ - ZB_ZCL_CMD_WWAH_SET_MAC_POLL_CCA_WAIT_TIME_ID, \ - ZB_ZCL_CMD_WWAH_SET_PENDING_NETWORK_UPDATE_ID, \ - ZB_ZCL_CMD_WWAH_REQUIRE_APS_ACKS_ON_UNICASTS_ID, \ - ZB_ZCL_CMD_WWAH_REMOVE_APS_ACKS_ON_UNICASTS_REQUIREMENT_ID, \ - ZB_ZCL_CMD_WWAH_APS_ACK_REQUIREMENT_QUERY_ID, \ - ZB_ZCL_CMD_WWAH_DEBUG_REPORT_QUERY_ID, \ - ZB_ZCL_CMD_WWAH_SURVEY_BEACONS_ID, \ - ZB_ZCL_CMD_WWAH_DISABLE_OTA_DOWNGRADES_ID, \ - ZB_ZCL_CMD_WWAH_DISABLE_MGMT_LEAVE_WITHOUT_REJOIN_ID, \ - ZB_ZCL_CMD_WWAH_DISABLE_TOUCHLINK_INTERPAN_MESSAGE_SUPPORT_ID, \ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_PARENT_CLASSIFICATION_ID, \ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_PARENT_CLASSIFICATION_ID, \ - ZB_ZCL_CMD_WWAH_ENABLE_TC_SECURITY_ON_NWK_KEY_ROTATION_ID, \ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_BAD_PARENT_RECOVERY_ID, \ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_BAD_PARENT_RECOVERY_ID, \ - ZB_ZCL_CMD_WWAH_ENABLE_CONFIGURATION_MODE_ID, \ - ZB_ZCL_CMD_WWAH_DISABLE_CONFIGURATION_MODE_ID, \ - ZB_ZCL_CMD_WWAH_USE_TRUST_CENTER_FOR_CLUSTER_ID, \ - ZB_ZCL_CMD_WWAH_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_ID - -#define ZB_ZCL_CLUSTER_ID_WWAH_SERVER_ROLE_RECEIVED_CMD_LIST ZB_ZCL_CLUSTER_ID_WWAH_CLIENT_ROLE_GENERATED_CMD_LIST - - -/** @brief Size of APS ACK Exempt Table */ -#define ZB_ZCL_WWAH_APS_ACK_EXEMPT_TABLE_SIZE 10 -ZB_ASSERT_VALUE_ALIGNED_TO_4(ZB_ZCL_WWAH_APS_ACK_EXEMPT_TABLE_SIZE * sizeof(zb_uint16_t)); - -/** @brief Size of APS Link Key Authorization Table */ -#define ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_TABLE_SIZE 10 -ZB_ASSERT_VALUE_ALIGNED_TO_4(ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_TABLE_SIZE * sizeof(zb_uint16_t)); - -/** @brief Size of Use Trust Center for Cluster Table */ -#define ZB_ZCL_WWAH_USE_TRUST_CENTER_FOR_CLUSTER_TABLE_SIZE 4 -ZB_ASSERT_VALUE_ALIGNED_TO_4(ZB_ZCL_WWAH_USE_TRUST_CENTER_FOR_CLUSTER_TABLE_SIZE * sizeof(zb_uint16_t)); - -/** @brief WWAH Cluster arrays "record is free" flag */ -#define ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD 0xFFFF - -/** @brief Debug Report ID field reserved value - * The value 0x00 is reserved to indicate that there are no debug reports and SHALL not be used - * as IDs of a debug report.*/ -#define ZB_ZCL_WWAH_RESERVED_DEBUG_REPORT_ID 0x00 - -#define ZB_ZCL_WWAH_DEBUG_REPORT_FREE_RECORD (zb_zcl_wwah_debug_report_t){ZB_ZCL_WWAH_RESERVED_DEBUG_REPORT_ID, 0, NULL} - -/** @brief Context WWAH cluster */ - -typedef ZB_PACKED_PRE struct zb_zcl_wwah_debug_report_s -{ - zb_uint8_t report_id; /**< Report ID. 0x00 means lack of report */ - zb_uint32_t report_size; /**< Report size */ - zb_char_t *report; /**< Pointer to report data*/ -} -ZB_PACKED_STRUCT zb_zcl_wwah_debug_report_t; - -typedef ZB_PACKED_PRE struct zb_zcl_wwah_classification_mask_s -{ - zb_bitfield_t tc_connectivity :1; /**< TC Connectivity value */ - zb_bitfield_t long_uptime :1; /**< Long Uptime value */ - zb_bitfield_t reserved :6; /**< Reserved */ -} -ZB_PACKED_STRUCT -zb_zcl_wwah_classification_mask_t; - -#define ZB_ZCL_WWAH_PERIODIC_CHECKINS_CLUSTER_MATCH_DESC_TIME (ZB_TIME_ONE_SECOND * 20) -#define ZB_ZCL_WWAH_PERIODIC_CHECKINS_MAX_FAILURE_CNT 3 - -#define ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_KEEPALIVE 0 -#define ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_CLUSTER_REVISION 1 -#define ZB_ZCL_WWAH_PERIODIC_CHECKINS_NOT_SUPPORTED 2 - -typedef ZB_PACKED_PRE struct zb_zcl_wwah_periodic_checkins_data_s -{ - zb_uint8_t poll_method; - zb_uint8_t tsn; - zb_uint8_t endpoint; - zb_uint8_t failure_cnt; - zb_uint32_t countdown; - zb_uint16_t keepalive_base; /* Base timeout in seconds*/ - zb_uint16_t keepalive_jitter; -} ZB_PACKED_STRUCT zb_zcl_wwah_periodic_checkins_data_t; - -typedef enum zb_zcl_wwah_bad_parent_recovery_signal_e -{ - ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_RSSI_WITH_PARENT_BAD = 0, - ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_RSSI_WITH_PARENT_OK, - - ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_APS_ACK_FAILED, - ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_APS_ACK_OK, - - ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED, - ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_OK, - - ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_RESERVED -} zb_zcl_wwah_bad_parent_recovery_signal_t; - -typedef ZB_PACKED_PRE struct zb_zcl_wwah_bad_parent_recovery_data_s -{ - zb_bitfield_t started:1; - zb_bitfield_t poll_control_checkin_failed_cnt:2; - zb_bitfield_t reserved:5; -} ZB_PACKED_STRUCT zb_zcl_wwah_bad_parent_recovery_data_t; - -typedef enum zb_zcl_wwah_behavior_e -{ - ZB_ZCL_WWAH_BEHAVIOR_OFF = 0, - ZB_ZCL_WWAH_BEHAVIOR_CLIENT, - ZB_ZCL_WWAH_BEHAVIOR_SERVER, - - ZB_ZCL_WWAH_BEHAVIOR_RESERVED -} zb_zcl_wwah_behavior_t; - -/*! @} */ /* WWAH cluster commands */ - -/*! - @cond internals_doc - @internal @name WWAH cluster internals - Internal structures for attribute representation in cluster definitions. - @{ -*/ - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_DISABLE_OTA_DOWNGRADES_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_DISABLE_OTA_DOWNGRADES_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_NWK_RETRY_COUNT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_NWK_RETRY_COUNT_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_MAC_RETRY_COUNT_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_MAC_RETRY_COUNT_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_TOUCHLINK_INTERPAN_ENABLED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_TOUCHLINK_INTERPAN_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_WWAH_PARENT_CLASSIFICATION_ENABLED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_WWAH_PARENT_CLASSIFICATION_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_ENABLED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_QUEUE_SIZE_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_QUEUE_SIZE_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_WWAH_REJOIN_ENABLED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_WWAH_REJOIN_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_MAC_POLL_FAILURE_WAIT_TIME_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_MAC_POLL_FAILURE_WAIT_TIME_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_CONFIGURATION_MODE_ENABLED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_CONFIGURATION_MODE_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_CURRENT_DEBUG_REPORT_ID_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_CURRENT_DEBUG_REPORT_ID_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_TC_SECURITY_ON_NWK_KEY_ROTATION_ENABLED_ID(data_ptr)\ -{ \ - ZB_ZCL_ATTR_WWAH_TC_SECURITY_ON_NWK_KEY_ROTATION_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_ID, \ - ZB_ZCL_ATTR_TYPE_BOOL, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_ID, \ - ZB_ZCL_ATTR_TYPE_U8, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_PANID_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_PANID_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_WWAH_OTA_MAX_OFFLINE_DURATION_ID(data_ptr) \ -{ \ - ZB_ZCL_ATTR_WWAH_OTA_MAX_OFFLINE_DURATION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) data_ptr \ -} - -typedef ZB_PACKED_PRE struct zb_zcl_wwah_cluster_list_s -{ - zb_uint8_t number_of_clusters; /**< Number of Clusters */ - zb_uint16_t *cluster_id; /**< Cluster ID */ -} -ZB_PACKED_STRUCT zb_zcl_wwah_cluster_list_t; - -/*! - @brief Parses various commands with cluster list variable length payload and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ - -#define ZB_ZCL_WWAH_GET_CLUSTER_LIST_CMD(data_buf, req, status) \ -{ \ - zb_zcl_wwah_cluster_list_t *src_ptr = (zb_zcl_wwah_cluster_list_t*)zb_buf_begin((data_buf)); \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - if (zb_buf_len((data_buf)) >= sizeof(zb_uint8_t)) \ - { \ - (req)->number_of_clusters = src_ptr->number_of_clusters; \ - if (src_ptr->number_of_clusters) \ - { \ - if (zb_buf_len((data_buf)) >= sizeof(zb_uint8_t) + \ - src_ptr->number_of_clusters * sizeof(zb_uint16_t)) \ - { \ - (req)->cluster_id = (zb_uint16_t*)(&(src_ptr->cluster_id)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - } \ -} - -#define ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_PAYLOAD_LEN (sizeof(zb_uint16_t)) - -/*! - @brief Parses APS Link Key Authorization Query command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_APS_LINK_KEY_AUTHORIZATION_QUERY(data_buf, req, status) \ -{ \ - zb_uint16_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_PAYLOAD_LEN ? \ - (zb_uint16_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_PAYLOAD_LEN); \ - status = ((req) == ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD) ? \ - ZB_ZCL_PARSE_STATUS_FAILURE : ZB_ZCL_PARSE_STATUS_SUCCESS; \ - \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @brief Enable WWAH App Event Retry Algorithm command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_s -{ - zb_uint8_t first_backoff_time_in_seconds; /**< First Backoff Time In Seconds */ - zb_uint8_t backoff_sequence_common_ratio; /**< Backoff Sequence Common Ratio */ - zb_uint32_t max_backoff_time_in_seconds; /**< Max Backoff Time In Seconds */ - zb_uint8_t max_re_delivery_attempts; /**< Max Re-Delivery Attempts */ -} -ZB_PACKED_STRUCT -zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_t; - -#define ZB_ZCL_WWAH_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_PAYLOAD_LEN (sizeof(zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_t)) -/*! - @brief Parses Enable WWAH App Event Retry Algorithm command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM(data_buf, req, status) \ -{ \ - zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_PAYLOAD_LEN ? \ - (zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_PAYLOAD_LEN); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @brief Enable WWAH Rejoin Algorithm command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_wwah_enable_wwah_rejoin_algorithm_s -{ - zb_uint16_t fast_rejoin_timeout_in_seconds; /**< Fast Rejoin Timeout In Seconds */ - zb_uint16_t duration_between_each_rejoin_in_seconds; /**< Duration Between Each Rejoin In Seconds */ - zb_uint16_t fast_rejoin_first_backoff_in_seconds; /**< Fast Rejoin First Backoff In Seconds */ - zb_uint16_t rejoin_max_backoff_time_in_seconds; /**< Max Backoff Time In Seconds */ - zb_uint16_t max_backoff_iterations; /**< Max Backoff Iterations */ -} -ZB_PACKED_STRUCT -zb_zcl_wwah_enable_wwah_rejoin_algorithm_t; - -#define ZB_ZCL_WWAH_ENABLE_WWAH_REJOIN_ALGORITHM_PAYLOAD_LEN (sizeof(zb_zcl_wwah_enable_wwah_rejoin_algorithm_t)) - -/*! - @brief Parses Enable WWAH Rejoin Algorithm command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_ENABLE_WWAH_REJOIN_ALGORITHM(data_buf, req, status) \ -{ \ - zb_zcl_wwah_enable_wwah_rejoin_algorithm_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_ENABLE_WWAH_REJOIN_ALGORITHM_PAYLOAD_LEN ? \ - (zb_zcl_wwah_enable_wwah_rejoin_algorithm_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_ENABLE_WWAH_REJOIN_ALGORITHM_PAYLOAD_LEN); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -#define ZB_ZCL_WWAH_SET_IAS_ZONE_ENROLLMENT_METHOD_PAYLOAD_LEN (sizeof(zb_uint8_t)) -/*! - @brief Parses Set IAS Zone Enrollment Method command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_SET_IAS_ZONE_ENROLLMENT_METHOD(data_buf, req, status) \ -{ \ - zb_uint8_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_SET_IAS_ZONE_ENROLLMENT_METHOD_PAYLOAD_LEN ? \ - (zb_uint8_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_SET_IAS_ZONE_ENROLLMENT_METHOD_PAYLOAD_LEN); \ - switch(*(zb_uint8_t*)req_ptr) \ - { \ - case ZB_ZCL_WWAH_ENROLLMENT_MODE_TRIP_TO_PAIR: \ - case ZB_ZCL_WWAH_ENROLLMENT_MODE_AUTO_ENROLL_RESPONSE: \ - case ZB_ZCL_WWAH_ENROLLMENT_MODE_AUTO_ENROLL_REQUEST: \ - { \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - break; \ - } \ - default: \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - break; \ - } \ - } \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -#define ZB_ZCL_WWAH_ENABLE_PERIODIC_ROUTER_CHECK_INS_PAYLOAD_LEN (sizeof(zb_uint16_t)) - -/*! - @brief Parses Enable Periodic Router Check-Ins command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_ENABLE_PERIODIC_ROUTER_CHECK_INS(data_buf, req, status) \ -{ \ - zb_uint16_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_ENABLE_PERIODIC_ROUTER_CHECK_INS_PAYLOAD_LEN ? \ - (zb_uint16_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_ENABLE_PERIODIC_ROUTER_CHECK_INS_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -#define ZB_ZCL_WWAH_SET_MAC_POLL_CCA_WAIT_TIME_PAYLOAD_LEN (sizeof(zb_uint8_t)) - -/*! - @brief Parses Set MAC Poll CCA Wait Time command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_SET_MAC_POLL_CCA_WAIT_TIME(data_buf, req, status) \ -{ \ - zb_uint8_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_SET_MAC_POLL_CCA_WAIT_TIME_PAYLOAD_LEN ? \ - (zb_uint8_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_SET_MAC_POLL_CCA_WAIT_TIME_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @brief Set Pending Network Update command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_wwah_set_pending_network_update_s -{ - zb_uint8_t channel; /**< Channel */ - zb_uint16_t pan_id; /**< PAN ID */ -} -ZB_PACKED_STRUCT -zb_zcl_wwah_set_pending_network_update_t; - -#define ZB_ZCL_WWAH_SET_PENDING_NETWORK_UPDATE_PAYLOAD_LEN (sizeof(zb_zcl_wwah_set_pending_network_update_t)) -/*! - @brief Parses Set Pending Network Update command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_SET_PENDING_NETWORK_UPDATE(data_buf, req, status) \ -{ \ - zb_zcl_wwah_set_pending_network_update_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_SET_PENDING_NETWORK_UPDATE_PAYLOAD_LEN ? \ - (zb_zcl_wwah_set_pending_network_update_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_SET_PENDING_NETWORK_UPDATE_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -#define ZB_ZCL_WWAH_DEBUG_REPORT_QUERY_PAYLOAD_LEN (sizeof(zb_uint8_t)) -/*! - @brief Parses Debug Report Query command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_DEBUG_REPORT_QUERY(data_buf, req, status) \ -{ \ - zb_uint8_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_DEBUG_REPORT_QUERY_PAYLOAD_LEN ? \ - (zb_uint8_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_DEBUG_REPORT_QUERY_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -#define ZB_ZCL_WWAH_SURVEY_BEACONS_PAYLOAD_LEN (sizeof(zb_uint8_t)) -/*! - @brief Parses Survey Beacons command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_SURVEY_BEACONS(data_buf, req, status) \ -{ \ - zb_uint8_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_SURVEY_BEACONS_PAYLOAD_LEN ? \ - (zb_uint8_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_SURVEY_BEACONS_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @brief APS Link Key Authorization Query Response command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_wwah_aps_link_key_authorization_query_response_s -{ - zb_uint16_t cluster_id; /**< Cluster ID */ - zb_uint8_t aps_link_key_authorization_status; /**< APS Link Key Authorization Status */ -} -ZB_PACKED_STRUCT -zb_zcl_wwah_aps_link_key_authorization_query_response_t; - -#define ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_RESPONSE_PAYLOAD_LEN (sizeof(zb_zcl_wwah_aps_link_key_authorization_query_response_t)) -/*! - @brief Parses APS Link Key Authorization Query Response command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_APS_LINK_KEY_AUTHORIZATION_QUERY_RESPONSE(data_buf, req, status) \ -{ \ - zb_zcl_wwah_aps_link_key_authorization_query_response_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_RESPONSE_PAYLOAD_LEN ? \ - (zb_zcl_wwah_aps_link_key_authorization_query_response_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_RESPONSE_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @brief Short Address Change command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_wwah_short_address_change_s -{ - zb_ieee_addr_t device_eui64; /**< DeviceEUI64 */ - zb_uint16_t device_short; /**< DeviceShort */ -} -ZB_PACKED_STRUCT -zb_zcl_wwah_short_address_change_t; - -#define ZB_ZCL_WWAH_SHORT_ADDRESS_CHANGE_PAYLOAD_LEN (sizeof(zb_zcl_wwah_short_address_change_t)) -/*! - @brief Parses Short Address Change command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_SHORT_ADDRESS_CHANGE(data_buf, req, status) \ -{ \ - zb_zcl_wwah_short_address_change_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_SHORT_ADDRESS_CHANGE_PAYLOAD_LEN ? \ - (zb_zcl_wwah_short_address_change_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_SHORT_ADDRESS_CHANGE_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @brief Power Descriptor Change command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_wwah_power_descriptor_change_s -{ - zb_uint32_t current_power_mode; /**< Current power mode */ - zb_uint32_t available_power_sources; /**< Available power sources */ - zb_uint32_t current_power_source; /**< Current power source */ - zb_uint32_t current_power_source_level; /**< Current power source level */ -} -ZB_PACKED_STRUCT -zb_zcl_wwah_power_descriptor_change_t; - - -/*! - @brief Parses Power Descriptor Change command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_POWER_DESCRIPTOR_CHANGE(data_buf, req, status) \ -{ \ - zb_zcl_wwah_power_descriptor_change_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_POWER_DESCRIPTOR_CHANGE_PAYLOAD_LEN ? \ - (zb_zcl_wwah_power_descriptor_change_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, sizeof(zb_zcl_wwah_power_descriptor_change_t)); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @brief Powering On/Off Notification command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_wwah_powering_on_off_notification_s -{ - zb_uint8_t power_notification_reason; /**< PowerNotificationReason */ - zb_uint16_t manufacturer_id; /**< Manufacturer ID */ - zb_uint8_t manufacturer_power_notification_reason_length; /**< Manufacturer Power Notification Reason Length */ - zb_uint8_t *manufacturer_power_notification_reason; /**< Manufacturer Power Notification Reason */ -} -ZB_PACKED_STRUCT -zb_zcl_wwah_powering_on_off_notification_t; - -#define ZB_ZCL_WWAH_POWERING_ON_OFF_NOTIFICATION_PAYLOAD_LEN (sizeof(zb_uint8_t) + sizeof(zb_uint16_t)+ sizeof(zb_uint8_t)) -/*! - @brief Parses Powering On/Off Notification command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_POWERING_ON_OFF_NOTIFICATION(data_buf, req, status) \ -{ \ - zb_zcl_wwah_powering_on_off_notification_t *src_ptr = \ - (zb_zcl_wwah_powering_on_off_notification_t*)zb_buf_begin((data_buf)); \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - if (zb_buf_len((data_buf)) >= ZB_ZCL_WWAH_POWERING_ON_OFF_NOTIFICATION_PAYLOAD_LEN) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_POWERING_ON_OFF_NOTIFICATION_PAYLOAD_LEN); \ - if (src_ptr->manufacturer_power_notification_reason_length) \ - { \ - if (zb_buf_len((data_buf)) >= ZB_ZCL_WWAH_POWERING_ON_OFF_NOTIFICATION_PAYLOAD_LEN + \ - src_ptr->manufacturer_power_notification_reason_length * sizeof(zb_uint8_t)) \ - { \ - (req)->manufacturer_power_notification_reason = \ - (zb_uint8_t*)(&(src_ptr->manufacturer_power_notification_reason)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - } \ - else \ - { \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - } \ -} - -/** @brief New Debug Report Notification command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_wwah_new_debug_report_notification_s -{ - zb_uint8_t debug_report_id; /**< Debug Report ID */ - zb_uint32_t size_of_report; /**< Size of Report */ -} -ZB_PACKED_STRUCT -zb_zcl_wwah_new_debug_report_notification_t; - -#define ZB_ZCL_WWAH_NEW_DEBUG_REPORT_NOTIFICATION_PAYLOAD_LEN (sizeof(zb_zcl_wwah_new_debug_report_notification_t)) -/*! - @brief Parses New Debug Report Notification command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_NEW_DEBUG_REPORT_NOTIFICATION(data_buf, req, status) \ -{ \ - zb_zcl_wwah_new_debug_report_notification_t *req_ptr = \ - zb_buf_len(data_buf) >= ZB_ZCL_WWAH_NEW_DEBUG_REPORT_NOTIFICATION_PAYLOAD_LEN ? \ - (zb_zcl_wwah_new_debug_report_notification_t*)zb_buf_begin(data_buf) : NULL; \ - if (req_ptr) \ - { \ - ZB_MEMCPY(&(req), req_ptr, ZB_ZCL_WWAH_NEW_DEBUG_REPORT_NOTIFICATION_PAYLOAD_LEN); \ - status = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ - else \ - { \ - status = ZB_ZCL_PARSE_STATUS_FAILURE; \ - } \ -} - -/** @brief Debug Report Query Response command structure */ -typedef ZB_PACKED_PRE struct zb_zcl_wwah_debug_report_query_response_s -{ - zb_uint8_t debug_report_id; /**< Debug Report ID */ - zb_uint8_t *report_data; /**< Report data */ -} -ZB_PACKED_STRUCT -zb_zcl_wwah_debug_report_query_response_t; - -/*! - @brief Parses Debug Report Query Response command and fills data request structure. - @param data_buf - pointer to zb_buf_t buffer containing command request data - @param req - variable to save command request - @param status - success or not read parameters - ZB_TRUE or ZB_FALSE - @note data_buf buffer should contain command request payload without ZCL header. -*/ -#define ZB_ZCL_WWAH_GET_DEBUG_REPORT_QUERY_RESPONSE(data_buf, req, status) \ -{ \ - zb_zcl_wwah_debug_report_query_response_t *src_ptr = \ - (zb_zcl_wwah_debug_report_query_response_t*)zb_buf_begin((data_buf)); \ - (status) = ZB_ZCL_PARSE_STATUS_FAILURE; \ - if (zb_buf_len((data_buf)) > sizeof(zb_uint8_t)) \ - { \ - (req)->debug_report_id = src_ptr->debug_report_id; \ - (req)->report_data = (zb_uint8_t*)(&(src_ptr->report_data)); \ - (status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \ - } \ -} - -/*! @brief Structure saved all WWAH attributes */ -typedef struct zb_zcl_wwah_attr_s -{ - zb_uint16_t cluster_revision; - zb_bool_t disable_ota_downgrades; - zb_bool_t mgmt_leave_without_rejoin_enabled; - zb_uint8_t nwk_retry_count; - zb_uint8_t mac_retry_count; - zb_bool_t router_check_in_enabled; - zb_bool_t touchlink_interpan_enabled; - zb_bool_t wwah_parent_classification_enabled; - zb_bool_t wwah_app_event_retry_enabled; - zb_uint8_t wwah_app_event_retry_queue_size; - zb_bool_t wwah_rejoin_enabled; - zb_uint8_t mac_poll_failure_wait_time; - zb_bool_t configuration_mode_enabled; - zb_uint8_t current_debug_report_id; - zb_bool_t tc_security_on_nwk_key_rotation_enabled; - zb_bool_t wwah_bad_parent_recovery_enabled; - zb_uint8_t pending_network_update_channel; - zb_uint16_t pending_network_update_panid; - zb_uint16_t ota_max_offline_duration; -} zb_zcl_wwah_attr_t; - -extern zb_zcl_wwah_attr_t wwah_attr; - -/** @internal @brief Declare attribute list for WWAH cluster - @param attr_list - attribute list name -*/ - -#define ZB_ZCL_DECLARE_WWAH_ATTRIB_LIST(attr_list) \ - zb_zcl_attr_t attr_list [] = { \ - { \ - ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID, \ - ZB_ZCL_ATTR_TYPE_U16, \ - ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ - (void*) &(wwah_attr.cluster_revision) \ - }, \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_DISABLE_OTA_DOWNGRADES_ID, &(wwah_attr.disable_ota_downgrades)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED_ID, &(wwah_attr.mgmt_leave_without_rejoin_enabled)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_NWK_RETRY_COUNT_ID, &(wwah_attr.nwk_retry_count)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_MAC_RETRY_COUNT_ID, &(wwah_attr.mac_retry_count)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID, &(wwah_attr.router_check_in_enabled)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_TOUCHLINK_INTERPAN_ENABLED_ID, &(wwah_attr.touchlink_interpan_enabled)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_WWAH_PARENT_CLASSIFICATION_ENABLED_ID, &(wwah_attr.wwah_parent_classification_enabled)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_ENABLED_ID, &(wwah_attr.wwah_app_event_retry_enabled)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_QUEUE_SIZE_ID, &(wwah_attr.wwah_app_event_retry_queue_size)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_WWAH_REJOIN_ENABLED_ID, &(wwah_attr.wwah_rejoin_enabled)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_MAC_POLL_FAILURE_WAIT_TIME_ID, &(wwah_attr.mac_poll_failure_wait_time)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_CONFIGURATION_MODE_ENABLED_ID, &(wwah_attr.configuration_mode_enabled)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_CURRENT_DEBUG_REPORT_ID_ID, &(wwah_attr.current_debug_report_id)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_TC_SECURITY_ON_NWK_KEY_ROTATION_ENABLED_ID, &(wwah_attr.tc_security_on_nwk_key_rotation_enabled)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_ID, &(wwah_attr.wwah_bad_parent_recovery_enabled)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_ID, &(wwah_attr.pending_network_update_channel)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_PANID_ID, &(wwah_attr.pending_network_update_panid)) \ - ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_WWAH_OTA_MAX_OFFLINE_DURATION_ID, &(wwah_attr.ota_max_offline_duration)) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST - - /* Declare Cluster Revision Attribute */ -#define ZB_ZCL_DECLARE_WWAH_CLIENT_ATTRIB_LIST(attr_list) \ - ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_WWAH) \ - ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST \ - -/*! @internal Number of attributes mandatory for reporting in WWAH cluster */ -#define ZB_ZCL_WWAH_REPORT_ATTR_COUNT 0 - -/***************************** commands *****************************/ - -/** @internal Structure for beaconSurvey data type - */ - -/** - * @brief Determine a parent choose priority (WWAH-Requirements C-20) - * - * End Devices examine all beacons in the Good Link Quality group - * (if received beacon with an RSSI above @see minRssiForReceivingPackets - * +30 dbm) and choose the parent with highest parent priority, as shown below. - * If no suitable parents exist in the Good Link Quality group, then the End - * Device shall examine all beacons in the Marginal Link Quality group. - */ -typedef enum zb_zcl_wwah_parent_priority_e -{ - /*! Invalid value for parent priority */ - ZB_ZCL_WWAH_PARENT_PRIORITY_INVALID = 0, - - /*! 0b00 - no TC connectivity and Short Uptime or no WWAH parent */ - ZB_ZCL_WWAH_PARENT_PRIORITY_VERY_LOW = 1, - - /*! 0b01 - no TC connectivity and Long Uptime */ - ZB_ZCL_WWAH_PARENT_PRIORITY_LOW = 2, - - /*! 0b10 - TC connectivity and Short Uptime */ - ZB_ZCL_WWAH_PARENT_PRIORITY_HIGH = 3, - - /*! 0b11 - TC connectivity and Long Uptime */ - ZB_ZCL_WWAH_PARENT_PRIORITY_VERY_HIGH = 4 -} -zb_zcl_wwah_parent_priority_t; - -typedef ZB_PACKED_PRE struct zb_zcl_wwah_beacon_survey_s -{ - /*! The DeviceShort field contains the 16 bit short address of the beaconing device. */ - zb_uint16_t device_short; - /*! This is the RSSI of the beacon, expressed in dBm. */ - zb_int8_t rssi; - /*! This is the parent classification mask. */ - zb_uint8_t classification_mask; -} ZB_PACKED_STRUCT zb_zcl_wwah_beacon_survey_t; - -/*! @brief The PowerNotificationReason field is an enum containing all possible reasons for the power notification. - */ -enum zb_zcl_wwah_power_notification_reason_e -{ - /*! Unknown value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_UNKNOWN = 0x00, - /*! Battery value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_BATTERY = 0x01, - /*! Brownout value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_BROWNOUT = 0x02, - /*! Watchdog value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_WATCHDOG = 0x03, - /*! Reset Pin value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_RESET_PIN = 0x04, - /*! Memory/HW Fault value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_MEMORY_OR_HW_FAULT = 0x05, - /*! Software Exception value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_SOFTWARE_EXCEPTION = 0x06, - /*! OTA / Bootload Success value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_OTA_OR_BOOTLOAD_SUCCESS = 0x07, - /*! Software Reset value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_SOFTWARE_RESET = 0x08, - /*! Power Button value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_POWER_BUTTON = 0x09, - /*! Temperature value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_TEMPERATURE = 0x0A, - /*! Bootload Failure value */ - ZB_ZCL_WWAH_POWER_NOTIFICATION_REASON_BOOTLOAD_FAILURE = 0x0B, -}; - -/*! @brief The Enrollment Mode field is an enum containing the possible enrollment methods for an IAS Zone server. - */ - - -enum zb_zcl_wwah_enrollment_mode_e -{ - /*! Trip-to-pair value */ - ZB_ZCL_WWAH_ENROLLMENT_MODE_TRIP_TO_PAIR = 0x00, - /*! Auto-Enroll-Response value */ - ZB_ZCL_WWAH_ENROLLMENT_MODE_AUTO_ENROLL_RESPONSE = 0x01, - /*! Auto-Enroll-Request value */ - ZB_ZCL_WWAH_ENROLLMENT_MODE_AUTO_ENROLL_REQUEST = 0x02 -}; - -/*! @} - @endcond */ /* WWAH cluster internals */ - -/*! @} */ /* ZCL WWAH cluster definitions */ - -/*! @brief Add cluster_id to Enable APS Link Key Authorization command - @param ptr - [in/out] (zb_uint8_t*) current position - @param cluster_id - Cluster ID value -*/ -#define ZB_ZCL_WWAH_SEND_ENABLE_APS_LINK_KEY_AUTHORIZATION_ADD(ptr, cluster_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (cluster_id)); \ -} - -/*! @brief Start Enable APS Link Key Authorization command - @param buffer - to put packet to - @param def_resp - enable/disable default response - @param number_of_clusters_to_exempt - Number of Clusters To Exempt value - @param ptr - [out] (zb_uint8_t*) current position for ZB_ZCL_WWAH_SEND_ENABLE_APS_LINK_KEY_AUTHORIZATION_ADD -*/ -#define ZB_ZCL_WWAH_SEND_ENABLE_APS_LINK_KEY_AUTHORIZATION_START( \ - buffer, def_resp, number_of_clusters_to_exempt, ptr) \ -{ \ - ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_ENABLE_APS_LINK_KEY_AUTHORIZATION_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (number_of_clusters_to_exempt)); \ -} - -/*! @brief End form Enable APS Link Key Authorization command - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_ENABLE_APS_LINK_KEY_AUTHORIZATION_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Start Disable APS Link Key Authorization command - @param buffer - to put packet to - @param def_resp - enable/disable default response - @param number_of_clusters_to_exempt - Number of Clusters To Exempt value - @param ptr - [out] (zb_uint8_t*) current position for ZB_ZCL_WWAH_SEND_DISABLE_APS_LINK_KEY_AUTHORIZATION_ADD -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_APS_LINK_KEY_AUTHORIZATION_START( \ - buffer, def_resp, number_of_clusters_to_exempt, ptr) \ -{ \ - ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DISABLE_APS_LINK_KEY_AUTHORIZATION_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (number_of_clusters_to_exempt)); \ -} - -/*! @brief Add cluster_id to Disable APS Link Key Authorization command - @param ptr - [in/out] (zb_uint8_t*) current position - @param cluster_id - Cluster ID value -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_APS_LINK_KEY_AUTHORIZATION_ADD(ptr, cluster_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (cluster_id)); \ -} - -/*! @brief End form Disable APS Link Key Authorization command - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_APS_LINK_KEY_AUTHORIZATION_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send APS Link Key Authorization Query command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param cluster_id - Cluster ID value*/ -#define ZB_ZCL_WWAH_SEND_APS_LINK_KEY_AUTHORIZATION_QUERY( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, cluster_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_ID); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (cluster_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Request New APS Link Key command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_REQUEST_NEW_APS_LINK_KEY( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_REQUEST_NEW_APS_LINK_KEY_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Enable WWAH App Event Retry Algorithm command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param first_backoff_time_in_seconds - First Backoff Time In Seconds value - @param backoff_sequence_common_ratio - Backoff Sequence Common Ratio value - @param max_backoff_time_in_seconds - Max Backoff Time In Seconds value - @param max_re_delivery_attempts - Max Re_Delivery Attempts value*/ -#define ZB_ZCL_WWAH_SEND_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - first_backoff_time_in_seconds, backoff_sequence_common_ratio, \ - max_backoff_time_in_seconds, max_re_delivery_attempts) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (first_backoff_time_in_seconds)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (backoff_sequence_common_ratio)); \ - ZB_ZCL_PACKET_PUT_DATA32(ptr, (max_backoff_time_in_seconds)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (max_re_delivery_attempts)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Disable WWAH App Event Retry Algorithm command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_WWAH_APP_EVENT_RETRY_ALGORITHM( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Request Time command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_REQUEST_TIME( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_REQUEST_TIME_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Enable WWAH Rejoin Algorithm command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param fast_rejoin_timeout_in_seconds - Fast Rejoin Timeout In Seconds value - @param duration_between_each_rejoin_in_seconds - Duration Between Each Rejoin In Seconds value - @param fast_rejoin_first_backoff_in_seconds - Fast Rejoin First Backoff In Seconds value - @param max_backoff_time_in_seconds - Max Backoff Time In Seconds value - @param max_backoff_iterations - max backoff iterations*/ -#define ZB_ZCL_WWAH_SEND_ENABLE_WWAH_REJOIN_ALGORITHM( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, \ - fast_rejoin_timeout_in_seconds, duration_between_each_rejoin_in_seconds, \ - fast_rejoin_first_backoff_in_seconds, max_backoff_time_in_seconds, \ - max_backoff_iterations) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_REJOIN_ALGORITHM_ID); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (fast_rejoin_timeout_in_seconds)); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (duration_between_each_rejoin_in_seconds)); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (fast_rejoin_first_backoff_in_seconds)); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (max_backoff_time_in_seconds)); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (max_backoff_iterations)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Disable WWAH Rejoin Algorithm command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_WWAH_REJOIN_ALGORITHM( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_REJOIN_ALGORITHM_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Set IAS Zone Enrollment Method command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param enrollment_mode - Enrollment Mode value*/ -#define ZB_ZCL_WWAH_SEND_SET_IAS_ZONE_ENROLLMENT_METHOD( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, enrollment_mode) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_SET_IAS_ZONE_ENROLLMENT_METHOD_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (enrollment_mode)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Clear Binding Table command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_CLEAR_BINDING_TABLE( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_CLEAR_BINDING_TABLE_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Enable Periodic Router Check Ins command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param check_in_interval - Check_In Interval value*/ -#define ZB_ZCL_WWAH_SEND_ENABLE_PERIODIC_ROUTER_CHECK_INS( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, check_in_interval) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_ENABLE_PERIODIC_ROUTER_CHECK_INS_ID); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (check_in_interval)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Disable Periodic Router Check Ins command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_PERIODIC_ROUTER_CHECK_INS( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DISABLE_PERIODIC_ROUTER_CHECK_INS_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Set MAC Poll CCA Wait Time command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param wait_time - Wait Time value*/ -#define ZB_ZCL_WWAH_SEND_SET_MAC_POLL_CCA_WAIT_TIME( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, wait_time) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_SET_MAC_POLL_CCA_WAIT_TIME_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (wait_time)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Set Pending Network Update command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param channel - Channel value - @param pan_id - PAN ID value*/ -#define ZB_ZCL_WWAH_SEND_SET_PENDING_NETWORK_UPDATE( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, channel, pan_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_SET_PENDING_NETWORK_UPDATE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (channel)); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (pan_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Add cluster_id to Require APS ACKs on Unicasts command - @param ptr - [in/out] (zb_uint8_t*) current position - @param cluster_id - Cluster ID value -*/ -#define ZB_ZCL_WWAH_SEND_REQUIRE_APS_ACKS_ON_UNICASTS_ADD(ptr, cluster_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (cluster_id)); \ -} - -/*! @brief Start Require APS ACKs on Unicasts command - @param buffer - to put packet to - @param def_resp - enable/disable default response - @param number_of_clusters_to_exempt - Number of Clusters to Exempt value - @param ptr - [out] (zb_uint8_t*) current position for ZB_ZCL_WWAH_SEND_REQUIRE_APS_ACKS_ON_UNICASTS_ADD -*/ -#define ZB_ZCL_WWAH_SEND_REQUIRE_APS_ACKS_ON_UNICASTS_START( \ - buffer, def_resp, number_of_clusters_to_exempt, ptr) \ -{ \ - ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_REQUIRE_APS_ACKS_ON_UNICASTS_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (number_of_clusters_to_exempt)); \ -} - -/*! @brief End form Require APS ACKs on Unicasts command - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_REQUIRE_APS_ACKS_ON_UNICASTS_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Remove APS ACKs on Unicasts Requirement command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_REMOVE_APS_ACKS_ON_UNICASTS_REQUIREMENT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_REMOVE_APS_ACKS_ON_UNICASTS_REQUIREMENT_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send APS ACK Requirement Query command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_APS_ACK_REQUIREMENT_QUERY( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_APS_ACK_REQUIREMENT_QUERY_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Debug Report Query command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param debug_report_id - Debug Report ID value*/ -#define ZB_ZCL_WWAH_SEND_DEBUG_REPORT_QUERY( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, debug_report_id) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DEBUG_REPORT_QUERY_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (debug_report_id)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Survey Beacons command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status - @param standard_beacons - Standard Beacons value*/ -#define ZB_ZCL_WWAH_SEND_SURVEY_BEACONS( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb, standard_beacons) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_SURVEY_BEACONS_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (standard_beacons)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Disable OTA Downgrades command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_OTA_DOWNGRADES( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DISABLE_OTA_DOWNGRADES_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Disable MGMT Leave Without Rejoin command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_MGMT_LEAVE_WITHOUT_REJOIN( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DISABLE_MGMT_LEAVE_WITHOUT_REJOIN_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Disable Touchlink Interpan Message Support command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_TOUCHLINK_INTERPAN_MESSAGE_SUPPORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DISABLE_TOUCHLINK_INTERPAN_MESSAGE_SUPPORT_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Enable WWAH Parent Classification command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_ENABLE_WWAH_PARENT_CLASSIFICATION( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_PARENT_CLASSIFICATION_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} -/*! @brief Send Disable WWAH Parent Classification command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_WWAH_PARENT_CLASSIFICATION( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_PARENT_CLASSIFICATION_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Enable TC Security On NWK Key Rotation command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_ENABLE_TC_SECURITY_ON_NWK_KEY_ROTATION( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_ENABLE_TC_SECURITY_ON_NWK_KEY_ROTATION_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} -/*! @brief Send Enable WWAH Bad Parent Recovery command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_ENABLE_WWAH_BAD_PARENT_RECOVERY( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_ENABLE_WWAH_BAD_PARENT_RECOVERY_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Disable WWAH Bad Parent Recovery command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_WWAH_BAD_PARENT_RECOVERY( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DISABLE_WWAH_BAD_PARENT_RECOVERY_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Enable Configuration Mode command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_ENABLE_CONFIGURATION_MODE( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_ENABLE_CONFIGURATION_MODE_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Disable Configuration Mode command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_DISABLE_CONFIGURATION_MODE( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DISABLE_CONFIGURATION_MODE_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Add cluster_id to Use Trust Center for Cluster command - @param ptr - [in/out] (zb_uint8_t*) current position - @param cluster_id - Cluster ID value -*/ -#define ZB_ZCL_WWAH_SEND_USE_TRUST_CENTER_FOR_CLUSTER_ADD(ptr, cluster_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (cluster_id)); \ -} - -/*! @brief Start Use Trust Center for Cluster command - @param buffer - to put packet to - @param def_resp - enable/disable default response - @param number_of_clusters - Number of Clusters value - @param ptr - [out] (zb_uint8_t*) current position for ZB_ZCL_WWAH_SEND_USE_TRUST_CENTER_FOR_CLUSTER_ADD -*/ -#define ZB_ZCL_WWAH_SEND_USE_TRUST_CENTER_FOR_CLUSTER_START( \ - buffer, def_resp, number_of_clusters, ptr) \ -{ \ - ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_USE_TRUST_CENTER_FOR_CLUSTER_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (number_of_clusters)); \ -} - -/*! @brief End form Use Trust Center for Cluster command - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_USE_TRUST_CENTER_FOR_CLUSTER_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Trust Center for Cluster Server Query command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param def_resp - enable/disable default response - @param cb - callback for getting command send status -*/ -#define ZB_ZCL_WWAH_SEND_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_SRV, ZB_ZCL_MANUFACTURER_SPECIFIC, def_resp); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_ID); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send APS Link Key Authorization Query Response command - @param buffer - to put packet to - @param seq - sequence - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status - @param cluster_id - Cluster ID value - @param aps_link_key_authorization_status - APS Link Key Authorization Status value*/ -#define ZB_ZCL_WWAH_SEND_APS_LINK_KEY_AUTHORIZATION_QUERY_RESPONSE( \ - buffer, seq, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb, cluster_id, \ - aps_link_key_authorization_status) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, (seq), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_RESPONSE_ID); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (cluster_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (aps_link_key_authorization_status)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Powering Off Notification command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status - @param power_notification_reason - PowerNotificationReason value - @param manufacturer_id - Manufacturer ID value - @param manufacturer_power_notification_reason_length - Manufacturer Power Notification Reason Length value - @param manufacturer_power_notification_reason - Manufacturer Power Notification Reason value*/ -#define ZB_ZCL_WWAH_SEND_POWERING_OFF_NOTIFICATION( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb, \ - power_notification_reason, manufacturer_id, \ - manufacturer_power_notification_reason_length, \ - manufacturer_power_notification_reason) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_POWERING_OFF_NOTIFICATION_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (power_notification_reason)); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (manufacturer_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (manufacturer_power_notification_reason_length)); \ - ZB_ZCL_PACKET_PUT_DATA_N(ptr, (manufacturer_power_notification_reason), \ - (manufacturer_power_notification_reason_length)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Powering On Notification command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status - @param power_notification_reason - PowerNotificationReason value - @param manufacturer_id - Manufacturer ID value - @param manufacturer_power_notification_reason_length - Manufacturer Power Notification Reason Length value - @param manufacturer_power_notification_reason - Manufacturer Power Notification Reason value*/ -#define ZB_ZCL_WWAH_SEND_POWERING_ON_NOTIFICATION( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb, \ - power_notification_reason, manufacturer_id, \ - manufacturer_power_notification_reason_length, \ - manufacturer_power_notification_reason) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_POWERING_ON_NOTIFICATION_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (power_notification_reason)); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (manufacturer_id)); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (manufacturer_power_notification_reason_length)); \ - ZB_ZCL_PACKET_PUT_DATA_N(ptr, (manufacturer_power_notification_reason), \ - (manufacturer_power_notification_reason_length)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Short Address Change command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status - @param device_eui64 - DeviceEUI64 value - @param device_short - DeviceShort value*/ -#define ZB_ZCL_WWAH_SEND_SHORT_ADDRESS_CHANGE( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb, device_eui64, device_short) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_SHORT_ADDRESS_CHANGE_ID); \ - ZB_ZCL_PACKET_PUT_DATA64(ptr, (device_eui64)); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (device_short)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Add cluster_id to APS ACK Requirement Query Response command - @param ptr - [in/out] (zb_uint8_t*) current position - @param cluster_id - Cluster ID value -*/ -#define ZB_ZCL_WWAH_SEND_APS_ACK_REQUIREMENT_QUERY_RESPONSE_ADD(ptr, cluster_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (cluster_id)); \ -} - -/*! @brief Start APS ACK Requirement Query Response command - @param buffer - to put packet to - @param seq - sequence - @param number_of_clusters_to_exempt - Number of Clusters to Exempt value - @param ptr - [out] (zb_uint8_t*) current position for ZB_ZCL_WWAH_SEND_APS_ACK_REQUIREMENT_QUERY_RESPONSE_ADD -*/ -#define ZB_ZCL_WWAH_SEND_APS_ACK_REQUIREMENT_QUERY_RESPONSE_START( \ - buffer, seq, number_of_clusters_to_exempt, ptr) \ -{ \ - (ptr) = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, (seq), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_APS_ACK_REQUIREMENT_QUERY_RESPONSE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (number_of_clusters_to_exempt)); \ -} - -/*! @brief End form APS ACK Requirement Query Response command - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier -*/ -#define ZB_ZCL_WWAH_SEND_APS_ACK_REQUIREMENT_QUERY_RESPONSE_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, NULL); \ -} - -/*! @brief Send Power Descriptor Change command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status - @param node_power_desc - Node Power Descriptor value */ -#define ZB_ZCL_WWAH_SEND_POWER_DESCRIPTOR_CHANGE( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb, node_power_desc) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_POWER_DESCRIPTOR_CHANGE_ID); \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (node_power_desc)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send New Debug Report Notification command - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status - @param debug_report_id - Debug Report ID value - @param size_of_report - Size of Report value*/ -#define ZB_ZCL_WWAH_SEND_NEW_DEBUG_REPORT_NOTIFICATION( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb, debug_report_id, \ - size_of_report) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, ZB_ZCL_GET_SEQ_NUM(), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_NEW_DEBUG_REPORT_NOTIFICATION_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (debug_report_id)); \ - ZB_ZCL_PACKET_PUT_DATA32(ptr, (size_of_report)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Send Debug Report Query Response command - @param buffer - to put packet to - @param seq - sequence - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier - @param cb - callback for getting command send status - @param debug_report_id - Debug Report ID value - @param report_data - Report data value - @param size_of_report - Report data size */ - -#define ZB_ZCL_WWAH_SEND_DEBUG_REPORT_QUERY_RESPONSE( \ - buffer, seq, addr, dst_addr_mode, dst_ep, ep, prfl_id, cb, debug_report_id, report_data, \ - size_of_report) \ -{ \ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, (seq), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_DEBUG_REPORT_QUERY_RESPONSE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (debug_report_id)); \ - ZB_ZCL_PACKET_PUT_DATA_N(ptr, (report_data), (size_of_report)); \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, cb); \ -} - -/*! @brief Add cluster_id to Trust Center for Cluster Server Query Response command - @param ptr - [in/out] (zb_uint8_t*) current position - @param cluster_id - Cluster ID value -*/ -#define ZB_ZCL_WWAH_SEND_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_RESPONSE_ADD(ptr, cluster_id) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA16(ptr, (cluster_id)); \ -} - -/*! @brief Start Trust Center for Cluster Server Query Response command - @param buffer - to put packet to - @param seq - sequence - @param number_of_clusters - Number of Clusters value - @param ptr - [out] (zb_uint8_t*) current position for ZB_ZCL_WWAH_SEND_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_RESPONSE_ADD -*/ -#define ZB_ZCL_WWAH_SEND_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_RESPONSE_START( \ - buffer, seq, number_of_clusters, ptr) \ -{ \ - (ptr) = ZB_ZCL_START_PACKET(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, (seq), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_RESPONSE_ID); \ - ZB_ZCL_PACKET_PUT_DATA8(ptr, (number_of_clusters)); \ -} - -/*! @brief End form Trust Center for Cluster Server Query Response command - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier -*/ -#define ZB_ZCL_WWAH_SEND_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_RESPONSE_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, NULL); \ -} - -/*! @brief Start Survey Beacons Response command - @param buffer - to put packet to - @param seq - sequence -*/ -#define ZB_ZCL_WWAH_SEND_SURVEY_BEACONS_RESPONSE_START( \ - buffer, seq) \ -{ \ - zb_uint8_t *ptr = zb_buf_begin(buffer); \ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RESP_FRAME_CONTROL_A(ptr, \ - ZB_ZCL_FRAME_DIRECTION_TO_CLI, ZB_ZCL_MANUFACTURER_SPECIFIC); \ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(ptr, (seq), \ - ZB_ZCL_MANUFACTURER_SPECIFIC, WWAH_MANUFACTURER_CODE, \ - ZB_ZCL_CMD_WWAH_SURVEY_BEACONS_RESPONSE_ID); \ -} - -/*! @brief Add beacons number and beacon survey info to Survey Beacons Response command - @param ptr - [in/out] (zb_uint8_t*) current position - @param src - source pointer to the first Beacon value - @param num - number of beacons -*/ -#define ZB_ZCL_WWAH_SEND_SURVEY_BEACONS_RESPONSE_ADD_ALL(ptr, src, num) \ -{ \ - ZB_ZCL_PACKET_PUT_DATA8((ptr), (num)); \ - ZB_MEMMOVE((ptr), (src), ((num) * sizeof(zb_zcl_wwah_beacon_survey_t))); \ - (ptr) += ((num) * sizeof(zb_zcl_wwah_beacon_survey_t)); \ -} - -/*! @brief End form Survey Beacons Response command - @param ptr - (zb_uint8_t*) current position - @param buffer - to put packet to - @param addr - address to send packet to - @param dst_addr_mode - addressing mode - @param dst_ep - destination endpoint - @param ep - sending endpoint - @param prfl_id - profile identifier -*/ -#define ZB_ZCL_WWAH_SEND_SURVEY_BEACONS_RESPONSE_END( \ - ptr, buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id) \ -{ \ - ZB_ZCL_FINISH_PACKET(buffer, ptr) \ - ZB_ZCL_SEND_COMMAND_SHORT( \ - buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_WWAH, NULL); \ -} -zb_bool_t zb_is_wwah_server(void); -void wwah_post_commissioning_actions(void); -zb_bool_t zb_zcl_wwah_check_new_channel(zb_uint32_t new_channel_mask); -zb_bool_t zb_zcl_wwah_check_new_panid(zb_uint16_t new_panid); -zb_uint8_t zb_zcl_wwah_mac_poll_cca_retry_count(void); -zb_time_t zb_zcl_wwah_mac_poll_failure_wait_time(void); -zb_bool_t zb_zcl_wwah_check_if_forced_to_use_tc(zb_uint16_t cluster_id); -zb_bool_t zb_zcl_wwah_check_zdo_command(zb_apsde_data_indication_t *di); -zb_bool_t zb_zcl_wwah_check_if_aps_ack_needed(zb_uint16_t cluster_id); -zb_bool_t zb_zcl_wwah_check_if_aps_link_key_authorization_needed(zb_uint16_t cluster_id); -zb_bool_t zb_zcl_wwah_check_cluster_permission(zb_uint16_t nwk_addr, zb_uint16_t cluster_id); -zb_bool_t zb_zcl_wwah_check_if_leave_without_rejoin_allowed(void); -zb_bool_t zb_zcl_wwah_check_if_wwah_rejoin_enabled(void); -void zb_zcl_wwah_schedule_send_power_descriptor_change(void); -zb_bool_t zb_zcl_wwah_check_zdo_command(zb_apsde_data_indication_t *di); -zb_bool_t zb_zcl_wwah_check_if_interpan_supported(void); -zb_bool_t zb_zcl_wwah_check_if_downgrade_disabled(void); -zb_bool_t zb_zcl_wwah_periodic_checkin_read_attr_handle(zb_uint8_t param); -zb_bool_t zb_zcl_wwah_periodic_checkin_block_zcl_cmd(zb_zcl_parsed_hdr_t *cmd_info); -void zb_zcl_wwah_periodic_checkin_tc_poll(zb_uint8_t param); -void zb_zcl_wwah_periodic_checkin_match_desc_req(zb_uint8_t param); -void zb_zcl_wwah_periodic_checkin_match_desc_req_delayed(zb_uint8_t param); -void zb_zcl_wwah_stop_periodic_checkin(void); -void zb_zcl_wwah_start_periodic_checkin(void); -zb_bool_t zb_zcl_wwah_check_src_addr_for_cluster(zb_uint16_t short_addr, zb_uint16_t cluster_id); - -void zb_zcl_wwah_set_wwah_behavior(zb_uint8_t behavior); -void zb_zcl_wwah_stop_bad_parent_recovery(void); -void zb_zcl_wwah_start_bad_parent_recovery(void); - -#ifdef ZB_JOIN_CLIENT -zb_ret_t zb_zcl_wwah_get_rejoin_tmo(zb_uint16_t attempt, zb_time_t *tmo); -#endif - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#define ZB_ZCL_WWAH_REPORT_ATTR_COUNT 0 - -#if (defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && (defined ZB_ZCL_ENABLE_WWAH_SERVER || defined ZB_ZCL_ENABLE_WWAH_CLIENT)) -typedef ZB_PACKED_PRE struct zb_zcl_wwah_context_s -{ - zb_uint8_t wwah_behavior; -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER - zb_uint8_t wwah_hub_endpoint; - zb_uint16_t wwah_hub_address; - zb_uint16_t time_server_addr; - zb_uint8_t time_server_endpoint; - - zb_uint8_t aps_ack_exempt_table_cnt; - /* This is a list of clusters that should be exempt from requiring APS ACKs on unicasts. */ - zb_uint16_t aps_ack_exempt_table[ZB_ZCL_WWAH_APS_ACK_EXEMPT_TABLE_SIZE]; - - /* ZB_TRUE - enforces that all cluster commands for the cluster have APS level security - * except for those in the exemption list*/ - /* ZB_FALSE - enforces that all cluster commands for the cluster doesn't have APS level security - * except for those in the exemption list. This is default value*/ - zb_bool_t aps_link_key_enabled_by_default; - - zb_uint8_t aps_link_key_authorization_table_cnt; - /* This is a exemption list of clusters for requiring APS level security */ - zb_uint16_t aps_link_key_authorization_table[ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_TABLE_SIZE]; - - zb_uint8_t use_trust_center_for_cluster_table_cnt; - /* This is a list of clusters that should be forced to use the Trust Center. */ - zb_uint16_t use_trust_center_for_cluster_table[ZB_ZCL_WWAH_USE_TRUST_CENTER_FOR_CLUSTER_TABLE_SIZE]; - - /* ======= Survey Beacon related context ======= */ - zb_uint8_t survey_beacons_seq_number; - zb_uint8_t survey_beacons_in_progress; - - zb_zcl_wwah_periodic_checkins_data_t periodic_checkins; - - zb_zcl_wwah_enable_wwah_rejoin_algorithm_t rejoin_alg; - zb_zcl_wwah_bad_parent_recovery_data_t bad_parent_recovery; -#endif -#if !(defined ZB_ZCL_ENABLE_WWAH_SERVER || defined ZB_ZCL_ENABLE_WWAH_CLIENT) - zb_uint8_t make_iso_compiler_happy; -#endif -} zb_zcl_wwah_context_t; -#endif - -#define ZB_ZCL_WWAH_REJOIN_SLEEPY_ED_TIMEOUT (ZB_TIME_ONE_SECOND * 60 * 15) -#define ZB_ZCL_WWAH_REJOIN_NON_SLEEPY_ED_ROUTER_TIMEOUT (ZB_TIME_ONE_SECOND * 60 * 60 * 24) -/* For debug purpose: #define ZB_ZCL_WWAH_REJOIN_NON_SLEEPY_ED_ROUTER_TIMEOUT (ZB_TIME_ONE_SECOND * 60)*/ - -#define ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_TIMEOUT (ZB_TIME_ONE_SECOND * 60 * 60 * 24) -/* For debug purpose: #define ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_TIMEOUT (ZB_TIME_ONE_SECOND * 30)*/ -#define ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED_CNT 3 -/* FIXME: Is it defined somewhere in WWAH spec? */ -#define ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_RSSI_IS_GOOD(rssi) (rssi >= -100) -void zb_zcl_wwah_bad_parent_recovery_signal(zb_zcl_wwah_bad_parent_recovery_signal_t sig); - -zb_ret_t zb_zcl_wwah_request_new_aps_link_key_handler(zb_uint8_t param); -zb_ret_t zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_handler(zb_uint8_t param); -zb_ret_t zb_zcl_wwah_disable_wwah_app_event_retry_algorithm_handler(zb_uint8_t param); -zb_ret_t zb_zcl_wwah_request_time_handler(zb_uint8_t param); -zb_ret_t zb_zcl_wwah_enable_wwah_rejoin_algorithm_handler(zb_uint8_t param); -zb_ret_t zb_zcl_wwah_disable_wwah_rejoin_algorithm_handler(zb_uint8_t param); - -void zb_zcl_wwah_init_server(void); -void zb_zcl_wwah_init_server_attr(void); -void zb_zcl_wwah_init_client(void); -zb_ret_t zb_zcl_wwah_update_time(zb_uint8_t param); -#define ZB_ZCL_CLUSTER_ID_WWAH_SERVER_ROLE_INIT zb_zcl_wwah_init_server -#define ZB_ZCL_CLUSTER_ID_WWAH_CLIENT_ROLE_INIT zb_zcl_wwah_init_client - -#endif /* ZB_ZCL_WWAH_H */ diff --git a/zboss/development/lib/cortex-m33/hard-float/libgppb.a b/zboss/development/lib/cortex-m33/hard-float/libgppb.a deleted file mode 100644 index 9698b6ddae9a26f20c9f365c065a5852239e9070..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78026 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 WYsZgqqH+747!uf|oaA4l_x}Knb2*^^ diff --git a/zboss/development/lib/cortex-m33/hard-float/libncp-dev.ed.a b/zboss/development/lib/cortex-m33/hard-float/libncp-dev.ed.a deleted file mode 100644 index b8a3db610eabd40475da41449ff435ba8e180d14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96858 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 z 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

Mrm;xlo+4J>V}KU2$fE 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 diff --git a/zboss/development/lib/cortex-m33/hard-float/libzboss.a b/zboss/development/lib/cortex-m33/hard-float/libzboss.a deleted file mode 100644 index ae29de2f9d7e45eb92731c2dc125b714ef81117e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 871294 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�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

?Mtpb;eWVbFOv|Y5FInX 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

SK9mRU5Myq(wExzJl zqPj7EVtUIelnYP6S%2Et<ye%kLZae!%~X#c$zx)lb+ZVd(niNLMd^ zUUgu@gLaAN)#6)=kgjiUwZb8;BDxo~MXUtqLRr@MyRnj{Bz8?k0JkVD4Lnno(=i%l zORfZ?Pf?=&__BbD*|YXQC*@_!aJ(z)s4pvUGNHRzAQ5?VWuIk%a@+$SZ)7254sXMq3cd)r5fdFIi86p zF*2~qBYziBh@Za;ICXQ-(k}-^F4_Ky^e-dbuB1N;x37#J{BTAtZUK9|G}2m`kUGk_ z#9xdfdyi)MkU9}}&#=UCbx7KZekk(QiXQD?j>{36AFDh5%v|yLimjEhKFjc^6}9J! za;4i`mN9Ku#_mI(-&57OO)b{h&}-}+`>B<>){*`}l@B+2Evx@<+?YWLFUn>H}*X~#aA(wIw{)=WhYw2A z;En+kx7wAX0w;DiwUqr!M^yC=!D0&|B(}+!iNHgm3`BgzfyYo?U7t`s-+ z5Vd+mr&a!XJALG;Ca$Mh^4xD#-)EMEjBRs73CPFoIDyUA*};?kBH5#(ytP|*@V201 z*!7j2(EUcd4flQd##hOH@z?Cnc2(|-ZM#?HL@+VC)hg;MWQnx}(AxPTea6dt$Ura6 zQ9`frOidt>*=DW$Z|sEfi?TIatuUI}mJ`Vw?-yzGMXX}~Mr+mEo&E%Op#4Fm;}F`) zcKrNB9H|q{hw(i}4>@s4l!FnWyk{oAHGus3FfDT@G~RGhg}1lK)-{+|zoS3arGEI; zomgcSKQ{Vil!6@Mg^I7Me%)v}s5nx{5Ix-$H08s2C~M`@Jfr&GoE*dLxt zuAbqtn#XT`>*j*SX^o@@)*NXrzd6vA5jfH?_hvn=vc)*HYg-7dyBg06*{x`;s@pXk zbh1w9?FL|#xzUpvmKp4kbIuVZEK}6<0=kI$nS+`xrFa2#IwwY5>NwI8 z(Ka1J8cJ!PC<{GGrVPjRxxOq>=7NdL*8E9NbQYkclP)?G>nzrV3q4wcp0LM;v5KtA z=kKx6dPH&#Q8G%-i%#7B9HqInGi}nM&g)K|I;GoR+E;?U8b7qf{_Ok&oKXk6e=x z*#9Wn%7Yk>J!(%F^+v{H`>pcFMD2-frO&k)k^OC00UGU?qh=otx5}6obkzixcarCg z^tAo1+wVIc2W>@vqw3(VI;fq!okU6Nkg{+EV*PU#Muq7jEi=%LY{2BuPrVz3k*8hT z`k-#h7Af#_AaQ2GI+~NwSHDgFYDd)w@irZsL9P4ILrHy#+EsqC9V0RHQll|S^sPMO zXpg{7TWa37Hh;$xc8{E55j&nlerUTiQ8@lA;qx+bwkA-DH}1k5*-QKiE9&!wpN#3( zom_?9BcOYt*V^9^W7GHXHZ3`#v7dG1s1}CnOl2)cP2RX!yipY;#QVvqr&L?&Ez=p> z^jo6rMP#3Xc~i8(m7}hKp7Xl=y@It^BaXR;K&`%Sj`e``dwvX{cXh7R37$r|?G?T@2AuCF@Mo-?!uYPyV7`u$P(EwB1RyA^&*$(lC7 zmw4D7KPp(uJ6-R>6Y^n~`@Rc#{wYr!&~uH{_5a2?O|HvyO;CIzWgMKdPqlY8nLk~e zg+YGK4R>F+nJLzN!b_P*PA&kfI6Y}fEkvE=x21b?l= z!dYk6@D8zL{#?QD&S`Vz-8H;JESbNL>xriTb_OT=pDFP6I$UQuPkadA14J_aR|Nmd z4i`TtxF%rrGx+-n{<#iIKj(=L0i4R1j6Xo|PjR^TMaeY*%+4qC4|F~86tK=R{Ld12 zZuvRO;4d=xiwysW;U5ur4>(*A=ZOyitQbg^uSD>>`Bh@@4>tG*3;yK}*I?&~58M=x zj2{*JnJj?9xFwGy?-WbsFBSZgoR1%+GMM_yJH?Xu%LV`Q4p+JJ#0TCfmdrm)@W&i^ z@bTJXc&Au0KWmL^c!yZB{|MI;PrNfM*?**n&n;gg4gOIE|0u)1((tboc=--jrSrrG z-Vv4@{}{o~Ixo!_{UGcBzCI=Mj}`ncI9zVYpi{uQ(BQvN@N<2IG+0F8F##)X@W%ze zD|Ot%P5df@ze>vQ;8z*^H3ol;;O}y{YMduN1aJdEa(WYnf34wPEAR>&F1IC=coPi% z34(u`!|(kH$oMB2{F4N~o1c@MkP`ngga0zaAB#skhIfQ*^w4ar`HfW@(l2QOHtE+5 z`Y#5}H8t9h|15*%*)iJCKW@;|47$#sd7h{?4F3pdI>qqgI^WHTUMT2()^8QfHZvC~ zI7DV;82+U4XHMnfAJ^Ki{A)HRxFe&GQ+xVfaT4dW%8xyhLrt{}+Qk0h;nn z#V;5AW8a|WmgR}(6w*H;{0CYS70o)4i~jF=MdK4R=pt*eq8}G@#9F85m4Y5@?ND@F z&?S~W@2?Lc$whzjXZUMFc|SJjY&9269{Qhc(4#?9-dV_pT=YlR8vYFiz1*N5HR$IJ z`qu{iwn6{hp!<5h-&5Y927ReP&oSsl2K|IVZv)Nr?!_+`{pst9<~hi@=r2Dq`1@vn zQ5niJ#-OKyCf;EDa#3qXTn1n##dy}=YnQ@viyv) z>J-g38Yf6u%N4yu&||EpjPSdZzfAvF>m9@Y?*`oui!2!5B%z-Rtx7JsP=@l=8#LFF zXhZ+C2K`He?l9=T8gv$32^fDIzg+x{Df$5+PnA^zS{ueU&!F!x=#2)w%b@>i&;xqN z_$fp#PNKd5v^I?Ia)VxA&?^o4SuueLUn9ddMxKH7x>ELLx#6ot-JBO>zB@R}&={3&o zE(~|EKm9y=Iot*M#s-LPtNFP|n@j$jmG=}6M{Z2VVMcT4sblT7vRdD&C$-RYs}PoQ ztL-SfU8}BPG161Fh?n!tuWy`*o2|e>SQ$zz;%-=gb=cm3@K$P*pp=jP*UKFy0#9g3 zd&tNM%j{IE@fX(3y@^f|O2(&m$|xbojaA@tZdg2Bb4xzusDyG+kP5ii`DV7@`JbN*moN)5jyP<|rdT3ePnwqd;ojxqian=(mTbgPP-mmX_h!59q#O?!mY7cRL@cUtkluADp=dO& z=LWc@MRRbI7q)(V4*#4w(OgoIUR~)`tkdV={>15vn(Cn`v`%y9)-9M-k9=D+|EBp1 zZbfg%t%NfFbmAzW$P*?GTi%e{x6I*Pj@YZF1yPyd)HQ}dEvawTLb%x}HzYbCJ-YO2 zdhP_SQipF1f@?)u{sJ41RPCV=p*;)`Iz>^^wS)uFwm7JrY~b zkq~wxvd?k%im|LLXvDrOIE!t2-kjDQAd9vvNN#emM-x@W8Sr!yT?pr>n;YZg?#;S+ zGTok*4Ffo@Ms)ASSarT&n35Eo&Ql{3nwSetV2R7r2=8G0e zUhkRQm2)fWt=tU9x>Jun9#XQG6IZi3BL>e-%x+3jAywxnyCUSN8f2tk_w+3b^##tX z_9Ce%MheM=K)1P2lB&GjqL2d*G$=R7&Ku)s_ey772-L8ek;)P(3!mKm=o!06&s2Ft zNtmZDL>+eY-Nq%9k@c>716|)NBK36M=pL~P5c%qKolSfn;cIi~R=$J4=F2Ti;bPaF@5iCr zut$zIJ_1$J#!D*avHW+)`4s=1axa`8la!nZEc}+-w?JIJFVPMwyOef|yc0FFRNiGt zdWv$Nq3pTJrbzT(K^yU}RQ4L!{=1aiz~_6If0;UacDan7a+JWm5aC4nG++Md`LsUx zj>dSy%C3dY^fG<4DX;$?sSoO_1~lU_!;e+`ab=T_ch;7}W;p7T;WA-UPn<~)eOuj8 z`GDL*8G2BjjUW1s)HnHVAm4rJ&dL^f<~-$nlUfBMJ!$-d;ZIrLeXg{v@rb4a;;-Q>TpFEpY=o|W@9#ZKYSuFG^($Orx zt5QD~(j9uJrH$}YU{g*}p1<$Pl}&%>tq*O;RS28;)sr;zAmoG|sz|q}@JQcO(8LSU z9s0YP_7BzFve1{vH>7tV-66*VeR&$VIu@pIDf|DE!GpEl$Wdt4z0zo{|aY}$w{hxSJBkPq^U_5nDfNVlkR z_l(l>CJQq!a7Vrfy*?}NJmQ_LbLsw^+Kanc>M?|HP_5AacG|7@gZPNcb8#pa=MSl$ zZ_-|4SuM1;AUy4@NRM*gP5XJv`VDR5YddYo@fq!ZK^pw95k8kT-22nshH^q1>ET{7 z@^RjteEe4E|0&8JZRp`DWlyF3Gqk6)p{E(Nwzx@aQlEJzMtV?=PQ39&&%+mJKEza+K;QdiV?mMbm1CT-#zIMJ@=&z zImgn5TnXC0Qu08L-yq$h+I_f-diZZj-^kw=;7|E>E1T&nMB!mR6#l#1E6?(Cx_mAH zAMNo9QA|BcYp;y?HbBVIq9+6&7`wg_)wBK~|uaxmZ&m(CA_bS?d zQ1ue|@=eljtMY<=e+lV#a1Iu2q<0N%RNC*;MtU~UMq|3Stl$1as=lDG3jIS*1@uR{`om_u9ZVbfEb0mDY05ue*@FMS zWc_73_z&+zm*aW$KBQg=Qp~C+ZSns6F!Ghg4Ip0)JhSI=rrl*Y-GsZ#;kUX)No-R4NpE1@IiwW4spmzL7q-{nI}yVTJv<9F?D&9!T54&-Z!iT z@x1=(Sw?SWJL*!N&itnv7g(gKPCFBt#496Cn%aVVdgd;PRp)>_-HTCsUcQq!CFtqr z+EOqlN#IPbrC|J$(`+e1eyQoPq;N>_=S-9(vC1SHGXZ+aEQwR9(K{b>IyFkp)H7a5 zkSQZKrizjRcqfX*>`Jol=g+ew@t!_vX9gq%|7qt!Qt&bpK6h5c69%(ApEEyVG;OKo zLjLE+bo^7@h0XDRHXNJMl;f9$UmQPS&XH?NE(gK!Dt{ao&cYAF3^B%qCC-7OpEeqA z1{}P2IlyCh;-%xK@$h<(gf|!T4E(gw*chH9;pGD_4maWvSL1PP;+5|e(2wJ%jmFyo z2d{infj1j&#KX|U!NV{t32!#QIeyee<6+p6gtr@bQMeJ0;~FjB-|*~}Z_R1&J^`Os zzQZ28o*uk`2=B#v8N^la*G9|N5AI$(?DTQ;mjh-k-xve002x}V!4w}!o)6;1n*zK_ zxHG-E_-VW=4Lq(%Dull_Aca|M@GXZ2b*ha{$08%%6^M5Qm>BPw`002bH}IwgQsYto z-gM*)cgw+7Ja{_{Jgx~_2!Cy~d_Obrnt?Y3Oq8!5ep^9;O#G&$}Di!kJ);hDQ$ zycqCwxjzg38jo`rUiq4V$ML;3@D^r~!M7TGsp{{|M!ZuI?+hR?9TEI=ygxMXVrYEg z@YhDC;|T+AJMc2WM7$FGG~R9luK{=~HJIWf`GSGB8+goL;tj@6i%w zKAz|0)pLG@eE%dK^{w&FKsop7xepS-I;V}s%L1PlZw2r;pF%voH)_1m23|87$GsX% z@sT{&z}r63O)vWvjmNc|UirrMkn?QBpwaTpFz|BDmFF^1zF~@w`STqEuLX@Q^{b6e z`uzsp%fQP46Ymaq!cpV0w4ZL?`1GizAF4Q-lYa!dvAEAz#DJiZAYeVR(LfYyu~J7uAG+y zi!i!=EHdzBk9Nyn0-RdDjRxLf;ISNNqtp8@23|Apn4e5NK9+ZF$U{S0W0TJBgFqec}0QmBYXE-Ds<&@}2Y7a&WIE&l8wkI^#G# z_`>E1S}@2)kmWmxZgLcZ8~m*?Zfb6-pnZ2 zzw(o`@I#-Z#b2-fQ}su^-t6`Ls+J`WF3A@AkbPDc}%+CNAXm~Q>fs=dqk4?GX?)_%`RF6hX8-bX-_DrPrTiE{V@RX z817FU4w|W^47rg1Dvv+Y@pb&@&-$GU`5#pDTtR1wGg|Q|j7T@9TE(gA>hRIJxj5{8 z&JF6!b$O917F$-f|Bf!;+79>+tj9%>d1Mqm9P<9vr-Qyz3+kH_AsGjrRhc ziKqLvSMbbwt_}TYev2QUV6JjB!9id%W=8qcYdr>ppI{?msY=ffYdH|i7F zKIrT#&WMutK9c889pk|BLFaWvE9^PqR@Ah_bvRptl2*(fop{O4h*d1ksy))!w79G( z4RY_O+08fI+^=|ryxsx+$>4R}onFGyBKI&)b36+NwSsKWg@u^=S{_ ze5*?!d!0&q9GYF)l$^StNPXSnCl~V`v}f(?7*EXDX=md!s@#tAM9M!eXI#=6Q#V!vRCZYjOP|l+Ev}< z4+OgYhBJtI#d6OnpPh98rx$Jv9=TVXUh>RhU&S*wZ}02_3D@8Jf6BXh5Gi6P9Bv0) z1`8WOWswnY*G11o3p)!f9KpjYEe;F+xdnfYo%2u&#k0{)RIIcVPOwmHu29ax!g4t+ z1PifoK@hZC!NTuL@-j(o&YxBT*_W5Rd6SvVym`sI_i}BZnw@+;zl-Zs+Z*p&&vw~( zB&uCsY~|efZef4&ElIw-Q9J63yAl7-#Q#+7d;J7arA+L;TZ2PSC6Wn`Y~~*at^C8F z>0(Fm)-!6Q|0|NODs_eJZ4{YkJBulPGP=M13lxPc{9hBQZimQ0h}5{TgY~uoiiPGv3EOkAgCE zJi@O6XZQNZ)W04??Y?~F@h_wHw-Nq1!hb|~&D{&57p;%*u?Rm9;ap!})kXYppS5n( zJ{RFPfwQWO%zerpN9`{n{F9~UJCOe6rH)rz=*`lT;M6gESuBjAxl92JiR|uC-fm2P zt8=*%X!j|2J@|c~U9-4#ls_1Ymwa*jWd@N!2-0Ab|sMwY}*Bp9ah*#mt%*FCwt~GFrynNz}nJ#Gahw%Qv zdYqfK6tLdL4f`d5)L)Eu*~GmkW(aX!N;LAPWRX2&*q#C3v=u*{;?h}o-T=<@44je@?OIfa z>c8q7FAC3u#tmbcFob_Z6=mgsub6^VjU|t4#UbfNjs0f*yAkk@&13k!lO+277%KdE z!dHwN3T(6@E)7`~3RgC-)3ZuKeB7 z@!4lu0?|QJ)W77xJc1ugNv5T#0c4LLmWHUN_3HWEm3s%RMIA(e?jOs%1~j?E{dHD* T9V8#7cwRKb_0m3Dk`#Xe;UIs6 diff --git a/zboss/development/lib/cortex-m33/hard-float/libzboss.ed.a b/zboss/development/lib/cortex-m33/hard-float/libzboss.ed.a deleted file mode 100644 index fb179e5b478734d737bd894c1234d48aa0f77ee5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 688254 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 y?lyzOUq#27E)1~h7M|U3 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�+=1DGR_+tEc&=TK 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 UwIfe-?)h*i7~d(A#9xi~zjL~~!vFvP diff --git a/zboss/development/lib/cortex-m4/hard-float/libncp-dev.a b/zboss/development/lib/cortex-m4/hard-float/libncp-dev.a deleted file mode 100644 index 4cc39939a01d88bfb7e00dc207d9809ac804e9e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103058 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 Ohi4d@l#~2x^!^W#@EZOA diff --git a/zboss/development/lib/cortex-m4/hard-float/libncp-dev.ed.a b/zboss/development/lib/cortex-m4/hard-float/libncp-dev.ed.a deleted file mode 100644 index 9d7b88bf42aecacfb30a381181a6b63d3f8b6bf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96730 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%0DjK+NW4Ab<4%GaB7%S=?5oHO?i* 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

Nm6oR-oU>7e&KjT~j}9+}WfP1IPmG*d9FCVI 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≫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�<-QZ~xO10s)PYRL&lmWtJL&S(58?BUp>+Hq z0{;pdi@Sp<$2*47@rMa{x~MMv@gSb%H|-?Y^mRDiIh3BhK;WyrMo5Mn*zA8n7k*IS zr^+96;fGxKA%Wj)V}|gw0V23lEezCyM zw>L0TEids$x$s8`d{a~~F-Gx^?F@{Hbo!$O{wf%gPZx z>4MK;MOcpUV_fh=7d#6vNzA|>>Ub`5#ecyC(~hTdr0>?Tea#jBAz;$y804K)=b|qY z=D4TM<|iz;RKWS#r!AO$jCV-gV)uR7K6km``z(A(uRz7t;RVN^iR0 zOt0jRBY6PE`*6U@vAmzO;^*NvHQ2AS;9}4jfbqM~g}=%LZ+5}ow9*GqPXjPsUvS00 z=7N9Yf={~OT$hgP1ul5J3!dbHZvf2pStI(xXsy{5f4>z!MU;Pxw$*|;XAZzI^gR~L zcec1ekMeieds|r7R6mO*({SIG)U_26P=#xp6^Cvuui=u{F^NmREUjDOh?GL4uJEWW zD0Fw_y-P61R4YuvNy|{DPcy5wE_L-#?_{ADCUjk?rj|~qv9T@=IrgHaW?V8AA5*G9 zGY)!Xw~9j55o$yrlAWzCEEVoj%ATS&dcSX}H@#J*?Mfn4XG_y->{Z#488}oX?ZVZy z#OLFZwNzEI481GVsmy30OX&nVRdnrqT;qEM3*{^Dy%EGcA;%1O(-%$!&BXo1?HeK z+Bj!nQ(7NVH6iTxk!7h6s=Bn~gBsxTpwlsbkY5?xD$xvqs%Qg1_S(v__3 zS*k8o17uuj!8&zjnNq6Qv!E=;e3&nk9Ytx%Ge(9q&cC@nb*-F8flKciq(ZCc;S3}5 z!v5S6+#`3EdeEvG;&wHFVY@nOk^Nj~Fqf(NhgvN%k-cAxeL1{PbG?NL;&K$qcuebJ z-IO`Q((S_s9am}8!J9@O;au-!BK%hRH&`~!W@=h1U=MWV_^zj}T!j8C`8~;Srt{2} zU!|FIEuFGj>;5v(JwSZW{Uv?GpMcMFCjC0tcB9XiG~QhvP3jO)0H~QfJI{M)I2c(O9s+bOyBIPY=&!KG!Ae=*neeADe2FZlt<$>7YWKS>n~tdO^~6KrzC!p~e@_W$9KBRvih@%{0T+v5)xf{cF zc%DAW)j=QpiG06c*?2_#Uru@$FG43A_0Mk&);qsDNoO^E)Y}8}(da0esIPj!1!%V_ zz>Ke^4}3Ig|!AT+*H`vRd5sj&Cuk-s!y~2@ZO!g?qKPobQyqTQ>Xk4)iEQtf?3l%kNn zSWksJD>t?LaS-kuA+}93YJEE#7YdzEh32$-d0;os4S_7n(LZ?B&;=;MK zISm#*b?n7N50qXO5Iu23KGyQ0M{LhU#hAHGO=Gyo!Y9sk=e2%~hTjKI#DbFr^7o~HiNlBaVMk#0iS9-pt1rbJi8F&=ER{Um}7)DnNAfO5fSkc22oknjO=#dxFBVUT% zHvD$dD@Dcf9j2V3w-o_S{6xI%a+1IPcoe<$h%hHTEtsmm93U%t zlYz(Nil+b~9#F(AJc2P7y%|Bdb|8OT8!39Xy6CM#gtJc*kFL>0Z*?%$9(jmY^d5E5 zdl?bqNWgN69``Vv<=q~XYf*E! zjliSm{oY0IZP4Sst#XRqZ(Q`^ptlD|q{n$n(F-804j9!YTo%^2+{aZ;(enb&*{s9nJt>lG{c$4K%@t1LYC_BLaxQcooc$X-^!XZdpXFj9R`I2CSV|@l5 zmKQ;y4=COMYQqL=S^{&Ha->7&KC`eUtZBb;Bvg1}A&u?xIgR*6ftB2kvXNVHnRR60 zEY2*jufW-77HA{){N34M+}2r|3C-f;S8noO)vn3=J4*w&+e?RKwixu^vJIi1*~=ZC z&>Ml(JL=U;gvGE^;mUY+XmrhrxHonHIx$*dU!gZQ^6I&_hr;2ehjG_lc1dwNZk6kP z$uqaf_g=|jXpD9Bmm0VsXf}=Yb`2EJ!>|bZusJmMVOX4{72VLUeebnSe{Ja|SezYp zr1tjO&66Y}EJ=Xw(jc#kaw^o~j3<{$CsKwSMX+OHYmR zb=oDqNOHqEwp|-9wX_+je)=lhM+x_TS=S=$$-u~2Jc3?FA6<2-aGh3 z^bA=Kv@XY-3S)hR{-jUbF31pS?gnGe3ym#bn#IKQ@~b;!53~gfvT*95p`5yg=m(w^ z(f%F0m5=4sgQUsU4DV%q7|g95wP4q!2d&Xy9Oyov;l@I`kf&N$Mr@Zj&{-BVsITmq zY)IWN#u@)3tMb3x&Kl>hl=F&x)6_aty(J_Db&k^UGX(z2HUaf^RrmoHen8-Ju9c2& zfRv-%v~>FNPP%zE3co;7jygr@_)^D+bM6&*s8hr>a;iN1;z&8_5T&Q@FYtHSC~{&| zAnmB74BZ=-NU zpK`s~QR91+^%cQ00B^rf!B>v&!PyFcPZ(Q!0{$1|GBk)Qir@CFyW3owHY;NhKY z30M4YT=4rYxUXZe!Tk8$tsLR20W(Q89_n<|x#Ia<&3NL{&K7NGq~JVlmka;rR(w$4 z57gdu#Y;J*y%4F@ikgM|9v3#1x0geY{6a+^>a1 zw?eEw>o#1sg*{B@fUwQTg;0QSqoboZT2WjF=IVoXv`|;DMb6HIWaNyg#P?g~1(uAf zSg!ebUy*oM;Ny;OFWS!t(Z|Ob$0Y3tea3=0ck!ODpV3G94*C~KTapF%_!8+$rRn({TvX4hP?Uv^PXL3>S3E zC7l9%Pzt)2S+c9kEtwzu6-7p{8rT>XkxddJ04-{dS zD8hIERrHZR`C$HhyE0t(xw1YAq848h@D0Uyg!8Rez{F#kmM(-g1^nhl>DQ}Y%}`d+ z#t7{pZaDYc~Ni#Biml5)O1Qc2A8rGmO|sW>1~*$ zWArw%QW%_S>_Jp3uiSHvmeXLm2i3>k@c&QR?~kAhD#t!fHyV#~|EC)JL_vh9y+`5& z@Id4$-oqU8bj^4UieK`NqQ|cYC%t;miy(~jm{!qK>nKI98ZUXyOUfyF%MswDw+-|- zE=iAkDSB=A4H6;`ctUxACtdU^Fv%T2m~x804-nv_R}3OE5XSOyb*|{qrkRt!6QEa(c;ys5t{j$-DS9`#=uJ5dy}2%W+d+@{l3t#J9`_pY-)`TT zpce$JoZ^pidS`hLfL=b3NRM9!ia+WylOEfi?heqKEPsl>jN|hx{vax@qG$&fuO!O&BWM%v-jBsp$2nzpIdWo^;&aRQ3Lj;R>GHiJKUG>##-C5aa#5k z%kDz8yj5V`MBGTR*}jn|Aa+Rn)gGMvPv3JAxjFuf!};odF+F^VvicvV?f(7mjEivB zL+)pszuP1Br*J9`cgJXDrwX~tcdxLR;oE+r>BYdy*{xX=WO{YK2eUG+^42_P?#jKN zDJ+@{zsuTBQuhcL#oojFap%V7I7>RFB^djGJhNG>AAYXzcxTB{eZ4jwdp3d_9s7;< zTKkP^r!2nTYv1_+{gvGpOwlbn8|%zn75bxKECAuykIruH*O% z;qhSh!%|R;$07l%HyQvq?jfbq%MkQ}B9?#L_yHF_XV;YDo>4lzOl>-%$&XlXA|6}! zV$PGPxQb3W?jfb8&(fA4n&~-Dau12=Iaf)SrF|Jc7!UO<#Pcnba@bb#7w_*c$EC>?0E zU16UvP-hC)>*)#)sJ&*@>z+4miz%x{|Xa|c3 z%BHHSr>;D{GgBtkZKeI5n?(G&bG51ZzH>A~YNG~$_E%c^R!7>Vl4B1k9bL>>nL$f$ zwa~KV8j|1Y4ClP^k@bVfii3J(D2AN6K|$L9w;R zFiOtW+%pk#dp-OD z?4f`qVVjh?72GpHQn43u6a7mp{o$aczYc!aGaUSEhR^)B(m!9`ZSFZ2@?*j%-*);~ zRPLgWde}oB{I7=3^8I^z6QTpk(XB>X>cd)o#`iw{Q&{Pv8EU4ffu2G_H#tKu=5&$5 zO(*D_IL-oxQ%DN!G})>i{joO(Q0@Fa;9RX%0ci3xr>0_bZGor03EX(3L5Hp@`p`$= zp$qoNcL51lj{TMnT_o*$>P2+WX$Z^1LmWQrvsdGBmSZ#EB0S0|dRHL;-BF8J5qSVO zmPn6vpy)N>x0BwBfHACXr|P8vAx?Uu0gxZkqp#>~z;7qLcK~y}q@3b!9Ri&6DjfWA zOe=ci$4QUpIam(m6ukooaMGLNpqGU>MUVVA=?w$G^_Fs~yl*4GNpBtiwk6BUm6xKI zjr2}>cL3meKsm)lqv%yw^q3djI50F>{uFS!sa=()d_v(Q+ycdDHFc~M2_ z#g5PA;75Hgj~!QDChnshUfbGsqR^tYS6Z!uVB1NEIBIYCeZPC3eP-qmAHDbg`P}>Ie}6LBXYIZA z+H3E#-)F70pVhbv^YpTpy|B$=?Fijwp#4G{m-xC_*2*24fjwlI*tI>A&~dZz2TdFI zZmu5q+K`z$V85j$u`qaMjK5=DVqsoz1u$~{7%p#h1yj@M!4G1=unYF)`p$%Hu<~`) zuSTU+G99@}3s}4xk2pW=bkAfyr2WS*>1n~Ea&P!gz6azyopf$(7=RKxK=mFOz&&0% zzE|MywDHyGuJHYK3?B@%@&J6cQI5CV<6Ht?Irf7uDF8m6n^|} z-3DJd#{XOa@CiHjP&|iJj`0Ij2f{O9wI@hwhX~z8sXmQsi8%Q?;?(M1tulL8OH5wF zW3Tj}VIcGb#cEX;MHeFcNj*?&+wh6;YQp}cC1}dm%A_u?)LTf;N#uZ%^{yc-HUX#_ zzTHd=#vDU4vt_&C+N%iga8w>!Lngipsd&yCnE+PNA1HNV%?stW(v);#QQ%Bfz>u+%xR1Q7v*VM-D6lA06QC)q7j@1BQe_BZ7e zy{i$BO0O0Xl?Wp}rd9O#{zkRHuR zgCL(b`aR(F-BH$knj6 z!CUk~!^R?4{^~=JbN1!BLQUc7RfkR)fbPkyUbb)Lx~7XD$-2MXSL!xv!dFDctoq5yS2AcJ zyC$>`=_0_K*8e9>t>Hr}f0i--)ZKZMe?BB`Fn(*LR&q&n!75k$per)wLRiwR%ypf3 zHSdor>rVYg?jM_q!nyG{tie8L%i2YuG2tEI1>kxI z@_KyL7T@I^v=r=$|K0UC_xHJ8(DN~Hm;3Lr()L|g zLAyZLQ}#-%E_~Ey9DZwMUVL6Q?4}0mkk8L!)v)#ZA7VZI0rm-Q^IFReXbEme{t&hu zpA&lpuK&Mf*%ci-s~B?X$M=e`#E%Df%+c*`>t6YL5R`<{fIyBVx4gjW`tm(0_55-K#;n(E1G)(Y8fZ)Ii_Slch1Hw?QZaumO3Y$#xU z7^{yD)lNg6{o5FDU}JWA#&;i01R}JnJ^)r`$06@lSbde;y_tA%yLvn-i=V1wPA;m4luzQprW$(6q_0!!=AM+ij{+QzA&e{Ybx zwbAAfd=-sP2Tq5tw6v3Vi4%VSv>0-O>p~lYheAVPsdaF$rs1+6>ah>I#{>-hcQp_k3?I28Rew&wH1po zg{^g;-CAke{ke)fw5*P*p4h>Z_E_0{sOn_Qu)fOj8*7&OvTK&K&+7Tueuu@dnY};n z-UG%iy`^tgA46+#@lJEYFUqyOeYEL)|6B7|M!nG3b~kXxtk7E?P4p?#S^{XbnW8Li z$liObep4SG2)oF%I9n517dnL9cb4cA@5PcBMjD12()y`iY-O1z;kz))dk1#s@{RUK zdE0}H?HH|s`WPK{kq30@(06DLQX4>ht*(zx^#pLU0(th#3*g(U{EA&4FY+im-pt`b zL4Q`yD7!9X8e?&=HCXP7R(9_w?23)P;$gHEqqN^q9lr^kZmX2A#|zrYGXigEJeC@F zB(X>Iy(GpUN8hXLZilV!)V`O*%>r(!6<)N~7TyIf@O#Q^i^7%NKPmifihf7D&0nZ) zyO*{1x?Ow2@TQ-cV3dxF@{P~`gg1VaH#jUCgf{i3!au|c?YHj@;@y`U+luVBKUute z+5UNx{74dcwNSYx7#|&sbaq3dRbp#e*48&TZ6*k@qIFUvbZ#Vha=X zzVASnKfCWy{_l76&ErGkuj|Fyb@~jwFILr$>X+#2^aEXkv$gnrYo7X)8msJnyAJJ9 zv{aO9exGB-)?0iy(OzEDUK5U%7GV6^KVP-9WJ|3@OV!S0YxXv%_WY1&&)-Yzuag#} zb&Hw@R;Aw;W6g3a#05zSqx{W8&O;GX>+)o3!S$ErE^etF_NuW>FCEy~oN&+9&eP&Q zjc7rPcxBDdooPl(8}(Y^VDXJLu9LoguiSu} zDs%(()4v;WZ_!5^(cE}ec4d5X1YvhuVV-RlO?_x(cj(+>-$`U2%ryHa+_z@MM`U^9 ztG&-m8`k+9oSps3H|WTN;i`C!{vh*0iGH@S*<0Pgus}-K46h;ZDiNlam&Nq5MX`b6 zP1HlqgKvXxeqv0$VXb6!k7swl6z^T!w80is+Il3habnYfSv@bz|NT3uxPN`R3wE{J z>+S%?{S!}OG#fGh<#*CPtD|>dZ#Yfw zwyRLQ(+)$8O-Q>JIj6>{G-mj8``NkSz7M3?{4`<)$Udp~AnpdVbheodi61ZA@J{sn zyy)@s2Xy?l@F!M&#LdGU^*MElR#{5E=i$8d{at;@@9$B(Zs7UTc}TdAfEkX9ZtradZb(o*7S8#*eId zCgBll$Y{HJTgKLH;r?pP-M@b*V{35LRpB=>pjoJ270NiKm-;&UcJ*_)pOm$&l^l!? z1ZC#gpX;4(?pQUV^!?X1eV9|Gm3F=UD7foaI{h{GW?xtvSJPP&HsWzTF#6I?0~WRQ zi}ljUM}1?;qFT^{Qf5Qzj@)^p?#+fMaZSOmqm$a*TVRu0gVdJG7|)z?x`t*KcJ9E< zBiWj(v@-q-ZYuEPczz(`24WN$z2^Fvs8QU3p!;XV^ZFb)_7$vOBu%a4Kd_q8vLBCz zV>w;JfW0w-6_3AfS8<<$qAK%R^UXxXW4}z~M@TQP==Fq_b0l%l4NLW>wp7<1CGMFZ zR&<#N9iX@5;Z_5Gf5djbv{HM>_oNmdA?nj7)`|Ky+|klGq^lrX+nU>%^Q3Ef0ypxj}*V^d=`AJ?zwXJiES51D^^|}~Q2Xwx+QftxUBXoJMgtl$)iZ@mo@exL4`K?p) zit-W#SxkMVi>?u-~)pkC_v zfvfYGL|%>=n?H=)OciTBjt5-#u~zzg?CYUbj0)~2>~4er3g z9N;p>xH~gfTs`fQ4$p%RiL&P}uAKJ9QO{Ow%oL0zJ66q^w)*tT7*h_us9|lI*Kc!m zM&}2u(Uq#E4`Ow{cK)5QeyE46le)hEBdM&5jLyxtC*Yw(c4W;7zy33?yF<8l~eq z-CML^Mhk1p_XAa5t9w>F%~n}}Rylz5ax&~T=`*MF-10Q37vyAE)U|O_dY*mytMABK z&9G|qPgbqI6&qZ-y5|Q^ySK=`_QX4qlQGsfY+zNH;mI!9)PZYA15%e$hVA(%60giq zW6(eQ*%!}Kl1}Pt@~ovAKiZ5>b-n3p^2~?$CHT=s{7m=({G?MSw-Ta_`1Jhz_MMpg z{z+LsrY|Ew;hf)b&erF=6?jB{8$a5VXZqjaCmm0Kldd=Y&UJ`p`pfa7Y#!53#ZS5{ z^&tG-^gD^a$;RRr;-u?MzmxdKY!se+C0%d&osS`!{8i#doAFGa{C4G(ZuAp$>HU+G`z}WUDE1 z;1@gaiv@m}jg>43gA7Qvrb>UR>t;~eoEHV#~OdoOWqo9&s@h z17R_G(R_#yB)`XKlsLE%5lzq>w8a)6)c`CQo?fOBz{>QZu#yGP6h0*wZl@G9tPw81 zZJ8t{KG{h%M8y%~Lt1JU_@cLh*}=&6a@+25?_v@Zz3oNT_mgEN6n81I5-DO2O2Agh zF{cVlD>>q%WCmj!7cFmEWXl9A{G?>BrMC`|i#pWu(nYty7SPR$gq*mvgH343!Z1ZD zddIkZe$%aI#Zm$r^38Y$D$&yAw=Y;E^uSe!$cTuy&ky&4_KygBCsp8kvvkilDc+wj z&$*P+;ED&qeA0lo3O>6IG^uXRhNfgJEHM>noI6>g2o{&!iyTvM1%aiDmfcz3nDR|A zmD<_4*VRj70-umJrIDmITxTA9JG5nP>DQ96UV=nB$K?b`TluOjItyX-!=~kpcPv^V zYF3aFD#NKg5!sS0+4mN}Fnv=!J0)znH!NWaQL4s8lmt%i!Z7=RRU7~!~~77zkkOfrUQy3$q{V&X0~r9*Iyl!eHIU&-(Ztf zll*YC&vIV^pLkp{-`gBJWUeA187 z$NRVpK5hHoMj!cXrjPgHhfn(X^ugby^if`s56ZiYFv=UDpP76=8vzdotm=!qUgBlZ z2feBE!5@MIe<3Seyf5U#^s2sCe?KN1ux!3Bm3%XvGNg>Zg+7?t?vi*fTR!)}EN7fP z%1NDe)_a0JGUZ+%6E8cHKIqdXCHXTgc!32|j+}U5EBrqCO`7%)eU$S%^if|wwBVmx z@LuFI90~>8Qw(oFyQYuMbBsRl#rvCQ^;hu8`XRr=;b-0{`ypZR9?;YAinPqTtadWn zs{fU;9nseRGmPhZV}0BKI`qG0*`)tE+7n^WrOhVR*NgO5Lw1)w@B`pCGlF`ckN0pn z{Wa+4^w+|k3H^1*2R`}QPapO8oCP0dJm~RWEYcJ8xgPBbe8@8-m2bu&yfW@doh)+b(LJ_s+DMZF5o&jwPG$$ zPt8IlqvbN|Q_{-?R~o{nues7t(=$`^|EHtKmB9a4lzJ%o6@~&aZo^Bl`$q_UPI_7) zeBzmc{9S4Q}m7_AeCMukfhfSaf;qR5KE;;xi;pZoT8Ttq*Qu)0`eV^Kh~q7 zH^D)Va^sbVS5DD8-$Bn`sA&NpksjB0iXP?N@n^UDmk`0ZR5?YDXRE3Fl@uoV<6N%j zt#!~_g)^ynikO8*@aqnG5zu2_Ab$h#Q}mv4(BqlcVZ$2FAVk7v-S^k( z4tmX?$NokBittnXg&p*oK`(VoRrHoQ=+RcTs=wkCdRrXyo@03x5epBV_OOHAcG9!z z@7xr6FFNSG4IL!5cjXl6gARIoz?3R)36P0LIOd=SF@;{~z2%^{KZV|y6nZ{GzF+no zx-3-6W%5z{=ey@G2YC1ksi-dj?*au_I0T7{tZjEc@V0~TaR}kK%5oq`v^~(X-B=hp zd5{x_@O|A&;j@P9BQHgh1c zIjiUK#xDf*Ldqpk#^djWTG0?8Ke#DzTQGlS&FM1}jgMW|%<2hU-S%>rJQy>&|x3bMGOMApB`YBVCa z)omUji!m0GR7YFKq72^<{CmyCmM*G0sBe@Ue?2(fR2&PAknjF-O8L$@eI~?^3Fb42 zC-P_k%KiQ=BE)M3S~tRO)8hgn4u6}F&QqEh?Nd51>MqR}(vgP~ng#fCr5xi&JK#zO?7ZuHi6g$r0so5w z{#OTl$N?X9!0$U?Z^{5neuIFCl7%1bWKVX)i|=yD!Bd$N;*e??{I$OFKu@h+d{y|o zpKa__J6EMd|z0IPlIxUE5BpG{xgjW13`U7OEuub8nI0or&(@hOv?Ft)3W*y ziKv5b$%Y8A4fZgJt=CM0OUX-a&x#T^<5^tWFN*UWE+}T%N!hMJ9)$2JS8vYZ!H2nPxn9h~AcbQraTYj_ex79`7=y|EgwK(7 zaHw;A5HRibyhtC5@0aLfeGsLO#WP2=Oe}gi4v{X`tAs1)V{aByh=> zqPGRl+*TP+m0V~&zV2-rBB{cme*MI!uAdD zlp{}cTyv!2%?9&(MU4EX@Yt&P?H5aOp;!KyHeSjnPLLYtpRHT_Ua82-)<2(&ox1>D4#8$>eQ>ntu{Fc6c5ONyBh{x=nW-g) zRiv-Yi?y^1>-9OfF-P89WNFWdHRcnjjJ&q2nXe{}=G_<0g09O5*N~}e6MJj!4f`(F zH&IGl@7_B>FV35)ZE_2FXsOjC>kIb-S!pk~(!O}g<6fKCmzI8?m0mk5y|2wT({~wi zFV`P(6=@H7%V!p)aVfLW%Gw5BK6r))cMcsjHtg{h`9+;1}yni3aJ)2j68Bxjxpb^zL)|_wDLyr8t`BDash{60+z2De90}e!hAG z@0Y`lZ64~W`_sz!+3#RPTPE~cTN2M==OJ%^@>%a~CiX!6um_Sd-n=czsuI*m<`oARTM{;l$x`Bg9*#J}O)Y zZEVKWmovs)JKjv!mm?qNz5Br|?c6sLdp6>?9lt#h^Czb&eG|>spegp9YU5RDYbgHB zyx{B5#A>QJod4?eMjX18&}@BcW#J0wD!8hr6?Eo%ha6cDeg!&F-)&X8+Wk87;(_db z(GjEjy>`yN5>sj)X(j%Sk*0pZFJpP}%Iv?!MvP7zeFM2^r9EQjrbAEYubn|?@Cj|i z?rFL0&?JyM+qYsP%|E2*BFZwvr{A|n3r5Ur^MS-L(HeKQMzHq`wywUi%*+(Jy{rRL ze!o-Ocr1t-%vChsi}mdqrcV+(L9gj=ZMyR9*yNRuCWdKmCZ2mt)ScPf4$Ts97#AFB zCGT}=k9;JkB=@j?jNNnvQ}yi{t~1s1iQ#46!(CN7prhk9aMu)`7ObLfN9oiTPI)kL z>rLC^d3p&Z;i=J%1poEhFC$(L5LC_2lA`gR2}w33;fvd7g5&dJ|N zvDc2a?||mc2*cB|&3#!KbT8a_TeJHa<2iXX-Aija>S- zGiSblAKQs?=e>KTs*iO$oJVLXKi+^`a#-W*!`j%&_=gd#nb4&6`kpT|lnK4zcojlA zzK#={$_xBOv=HEazrMl!eraeuLWo`3`~>u@4<}wO-?nl+?tdHI+_%eR=tb)6g4+4> z`~NJaZv>9rJS#JzOBC}|EwD>Cw^zgAHGOk!!d(Q~Y6 z+rH~-`*sq)_Lw!uPLdh{pl>wb-*!vbEb;PWsc6k5mV_H#vQ)2dje#Hzm7lc}6%FHO! zR-2Q};{~M7+}>`e1P3l~AaAqt;iQOh`nK!Bk$pFxTJO3pg!r=ciD$()mW|PFx3G5L zn}^e(@^uk^Q2}NnIWvpW*UlBKcNcEgBPE962DacE&HFxDcWN&5;|{rS`&y9N;PExC z!uiPK<(Pj)C-7chSr3~MuQ%yimO?tPv60M*Dv0-cVBhZQP1WV zu?~=}WggnWjzZO!NQ-pPD~vzIycV_J#+1DQ_RH^E_4tp};fS{UeTPQ+TEsRZ?aeRPrxmVC{6248;y?3R5@Yj!=DW5-FU&Eo zg|)ul0k_qg)y()Z$^gtw667$g$8QdkEnpk~LsNql6dWiZa zd~a$^lmnYD@?F)0Ju@`iMxj}yGAxS_InQ69)=&TB-#}8&T6mhlFIqfmygl2{WGIuCy=KJVzSfpf|w5?*Q#PNXPW7BbSiKz=P$eo0`tg zK<%f9OY$?&!4D3ZQyg_w)6?e*{INDpzK}5@y)yh<4hyr?T}@9v#F3s7A4x~u)pYy< zfgiC^k~PO5>awQe4;T3RZG4`9CmnTD)A0jZCYTreWBuzwJl{jUI^zPI>Zq%lp1w%n zPqOigQqjR*u>-$Y;Il1AmwX~jUDb5@=L&qw~Q>=?raxgWd!|FImeIlE`>6(j;OCPt-=(wB@;Ps!SexJ8dN@M|idazQzGl zj+{Z{f!`RL9r53?;wwdbmbTY|Sx)M%D!HnVfOE7iM|$4*rX2Y>kt znWP!NT=c)|9Ptef*r_|a%@O~+1AZAW>AxuG57++F5&xkB#@fPmEKi{Wp5%Zpcfgc~ zSB~kIIpB>B_y>T=-)!(fUDg*J@suN1j`aTOfOWTumGw)xa^;9W$pO!DzzZDk9S)ef zw#t#-HV51WnEbOR=AxCoZo&Boq^|902fiEMEt2>pT9E~RQKTQEO$V$T^ZTk5{{)_M zk;~T|@huMcdk**~D!r)R^R?F;@h2UyD`iQ+{PP^}SO+}a0aMpjIi_FffHyhde{;Y; z2F&`|BkHeAd({zt$^j3?cQ56bU%3OG1~^&Y7=P>!KSG>9K{wtsf5~mjq3^3?$&00V za-klmz8m8T5%n=zDGmzVwVRV#i%lz**73TXy7`b8m&&))q7xt7?ZjszS<086f z>+ghqB6I+4R+K!1WDpvHjf=#6+bUcjCxb;{?fiIq&8_k#XQ_@0@r@gAS_19x#S0rn zHQzoTTDN>-iROvR1!Lrn|iCDBymgz_V9j)o4RRK|dO z#hvpTWdp5STwf0zYgr>nB}J+&Qhi-%B#N}3OFHHg)L%bA$R%BiR8?0}rPEoFjFFX` zRJIfX0jeePJ&H@oSy)Gm>YIp3>Y1}zg?0wRmfXCQiX~}XPBE2~brEmE*2zy(N@bL) zGYHP$8t?iW7vQ39RrQ}DOVf*9DS`wqDz!}+)xa=lf-GEg#}Ww3+_gx)e{n-Nq;&A= z$oGv)Z(O=Sppr4w;?l;LJC`h5Oa*I^M`}NCC_`J4O?S+<6;IQLA)Ah+a%=Umn;Ibw z6{=r`!Dk7sg_ogrOSB6lHE5kYP{WBz-8ZU>pJer-TCJjl>ZKm6J+9b7Qfd_H?KZa5 z?x(U~)=ZPGqJdR+-M0g%Sg;>L@JW zrzwts%Gt{OWYG$3x)J6P$lcjk!UTYnzG8DyIRaM%_NEJuIoOXMb&0wAqb~7O_^#_M zU19i_6TU&}xDKDoeIIZ!PjmjJE-H7KE*z8u=mVc?D~5|bHejAFxaP?{FT(|l@Jkpz z-_of>cz`g%i|H@m`U!OEq?~@{LQ5VCcwBptPoM~YG4YY^Hu{Skd|iVsj?=z15Nz1CtSp&U*T{Te{Dv z*AUayTe`OZo+8{J<=I?~mi!pe%kV%rH^#) z(MLM!rZ64P3CMRbeUzhwKHk?@`cT|b?NGd@6;`?KO1^ItRm)sy-H!);zfTx^zCs`6 z?WPYtG>Z?e>8X=jLjP-!XQKags~oE}Z64u>RUXj0n=t5arN721*IG>zY^N! zn`J(td?-INQUPZcY0;eKZQ5moR_I zu8DSK!2{?cvtIceZuQ%U>@S)3N}U?M_gc~gpR?hU9#FN+Z%8<^*^=LUz_Kj>{I6U1 z_t6J`Y@g(3GkpYpoBjsKnb8Nm^WhJ_-)b-4wEE#ji=PKItpM?vXe>qa*IM=VkTqVk zSn`_41X1FBGe73Loj%&ZbC&-r`e;L8K^~SqDlY<`^~f^_`pxvwF7LPCjh4TO{wUNpebzU9);E3BcP7h^c0YtZ>gh}L zx5_)^GPhZBuZaH_hEK9=9RU7!3s3aVZ(Hr|QL8=?&-?I5XRKA;i|7MyF@3b(JLsdF z|3V+-cu0=}X`f|GzIsE9PzIRx>Fb%b7fN50!ptrJ8ls zGSFU1bM@lTZcbeY0*@wzJ{?2twvx>BlAX0Cl&ho9gDG}kXCtPsJcWs>2K~6HbqGid~wJ@ z<=^{mAss!nxuotJ(y>4^y%Ov_LlW^bkKg20|>id{_2V4_`6fp~rpcmn( z^!9@urcP0RITjx4u^f2#v)}290Ez)Cr}(3d(o}l!!sPqN1+wCA0r2o=)8m?>xAJlg zlS2b}}tcY271P35Iwf;h&r`~UYg~#`M zk%L|U1IUXcU^&I#1rB;UL67BNdAYt;{C&wmk2?Eh2vbhcyV^nTDCk9jM0x@I6uspR zdIQj~x$aa>(c^co)bj2O%Jm-UfwWC;i-X=mR0793jQB5zxC9;iSj%D0=k{dM}e6%BGy+ z?^XxBqoBuiI_YsgrszHBpcjH-5Wfv6r|8jUZ)$lfF@f#`66vvBD|&kz^a40%>g|0z z<)C*Q^f(TX-h>o-uUPb$2i@hMcbR+?|H&$UZvYQ}ArHiDBW0Sa$i#YA<%W`ORq^r0@Sm?ZE5 zfzQ^5;yxA5)`$B4?R}g=9XM2fCyt_VV7_cVZbJTt_LBe83pw!;{|<;Os-JKU z?ya9pL^ztK-A{Oy^LhHoGr(gab^-p_-+SvP#bAQ{SUJ`Ho&DqzL`+ji@D<*;iVIc4 z|6Ki~V)BI-$d2;a{iK8pr}UF^Ab*BC4681@V$v)fH~ne;(#4ynjd+zZx-Yf9*g654 zc~5w@w-R=nk=AjL+`QG2O|P|N(;o=V>exVE?OmC7eJgSMAr1HP%++d6ypmTpt?-T9cqrQ)tv}_>&1_^oOu6}noOqVz>HHSt zdWZP*BPx6=s15bG59i&LhgA6;S}|{zc_OBl8*x30_i-IMRbvEj+gA07mvfDp%*L6G ze{|?w<+YJoXdnL%64I=d`v#(1bFFesYS%W-Oe<3kWbAJXX44)?1?-Vbr9F~oKJM-z z1!avSqqb-&G)rtbd!gajA!^(Dr)-Vz?xlX_J$tSykTUVSm&gY3>e?@HtKPcgm1Ra8jXT_KTe6zU&)s$50J zWGN@_**4@Z*3*#2>+UMTU1irbUKg&8yP&NCy$k4HWf@te=XCzCSv!A$kk8dhz8by2 zQ9Hj%%h9t9`euH~)!#V!d?E+_J+HPT{M)ZK*%pR0K4#)t0O)S@?aCD;k@&e~TdTb%%|01j zM#hj%&$jEQ4!P?w+?2)?*M*0mRn$Ww`?}ETp830({|zzZcIl9CeusYUO}OoJNa*`9 z{ergY&ZDza+6D9pYsOrujdVj7?@80!ePUAkH1{j|lTx$n+SW%BCty{^Ri-})O(4Nd z^S(2|iO2M9L&CYf;NjO+sBl*iw1;#{hI`B7;XW(gEZy8OH^UVVxi)pIi~9^cm{+qS zlzEqd=NC@7a%)bw^7M&2LVwhvPNB}2_|z-!`G&WOYYZm>LDJuRyvP*iQ^)s%-W9CD?FJ4EPPeYh7E zZiFnj5&rkCA$oa@&on~%$ttTRKmj&-TpbsOYvPs0#k>I%G5!wZyN++E&^$-<#D^2N z)r`fRZa?aeF-2%OFgE)#^t^J{$8N~Xv+wQuxcgMH-whE~fTW~+z!ZKJQrUe^^}D<_ z-gKt7kmAl(-MU>Y(oT&nSG>UG9+MdzyrShpc~e=SRY%Juw{t?GFaIBtB2Ug2YzuC! z>kNJ6pf9B!g>R&-_&EQiEYN^qfI?nc3b#0ue%lV?Y?pMD8&Ajg3jEt_6m^;)11LA1 zj_()v_uFjx?Ua0=oOn8Zroi80V`0&s;&^9KI)0YG57_jxQm{$Cp97yKB1uQN@Kk3& z>mSQsQLAzIwB<8C1%cRA4j7-!Y{&Q}8|JDKXd`CIP$MIuv zBlyvFPljD~nSPK1E^)y8mcgJh{G*inbr!ryz<%v(jItR38Nh8?{~njJK(=M;135SHFBIf&`oVfU*oXEY#x)jk;w^?pOj7@}DTib=Lyz6J)vg z(IBP7NrOe{LSCQKL{ifteD_Et$IT1m-BblOE~;C!1g8Bz0p%s3Re+3 zDJ7GXS4?>$Qa}nsl#S?5$e8&E`5lODLY7QrNw$@gkS(M`DM8}*BKDVpPDUlMW%GIE z3j~E0g?me92?4S&>0(R_k$E&Oxq0z2TWpEpb;}`5l@>~lK3#~=7DKADO)@z}>QZG4 zZ=b(n0j_ZoR-MFay<^FIVG;<|p&adA-4P>rXu@3^ke-7uB--u5C3xe@goaHf2J2$< zxl9~{@+>72n^NutX)Eb|`ok<+M>vS&9OoKg+4T=d8?&xLc}9{MlxJ+2*wAr?AU&R~ zk{-{HNKep3W}N$6IG793NBU*-15#E7c1eWn&v2YUaVE;d841tuGDll<#>j61qp%)-ND_a(xp%$w+!Te1k)WH%E&5BAyVqg*@bW0U<7eQd0w^l`ZK zNBSW84t>-YzdO*@RKVho`)1ceeqlSaMX*R_!o0bg^&6|kd}D~{+-{n;&!xm z_{$olzgRudRJ(RQ1@N$s!POe+-{{z%oP+CG7^$6C$_$=`@@WIiS;(I@D4d1-i9=fw zlkNXgyUqXni{t;^Sq_?=m`lCz>Cnu?`bGfw=e8cu9n#KZ-8j3gMHt%(ark5Vxf(w- zC;OWU+gb#$a*E!S2;jMAr4?~G=v|9v(jza5-f}#r(t82`*GbALdJPCjrS}Brg%L)2 zTFDoKo~Y#B(aW0*_qhAXqq;<-ZRf~ zqrFM69#TYA63ljNE9UD^uGxa^@sTLrBGtc5S{;|;-n*5Gj8nJ(CV zT4*#^dyc-Em{-&9TrK#GYW-C$5PIJGvGM-A!HaJAv(I&8TJyuz???6WcuY{ozjsUe zMmGAD?0rO=t+ z+K}6<3H9yr>V3+%yLQifF=3RAHVv_-H!Ryx%rB=c%hKC6gG^Zy(u3CRP4Jy26kF*?di)onP&NtA^U;LHD15D#ZfBAvxBJ+dJ{KbKJ zTbj46*wOGcTS#T|Ef|NbJs(&r-2d_Kjc0Im~ zA+PK`bV|>wJ7wld_>Zf$LA&3~{Uc%rlm(YRnmDJd4*v(1?O5(E8Z9;7VPk~lYHI6i zx-Hv0ZnGqlwearV0P94Y7Cny|dm^EijYsJi=d$b&m$kXg4SRA-t*9@~xw4J^g6gCL z)Yh*#;VG^L?yWGkoosm=Vduy~gZ z{AQx;F)S3~>mxPs3?mp?-MTXDPGpq1PiAP7ht-7c3cJd#7H_5wXFP7BE_5=y0JcVU zg$H!_3$;S6bU+8JI0Z9n@@neDIaFEe*2DwlLtBX-0Dft>uJzohTNAU(y$SsihPn{y zvTRZ9YTgk!*<2UVgF70wCVnvCtp>gPKKMTfpG3JYjlxov2Ad#W)OYC@qE8A78MLn8 zw(NuiOq}xFv&M|XWa+%H7ZRMBKXr9U-`949gE+5qZTDaLWS2kVBp@w#G9)31-KU~r zY5=&oM^)|A$F?SZJg(-%TJ-BXV_NC2qO^XpJ^!WHc=O+5S}}g&ye!d{Gi#vvBiPBg zta)p-$ILSGI(?!q?PxY4dFZQ*+m7CSCTOC!N(+Lrm8jOj{y;YgZMy_#d4Gg`nCUru zx4+ygdriR15j01eKGB-}g#qzy&ji{34cjK6RFG|OW8ip1b2kAfZggk z_G7S4v|V`lg*Yk9nDazp=L8q5a_^dujsN+uZFO7ukjn8hwUK!>qfOYP8wFcs-NRs; z>83d^CKls&Tlo`-g-xnwAG^OXaWzv>d0E<$BR%)7`xfy*L;6Pm~k4 zUn?w*&)Ed4Ru z(N?Sl>rQE~?bL=o;~%*m?W_*goM?+{J>c|uefvzd(MJoRy#6+M!me_l@0;nb#Toj@ zdeB=Z()ueayDyWyx+7ViT5V`L?KaZiiOD=Y1c$ zPQ90Z^7_2Eo^3>*Nw^NKpQcCk34e`&K6=%IiG{GIvpN}7YMEB zVrvA$X@3BvhaI0K(F~q~y5Pzh-K8(AB--`Bc1xFoen1YwtuhZS{;{T)WLo2Kersh| zFRRoJ?#+2VKk&Dh7WfDwbg1p_Jp;@~6D5HM5?Vkj!nX%J8G*vfF!xqIlvrBV$2{$Q zG%+^kfrOsJ8QER-XacLLBl-ItO4J*bUhPO%>t58{*6Kj#Ij|Zezy9d3|Klp7Ev0W) z_dDvc&cJJ71GBGf^(+VN7kQN}F{N!HFXk%ullh_yTFLKWL+E#64pBCBYQjT(mv`ip z`O8AnF~6Hv2^(ozLZ6xQe5x(_P+PNT7t;Eg$NFASbHkxi>kL<^*BlfzO2>0A>;KQOLdZB%Z3+viQM$`HSXY3ox6DI`d(aGHamHf3e1?DD$6fF1AD>fh%*&ez{Hdx%UTb|Jtvo%=V0%p3EW|gC z)26OkpbxzByG|L~dq?VeN%7_u90l7A)Q(Knx~UvhJNvh z&>MSiGWGE}qfc~ld@HNK3P;e5w=F~N_uy`aY;&dct@PS(b4Yr~i`HH?)yU zE-x`Lmd#;Jk1_vVc$27eJ}t7J>g=Zl;%O6X2(3@N_r*o9BeWjROp87b+ip9*$Y=iM zwc@*#F~-CS#kyS~ANJD*iJnM1P_)v-ky{&gXXmEG*hv|MH)FIa121DIF+Edz%!_zO zgCXr)CDT`-rz{rj*Wdm`Vu-=@&=&+}7tgq))-Nn}E#5~eF0=N4jxlbKae;{Un8(^D zBDMa$PplVqwqj(TIM#;npdkzugeRlcrTkCNI*(3Z0UEqR?Ok)hI( zU$$uH$J@_fE_)Uh0V^*ksO9)O9wm|%9Aymc-H{foe8QF)tPYkQ7qqpK|0FEzZfPZN zM60?7+bvJEuikvx3w#m#DAmtHZ8?^8Va%S^JUkF3mc5EO=eGt|*2Mc6!KVIKK7xBV zh6*?faByY68Flg1cya~nnz;HQz9+b&>5;^wN&Z^yXzs?-Xfw0u`Qstc512pQe(*q7 z151(zwL_=0JoLh{gIZ{MO*k)}lkMUfGLRD(j8&n(>?^*ij@;{AW!lMVOlxPfZN8}; z{m?r?(-Up|%mG*<4iY1o$NX_?-P@zs9pq}P3YjtJb&XS=-F z9@@og{vp;6TdQ{ptlD;Bz2Wm5CYB3WzU*xl*Hd~X?q=*!-<0>ucDG}{vASpM?)<;x z43T9qP)@_8k6GPQxOu$UVk6)fw9r{c_4WYgSy(sN=hDY^m-OH~N&n z#+7ADb^qwB)BgqE)yY0MM~u{@{OhOdnmy&)u&h&Ea=C)S6 z1x@bt2+vjPm6FvxtxsEP7tq=DG;8AWsH}svR_ntFz|orUYu?L5JHvh!BV&Jattfp? zdtG>|?+ZsBgT>21FtIdSgw}<(`PQ15MXJ#TPC_5DEF^W5Fa()Eo#-rQO%cN}xx*>2@6 zF%DX7$_u{WzUVtQV4!TPf->G*f_l5D%TWxmEb(n_cF z1ns(6-81ZIw$GcJ*NR>20}-yYzFWQEwH+(!z>}7}D$2aPojbcS{5O8ooY)Vj@wG4G zJ|U>hg};LHneEM_z&9cLXte#2507I6@W0{R{Ai-M%xFM~bE+DM<%Q%zZoDAd-$|*3 zoUVo0&xm=Sar|i|tD<~YE39|rxBIOY^tEtASz}H=yuH~c`fkMPp9`Y2zIkJ(4^leQ zIxA22@2}P=>^BFh|J9=ADS14)W5ur4dDdvs-0uCZHf~$=V)TkE!(ZCRs!Lf)JEMG^O?;tNz042`a$TP>P;QmD1Fqrm_BMvj4fY{af&moWLM|z*kjG@ zSO-6d7T%6kF~`mO zFyz)&z0`v{tE%IbF24D@5u4R>|bt7 zqxK#9%tp?H_&;t+Pwc5**y9X$&gWoFd4E+&j3+nD5D4<+Jmxo+fh zkM&&EHUjJAyMy}@&9Df&!FV)ZAOCP7RP*<-_wF6pd8T*+p7jam6b~rb`*F|v?vKwY zS_kYM!1f*0%hn;qkf~fJhsw*I-<-cO5rSaWnG(hi@7R~PFHi3}GkypBld+t3Js|P* z3gFie=WS88oM(oEhYi8pb{*6=fS3D>>H?$+lCyIP^$B}F?&{G$9#8}<*si@hIAC!;+mD``Agh&K&bQK-YLHMjX_J zyx!1gTJU2cS8c{Ai zPy4Gj8E4@CCRRqA*B`;IKv=%7VM!i=Wn5aPtzYvX+M>MQ03*=xu(2wu6zQm|)X-0Qz5{$b8yjSu(fA4@*3Qjm`I{5DWgZiD zdZU%ih8RiawHw>!w5mSoi4M7Io{-ODZ7iJmo5cRy{KZ;uU3GqEDQ8f~hI*{AqV#&B zv>>{x`C_cY4uo!P{#S9*bO5J9Ult|&>oMcxI@iDC-*-LsF4>;w4->}0rOnSw)8fC6 z=;cRn&Z))!(~??y?U>?Oy+!6EEa8#vY>U=$?vS5Kc$`ge)$+jW8Qi&6uqL*{LMSb_HK_Q*24+)QOFU& z@NS1|@M zh$vICT`~;vt2jx(h&$=M*sI>v?|)>?q5^B3tF}Pyhj3=avo4-1_{EuFJz6d5c!D0P z4y_5j5L(~B+brU3etaX4YjLg68m^m458&I!za<9b zKnn8765Ke^zl?U=A3*Q@x5Pj(QgL@MIU2l6FV#Eh?p+rNt~}K6NaD{^UdJBlk;Gr7 z9BSAR9*RDYUp`lRWAA~6x)pO&pZ_vp&-T;Er13C};QkiB34X2K-5v9Q*n1#n)V zg@@Nv*HlTI7jW0%(8YCPrCQsreQQ?FQgN0r*}i8{D|)qXUCP>*P1KKf&f2eR_CKFz zow3CQ4VO8oH5>EEQbUXDnm&p0o7}4#hOBiRcGczW0Zbo&1n6AsBnz@nM0vI(_IRMr z`QTowO&N$c46k`>=Z|o1xu>G0{fDrByk}~mnZY+9M(87nr;1yzd}#6b#jP{s#d%W;nnUD7XNi*g*9GkqdegU5<^42Z;|@J*2(4`tf+??7l|ICn_<-GP^`ciyF25jry}{Y zTe*(J3LW91o(1O3#~6B1bWgM3vgA}}qt${8F^Xs@VM?q;g60DjV~H==2lUoO9AQ;jqtoujh4MA!d)!$KFg7JP3Zu?oAx8 zm{AKVdG{vX6=S7QlS@uZGSK_y7Yjux%w+#JZEUP5DQ@uBj*fD#y zatChF$M%Wb!@Pshck}cuXRk9Ia{)nF)W!U1@Z6a9Ji{7yuZi{PmBx%%25<&~>u*oo5i`y!wDb3b_ayXr zuJc;=dS2^$p4Xx?KIRu~PSrNnQ=#p^lV6>RKw(PHlBdVmJPo$XAHrGDpu%&^0+D{* zDsRLcAK?z-1Z!%%(p^w79_Tj!91K*W%%4(KtL1THyIy2>& z(7m{uh;`;KbZx8@Pa6~7J#5RK&dTnoSE=3Aj+t{84{fa!XVqViN=&9JX?1OLZJiqq z;=ALVkPO#?-j~=UfiAS$9^Z#hjci) zUlZLb){*W`ZRC^YI8!SgbZjfm27T5oCT^3ry|}8L!S_PmBQ;RGZQr(*glpqSGb27C zW0ZNI>%X!yaWeiuqM*!xMft3GTN67g_Tg@ZYuC7h4hdIuu1hkzY zjZQ6IV7N=WEMBov$4D@2H)k}jp+~*gvpgAAHB}m}KUHm%hP07=?7qN0??TDEE?3k$ zrV{Jx&0(WOwV2uizOBZ#hrk0lfHsVUx4I|1dkgRsWdoWrpbh;SSG>$sHfD9tPoCZ* z%DxU?|L}Io8k<|2<*IStJF<4P;1{jk@?ScA=FWFmheiwEhOtf7WBb#rvqdqUC+-t- zzuVl{ULJOjJanom4>v%Y+QXII!_sEGQCwA2YG_ny4lm@^gc zIna{$-hc<+=H34c{)2LyJ7gxVGK5ZD#9Sw2Lgf6F18pknQV0*Xit%qk7S=EeV3Jy`zm| z>@RVKJfH(7qrBs$;lAqp4xW`)nrJn7%yE!~A4v?{s7`{v4SZvHmD#8E+IM7s`_en^ ziYYx`eELT*oPK1K#`cA~!_YelvQO2g>y}It zbK91_c!mrB?u%pY5p%dbt2HOQ8&eQ&8YUP+O!(NgauWSjN1m9$rNe^jW( zS6$46k;VF!K&!w#$vkmS&K{fuh-aB1Yy9U=q5U7z3Q}@uEdT!(Izf~HOuFRV5(5y( zyCo*Vr(B(M=^M!2?v|JYMDkdPAMci6dWK1-q&+3n+g%f1LKM@N;O7z&loFT!4M_K; z^P3^;%@KbpelEl_KZ*`Zm!W+N4~(aLsY~l4gRTF(zdM~?ACVqk*)8Y9@9V(tD`YrH z{|WqDxN(&EZ^utM2!p0L1B=`A{Ia#5AfD-2M=r!OJ$aQ5iu);!I!fv3`wM%COuq_0 z7vhFN0o5_U0?=?6K|4|1d*>_|UY*tuhRVTTPGT+Dwn1B8Q;K#DVG(l`pKMP-2mVM0{z!qJ?BydJ_@f;7qa6679QdOh_@f1WvVKQ9 z@Jk)|r2=2PAb|-bh7@OL=Q;4tONnKDjB~_~6ZE#*SWu2gaRxO0((4aO5h<>>yD3tl zkza))eTB%6a^TV>-vnU;lFsS*T_Er`S=i~4(8QnQz@H@Wn{E8$NGs`Ic8bo?rTf0!Lq zxGMD^d_${o;MWNJkd0MiKk>nUHHLKh(;V@pBi?kxPj|#mca&$k1Am4Ce}=Zo8ZS7f zy0jS%{Fx5?nSws;LrEv&Ln$!FtLyD)RmR_z0yF;GDX>LIc!qX`Bfl#|e#!QFMJhV# zZo9carq?Ge_WaZj)|~dJw*$UE{#NM&O5SEE%8d zA2R;9U4Jq@ALq}~U85d^Z{X&qbbh`p=qJOz?7;tu1OF?I__>bwxq{wvHr8DGi4TT$ zg9HBtfuGdty}^NhqXYj&NBn$8{Cq)gwv9F4e&Pde=XK!M3H%dbO?|;+H$%J5tt0 za$WzZJ+?}ic7K)Q7!`HEzjeUxIpA#jT}XPx4)|gRe1!w1%{Jwj|Gf@)hXekR1OBB0 z{<8x%?6xWSJI4W^>wqtEz*P?TS_jUz^l!1^<9N=+dh{+w{QVBN)dBz9 z0ly2F{BR|ai}mXJj`&OuA}q)JgMf+8IVo2gsZC0QM~SE(biwo@-_OpYMRDIpEs?lm7{V|MRr_9r4MzThiNa;Xftt z$7#QI;2(Fue|5lyPv*xtEEntDfCaOzbHT-hfR$s|tTg-zZJ{H+*@}MxxVc!*Zg<50 zn*;7}z^^*szW`=^92E5CY8lDJh&YER2F&=)A|C5sM|`ydzRtog5cn5q^%gA4dx>_p z1-@5`Ok(@DeE(WUoO_uW2t0nImVj~c&>#{ea~F1r$ZKezJN{b9t)l= z;OW}qj`Tlrz_jhi{I{c>=4vywcOCJ4Q;uNB&-o7cG6y`*0e{T_w>aP@9q_Xb_)Q1= zHwT>0hGRMMH^u>9>VWGU@M;JAeFyx41OBZ8eitz7k89pstZ%%1B}}wjtnWvq!Lzg) z3tlhcuhOnbgXd^V04vAxtg_yi0w-6Suffor?U#B9PK%s?I z7glZ8c5OEia6wz8)Hb@b-SAR-6u>U@KZkC7W1&apR4?Z!oR{ z*5BR-S|h73)S>6sL<91?Jy0Cs1k_Dme5RF8*Dzc!eW(B zmI9uJWw7%F+guCU+Uwg_wJn$^6!R-ZI4aQBheI_!grb@mC~%=sFWSfR8CJAFU(TY& zdMNq<`0C{lP2|0}18xsPfT1|nv@k_RJvh{OLkne6PtKB6%?-5q*N|MzlBQL7vtre9 z*d;?H3yTV@eP!PYDuP-%L^=Xf5Z@Lez!)fV2?Tq2cs9)Z3>uQK^hSeYeR4>vQ;3y8 zlMHEFO{XyRA9;DRITxYdO=PLH^rj6p+O!jugZNLXgNiu5cBORMqm*?;U~1{KB{gM8 zQ547PKt>zfrM2(6z<6fwd@x5OYZq!;1A9^3>SS3=3tQfcCk)*OZ5!W&n$ z3iVH@D`v%{%}b#)3=H(M|6xYamhuz_JKy5QCH3g43zjuDChIu~nM_QUHiGyoR)|St z>5_U37p;6sX2)oqwGgEdI;0k%7R|sFjcrX@(NiFTV$pPG1I?W3(l8Ju(q3bfLQfQW zenU&^Vosxt?Oqa$epx~qK@_zByv3_fe_{}619_-2&V6KHyD*8_r$s}$>iV1`H)3ZqDvll6Lw7|$q>X`qw^6w5NdD;c9l+?b&A z&$^fCPG@kY>%Y7eiQA1HDfBOGUIh!nFvZGxV5g!vV@P~U!}0|;-(26Mbxs;OCR>D+ zX)d17sG?tq>GGzfZA+ozkco}P)=B|YC3rI?3vaGsSnyRa7mFDgGdXX!x(%?-lQy(5 zK>a13SW)S_JQD|cvoN~Mbvo~uSQ2Th0Fzj@V=SeOM3EM#I6aXDjR>11(FoRUPY#4u zbVYQ>m6}N<#GR)V@?il2gTIXPYMfdVm3cAVIK_hptsB>S)_cvoJ+ri`hSB@m>uGiT zMzkn#*=aEAx8U(*dCSdO3Ngf_UPjgZ4H3Dp(4}T2-q^f?2FUTmqcR}_tQT|5By5Po zcKRYQr?q!*LA9X015;ju8A8K%B8(;FB+=B!B_BdPgTiX{rp~lAVRnVUT(D9-Q+Qx%h^lmAvOr~sPS3<2r*IXr>uL$CSjCt(00VZ9 zk*EQ86wzTDmaO1SgHJCUZ*p~@@A<|$*$`GV6a`Zc1V$gjKtcVnO>lo{RawXn^;b%6RcUvF|mxujZC&z?X}N2%p5U$iDj>>C0$e)zFrEUu*ee+ySk?v zmhadN*lM!uxJh!2Df))&m12@$zr_^Ufc~Y;|1E8notV{z(y*4~!WnriFp`=PNjpN! z5Ee5={>Q1v4fZ%;G#!hWMjJUe5>|00wer#ZnH^^N(gsoJmgRE2?FlWHx3U+pm|}=7 zTD5dJ*7U}cEu+|;Y!uY^5-b#&MGr$=np3r?Au;=kei^7Z$RjY&G1VG65bdYpvO`Ud z7`=D_5~zMOU!%|Ai1in(&adE&8_!$Ip^p~pK$RwNTfmaMxeY4}9VrH&Xd=0GRB2GP zxXs~h1g0`ngy=Zpw!>O$Y;I_s-~+Ua6%%i>OB*~vMR%=l<smDyTI51g?~`tzah&> zx%sX(HcHCDdLVz%oBf9mBR}>Hc-kuVOQnw&^)a7*&-}WxG-C8u*J)ZqaUs75{G#hH&PGA~~$j z@uV8(9fk8-sSngEKje;skNL2CMLmvF%XA1A^$Yp{{qHH;*#8L|*7P4ydYKV_2!5vj zy`rcZrwE=1XzX3p?!Qy@`bYUrKK5U#J&>-N>9VA}Md&X~M?6iZ(f<=AKf*=3q2Gvl zI^l>tJi4j>1_rM zL>D*^-H9E84Q0~5;1ApDIOJ6A7A4Jte5B}yqWq_nykKVivj5B_MSu7LX$W6flHvgF zTGENoPpiT=gR&l;Q1mHMWR?jU%W}oI3uU_^AGW9H_XAuxejvnH@8GnW=`#W$3!OwigkRqRI(xI;GpC?qgKtIE9(1nV& zlMa*l#fGc$q1+EL9LlOUlVY5|Op5V=qKo{O$A?xy~)5=eW*;q^Jk#B4&GRC&hfRhZOy;ixl;_50v$H zfE4xdOVYUO93m}top(q}Tw&WgRO$+w@u86}KcyA?ClpO7`Vr~5s{f$eVjhN^qF=s( zx@UPI-&LgNxlR(4`LaGqI~2W@6o=QAgL1rze)p(GuGj?CjuTzy9~oZhI-GZ6RjwSb z!0V+S^C7BOv@?dFz@>du<~M{C=~0EygYHVb?E5f2=|_K?ulSabLQc_sUy}OT*>2ky z4*II1e+B<~Mmv*2nej1F z$V^mc_6}o^{}n}lNjgcMDPn$^ z5%?j;bkfPLb2TaIwVCu&u5&l(rLJ=yDfqrk3b}YrkK^chQt-d1;@=`YjQav9^8HA~ z7i38PXGkx@yhnl`NC3wxQQXpbl+Jhn$JDdwv((kZS}O^W!>sCb^A4b|d{ zB+`p9Karw-n@Hb5{{^L-Je$Mu$1^#h-^%+F+k^d)v{O;h&$a&wSIpbqJj?cFze4#% ze?@(ar~h)uMVgTOF?^V?mVWdT(N9mP`wPa+8w>{({SSC!*?&OMg#|7kM13wIy%O^o zDcX56Ddc~Z6yxJ{Qlxu}6!IJ<1>b*?qCftX6z!kGeuVZYB7Gm@jPxp3*l^{#P4v?c z#u>v8;66bL+$E%lzlXHMaULT@`)nsg{dbX~eclCS{r#R4lL|g@bV9RThv!T~b6h7y z`f1nsi1gPeJo+E`Bczx#*uO(pV?H3g2IGhn?N>mGLCN!}?02HyV}6)S|Fy0&hqMI! zfE4S>FOXtBT|@dASFBgqZofd5MKk66!1WWloKrLk`J#S`>Rho-E1KmxOOURpT+U0B z58cEmLVb|39@tM2lTfD(;>el zr055aDE|+Y|DQ-vJ~Wx&!;~!ej*+4sgxr`PVw4yCwU89$qulJb2om!dnntYK&_zW3 zEF@jvI<2JW7h--!yFW(%D93q{6#ie3zK{F5qVJQU-}6i>`KFVi-e}*L_lt$3sKi@I zPdLt36}^uX?foDr`qQ^bQTb1iqQ1m(w|wy@_#gn7qG^A}ztVAjSCoJn1sbTcoJhJ4o3tLD{dK zCB@`7mi2~yF2*tXxfr+T=kpnk^nvvr_`iT~yJGGbmBzn@jN)+Q>si zddDgHBol`k`h<$NZ{8_}w9!1z&?mxp{mwV|+@SGKHuT}f+hS&ftrDJb@S|CKjOgb8 zK#?PuSklLE)!ysxxZc+r|PO~@BhnG10 z>{9&qt)UIaIs;2O@w^6N=wYA_YZXbHVo>s7c_mzxqM9&{?mYaW_??cA>mWN{u9>vM zGE6wGo3in%5k9<+nIrLUhMzqAF~5cQnRwITufb0{jmPzyiPr_ZT!axX6F-f22d+)L zweXkWr=6~se?)-Ew*~%bnh8|r`wXtld=DXC;xS)_>wK~G62LnFzggEB4@=(wUi8!Q znU{D2@Y8q%Gv(uR;uDD1PUC%q08_p=@U(mb5vTFavhZGopKE08G#(z=0(jF6yuo1B zcz7fW$QMDy-m1YAAH8^F3E(AxSA%et_YC|r-e)bmPT-}J?-~nliy>dWfp@cow-b1A z#A~O^i$|7#d!s|8g&H}T>`=N!$=jBHbrk%#y zX5mGz#=AZ+QNE%0X}mWrybXw$rNI;*z5ik1C4r~=3+EJ#=RzKe!?8tos2{w)Sa=(O zR|9^^cQ$?+uf)O|n<3xvfJHd+(eb^V*`E&pPq)W8h}U?RS$K1R*DDa@AC1Rvcul-s z;7tb$LT+p6mCQap2H+XXD0Z;*CHhKdUfE zw0uLsXX4EPUJc?Y-}#DD6YmuS<{(@J zL%4Rj-*Z3B^bCBZjGGl4Q+x`Vhd<%@q-zPqD*SKvoJ$```@!pwIM z@XUUo^Zl!ZHwSpSU(GP^$}GGt;BD5OLh*q(Bf)3Nw-9)p$c*yUDL%?K+rmp01pAdP zZ=HpA=yQI5xzfP9#lpL_AH16^ymt+}*#_Qb3vVs(?m)bDTE0gtyj}wjOCzs6p11IF z&PwtF;#@OOR3#Nd4*ZchiP3_^GW8sYjUXd0KRQJE(7G89|-@YiihgWCe%>v#Y15e9$g@u<3 zyd?NoUWn@9B`v(1VRFw_Lux$gZ!*i<3A`qScY}fV4GXUZi_LWN#F5Y57)Jcm=@YIM+^> zccq0FHSkt|S>ruu;f)1el?GFM^gdwWI~@TMDhZ3bQ@gmmGrz>n@_;LVhm;xFU)8w@^lb4~%m4H_labJ|ZH zI#S(+^iKodma}A^`7!(~2m3Aio-u5k6Q9D^GH(1D?+lBtsortUVZ|z^`NSK&72{jZ zk4raU(ghPHR9;klL1jE%dC`RGiB8N-1W4hFtcRYv{Q;J0t*i; zhPJgTvF=n@w5FU}Lv6oi{Ol9^SIWFHW@OaepW2=uPt1h%LCNXsCeGh+CTwVKsC1ud zIUa#!$qkj%eC$3P?(LWwDVf@Ps$uGhQ>Bp3jr{4xq$~7O?*kY0wGWRB&zX9nGk+?s zUq+Y%8;;v6X^%qTAE|Mo(=uoLuEIUi>6G+#)J|<8ZvND%3!(XVH_J4T`tB>=7?jgZ ztJKlB6ED0tYfR)oCHM+=*YxJX65?57GP>cP0!`6~|6`96|9ubBvdsKl2>U4mXWS17 z9?r~2k| zr8gV-G7rQ-C-a8Vg~u<4#^w#s*zCte>T*g#C!LCQsSRQ1CC}Am(ruoFwxky7L5{Qj z8t7{u6b`hgDF6R;9m{--@LdF2g5}ufvkG-A^I31Y#}I*)C>b9Ir4D7&QRi|H&yJ5; z@lkPJmt&t}k~)={-&haSm>>`qM(QAbOz_Y1_=B-wtT=)pIf6g#@tZ3W;t#U;2MPXa zj~_k7aAC}VL43}Lz6;|CC>U={j9?4n^g%GbK;$>sgDCK>coD|w@F4#X!SCNEhgkfD z7Js3|@28ab!z}(`g5Q?{i$cSN@njy9XN2G{^LR#hSG))ZR=o6|<9yxVVC_9>`TySX zKX3V8viz@E{@+;sW0wEV@U#D6nJ8Loh`tfQPkGAWXV6FypW`HypKX+f{_=U{=lw7b zDQ*q;^PEk}UnAlRoR{F&j`+V;@vNylwC@K2f1#6yn=q5GrSfp9d7ScdjO3yIYmJ+< z=zZ!2Dm1*P9Wba#5MR}ZFB!$gUqcIb^u@6bZd6jqOIlv;o!PwoGK!Dy4Nx%hOR3-& z?2w_cReX1(zl!re^yPQ^QlAM6LH!HJpMsIqSJ0sZU_7?mr1lhFDDK*&QwX8IW)>eZ z2b4gdc34bo;WpzV@)h-M-lw#vIBx18>y`Md8AnT)jZj>IP_g4LG*9qbFno6A#WGFW zSWh#6;1Fq-3VjPY^JM*v;u|~DFF(Cz3N0Fo*w`$TZFt!*bB5!KvGfu6kjrDn=fdsy zYFG%&9aOV_Fp!z~t%+}v<$5oM7d4#0Vt6sinIKl-IB`;hvp>crI8F`eM0w8$VR6WD zVWwk0FRJVt&h()R)VV9Hd9mDdif~g9`CTZ(i9b*A#TBhq6hz=^D&zxy2?AnRlXAQg zpX11+oZILZa@NXca>~y+Oy~m}-?n-MzG1~VuJ%?*oAebAa5&@nb)YkT5h^LLBP_?^ z=?30ulB64dpCF0fc04(;B&}d+$4OdjbOzlYMGs8J#2(`hlORX`1Ew#Z7#Ph^BoP=` z0lrT*h=NJd4VXS0eTPmTmUM$Cz|^PJo&WyUKQ#Z#dw^a|VORv5z6BI3KK(pq^YK1H zcOHIRS)Gm#!&}^Y%zS4dOgoMlI*wgF2iD+6Hy<93%Q$}I;g9(>;71uWUMH^O_-Uuh zfmav-JnkuQ+{W=^T8;N0u1&nn@SA1U@;!iXQ@&^6;rNc@N4YfKPjPMH?Sp?le%fg~ zKL46{`{2>?aXqB*j^WzG;~Djl8cgxg`$zmtyx+q^x#IZc;HUA7lzYXB=OfloM)9r!JhywC`WZ-elq4DZ1ybb-}-C*HGP-(inobNT>T^8O( z_-nLqijUqqExa7y>Gmj4e8hj=!aD#z??>9{vhTF;MjG;Qg{|e|w<-AV_2(1);Jsnt zaZgK^mvU-6dk;Pr4ZwKqw0!m+e3gO6`<})dh4iL;W$<&XYNzqIS8w*e$wvLLel*?` zg~xe;ZZ7;Y<)!$`y!e}maLg@99mQ`7_*|zQdFV(H<+*+ER3NirgkVV_@@4;`YEpYJAb+OCukT8lKWgzuEq*^Irr^7Y zAb!l^mmNc*lRwAe&$0M9^ZSnPCW82bEPl@HzT>-zAb+mK&ynRjzN-lG=UM!mnSIB1 z7eW34i=Q*E@A&Q_$Uns555|TAGau_~sFs70@ZwqhGnRij{62rCbH5e8 zEf60S-<)X{*3OYYe9Xb;LY`xM3H&~Oj)TuBJ;!+7=lu9V;@cg~!1%`l@wws~9y6Zz z4L^OJ_~y}!&&S;6#}_yk8gm`-`OTvrKg3B|@lv0M))Fd|f{qvO4dm+pZ=o&qhYF2L z>QUEMWM}ALlbSijgQ!^Yn+Zgy&dI=2$E1BcE}->cY9B?PrshMghvMnp>m!tZ4BL1# z_Y>*|lD_Gzn7&fWZ(`CX48--9^t1(*C}|5!>G*(@K6@jkZ{}?cPzjShof*|n!ahRF z79?g`LA{pglhABln@g;TLU=gg%q_lQ1r3e1{N84cJfU{x?0tn=1?UZMw1e zna=?8vBu^-L_bfEk1HNNoAaKcS4%axPKS3r!cDy82A=s0e;@cvyjlI=-EHCBYT!{W zE#LDN-n@SBc3OD%7at7;7i%4+K*5UuKTppe7v!0m6<#}ak^*P2~`(N zm?$1PFjwI`4_1Lqs|S53y>*Q=b; zms77)$#WS@)4Sa%&0ly%-8oHX)KN~zyVx!LyV}r!-skyj4q5-yK6KR$8NK0*@VKn* z->$v4Hq!muFJ|)1ACxXouT7(9Iql+3i;B*_K~<+-QgX)0}~m9O16)tobU{F;A{> z@BMl9@Vd8C$t}pO-5I$iu@*H4+uAjw65mO@iJE%oa`&}qmxuSpVH=yZaS7~|4-99Q zpVjS7dVkwzF3;cl!D?-JyS(XzRA&5hBStSAmK?+DicgOi9&@WkFMMZPelq{U?4xe> zJ}>W>sF8uMIY;({og-77EY!xHs$qr0=f9a1+8;yf^7P1Xo-7gXYFLlqnXjQAxs@;C zuMW@MaVG0=zublqImbWEHh;uU`bgfB<@9W4Ild-1_D zKe;<{XQ5A54WECi+)bR>6+ZG(XkTj2wD6JI&|~vMy*Z&MPTMd|)^w)?*t>^{p5(-H zU!d$KjrKV;x_U>(!J1-QDxg=*=0N(Oq-wS6RqKxm+Y!JHhO|?1ETQ^ z)+b9hrB6D{Wjn$c6Py>mwk49t=&Ct3vsj~Ff7QXQ*Vnx++9$vCx~a~&&(!91)!mTa z>t?w}GMtQ~`8l8OE>7gL@0=>_xbe6XE=_`e+SqA_*V4}YrrOBSXvVc&nI$u4$oV>y zaLN*0qZ1KvPV3ie2Ob?9c1oo0b+l_n;?dM#XZU<)T%!9_`Lu2#XC!K#a}zlwo6n{X z_*K=@!CL^%_-}?yo%;2;B^|}Lpg)JBmrUtRx{b%DgfJ(S7Po>UwmLuM1Q_V%O)jri=}K^L=RzIu$TO-a6|3juAgxX zIXPwS?s&(Zyp_6J>Bw?jLtUo(gw;1ZVzG$E`KT zepHJ4O$GD)kuladR}BBzvNBTM7uYi7c{^2hTNZGf-a9*|O&@slESI6I=SOM>bz_^m z*gco`hy$4U9<43ho4u9sSz_jMa3*aCdR1H?Ib}WF7tDM#HKgJ-%ssEqKXobUYt&mk z6?FqnW_-XoC_jZ&MQ_*%mxYgH$0l`eLaRKQI%|*9dycd4^0MxqzZc3Udd04PN@Y5m zYkvj*+1kU19yGQSdm)PbT~6SKC+t}wR7D{lo5B8KkofTPk5GFnt$&5s6XnRG2OWL zj$iS1YTdf{Y=`TK*g@3G=PHZnNo&WhhO^-+~;E_ zBY$cg+I9oSjEj5e1F5Xe8d2i^K<_7?qZ8u=<4!2z^=WVy@MXPNo9RRD1q`)~Sx@g++B-iwtX$KCVArt-2$%uZnUP3h62NkTjCl9CIs8 z$(cgj`^22wHuc5Am&7{2Ee~~ftrl%_!3$~Rql~z}P92=cEY1|=D=OZSa@NTiII}pC zkXPq?cvp%&aO33}iOq=5=z2Rf=YH1o#>>C77p+`bo?Mo^s&35My}0ZBI2Edp^TOx5 z+=t_dgF*t?C*i+sSjUUUZwo!vN*c~P+bhHoVulzTx*8nad5cyR z-a?aOqWllPoEqZnO$`!j#Fk!XYT2-jwHLkSKCHuLpGaO)hIwZ8iCdCCIN5vr<;a<|G5wbr=ZeR{!%YkQePau?QB9S>#2_Juh|m500XZ^`dX4i0sFH|2CD zd$`&<=fkzBh8`&o@~wDj7;>HSvUe}3*pW9YZ{|MqgS;lU@&_l69Sxm4qcXn)eW!rE z{Mr`^4J&9HB7bH+TsJL6BCt$EwRW1_!uO73p`S!=9qW*az1=1<$WvO=6MX8Ts` z7*IE&X@FR{HC!J#t6>ggUT2^@f%#H`Loc%aETXD39qxAz%mfjutb!Ru_ zGu^cOQE1Pb@2xF7n0eAYez@>AxF@=U2X|eK_Q=V3{%B-ycDF2bM)%IzaQFHwcV9Ho z`+_^+9imQ18GWx}$H2OwO*|zGNk`sRJNRJaq;q_K;a;q%vi2{-eJUp-GA`8paF(-= za{Zx?TxZl3VNITY9wl>1zg-*Z<{dKsP}a%tvF{dsXa3K!2JQbsM_zAyaIA~>_vq-% z?ojWDP-IM~JA*6o7u?FV`i&0Hdd3?&lp7^VW%>LxVVE^t(^b6F&Dsj&k>skG4I2BpQCa_TLV;7wqhD z&f`pb)T_gF7=>RMlht+Cuxm>{H+A~%Qxif*ii>A#o3b)_Mef#6-R-IU5xo|6;d`Av zxGb!M1|ALLjwPQ@Htxc1=QEE&)fXjMC`Od*S2^8tI-K4SP6W>(?5A5k?Ch<{4sW?3 z6*)=&`#nIsV(Qe3<7HP|b!~h~>x%g0D;6~_Ufj4iJ{Q(#a2{!Cb9_R@_{wn;D<)1D zKcQl@@Qt4kr@sQ93B=1I5+f?q5^M4)~{Cpp4+dl%%73VyzClP;<+ z1m%8akUu8)`Tj<_zWbR${v1mlz6J9g_cMe1g9N{P)j+$C5EW{|(Y!slBk-*G=P$Uj8z`(b>`6WO2?BOzT?^KpnOGw|Mwn?`L!bP;}(D1Wg$Ff@P$%R5Hmd#Gc)E6G3B;vXyc z*Lhri&z1b+E&lO>{|--{@m@;FUt#fA2>w|fSA};a`6pWZ69vD|HPPa)viPe6{~V92 z%Da;IlPvy8g1_41GT(l(KC3PMYQaC<CO@n0(VpYZrE^{ym;jm2MM#ZR%~rwF_pk86r|#fvb$j?WE*Ocnh8EITz28-~5= zAphl7{1sNbxaE30VdE3Ppt1>;m#n6s^>fF_i{sor* ziW4`9j8$hWRx3uv4V>(M(%K(nd4P_bqE~xw%;?6y*0)JTViO52|lsteVZS}S1w3g4L^O9s%GC(b2^Fj#7$$x~aH#txWmlnK1= zt^(5X&=Aw&XoH=WQMWWKxCO?a`iVtC`K1ZJsWPRKq5asAB`)o2F7EKMgu&OP_~xS? z=Bl(U#)g(v{0zin(N<_#V9}VOO<~*8%vUK__3Uun1RIO6jR{*<{NM>z#f8~GfhnSH zZbi1jyqEgWthrAL9{lj_WTDQ3h6e+csVwB8BKg4@%V}EiMF$O72%|dN74_{6O{#lR zth67xc^w9bW@&@w`OvqRV_QorY?OLk*yLw_ld;k!AJld>`fZ>qST&DmLOXR6k~1t& zYL!6uSKTw&#Ep&KH)dWTSPd|Iwg^w=Vi?L^>-X}-&^Fw+pZj(xKao-IbT+(|+{P$_ zSxPZvX!DMGaWOxDNf&_SqB%8up{LCui{2rOS<25Gn_)>&RLCbV2HFbqlrYrUj9$p8 zYEi3a*_|1g9mVUuXi}q-v`S$Eb?=!jWKlSfJ&Txv%^X)WB+26Gt{JfH&OlCFmVtSr zHbevYBU)FIH_~-mxLEYv?RDIB@uGin?So7>(25$kXQ=nea)0TQ4;mSTrYvmlUoGq1=Nu%-m*j8nI zqC3j@j@E;zt(cZ(+nX?LHMPKgAKJ5jF47gY#fPN0C5v@LY`L<* z1?4MT2gI6{Z6zpA>3~0!lzKu#E9El=`S~Os!r8g8DxUZI5cs*yAV1d&MY#8Koe;Z8 z+IEYAs?Dd7<2VqK~bS&m*zhl}$a+8is==6czd1p}u7W?$rn{x>Kd=lzM3?2cMm3 zLx#9TUsJZjP`(oQV{6qnt>6>!NXIAgqPt|e*wv-LP~ZB(&w67z!FPY(@InZ?AA>Tie zg6Vxy$d!Y|W(@i98~hmfVfM?3As=D;;z8&KqyJmb>jg@=`MnzD-av}}MSZFv6q3)_ zu}!E8(uY<5!6KjaOnh8Au}5Lsg!BPN+TZ~GFX;#V??_QjzB^(*6^d3V{AyC<%d?S` zTjcY1s(yeY$`70`F#a}W(+2f_5Bx%I(#@*>LSD9uhll#$_+Y(EB7ID@a}4-1=?A_T zXTWcwzZJGzNRiJvP*ESGkXztloUy#j5C28|Ac<21xnrQQCzQ>>?>bIg`33%yO8&oh zoWl%%O7@f3(>TM1@{`6%pMkuj-@|hzDf-_u(l5h?9x3?PZj@&&De7$&@aUgI3V(&7 zRaW?1<*!!pla+tE@@t&2$}ez$J74iFRNN3dtvgzD(wtMy?9+5G0=!`ZDW9ZQrMc{(03Z-e(B3 zj{hj>Gw6Gx&W($lKC!G#dvV@}$!i>P_utMo+i6?cUvl@!(&#f{J=}-E%Ph?bwtwb+ zOdJF(kBcQ~{}3O$&g(x}V8z#$4gDw0+V7L`d8@#_?7HpytOxsNHCBdwn2c7j*NFY_ z+N(v+c!$w_gKNeBQ2*;fZ}s>I`PDiyz)czK6=hIBEL`Qf^8c8=gihQxw2P<<-mkLp zt5N>y5_u2g{hd7g@gBtcBW{^^vo0OiE4;^Pr}1VXz{G0;ULnGW$Fv#`x7q;SJMi-! ztDVMMh5!?<)4-!#8gB!xP5HPk;#xyHjkgW~Cf-J)yfMUSyq&l<@%F)!uDq-V6Ymv6 zKHjr6-a!kGHVdi{rk$2=KLSj=L%_>L80&8kej4wuxHjdh?g#Hf@R@kM1|D%W9?uw< zc*}uzE8?}&@^K%;#Dn5OuYL2ttnse4@ZRl5zN;*}Lg4B078rOpTX-YF(q5V^pKVj2 z40!A(tiK@!-V+vH1@O35(@vLnvn5{z@aBPuc zczm|dcopD7*4})OlaXEr=~xRdI?`|7xPeF81}5I6z+=AJAzHXkTX==QV>?j368yA$ zv@L1kQMYtDybcSm!ob6&hxeF;w*`2cnSpZ5myY@+%=()SkhKV>e53FqANwP1SDNz8 z$&!0Xh!RfY(dMCv*9E*La1f8}tnuEn@a{n->E^%RT6opx%DJ6*V+=gnKsMzogAh+3 zUOO#c9{5c8)&egHCgSnlqUD=p;k}APe0J7O3r}2JZ;jJ_9cz@94 zecQsDjGIf122*_WzG>lYHt_fiuki-q!ffALfj5T$%4zvxxG>AR#lU0zXuOLoyjOvj z?*4Xxg}2ARyV$^^%}rB2Dg#}tg;RX=UT5KT8F-TwAIBSQYnynBf%hx{ltZ*|U$yWK z0gvO1{qIuz$VWWAUz>?*x?J3xIp1oBVJ6&OE8nr;WB=1m=lkzgzR~mi`_>dN>wLqQ zcg%831|F)~a~kiIg_mpKO*QZ)Sa{QcH_JoAy9jkX4t!=mC7))n1U~j-?Z`t%sv#_C zz*#%or+I?4Vwd~yJbX2>244g5r0S{ohdrM(u26h!l0MzX#WBAcBfsblN^+_!y4%6` zdv@+7=Y=~85;%{GFO&Qexd-rN5>Bcl%r}Rsb!*DA9w$P#^{WYP-gdeB* zlh=2=#4m(a^82Sht1q2=ybOHVGNs!*<;#%jZg*30$2CZ~##vjN-<{jBgr(2=QSHF) zzei|I=8tNl-M{Pj;gQ^PBHi)T;a)d*L2h$zaxB2(tWtTV;HV)4-LchcRH@a z^_0+cxc;>W&&p$X@oI)U2xpCy;cLNOd{ZS`3ST;)YzM@b3i3OgctYsChQ9BxXv;`q z<8xuf5#DqS&Z&paLF2k4f4L{ z$Vu}($LtgLwt+vylgyMYo)8+sck6yE=>M|Q&3bH6w*QH<&4q!&>KRf7^6YXjUeD+{ zK5E5t_V*pnCI{2U{776;w^A_PoUIu@$co1VXE^Fk3Z~~Q<~yD(4#x8-%y-m{6pZIn zmG5|VI2g~TB;WC@a4^15d_R7x#}bU?Sz*(K!OiCewkhwA)Rn~hyml; zXvg^b@blxN&i4cUnDg%ee~viIM}F2M&*BY-$4{T@d`kJR7V&w`=NPFR^MeU;&(VLI z;(rX+d8p4vt@t0Q__&B4BJAAZQaGmnql#aPYqr)v<3`2!vn+q5<)2~suebaQE&rD+ zfA9d(s`jPJm$t7qwJY(J7~k^pjVQiU@Za{Pd7IoP(n_c|-;Gy&Vym6$%s8EF@l6d2 z+E*tV`^7aG(gE;AC{IQ#?;pZokuUwRo4urdIZl130%~Cl#&qK97ppkJB{Z-gwLW~{ zy&z9hWjYt}UNa4bJn56}EC(x5z2)~_efOJ_f8?j1WV-f(daqgbbVoiu;o+8B7U|-t z9gszh^*DHeLjtvXtfUwe_Z)Dl9u~;f`6RaSJdIiPlxjvfjXq8lU6v+XGkZ=1t)bcbDj%T zI!-4k9%$|$638Es^S^E|Bmvd|4q7=ct6%o-!jG`zF{`uHSr?wFg($aWe#I=dXXSQ^BHzVA{%Q5hXtMQ(+ z@YeQ&_n3uOVBm2jr}4ThyeIm>d)2}lVc>D)r}6$`;q8InT>0tt_yFN%c}E&}${vJ1yTl3$F@z#9`if_-VW~79P*dv+lLi zcwe^grU8#DOyY6ns_~w(@TmVdj(F`f9^dnu<(+Tfaiy#AUbFD{GJ$XqO8ON^eyj+DZ)yNuh&a&#rU5C*F~1pLkEU)f}6Vr=NI3Taqsf7FrR2 z3oQt5T{E>eHw^1jRU1;js&p&wz~4}5IJqx%pz_VNn^SJZ_SBP=n^V~p#U(GcX0%=2 zc4r$oW7FO835iIzFNuHU>*!I{>s0S3y0WOwDH+{#ckS4{>r?wnsE-F==6d<&Asg1ivYrxeZGh2nrBhbX-GMqhx%I_SsILpZnc6cYg+Lf3&)wzb>&*8L*CixRrU|GvjL|H#`GD?;iN6+qO7tRLT_Ubnf^Vk&Q1xhPWc=sQtFQ>~n(l<(E&cg> z(24Q>Us|0~=-!PMTGFs>dRuHW?R{%i3`#b1b;WnM9Ug@4;oXqp-#-}?xO zUPuiQayq3y=+P;h^WQ;zjjet&>(IWRj~Z!w^RN4arXS(`sF4j=Ty|wx89Tn-%MdCteieJC1xgCVQtq z>fM8td>O?V&|32ksgQU#=RVVwayuVP{Zm-VT())gi32OqUb!qOFsl%k&lzIi(U9|1 z_!<5J^p1QNGeZa^{2^wC?_zfNacV$kaUvr6j>z>kvz&Mvx{fIa*SQa&ydz;T4>sYp zk6fSHS(-IwVE1~=YSBdLR`C}02<0`dru)|#vu%geqLP6T+$3uIQD{$itbFo;_2mTz z?kpdDptHQ_z?$+&-I+?Wh;weJq;AHVWF+z9WL#)IDov;wiOuolEm$@odn8MvNv&5O{R z#55VbZpQOH50r22+Eo6P6RqFR(ej)dEs3f!wDv$JRgcuW@?6hTxc|*pH&5yUx^PE^ zkT2YEZz`h#vs>xCsYt~csjN#j;qB~&2fk4rJrF+nmC$S3B4gqQe=1_HKD6$VSb6Gz z``Fc~(q3oxIVdO|FP#aBUZ^O;%-HF3@BRfr!~_u}f?Q_n!}OSmRftaNIX$T!u_SZdai^A_K+mrf6f z8U9_g3R8Wrt!Yw|a)x{mW|9b7}qYmvCQeF5TZ#2>##ooGCbVl>EHs%<0jR zx6mrTUXAtw-`c##LI0&E2O(%Rgw!HsOX<#@Xx(Ap&%sQVA>zpGg!cAG`Jfdgx0#nPU(;nhi<~XCO-;2dd~fk#E)>dku~tGRAJ@y z&h0D19rAuL3HCw1Gm&>08NWRhj?aGo&(N1vdf@Snd|1Z}mqbd!s(l~t2q(b-%}IZ5 zeF)lJG7oT-L%zuFhSe`6zq4ARWK16|wLXfHx@bFp9uC*R?r2GP`t6v%AhoxDfHlSy zzj`lv%fLj|(E;v|L}%h5QL0ntM-rLIjDxdJ++D9{*RLfnPRvLQ5ckR!abn(3Xy}zBei2tB8I!uS&6d+ZdNjp+>;8;!A$SniCC`} z?#O&}z^wYM8&W&--3fQ#Z}yCzzvq1Vl(;jn_A~0R{>%4U(l1-ZjybdL+#*{8=}WH} z@#eP2jt+EzQi*p=$G+D2_PcIx=8z$yN7vR~cipYGIw9yH!zwX6wQf!c^cSt1G7S39 zRBdMyQbuD&l!qqqPU0nT<6cIz{p|Wh=PAy z-EAdq5%GV~lP^+4OUkSiOj}U?FWnnbTk>6`nNkw3J9W`JJ!hhY!>jK|ZK>Rl+FE%E zKCY*?3ZHWcb==(xjdDY1dvqdWb|UT7(3>+D)<;#(Q)AGV?!KM@)1A`M3DypEgvxQj zHh2gEZHYpG{P>+X?ZQ;X)+&YKbpyFE>qTXqlj99`(h zB=-L{?L3%fJ@-Gcf5rC(zKb}6;o0d0=qFPd!2PTsf2Md2r%ZR?M?0xZf2(B2U%rL$ z9d+{r(?hT&eJRYhCVckI zwfJ)d|7H)LPszUH{#g(|Pw-FoSojvhcic}4@)rpHxgLx3CoTVCuT%8he+%Lb5qQ(Q z^g~2`KAw#C+fT-?Gx*uQPZ@sV?=$?2_s?GS-R}#^Qz+!w?xp8j4&QOVFUUVk@IULZ z*!zJaEdCLK-)|MZN%0+Z0R{1k1pj=Gg>OH6M_oWc{D>9NGUD_&4HP>{dG!FGXo zmo^zRgm~6h6@Jo{=nFx^u%Z@BKT`0^R~uxJ{%KzO`;ss=?2NL~j}qzq{_P`4{xXZd zOz`{lS4K9^QMXV~zA+a67>}11VVv3v@{hIn$6Ea3E&lNqzw|eFspR-sZ1`Efs|-K$ zzsc}39$PZX$@-qCy#XtBl)u7@;YAoJ=Yq2OU%`+2&r3nIW4+y?J)rbIX!)PD{QqqE z_gennTK*3$|0&B)8+qC>e}2QJ9sMW{uax>0e<3F;K#cQb<=1^{#R5y`#H}iyk*6QBQibv9W}?2(9Kr-eJZ{kLi2pXV^;ij%l`|-&u?6*o9M9eKQHhLo%b#N zm~n27@(#EBW$?4Uc#om(p~=e6I}Pnh&r*KgL-R1+7b^ck5ntrAz^@(gA5ig}3Gu*7orgdNZ9HnmDDvJzE-=rkNLfjnv%M4%1jku!;Bb)L$V#^swbaZ!e?)-=SIMGQoF{0gZ)<0a{H71OZCX(1n?HrmcMZrQxtYxOOi#6H!f`s41@HFSUkJ)M*4=P#)f4JT3TSgU33$Q z%naX)AztAsb#7hl8MnD5^ z2)DEHii)%y3TR-kTy8Z%cP6tesR(D@)@yc zq2p{rcu~Fl{w>z1&OF`dIGyAN4w5)UOVn8_;Pbv5!yAV1CzSITsmf}01_~N+P##-<_lA_~DlPDkQO03&Rk$)#C>Vwa+G3b_f zp0pk1B(29YFDV`@c>a>%e22mEL`hK}Iiz^d;J$YV2TKY_J5WAS=-e1Vy2x?jijE}3 z!vb#a4(nOe172^4dbkyQ4F8hSwSxF*^nY1?mqd9M!msNy^cDFXSEy5dH^=%PM1J7q zk*-l^)_})#4AYGzMYu*Q6->0sVabAr?8i)pCKj|)(K{4ftLQz7KBefhif&PKyP`W4eO}Q$ioUGqD~i6V zXqTezfU^F6Pm20Wk=CQ!C_nvokfNSA9#|ji6y2ccMnywRcfabtm_J0jpi@j__ydkp zOS)d3S0QEnkaj3~H!0F>CPg|?F61Z5)gX176afcaS@b)Bk8yhy{jEwD560^T`rGAq zSd>@P6UNtL2xtGv1!Z^vDLQG63a6j-P)3T%uOdbHMLTYk^AOXMpL`=hL!0FIWcV{BgAvvz7duS&4KBda9`zxpzFPOi!Gamjz)GP7gqz|M2ff9GRqO%m8 zLyCE3uJUs}BOlLNG5>|6k6?U&QqCylLcFer{^;L!7FDh>tS1QnAS9#vc|`Gj`%|EsV7RGP(CAl_dW>2*mUy6*}p5G_(0H-1Y@v3fI>Oo6n07C(X5 zK8u=Qtg)Q2@-!ATeUfms!?jDF2(ETM?#Z!F0&nTUwNxP1Ucdw*&6PTkn$9Rk}s_MHXq~Y&cl!6@^pL^;IZ?41!3An)WulP zZ2W4Jf8N=09mlztJp3`g+4z}wAHjbIe%figIs}+_TYwiw81cA1(0J{*Ht{;);rm1F zG+q(`CSDitqTnSS<QH?KIvN z1ekag=SV)v$N695y^U)VZyF*Pubsww69FdPLg3{hjCh0a(|D(FZQ{*A#Ip#~PUD?K zfQgp`-a>>CkGLAI2w*1OM~Ik%c?*F z+gL2u&BQBIeC&tcvhWI#h$y<_2Z8uG=#tmSh< z!Tz@#c#}1l;-mL379REI#1T&UaOvSqwD6t+-eRQHPRlnQd}euf0%R?ih&K{HE#Djq zF9(A+-T0kl;nkGNd5U=N`Hy;LVhm;xF^! z@7Lf9%PB>KZv)>XaV7ugE=E!kK1QoYQj3-s&#J+2p~nR(P;` z;axnH$dl{m+?@ywYxZ43*dB~Ecv)J7C1(u`B~C@#US@xaVMSvFlay*u3V?%YD`vRT`ax1X;#eU|T(;>=pBKJO;;%_)hg6JL=( zm9NB?7bQC94QQoHroFlC4p5jgb-HYM|D%n|LS(u__>Ed=r}`*3<)1n)o>f!~KS zpe4a>OQ}=BjT1c^tuw#$2dO72H`Qjr&TzCQb2?6BE)rHPVIMeJm|V>&O*n4W#& zu|R!{PQ(O1v7^)FI52v@S57T2X)bI8lRvyRw>)xiPciCOv`nOKfS6xsPuVpzHI;NS#v_zfL5p;*{&K9&9qew)gJ`Aiw1&Ie;2$w(A-m7-iE-5C71G^MM#Y@9m2x&P-)5V_u_&$-Ly>uA^}`gtPvP38_(# z**iEhv(rRpo#=6(+iYEGc7=n{%Fmf!hosvXkpZj6?&*N4T7 zm&6&;BbUJnWoCBwcJx1-*96xHoUPnhIiNh&EoWDrS$E4%cFU8~ulJOwk>HjllAM8_ zten~@Ip6EycSmn#9o|RDXZKc49G%#5^4PJ==@}Cl!dQ7Gd3zNs%WL<4Tqg&g1$-BA zc&p?+nQLd-8@veAUyte47y{vV#xa;aQ>;~)o@-W~ab)@`{G`hi@4OjbgI_4HawJ~V z!i$PCL1K-7KOw{u?_K<)i;8!jjIYKoB;ItYC=i~B49XW1>GfI(ZwY;7!JlLC!@d;4 zi7j1@&tlcMiv-!RBO!l_g8vrcFak@fGVAK@p)70);Z z(-#STzy9s=$1VQ2;NR|{#=R?E@QkDB!cM8!L(ySuU0dhLU2F{H82@*cpU=J8G5*Jv z|3550_u#Z6|0&CFetXLJ)9FN6Y^(#xe~ab6&GJ8B`Jb@-yDb0fmj8(5&oCY?n16xg zFSq=)mVdG3Z-bvz!v4=QU*ELipH=ZSBEG=sQhxR%j>Zp_pW~f6W`-M6CgmFqKk+L> z{4mEpBlcN~zuofRW%<8t`Tx=K|HShD%JPTsK1w^vC(gDA!y{q`efiRcc6nL~TMWTq zc_;=u3N6cT!b@b>*Xql{ci=LWcUZ*&@i@|?ZfR<(q z+N9;sQt(JdS_T|+(7ClXCTY@0oMfN@7Ox(#4YNQhRY?PJV++*wD0vkEH)XJMpf**4 z<>uKQafm{n4EdXng{9N$f}DvPJVwGz1R+mj{bE?%(I>RXD2^#>bWXczowkvC2-hno+7kMGx5jR!a>6PE83SkxaN6DB%>?Xm-Os@=EBF(i0wbhxBrDiCiHpo1l%kB9V6OVNH)+tM3x(h^C~frM6k z_B=qfz-*n0lfy+E!eLKrSk;d6gG+ofX$)Kr+e~J6m95aa^v0$jp9~KqXBTK}Zh|JH z#cD7wxMk^$i_qP*q9oN<(ww*|!1NfpRK5d?T_)f2$7+;~mnmu=d!Sm2)+)ZKa+MjI zruZ+H?^Br$EKUsR=8;~Z_T#5Rza{-MlnocW%)5_%N|pq{a@|Y3bqaR_>1QM^(|;9y%27ss;9N`! z98`fQ?-E6uNr870Dfn+CMg81OS|iWRuwJ=tV}4smkL~;oL%vZ`G(r`_ z!Cy_9CErsQpKO`nyyeEw4-n_?4Lz9C_dz`aYX%0Q}Uz#mN0#dvY`Zd(L|#Ewv(cqqCM)>xuQj? z|2C-e8jDrCK>jV@r(D|=WjnJUJVjdN=RXmCjt?}EXs;!tjq+u744yUggP--m`g)8M z^`LQg!XFxeKYy#PFl$~Er-8kNPhj`l;`CNG>agy|@djsG%*p^M?)i9LwE{Xl zq839fVm=;~%O?Le_3^xcHCTZ4v^TMI+^4&p1=3i}qRXgmYysBO-qZrzEPeU~UVzQY zKh0v%XD6h^?=L+6+ea~mV;H#jW#UJNVH0p6G(Lu*!dO` zKsnAebexmSeaI%v*PMSw;zu6-=;vOPiHBh?=3fxuG#;k?0A3P!We6i4>p=RJ8v;zc>G_TmM;P&9_-VYuxHj?j zz*B=T?KIw72r%)Q47?n~X}l=Xn|Qn#Zq#6kkKPEFOuV(gn~reGH;D20vE0=b-bUa( zk8tg@d{q`+7x0?EM7&)5G#>Y;@!#vGbJ4*j!>^sjTWH}`7s&f7@z69L-Zv~f+8L

(aZAzrhM~&*NO0v_!Z%&@itp{oAF*FUH^N;!aD%G zISMas;Ju{qbe+w|WWn``cC1_eUIibTicKKgli-`AJ)q>FBL%DHehI!Le&-?tOCV8> zTu_!3c%GXz5d8{e(N5#p`|4%rOusZT(0sg`v^6%YYE_EkPPeaqLB$0VKk2^u%M{qq zi=U4Xm)tQh5rLkNA!2_hGl~6Qr6WY{XfpwHmCXLemdwOmiFFC5cwkB9Q`~=%+JBrQ z*;&;h?dGF{!jbinP500GOX0ZE=jN_SNRHgz+`$<~-2ru7U-;sN)Ew*yCAuQmH~P%V zc_Q7u)I4bUco}~)j%Ey4gIz8e-ia%j(}vWCm(9y6*q?PYH(Z$b;*5;-Qp-oi!*g~G z#g41w%6K?hGBhF6?#C{6bbaLErZ1kHe=jtLQQq63W$n7|_5^=0elQ2bXQi8oGZW_^(&{bk)#~GYfnF-|=+hMX=*8QuyEdfGzLfjhSz>RNz80a|=Il#Z8_U{m7ki%60k^$-*%#Fr1LSd& zw+r|bcEUcmY-m>T{!dxbd?g^w=MuRkG0`@UrbbuX-rF0#7gS32l8|iR(Xs(qM`GcM zL}WedB>PA#6nWTL-#N@(cX8t9sc7dliOi>EiLxNkS5B<>{)|M8XeZsCGZSuNjtG(A zx2bj>H>@Ht6#AY@d$YpXpv14u%-LU4Ecs+_2xo@(cd8I_IAxcexa9k+vD+%Ya$?f= z<;jByJ?wWp3n}!i;hOgoI`&1U^y}EAk5tN?_|Q7ygdRr!i$#k&6R;w1B$h2ohyIjU z8&T!SJvw4=BvH~Gd0O>L;UCuhP->vu`P~#rys;}%l6};5GoC_dk{Ivo$}5=wOkShU zRGlGOapWOq?BOmy=6H|LvgbxdhjwQaOA81Gdm;}%zIAUZ7SDL-?%L47hgUyW>tc^P z)_q0*F`gJ8dZEmt=JL=1=F_G0$80_l4TsCa>rWi~j5jizvOjcPWB7j8H4yz!j)Ksp zaiyVDtm1RtxHu@rLg?YQQzP%sM-0b8dbVKAxDG7=t!v`67ww&($28l7}9y z^dprez&DL?ncvGulq8B(TaTzH>Us$Ja4MgRY-)Y(A@t+tYBzPA9QNk6FPA?kw9`3d z4|G?HTD!03A>`#2yOjb>=!L8A$v6^oGQU@nn2?Y?#VI@3y&pB^l<)6;G*#$Co^gc+ zqF<<*Ef^i|KBL3!%|RXK><$&Xs+J=U4Ztaz9N2vrfR-F4EIs@?EIoWDmr}cz+=Z~8 zuFjq=_vwH2US#4+Xpv2;|Ec!zuD@GJp1%`)P4+JNH%vWg&>boDZb@A^5fR3=^+IqP0e;`SZ)hfNoTh7LYIX~%rbH7@;l?dCc9 zm*L0yx(8**Lw$V3in@tObsWAAO? zqbkn*@pJaIcH|hGtbQM#9!{A>pk>p5B(Jn?fw4weNX%^JoJ7K{bvuIt_>b3 zZ?1!7QlBu+; z;UV7&KhC^^UD_6WZK-PzjV1~$zOS%pSFLc>H;aeRq#*!ir`c6V6=xquKwAz=8*8s$ z(FD5?buIW-DvH2LSXy7#tW^RrJoXfj>yYz1+^uBGuPT8bh1_3zRC4E2l~+`zbv{NV z`{fV=5#l@BkTXDZQw-Om(r#GMbThuB)#JMnvnDt*#3w!0n7!GYflC`(#0NS?iW1?( z7lz9vPgk&byJSL-I*fad-&HtYF2s$F?49 z{%`1GLVJY%c$C2hA1}B}`jDIZy2+O>>0;^AE>R}RQB5C<1#=|L_cZCN=ud!Z0{yeF ze+Is<4BwTce~a`x=ugD=5=nQ`pCtD^Gk=yB^#(|T^~`xX&m4)-FPHn~i{y6~$l1p5 zboqT@3hdcP`WMoFoj%I@uJjF-JB<9KUqB!AIGH~1xX+YlnS73Zg}o1m^|FR^rL0es zQ`F})!}tlqA>@Ag=OQ2aRoDlPa%Do1=~ML42`-^O9djC%cZOYGzVor4l{6L?7Sl(4 z@qIv_^+5mc{vP7ooAM3dtX|6-!SzrX66<;BxZ+dZF)of&_s&1nx;V$c%Bc}By0vQ^ zERKOEp9gGH^6(eL51;MW4U_ABSK*ptMdcJ8*Ru3=wNBtgkdSz3_$j>QxYqIB0v5+k z$|<}C1n77#VyMeCX5vvUg?AUOb-X!P+hTuIPT_STK*!rV!p0#UN8t*O&omuxA@Eo) z$|<}j5TN57(D1Slr|^D>YvPsTN7o8G)|GOM<8MEH7%Ih8_>aJMGV6ZFz!yShT))F3 zNaV{hQ8wTuogam~K?`7>bl!EpLny~vc9i(9_{5t<+GOI=-zTm6opa8~ulwz{8!Wk> zrpO43b(BxdzkU1H6BDnxKXwXiem|Uulm~F$L1*mVSlV7#SH2=}?9eLXd|10Z<6W@= z77_pbvF*FCLQ$SBRxQpF>uK+c-6}@uksf2?N~}r!$XAp+Rp9Mj17{?d!;Jeb=e~{a zSHxyYTiLMFTv9zN5G&}pCKgcpGfL9pPp&+!s0Ux$alC}~oQ(}wcPg>9*t4abd?Wl^ zuT`v4b|j4L;KT_OX1TxQ_1-ke71;E+W{+7_{kdJIU3?l>1;i@DeTn*t+^3yg2e~Mf zcPG*OVhykJavV1IC4L7O=d)_TX8IUx3;97>*Ycq%wG{+emN!z=fCcTrG|3;$xo>OAGP(K%TVpj-Sxvl4oMEH^W6H9X+ zNEmx+XZa6SA(zB_r0YJISPW&??C}rHDmuXZHuL+lhi#nom%YOVeebUu9ZIAfDukYY zQI9$04x}$`tM12Ur1*xXuPS7&zzeUh9{q9*yDEMp*4EMntt0F5)-2qY9(d)MgzwO^ z34i!&v-0!oOTEZBw}Sa)XAfHMn|*0nU%Bp7aF{*opEj#Z ztR5dZP}0_PbhcFz2TFNeN3ah%rQ@${tBd=lWgH6hMND70uXtwE-xm>io9EQE_3vC; zJ#gSFz2>xe*O?XbuJnl($at@DrERJGJaLACUG}B1UwisX71qep-jvZ>_$qM=9 z;)IP%oUoBeE~{;O!oR+{(?YK>%L1{nAKvl7oSwkFj4N9hc)%)~DR)sgyGgRjKHu}? zYO}2UpgH}?mFbV84HNktOktE>)|39=>1|)^4+eM+K>FkMI&A5#bex(oI(=ccIqlCo z$@y6IwFl`(#)SHh8&~dqBk}rXvx*_F;?#jn)q&V$FJm9wNY$D~iCKg@ITxpWZ2o@o zWRI^&TkFpb7$eg5MvmN#b;KW;_8n^#kCgX(7J5DI(DmvLe-tMP?C4Dw>yI6fEWa%$ zJ!}6#oY|2tS`VcOf4$n;yMC6r_wF6$`BI8-Hv+9=^kgW8R6fX zi(XgI{XZ3DSDI7F^Ou)_P@FwJk;DPUywe-9=iwZgYNPnRYNIE<8|TVczt4Mf;qTI| zS9T<<#a|L@zWu#cf1WRN)?a#>j?T&*7C)TC2zCXrlc&Do+8ulr*{k2&p=IH@V(-@q z?pA%ur=C~c(gyoK`Pw7jvySr{`1CB^<^0FB$5PP!Nd~;6HOI9_cltDgLukHlY+Dy=*KEWBQvtw0G|b*8`Lz|7M9-iEH-WpL*gC z%6OKW_If|`#Aj*abK;eF=t>WLnTPh;D_-M?f7nBN?H9jZ%VbK8Ap4+V$Va1nlz~8UVDuSntshtNu((%xz$623k`6lz*1;qOI_1V z_06kcB(f>4R>WGGRyD)!qKAdCT=K*U=MbZmYK2p+f}Yf}EQRst;w#&&p5T*K(Z8`S zj?D|J8kaA%_eUsORuDb8dYIgO@Np}!j!8=*ioF&R%WczA+YgY;z`H!jN>detQ&ekL zLycWklsl2CVsa1N^WbR@uK`kL{|7AlvTkpzZCj)_r7&gd>KVxfry*L=RpQN!P05u} z5u)k#yLS@Eg;{3{2+L_VoO_*DD80&_M;o}hOgKuq(KhmH+X#aka(PNFO2HoP>P6TD z(X>K!NTyh28xLiUC;ffFwPA+hco)p&qIinc^!7T~4qa4-+sLk0mtkQks28nqX&b9o zEpod|2eX0HvAn`eb8=^os3!gPv!m5!%C$H0NwLANr_qV!O^LGd7Xb;RxR5 zTG(H;_kyTC;EBQ0K&+=^;=v=g*4VmpQVqr z(mnL?p#C*|#Q#as{qT7X^fCGXPteC&=|}Xdzzd&ir5qh_t#llHY4{sr_ekTy24)_M{704nmsnlabVxOPk&>coG6 ze$+5Nq(2MqI6R2C_ki}MNOK%Ud8_CHe+GTvLsWrF8?4lc=ctf!peh9)s?5MRUW`>3 zFY-q`!@0+Ra&ZsFHPT-~AAv$13{byD8vbMSFR^u5>HmZ@{=4|8o1gH^U>yhvh~Q4BwTK zMtF$%qaE3P%9T=_#ruj)%EaoJzPGHHN|6Q2)pM2f^B9)OYPyo zL*^g;2!L)g20wI3asR?|>9~^i@gH0fe&oZDOE`3Gmt!2=nfURZ{Uko#uS4=xAc*th zN5}h~YsC@#=oa9{XoJuDfIR#$Kir~jJYdBUrkujVqrrvu67c3AjCj146yCq$T9=RC z{;oopatiNe1nBaO8Y!Pm2&Y^MZ!4~KypKSPLYQ)@p1+9z9d8Ekh(r1KtW$VD!nKaa zeeBr?Q%>Ri00BB)RKw#lMB%-GYaK5PfCvMmQ{{aPw2pTX@GeCda(QVz}ErHvAAZrnJ?vK+X64?5_l(GtAt0W!b7vW_+CIchHDup zKKs)y)HY61U%axsyy|52#jALOY5L-)8mAcL_}=is!e1?19@)RZtO%7QddhcGCwFY@ zj_qp;fBVj;`fG!~eJ5w`Yer4~Osg|Cd|;$85+`8Zov_b({`aHlC1=I_Sc|?pQ3zes zv5UDj`vO9e?9Rf1*+9d%ZKj>w> z-o3pb_S?i&9eEGdM4=lFZQwPrY@F)(N7{1Q|{i$b@>vU3qQP=k`)R4J_KdB zs3#MBBOF#}me5OwObDGEMt)CFE?Xw+!K-8WG5=$xID_`_fl$VGc77f!>8z(aL_J-! zIR|>q@$C;ME?w{c9?mhX`PDnVZ|BC+@V)DlSSB>r{b9=WTH?S3({~idCd8^@n`Vb# z`|Otp$sF*TMbSB;r-Y+95Ayp)H8hm*ts`!yv*VbKC`Qw&(;h1prK~ITJ?O=HtT$at!l6^7BM$ zfmZ&Xy+-(5-f1(xvVHhKUY7a2Q(^|rajh;q6#H}xi1XL=FEk#gUe|w)KPzDlOHY{d zj`rN07!}HVVx&A7yL8w5V@=RGx9e+aEG+jogmy)abWb_b8%pZ?XS3CA`)5CQ71MFe zIXdGUZ}7W~?kpqV(aFY3Q*)M)?uo}FU2_)RsP6nS#M(hel80|x$63ZO4?kYOnzIn= z#&c8D0e6Q$p+j?)(D-ly_?=}mNWQPH!oM7px6FwaV}hw3`XUc~1!$({_ktYMN3EpS z!OubYIfhq`V~l$g0iX0%5B(Tu;@yH@4(j7ap7@`7XpWi5UoG+szKwty7i&*Q|CFTJ zZ;11vsuhP0PPTi#Yx%@;12}Q2H``s@2~XYGhs1k&u`6EhvaSeMKmCW7 zXV6sQxxsY_I<}wg)N}?-DEKTH>E%PW5$;U<590Spd=tULG3Ew#=-+r1-U9IHc%e-D-X|Vzk0f5)gZCl; z)*(ze=1a%>M#pOdUOB>u$8aUzdR*)BU4)9{J3u)l-(3jM@gCFg__kDd+i|Vqy$C$M zBa~BkPa#0ZI{-Y^HRa>GRN?&`*E$~0Kjk|_Ifcjfla3dLP+^1-k8fjzr`Cj67j#_H zxX`{7|CtwmZ{r8i<026MegeLend5WKAP%9}x9~U;`G(+AHq}RQX*8g7j9^C6sY~x1 zKZ0^36cc>KclNY%rrC3L`~N5DhMqg6>ZEP0$4?a*CUrx{L7fnLk&8|0Oi4YX54uXF zop58IAk8oLfLcZAavmOlPF(JVCN#V5O*}KLCLR=fJ=frxV{ObHi|N<3n`L?3{(<~7 zd;jf{_B71Kv&DSOEHTz+Cr8Pav~NA>o#V4#+L;zBm2;Y!cI2O7mSO*AG4wuTb7Gdz zjk6vIVBfDj?~(duZBs6+=^tq+iOdR0bMIe2yuc{Sd)1aI-JYX~|7$Q0Wa#FBJnOtz ze!>bD&%sVz_``+lX313Se7CVfKMcxof3Vn|2i_n`78uCSu;+)LYfr~)PA}Pcvd+RW zKW6~5kyrOH&tC5N$G+KeZ80@#DT!T2f9ln`1Ll}VXa0I;0QF(VqBhd~QgXAT1N(Rl z854nw_G*Kw{hSNgHs*BJL$W30&iy4Rllr1naZz?u$o+*yb0{_|RIuz1eg-d^S~zGpH|2x$FQ z^+uul%hLkBQGLn*0~(aW2ZmwiK6{6WRe^`GbZ9*x`pPcr!E3P#y1*KRJIowsr>Qu2 zJbca}yVcTSuVNPJln3=ckZ=02Hple$C5p@IZc>~(d&w7)=NL>ttt-AT_MH0%MvFAP zy@lw%|GL8%H$L{ccI@H~6UkU#5)0ryw(lm|sb{DkmIMy>;8?v_cKI{3YpLsKH?gn@ATNan-CWfBJ7?dUp7zS_x2qzM`@J93BG>L& zg_y_tmCgA*M~8(1SRZ(_`n?`?mO;ELa^&<1e=P0dk>Svwzue#FA2l(W9V-<(-q$52 z)uDI61-q~oX4kv)eMQvK6k*+rXDNfl>vs*CYrdBrCzZkH=keeU{!hofH?fMg%GbaT z?)J|O%z-Yc=(ne9FAAQoZDMspJ$ny*aM~v|t%M7(Mo+ic$Np_4BnZ7j{phk{% z0Chjz`3H>~5he1+KkAAyy`KTX;f1d`?o)TC&lLQfNgfP{G)LV~H-DDkXIX6Ll$11e zMcw?_f}eF`yKHqKeCmq2`9p&Lg{1sWN+#eMhMPY}@N-;jyBu{PeCmq2`9}%re%;cDLil>Tbi2b^-nXUpdBqpa}S+L&>(WY41LL&RLZs z|7;J6YSBIL5E^@PE-mKj5LaOFZ^O>ZbnI6MtOBA3~h}XtjaOgP<@X9mmZ*Fc{aXt4&H$h*ob=8U$^~D#?0$pp_*3y=M>TtAV(LmGnETKmy6`f|N z(Sl@M)aJ3HtsC89>t@DS)5st13r`kSs3^{tpgpMHJvfMxaDd|_! zKUc21BK}`UW6-gj{(1Iz%?D<_*NMYt8F9+#PnWu@c%WWI8akhg>3>?THzS;DOSI?A zcX?(++6$No9Y@lTV;gIaUVVdeA;Bl<{5R!wZF@Q?{4FFD5@g75+7(p};2a zFO~MBQE!xw<=adj^gjBR8O9;{mjfI1!uTBeh!0Djx>5|MPA$XdNPmI!g*^t;M;mF@ z2Ys{ybyTVQ%5ki3GQLaDM|obNe}!S}mGpl4XpaN*D`1C_J{Asl!Y@QU&;}99JC1T* zX}1S)P6b^EdGZ;K#$i0e*`G5%BXy49GrkbMkKw2f)+5Wo^qE)7e*Rep7hO@{M5K=* z2zk*|BAoq2<-`07Bps%YauJu|f7ADf=KAH6#Wx8&LhMK1$-LuTUkmJHC;bBcGdBB&KMbL({%?I7Do5V9y~RBXPdqDme=6sf7Zc&*Rb@mZeHWO> zSA-vV_~Y~Ndi-=e-n(u1DW~x25TN5d1Tfy;#N+cr;cdmWj`tjBeeS35zKL)h?=9eM zM;P%am%{sZTt`dvlv8*|5uoF} z3%pAaMm#>x6kZ9ybi8+gHwy8}DZH^@((z{GIPH-QW`%c+2M?2V;}A2DPT_sVgLe_| z`oU9#AF48mx7LGq2mpLuE2r>o_2A9Owe?qt2k0c;W)B{11(zx?$w%@b58eXcQ7+=K zepGpX?7@oyuMqLdp*n@5{cFAcmTL0x{h{#Q^x!Q8-bE6Fo+|Gf9=uzCr}}fAhBxTJ z+YUUILpg=V^#EPI7qs&7eX8V}hysB%dH?PK-Z%v&`AC+6PsiJ@m6z{Nh4&eWr|Rh~ z;3=7i!@TGkBwx8r8q`0=5Gm=%#~;@r(BMq<1x78 zx5NxSiT=rL6eJr47u01loC>b{+XiHu&0;oeOrCl9#gl7W<+H6#EA7MGkIEY#VJ&Au6uU<4L{GoOeyZw!||NXm80Ve!hSlU#>p$Wq(Ow@vq*o zrfy7p_dMT*jfwA^XX5`;=NTI&#GXk!ao+6r&1USq#}8vY=CJPW_MG{fX`8RqQZhc`+x>xuV>3u*nk3lG+Ms7n!lF zV*6{dQSzt7C2JfzO55;YrOx&jw`a%3idr-`bikh@YO_3c53XmRCZn5C)BN7%s!i16 z`fZ8Kj*=GEy#Nt?Qj2Lp39b#HCKcT}e(@MY0h+WfIMcbRRzDfSmzoH8G;YpaQG z-BDOv*Xh6a538+vx2*QvyJWR_Z}Dp5-U%_*xc%KYjo-_Qe&4&Mps4N6>ObxCCCuq& z1ufc?cNG-fA;0Gr6q_+qNNU#|a)!MkmI&XR%WLpGKdXH0%H6Q>UeocwPG5<&G7vXP zYT^&$3;vi4tKV-uzmg}!Z>!i)?eDQuW^6Cty*n|y+$>9%A!!%pcA6Er9Rs}!v?X|7z-n>i72g%B-GI^NiyBj{oYl%KqF_AZ7BQ*6k7u zpEst{>L@Jshr7_@(ZhXbwfpWpj9TWo_eG+XnTM$3WI0%#c-Lg@e)d=CymBEm0^?xy9-N<@z^T>D@?vL|4H0eQ)24Aa%#`MuYRfBS5BOB<+R7& za$hBChQ~T$d@7B_$r2AI!s|ut!-iI#(5FF^oC(dVfoY}GrcTs5ln=KPysRpGX*;lHP- z-MZ(I)xLXbSDW_~tv2o{2-_MLqK!n~|E<>NT5z9P@-9oA8!SZ~7&dR1CpV*LYul1G z2c2h}Q$DlekGQjJ7w_ua4y~%kZF^vLk7AvevUlO$xDdH#qLq>67(es_?wMA>tYpdJ!UTX>6 zjkN82^Nhv*E)&mhvm`jz*sueZwC2D6-_5qvepu9_{!&Ohmz{eR&(WH*VM`F!_cjEu z(}v~B+hv4>g}}96PaL*}51eK)l$sz%dSF|y;@gRBYpr94T8!z?SSc~to6qsBw_@|( z|EPJU)GGtehN-b&(U)NVPNa@2jWerg&%mwzX9fq3y|vTd7d7p8TPMgU{qf%EZAJN3 z&Gfk0H&ez#BFY)yx5n$1hQZ4+Xa(9$T6!9t*N|K#IUj+-23+tlKG&34+v0s*OP zXkl6*))#Dku3R`Sm5nSnKUXFkN4*HQJhq<1;v@@K9vqj-W)|@|KC~TI795w#h8Fpq z`8HP$9GA+57Wp?PS=`d5vZ2MfG{=)m@bih8e=;%ZbEpk1EK>{q^@88lo9Ij?;Y{Cg zscdRdzCB46=I*#uHnqslH6`0QEl)a?O)YnQ*@IY_82kmE_OtaUqKZMRR3{1W7kc;$ zh2BL&l0{#+pgds@e^~G@Nb-l1SG?eP?d}%hY}#=aRtntlcFBEjx7=^_i#2XT8Roa8Sa~@Rh4L$5(c( z+-X)WYHhr+9=6d^>mi6OV#o-ez@a-JzIxR)ty;ma`#c}pIaDI0y)P!Do`@&O$Kfr4 zvI|R)BAqJ=N($ms4C)ey2z&;jwt`#JMN?FWw=A_!!Z->224E#sGLotiM0e?sKuYmV z?8e4cPYGL?hmcCD&Zq+EQnSMUX7veim_t&Bg6KC2D|YJR8_pqDDj)IMMp(Q;3#HPk zkhSGjz|ngd)Fbqh=2`d?tKBTBtA&*KY-7=6Wni-o$g) z+1c%8mU7wWXDq5+u>vwfmPN!$buKbY-8i%u>YOy;b#rx5K@j&a*e z({*Xk{c$ha@o2L8wp4ORbAoKdRQBqaRUAht*Ft6L1ky0+&|RQRs0;$S?{O-9@iEaX z-pSP4;Hb-2V~?YKG5b3}Ar>Tq49AOt&pOhj@M#l_&u-cTTMXZKk-cA(`W_sO(H7WJ z`g7&^*}&yH-Z$GmU!CW(e+xAEx6_B72J;~w{uK705laWl*P z0%+e%dmk%t!=MYt+V#r%Qt~gC>7FA$((R!iwe^Nr&))^ja0P zK#BT`FuhiP9Mw~9Q9k7J8Pbry0Y2rRT$Eqchrk7YCHcTl+|28w4LtCpssz7ipIUn@ zo%JWuEs^>ub#kBXQkgI6L9`$EE+ro1UO^x2qVhe9G~~*of4x11qkQF{eGqm$e3pyj zgv`%Ly{8-GK3?!6D+kyAf3-FoGi}d68_jjEe z?|JMd2Lq0_1RjDXe)*pqn|KqtS%o1v?<;&Li~FJC!LgsApZE$Mit2g`yQ1CIA;(i6 z!{HuTIgAud`>vwDOdTfHY>Ls5!|=%k)YM}Xn)71y0=Ww(MAy>WnWf<2%hrKHHri{~ z3AdA{d|i5(oEM?};`GL!@U1v`NlOdVaP;A)^Pc%<)6c;pCh7e0Y9f67`~EmQy!c$1 zgdchM<8uj*BQgI;gHLxUep%wm{-^Npm~`P)YIsbm@K)p6#82TZ#C0mXRS4JRi)wh3 zOW|$9wT_3!q<9X(6Hdvu8I+E<0C-`9vAmi1DZHQITE}|{G@p~oDZJ+qpyRayuL@zr zV|f(bySUczIzdcCm~sm5Z3O6ePigXHBTnI+j`TX-Gaw#QV3LpIXoTx{F9B~3!YLoy zS>aJfRL5KBv)A6hA{0Zf#S?|&uVQy#nmM7*HDBp=DgJb14IPqi=K&kFBX z9=t<{NY%bS_u!3!P+{OuK8}wR-iIE%tbkoFU=fadbnkocDm6Ub?+Wi!)IV60_uB&C z#R(vt!pi}lUVjUKR}LP^$MKcI`;-Uo1>o@>R!-sZj5{4~orV_%v%;(O;DzyEXjNeF z5iQ(x9=vCOr}|4VI20bwAJxmd5qMK220ewh%7gb2@OWRayyNgwc;E2gy$HNY#4ATW zI_{6s%bRtY)4t;ouke24!TSh!F9`(upThfr2X7+q7K4TImEx!H-UMF|G;RywUQBn& z$N)s!4h*apwkaL?Fa%6G#_^W{KKv!SNDjcyNpjgdB*~k^#`PTVg@HL4*E8{>e5_B_ ziINSMM#Bg^PgNm76Nk>LV{#YDJ6cPq_%Jw_TDb(vB-m!v040-8vgJ@wHMQzw^{-x{ zu$qoZkr6h69Y$7XJU%;n42&fAy6^ zWxp(P*or*c9qGR{!jrEv=7qYN`fsg%A#Y=~wa-Qi?G9YH{XJvEv)#F|VMu>x{Jq}e z$8SYlbR4e|d!dKN{PG)K+PrXdWXysU#apX40D<4}jBwR%GyIWAlY&40kWuCe8a&tB7JbVd&QAUnQ(#@2!w8DojIw3T$??4_Eu)&AG_)#PRCH8oV`#Wf!%bFgbz>^32n8M(i043JIm zZy!9`uk!RFj*M*_?3b}skZ4_-)!EsWA!M3)*qHhB;6T4Q7=rc$ThBo2r9?Pt4T^8I zqQ?Jk)5LS`9d=s3F>su|a#r%rvO_G_-O77XyScz(0fG0RAjd;Hdh zB^*JQ3p(Avl8Z(M#kv{s?D$M!w~urfKYnZbGJMi(=^V7*!;)qnV(a1cnlL!Z#Suml zGS$*XvES5|K@u|R#wM)@B;Yt!$i(1(6wWa$&%IFb>_Z>N&)%r>t9&r5 zOPNmabFlKataYjVUM#1p`I0-qWDT%Ql3{igB`aPJ*BjKecHuN_ieNU_P!v0BCqjzi zS=st2WEm1H+1Vpfu!~^58qww0LsGDc;D1=D`+r-fTfGH2 zXVBkR?ALTL{P@gJd^2!ejGuCf?-~T?eE$NP&rRhNUo!%9zE;qDo++o^>R&;C&bJM8 zDn33_^?A)LcujNu%V!|VLp=JA;-};72b~J<5rpe_8#O#Ww-ugxHmiE!p5QRzl~d*I zL4ckw^(%;@oZ?f@YK2F8AEk;3zT!KKYhAvlARo)e@@C_wSr!F~G)A>fBlm45EM4Y-eOh7L0v-wn%m4Nw2oA2KF9 z*WGm3oY{1E4!RKK;AbRk!q+ z=40K~ybT>sb(=*+v5||9_F@`+oVw4P9n#w3aB&sRn+0CtMGJu#0HXCM5nEevWxZ_A zCF5dFn<907{Yj_hdDNkuayFW%bm$rvHjn1l2G&%@pGwEr{n zaE?1{hXgpIwtt-c{MJD z<2&yyc}G5q-c;v6ss>lz$Gk+#csny>{-n(u3#4xqk?aXObn%Lwk5o@d^DPNkZ6 zS5~R1Ze^7=?*?H{n$8jPa!iTrB)G6shzoZDXAXS=cpZ^bBxK^G0in&iK{@koNi14a zTVK1RanY*fm_c!7qyiKz7ZAWM=i+uAl8`wvp}n?1STQl@xFZu4%dsteek;kuLd}W7 zIrir~+!ddK|5Fl2;7*geG2V2@Pt5ZX&#@Zw75tSRe2tHNl6-&nyxrA4u1PNH#5-?C zP_p5Yyr@~dLwKjI3dS?7MzD9@{;{Gs`RYJg*GZA@ka;^Y9Wp_;JI0V;i7Y1QdX7#% za%HIXC|9^d=al}RYVOWwt#TN;3&-afpF=8+eI8vk=@j2J2+{eLg66YQImPFlyWawa zh+=}zdyeia`004hf#$PYIfeIS1n6@eHOJzdgU@o}(f7{XKSWq6yhjkON7dFSpEkuRUS%=hEw?m+=Y zhd+VGuMn!9zv{tj0KjAg24CTEEkMV+MU#)CD}}d3;+0E`uL0mf4G+;m{wHyv&+!j| z?;H;wN%AWhNarEZX8gjqF2#@evfofPeeV7&9w28iv2^OvJI8+r<@lkB1h2ZpD;+N` zY}#nCjgoxQH}NTz=a!d?kK&(fljH^agIjWre;G8uc-mJ!EH7+cVosiTaQ{1x{`%aQ zQS!~|QxBYaVNSz_>T&zNQC)m+e_~VdD+>dCU-Sj~s;&Krjm5dq*E-i$pVBitZiab| z*MH|*eOCqw6M?X=Z%xqGH^;Xmy03Fhb!GPr1!u>8(`%IA7k;N#)k~tw7#F%YJvKh} zN@DZWKkUT!@Bbj@uG zoUl71w=FC>Y?%z3^iE>_X|c?zEA)b^37;C z=IoJH>3wtjSYAR2V7HxN=!3I;ZEI0`>pM_;qE2$5moY0hu=;e-hO#zKSj&mVdgP9q@J}a{*77=B+YDdPPe{&FLKB^iF?W&BU_uf9Vw%+P#>K|kD_fo#} zuHggeVx`86MRuh@de;8KiS&@YXWH6+UBW+Tmqo9ebXhmQlXc^tlUZU7`g}VRpPy3F z5!$WlLr*hIrg?WreWuC!WZv69?C6hVpw}kbg!ge;Y(#80EIo`8rCq;c*u|)UAX_rvI(HMp1fWQ+P2?@YvenqaA^6rjK{!UxFv2|2IhQ>x=px$_vC?2tI#bH4xH@ z-|QUL5srhu$G4;J?(pYberCTq=S*IKnXI{IZhfH~Xs1pXd3C z(?pArzrX9^3yr=GKc3^(zQo4rg6JLF>)Hb`=wkKX*kwo)N_Q!}%P29hT8oV+7Ho zH%`rqu5EuU-M>F_a*Z547(~KV|`t7z z*J`)=)*5&RTlvvT+s*PzMSO1bn)V!=9y(*?pB#tZ^hOn~xDo+JB-{fxcK;g)A9U+9mVRzR+#%lAW!kf46sG`|G#^$w3q% zEIn$VJT|pZ_=VA@5$ex<8q`Bm&FMeGe(=y?U8q5C^L%UA^)by$)t+%tmDhYTUxO zC&03mp+!}0713*v+fSrDm(Y&Lkt?S>)=RF_qsL3in!9?%Nmt@o$$rfDS<%H98y1^q zrD2S?$v5rbD~XMN*cda$ZJRarz?SOVgVuHEN9k7IYzr~X(=j5wv)Z@MtlUx^I9OL; zj?NjAC!Y97J+<&kjx)^)jxgEkPxblJ{e7QJf1VgYt8b3gBGPZ{zNO%~*sppsahlId zy`y4>WZ#24^E+c-+};I9mmmG zfc^5TtWBKYB=5NQwRU(H^|oy)dRvaQVSfLxVMYn);;+q`cks^Yk^6=X`u3Ppe}<4X zc-ERD`uDC+WUMzUcHzwH!##~h{W)uzx3+Ifq;=Hvhpes5b?vwtj&;=9JtwXBoTsNq zt2y|d*0O0<#$G%J(|xbl_kprU!@jRku3lk%=lWUe0#iT|<}HhC(Hvkv#n zi!H&OwYK?N$$Nu+gO1;-Mx!lGi4}`lSEG@>q`9|Wd&G>bU zh^bzRFSi-~*sBR6yy(L_j&7(nUpB&%51p}7-LD74o%m$?tLa&<;3+*~)ZQoCEj+Cw zW&WNiawONW3+WBB@|nSYe0R*ntRiE;%-G+n;*HX`kcz3To*DMM@b-!Ae@&L5rKQ4Esgz`Xg^p?gG=u+ zaE_X4y9S&LmR_#6G>>+VE$`GKb+ zM@r;-RhGy%GJ0Wq{;oVxBY)}LIBW4i;O;?+LqMCF)pu7gyYDMzHoh}w_07RkE|@V4 z&*b}ILoPphM^i%Twx%($DlPNRA$j()oL@(5N{qb4ZT*EMVXcZPX9oA)6t(n+Eu-kv0rOrANFs$P?s4s#&uSkc$94SSMoFD`rjJCq&1taUmV7_|-}dDmQ^KVCKcPR*HD<@z`t;1B4L_c-RtP_yWZ-I` zhe=H_yj^FX! z=`*!hu2&B8#1HetXL;hOf$KQx)4TD93whp7vUv6DM|k*02>z-hKQ%ku@_}Q0jH&$H;-$HM7;};2j_C4FN zH#^S4Ik|5B62b3$zbJ8-ab+22c=*o{{7(Ix;o(2i!+)mWU!LSTGkL`e%b4KdpCI_1 z@=oyZmwEWh1i#b1{7CIM3p@AR<(*_)jcDGV5&ZKZp7$remDvtT@|v??@7SIGY)^h? zYuqf)6c7It!T(s2YfAEp7nV`s;ja+u_|Fym zcO`kwOeO_?9u(!#~#(f1xM-LV@SJ zZ}cx~l=mV}`isSPZ50^8#Rf&dC;crC{aw(kPsZio{q=K6j}r7SaV8|=Z92;sl=1x{ z9{al(DIGELJoH%542s~FgOkyxdEzgS@pk?rjq5z|OJ)3Kkv`Y>f~5J3pk5Qts9+Md z5%&{4D{0ml^_pIhG@qf=Yx=XK`Oe9KURWC1is?H9J=UPkGwDkOU1U@y+tRM1IWj&h z;!BK1Nk;^IhH<;3TLpclalfS333`ITGar>>nV*yK<+#p)7V~~j{9zCMk%tc9BPivy z)1PgeA?fV`Z;J6LNxvoN3gaS4`;jQem}b;TdcBB0*WekE#Jft+(+!>xN%|o{pKm-a z>9C+LFrJt6QbE@kzmas6pl2EXCF!RicMk3s(~k)0Lh$oI6QAFLb8vsmkTiRC4!l%36BhG!akFZz5jg6uL|zrOZ#*-@Cp}d@7b!zJw(+Sbn>)=_X-E ztgfLRSkxA8Tp_%ha1LP;43EKx9ZZ&`jHp}QoH{~D$dvKg6^j~|8q&xdy|{hWqy5=h znA(#(tTRy5uzDHqo`J;bWZ3}oCa#Q_K7U)smi3izM*#70JfZ` ziYhJ~70Ck*he|v&Lb zf((azLXKN)oiXC)%kc5^fy;a;Up0N;te}s2XoFAwTcp1LzN!bN<8z<JAFBQfN+k(`k?J0-zLaHK7{M?G2c&1oNHwKWAK^oDf&nkVmSCjIUwKVl5U_6 zn&X&EEK_Wk;V;VY*WnZA5Pjf;;S;BlKGKPNA&+=g;W|84rH|BvV+9c?6$E~Jn4m`We=Uqc_6-b5em$T<}2X)}Guzl}cX>oNMM zl*yC_I8pd)N0y&_f0IsoQb*f<3CTg8ql-OcZ0SU4uUzeQCtivAC^M<>exhMvk|Fir zFd3bCh?r6yXPD>S60Y8bG_5PgRVmY_7$~OXb8y6OpY*9 zG9*V@Cxl2j5lV^Wj6G9EJEPE)(Q-VRGEN_vdKprTQ5_c1X84!7c9H{FCxLbgtGcs? zvME`#yPShshexCx^61dO)u7i&qD3Yfg)kbb#v%v8&ZFRy#=R*svPZ!G@P?8xc*NpS zp43O@dr^0IJPTKZ|K!8;UpOxxF-B$NXmFr{i%vbP;~aDZCm4=y=a*cxi}JcuR1t<0U}zour(?@FDaa}DH-w_XA8~FM)JXMarAWSdE{vvx! z!Ey}8PnCn`s^c%&U%1~O0$MqRmklNz51PtiOiH{F_$j=p9z2c*^mcKv%rfYUO9#Lq6cpy@Jhi% z`S=x0;T`qheFVHz{r6SWIVImC9=zoMQTN9gU{><|%7gb1@LCm^ z+vvf23wUoSFv&-f-vRXcdk%PW5KcUP z)l_)2$HMAT&%YOuh;wk|$Vc~-2hWdAw;18X<5y3G*WJLbV#h&d#`g(|1;`aO89z`F`el#gFY6<#_n^zy!&W%GIQEb!^|_Y&~JU?Sdh z{1o099=s@CrkwjLM?ShD58k`LyAl)w0g)W~TgNG`FE2r=t^x$m-p6V~Nz^w3o;=!8%JbuekPT~E?gSQQMd%?u^;8;`P zz3Rbx8-o$9;V7q|g8_Fr!dUQ0H9qx&Pp_9&JZ#l_@Irv9e8)<>a+%R`;4xk~)){}L z;6vAstMKoGPnVB8bo7<1q~8T!9QWpYTyq(Q`LaGK8}O2DAzscGGg3N*$1$1CcNfZ0 z1zD6+d}mLqsubHU<-bqdr&)3C)RWz(dDR&rx8y#}2IG2TZTlYV9NCkDohu{nHLDNL z%-Ofo>Nm|jW@e4i-(iGmor%SRm8d3z!_(>l1NC{OJDd!l_Ac1JwX46WsERbL_48w$oI>=-_8Ln3p^ zupP9|yJfXe=4n(#ysk*wEB*=E%Xo%IEu@w?;?LXt?{bJ4Zj#d4IU@MB<&8ME`miH5*bsB zq6ez)>Ndl6ILm4l3$63+V3%37N1*L~I~XzAnJyPOY!dPs{kP)Ldv_wuXowjbzmxEX zm@jvmd3Z|5V-`s+q03CJbGwYQAaijbwti=p&~9A}MDiNsy$^^HB3d}9`oz2f*ToC@ zs}fzd+}!PBjyM%%&A5!^MSm-5>d!Fmt1dj4b5UCRxQ3pDv?~5GyjO?c@Suyq+MUMPS(R;m!pAsE+OU;A%rLk$FJ3%qN zuW4|{4NV=D>{kWR%IJBrMK|y0Yci+zU4Mh@RX1F}Wi@*g`|}3uK8YNu8~MxL2lLs# zxX*<0nN>kqC&oaQZ%=0^8r&W1%Bo^MCUzf_Qqp&H28DGk#woku;VA81+wByNhBWT1 za&ixk6=C1h)v|U%C|CWIM6W{h#~KRl7Aa}>wL|kimesSZ_|f)jYV13FYkL3|)KJ&Z z@vYh&IkI}ntJq19s7VtwYFh+bk2Bt}JEJ2Y_jf*99qczzxBdf>Blk|RTg52KDz^8C zJlX!ej^B@I0OF62USdAkd_!Jtzh!+97{Q+M*gG98TRHXx+oxOKUtQY$^ZX;d3D^{K zWKM7YQoD_og}uT`(leXW`pq;vWgx46Aj?QN^^(tB-0?13YWr#7kA+bem(8^0vu&6? zCfewVna6q`>AZN%qaE>N8oPdR!a33`bEVlV(p--;Pj@z_xBAjEdQ*~Nw;y&p2i#>HEa<}58ySPIUXJ5~b z97(Hjo`2lcwn6H&$9HWi!718xzWcUznj1pk&%HE}f zP331*#>a%CJY5}kiFjZ9oX@*%_GfX0{-3wwteAa@c{oPfazk79aaSF)JZr0c2O~$G znt7!6&CVyQzqd1UpWX6i>`>>H&eHs#sMFq#t)0`OTRYzDd~M8|q9yJ9L1tAI?p0NL ztfR=`fcfPNv;P9C=I~E)x3v5EBfi|4t<7(?|2(4>J@HN4HA7Q{Pa;*e*aPp}`+U-~ z2AmM1AqeacB(i&_e=+RzizjTh+(m<3C44s=zj^et(B+RDx#%*xw|}eSj~#qM2Iu89 z1m{J9cnTN!s@C8+%IE1OymgGQ8II59kIyK&;M|OP!3J`YCld5kaeu)2>WL|M$6`P9 zn1-iiPguWe7$|GQF!5&d-OG2Iy=#>{;^r$~gO4InFO^-f(QnF*5fj=#KXO z-TVPzbBFvL`1ugexnCQ8w$lc@2%x=xclvbkU7hKp`1uge^b!1Qm#!{^Z(;Q9PM={c zLJZT3@5zW~`i+8{|2SHA9QP}@(_^x%IqpYr$8+V^aTZo?-SL<_X^#61-0>rYJeGdM1ByKSB_93~Py894czeR5m@Isaap!lYiV{Bc z``z&qJn?0oc&@BDj{5uV^js-(9QE_v@n<`cxS~G3JDw|9j-&p)JHEn+#Fd4WC3iem znjA;{dUrfmjvPmQdUrfmf*ePEd3QYTF2_+n-W`9w&|l&GxCcKU;+f(({A_o=x)8o) zT;NH6fhT^ZCw`_UzQz+@p@#Q^iMqWOCGw%L;uc0AM?<eK}|(5#tE%cUU25EH@&*(Z(H;o+#)s#^WyfbmK)yw~F|&#@mwKEa)QRub`D< z{v)+TInu?TnZGS>iBTzOEZZXgGmLpI`b^_m7yks~21#cL{<7qL13UdB<0~?Lfrvlb z_$FxOnE$tAyeCfSYpC^mj;C_)eCJt)EZ;go zPd6&r5u{`OYJUP&Y`}kkahc@L7xYZA?#=W|1zls@D&uW=W*Hk@^lak^N!xgHjh{*y z%c;PhXS^n9TmFlUBa)^pIaqDYz>tyo+3kIqSig1XD-3>5bm%LMOC&uY-;Odv1x} zxa6TGxC&~mZCt)6-YPa*C?Q&~`J(pvdi$hxWJ-Q-9N}Oq79KWOQ1iy#JfU`bh{C87 z>sz47w{+F=da9oHr7!!y^f6kh~j_a3hXL@kf<}E z0PigZ<7M$gl_>3gFCQeY6OGdtU*1^P*ebS>fJr23TGhHpODMu>SF9cq*3cMlZX6PN zV{O|a)|4J$SD$PKWW)USk~Nh<05Q2 zsV#Q}FRypA@r-Ic8B+`ia6{BJ#bpCJ+lJWQ>@bbB%k6u^#&EU-k-^ra)N>O`pRLV{ znwBkdWm<=(X>Po}!CkuyU0%P;9Vl*pof&zm-BYR;iaS})*G_bT;2~Lv=ggv}W|xR| zAQfqKU?;SGMO~^WmRL_f8b`3Vu4-`wQ|tBw!EC`=v>NJ+Tsj!^D4WpgOsJkri%=a+ zc;YQ@x>@xVvfyC#x+Du_XaFQ0LpmDKPY`@#ZQY{gHke4q);4rWRnIAc8)|Q=Co5Q5 z?0puQs|{geHxnQB8t|OY{8zcJ;}*HEEotBsfG-m-R}l}oP||$=alg&D6VM88G2>DGRM4X^|e~7x&j1yS-Vyh)fri>Ad+d9r2XUb|hUO)BR2RCB&g~?y;Ps zYkY!Hox|{ngFA;6Pbfa(_>@w^JXfS^B;<-w4>s{wOc|4Wg{O>74s}w-YJ;AX@$TVI zN)~-Ea$+I1A<2oEbg1OOC1s`>+=&@aIMx{g>5O`YL}|mCA#vUT&Jc#=P-jR?a?mp* z#u@&kjFJPPA#u)-Xh>9wQPB_{ZD2Gcjy)HX5NC)qgu^pfN*V8rX@*1(89=!>)Qyvz z47p;}{o#zHhD3XZS|?!m7y;eGuOaE3Ay?|Y?Zi7nvJ-%?u&F^9qmRdi0C)#%DH&1? z-G(r_2601Twc*^5IA>rtB#QFuW4R#=-oai<27P=tgn?OnEQ4z(_z!O#;i*DmErRbT zIU_&VcPJ+Ket8{% z&o5>4=_*mMQuy`w1@I#u7_Q{|4z6`P?hQ~Fh!SHb`j6wM<2?mDRlZ?}Q+PkawT`zJ1nWgP zRnN~OK*xIqcpR5dzTx;Oyx-$m$4h`v*&slS)3GZKC77rOC(jc!hVq2ajima9sZXaQ7zQQ5EUl zc%5F-oumz&kYHyKI%$@Wuw+5D;Lx3=$p%RvQ5Kb~(4C!4Gvmx90T)!RgNSokyz>EZ z90yb&!W~=GgvA*UXKosB459-rLrdBj(-^gfc;)|l&(b-4#BuI-pa1iG&#k9V*Qu(v ze)ZP=R-IZTCB=7^0`D^!e=#7I@G2E}v=?Hm1O{EgqrJOw{=Sjn(HBw)?_mYr-2fPW z6TA%yJOdJ0N(&T2{Jse8o-mz`jP7SOW%X%R^UyN z;oT;~`&Pl<`@mZ(F(=ZI@wx(U4)Dydr}8oej}+fz_y=hqzNKimcEclvwpMkGFO4O8F*6twaD<6EATW3h{iFJf-|p{De$(*@Wz2c;;&tS z7xg`OKULs8Bg3OMUc%d{z%#?)X7QyvXyoblEbyfAH&KRnSb;}#{RTdU!XKP@MQ1k2 z@ea%QO9h3*-+wCbtZ=wl`khhWy(Yt(EW^VkEJ5XE0r1KNmiT`-^U9;ZI|)29T&Vof z7j%ig5R?yj`P&Nzd3l!bRG^c`_Y>er<&VC&OL!>?yiwZVwc--qcm-ZGDw)*YXUg#G z3cOhWq1w+-csOAgS(_8{%RF?(`5Y73IHj-n-q9Y054YpgD&CG z9zA*b6$8%<_c}bZVnD+CwF2)f@E(M_q$Ipf1zscYW`cP-dSv%o8bJ>lJfN5b08gsFHV{kvO;F&?1YWHK23^9lDDVuJ#FEN$jtoz^SLPYu-BeCg;LQP^#9y8a zZ>562v)_YPqrfYc;mwobJ)*$VBav^G9~%{TcLPt#j{+Iq3ktjl5YfDpq@?tFUV&FD z;}276f&6$|foBHZ&Fb$d1>Ra2fAeK{e^ua30Uo8Zq$K{XD)4?P!=n`pxl@C-<#o8|8&1>PsXL(n`Pt#Fa> zUR2=40q(ej!OM7_S2+L1)ATG4(Kg+QZxBfXqoHzCF`wdlV z?qT55a$V&&VfPU8ag1|26aVUo0N0j&m3j@h{y?_>N==-lKbypcRB6)s@9oJQ-Qj7^ zS`H357*YN&Ums56(P1T=S5I|DP*M#SOmtp-Fuia- z{U(V#sCTEjq*u@j=g|-MVbsbFD>{!p7(a~ves_0(guX@%D>YinV0r^jKg_?pH6?x` z6!h}mfZRtY+-WvuSgC_rd!mmF%>7Y+OZT#qyeui=!zvk|lX&VRgm?ml#NC~ zY=a&Ko$7-MeaB|eo&TnsD9CO^pC-Cf=?^mt_w9zkoys}+t0WzCl)t3^x4wA>&WO87 zO7R(|oK_EtZXkR9AyrV`{6k7UZ~h@gP%Z_|j8f+1cb9wp}BY~<^gBu6Oe2!qrFJe2=GL`P*s87{Rol9F0zYEwzhv5F2SA>R-kjgN?i z9tv+E9ywky%vLAQFlZgvpkFwG#PziIm|BOtWhJY&Z z(7ZjhLlh4q9*V0}_VCKKz=6)Hl9cqSl!>PyU1-g@q@>rW(=*flJ2LUi+cU&-5q?-E z-YgXOfJ{7-_Pt<_yW`Mq->vGtE`9R&K7H!gzDu8~2X47_%*b2E#E(HUIx)IC&Ju1J z*~-lP{i+j9-6o43rx|?dVR+YB{Jb7*8RT`nWq{Y?EZ8FpU$j$kB;Dx7E-Cl=Zz~y0 zTazZ=>(9&Nw6mWbN_R0!%Rqr@c48VY_X@WFTO5{wwj2xgW$KTZT)CoK=%KvCzkAe< zq=B|ndJ7#b=V;ajW=R7g4QHb#sPiF3Uj~KtYlELjVO2g%_iK+{6W5X@4d2|TD zBJOcz$ya(Q?N51TT3m=dZY71%A2DO^{Tr)jY;B$IW&s%aBKH`MXDB`P!pJ?Fg}a;n7)qi1+87P|IHthw#=g#89XW z9|dw=Joy5*e||YKsN^8N58X3wz|r=ABg^BBmi} z6ar3zIcv7l?Th2Ct9=~Kn=#~anV)oB?DBcSgq`^~)q}Xjy~Cu7HzkC2#LS=)Dz?|ELs?>LT{5^(M87dM zx;3G-^3bg_Pj=}i-O;B{&f?3h!8j^*jAdNLOlEA|;|o`fNJ;98Z8cx!%*IyJM88J` zedeswUC|S-dDM7MxEw!AV?NzwY}HM?>e0f+GV60sh}q}S;eC%UUUjx>LpIkJ*J^zI zM-#ts>y!TO(VH!^jIF1;;wJWbLe1}ctk+&m7wY@}_IU`BPlna-KJ{&|qDo zs08z{+$u?N#}HGPa-u^MGXJCC-2W;TshG z4ZQ!90Eu8GSy@mdVGb*rrw9&TE;&;Cj0$&>=!TUVQfsh(l46II8WM1@do<7A*Z_%O z-Yhc*Uh$%a#2f5?6z_ld+nC@!j3>DNGyo!(mKZy^91q#$G-O;0heUi z-FQ^k7fm#>gVwIN2rgPlCxOFZ<`R2v^qnEzE_-UBn0xAAyr-tVZw{Y{1WZJ3Fk(uC##X&fpk z3U3e(xsy)wfTLj`^JU&_VELjMpL*aP!B&W7s-sb8Pw0LLqEFz>QH;i`WZuG?quEK( z+|HXvu}?%Zg&l?ZOZOxYJ+%R}uQw~m9M7snGquD~SY@;axUGuu8>bljmFI3@qc_Z!s;;+-f)=?~C z6+IBy|73rq6fW^61VO9B3H83Z)z|~b-@PSRe3z8?XsTM%K;*-hZw1jwhQ^kaPE5ej zbgURfW&9*c!I=m}KQ~VaVIi*&w&Zm<62uvqzTfW;yW-NXw(t0-VEJI^g!}Jt#{{U9 zJ!|;%p&PYs8Xlox!8UGSlcMlFi6g|e?T5$$WkiJg4*LNDDL?)p;de@!#3i2sJQgt~ z+ODCT{r(U$mQS0P|C2y@xjEE7MYO`X8dYJ1v#}A|rIqQ*b0z<}AS-9Q8(o(mv!e*C zZNqnj`>`uq*sVx)yctgzCOS8fzDQ`pROp=exxqUHIWi0j1*k0v!v}tnu1I%?{@O{0 zzvo1Ak7yo%PB+ z`$YGjD%?q$qP0m9y=0CidW4%odX0Fu5%}fP2jM&;;-G0|qo;`Jvs7415eBnlFX2+# z9(J$jUM=oD1FnYrqao$#!7Q2SP9Di0&qw31IfLB6M=|N(14+cEQxutzKhKj6zW?vO zdju6uDj_#(qk}$41o`008Q+fn08O9){eC(LSgNqY4d@U1`EFDC{eA+qnQzd4fG*Iy z{s0{%9bZBJNjkns{eD^rj@nadd;{Naq(tJ|C8GNNCiowt-?TCQ$6jdvn-sp-dVjwM zK9wo;f}7TV!h;w@@O3FtxWnx+VM|5jpY-zIVucb{#1-26e}Z*+qy7Wr1pnV8|88$^ z(=hmy|L(_2DFu1w@7$y#xe{B-PU3(5MKB)ClO%uQHE5kKnW-%#m57JvAYSrnny5<} zxsjTHhx(%*q9b`(8SXaNNs8KDQj_q=zh{-AaivkTwBDHLD7@u(4yFw-N7hyuZPmghx^m-g;Qb@!Eh#{16`L65f8i%khjb48l%QQha|6 z3prjp@F=YakNRB+?-JhScp5Nt8FrGA@Ginaj(1RoNBx?FHxgiSyib5fV=PHY@f`so zIo@Sid?P?C;bkfCXl?sg2@JY~H$#E;% zl!T|ex1|;i!}C|e>8!lBWhTNUJc>sw9x2>>WDJ7l>jE_X{QsNb<$_LL4)SGq)TT&y zKUUyvhr@0H78TKvTBpEU47_C66Mr;oCE@K;;L%z2RBt5(XI?$0z-tGdR4>PXLc)7T zf%hZerHL4%NqBAr-X>Xm6J>aMWMK?N&KZN z@OA^w3>r$mad@Qo)+zA*3_MB~NlAEB3cMZ}f7HfHc*=WBu6$2?wD@z<@u>y_c9%JBS(_CyN|{L!qQgtt`0lgjW| z-Oblw(B20`xm60M8FbSn19XZbDbgh#$owqm2EZfHF2qCO5+4*-;04q+bOtV&g@mVE zhhaiI))0uOBsz?aYwN1lt(?*_m0ynWLu-@MXJuvx>o$IP9mXd@c!6~ok%+;_BlO+P zU~dq=e&@UR+Yq*;TS^8)s-^RsRXDxd$e&qF>(_IZ~L|=hZ#Pf=S{Asajw{Oiniq3B)S%k{^G(5E4 zmikOdQGJrn)RQ?!a)eIiGKIMXX2Q$GL-X);3U}%=hQrhI>vPFWb(`kdH;V3p8TabN)CDmZcJ9$6Z zhd#p$J83LIbW|Iu{8M?AYO(|GRMsUW;mw7G9FO{c%4fnOzY-p%O@r`Wfca+pErPuq z&kO(*B_5CXlJFYwF6Zwu%<_IydjF|{?xXLa+al6Y*(CJ|o)6;|nl|S5%KikF!80g3EW9wMjk(|;0YI@Mb&0^k#EXL1GR{OcB zk$5zC-3ewEGoT3;{qTdZY%OXXT?Hr}|*YvNiy(9mvu4k z2F7`Dwn8fR9^K|t>etLK^J^w=!=4~*AD6WZYlBEW@Oe1%=blUc{GNd$Y#cZCZ9lV4 zvA<;hyzA9$eP6^OGQaP~%Gm4e1J=-i*US9lDog$2TEEJf8@s?8q4_E{2R6ArT-$d$ zH~wRh2dv#Hd8zoo`~wRfIhdTJeNu;2NE%-oBN-wYYm79$-GTSrreWJs-j=g;Rx^vG zF0~DQ^enZ`ozXVSzLg1gs+_i*^zTm7G`3)_8cxt>)ojO zm9JE%-m1f!W~-hzx9Op)Lwz@9b6ZtU{mPddzPBZ6fK#!7E$y~zd${w!#7#(QHqhHX z(Y`UikY9VnC2uIey)6(PKWjhHwIk1Z&D;KXOIXup`y%V(E8q7gry*_3n)F51qG~Sf zub%T)$7GDmIq!eaO#hqs|IPS+(Vg1HQmq5aI>vm+rD}Vv*X-%muQXU8gGaCod2gi%lwIH%k(+@Z?7rB+p(_4@@S9N z=Y8BRZb!UhnLfO-v;Klk_s%a}8wXCSJF7o#*f^k9e_Z1RCGAoh)u-B}+DVinE9*T* z`v)FwiV9rUq<4BY4nDMKBT}lfy0dX3`0T9xm=CwFez6#8&zgL^^})7Xb=Lpv?YU<_r*)VWgl~h;VykS7Es$S98 zwIL5H+SDWaG`ln+KNCIA*xwiV*_gh}Q)o@9OKRCLz^ap0UJ=7A@3~71^X=91@b;c3 zyy>x)Mb^#s@H)z|$LkkaHR)WM&99krqN^zH^K(xe;-=i$TQXR`Dnl&8QnRodFH~iz zJ*M)O%I632*f=sLoO0Pn|C{kY`g?QA(9Kzx#a3u+!wS397PofC+#>97i+U`(rFW5E z6AnJY{T?cVT`TPMTfNNku7}=Y0^G#qgz?;* z_isz1x6MZS--7=*=-bmq=8W!@Lg)yDAox0HJnw&v_jQ=}^@`}L2fo%1*7IS$`Mt4I zmcxfV+8ug6eotnr+&a2D=;u-_vHBaTR7}swSHCWKqquv4*8ZsdjeM54#a^03b)sZ& z)M}O}tnAEan~1tEyiadiGx}ne1~vJa?3r$hV=3F%uj2O9?tsp*lm0Di1Fs)ui>)X9 zeXI}mO#9&qo3*<7q~Bb&0j5H@d;{9tGV*hebrH<|^xZ`#{f@HuHtwls@U}Vfr2imy z(tjR%EE6Jh<1YE{KF-Xx%W)3G8c zNva`T(MNVR;qP$2df`2k@@0Nae3`Wn|J;l(Jltee_mcY15j(0^6pV17FSvz)Z=Lb+ z?EK2F+_4Vsj!-UU;D$D~@+F@p;vx4Ktcx9Mh`hY)Ce$8qHqID1FoG*{bGK_|Tt%2) zf+v=8k9$XboO46JZFOALQfDDzeN2TsiQ3TbRxPb6C@ghyNT1TRWsWLqS!JZdX6@+j z;gDjH9sRvrWaUD?CZVI>x+>eRx$UWJk9&zT!I6l)rsV&Wz8ZM#!0L&Lt6c0T9I>H4 za&@+KX=RA7J)4`&4d}Rhf0A+a=+px0E%>ydeXZTxEW;3IdlfNa5zDVXG4OD9C!az{ zh44~Jq3{SF7lFQTCznF4b5WwyI>+a0>d|*j+N0{|&y6etx0-ak+4kOI1*e>2L;v~e zLaS!xhW_Y# z#^NOx56LvN{`rzWx??-;^3q^+K11u)XtY(InGYk#`*_b zC+Ztq>V{>moQ5LT#)d4{v4)8*Qxe^NHejPPNH1bZ;9%U;60?04-@DC*uJI-FeeOP% zXctx&Q+O*|p?YpQ5hFqb+6ZnBQ%I8u*pbi^M$ z;Rrvfb`F6XuWO_8qU(h7j7wdA6r4Q;&NhOxHQ=lUoGo&lXvlG?8#7%wjTYC&#*r?P z2=;kGdH%x2z2p&k$Yo_x9%MOiho)MUxu*JpjP6SDZ5}C)~ZWzR>kv{cKlULyBu@L!4`8LzwHmhMkA1osq3- zUo?l3aL?q3iq`p?o^HLxF*)oV{Hy$$<&S6k+{}_$$t9P#6Cc>^knWNr9&Oh)+aw+- zP&-EU-hyoYjsUAEvRD+9!;36AbWVqrQlUz$1 zqg*>1S<30&YG-IfWb2a6Wv#LGp6S3OvTFn!l-H74i5q{@+=(1N+J~ zssZmG}5HMZ!9JiT-9fhkMER zHT-bolJ!S47cK^BMp#kY-FUD!LDItu#VMOOYFxokK#0=!X)C~hT zx6RL`#XBF zkZ$6i+BE->pUzh!4f*yg<;QLgGVv4bIk;2SI`CNg21g-UHF|%rUFD2JTk`VtjbAJa zZ7nG}G#ly7S-9C~b+fkO!!Gezj9jVbIiB6-C~_2Vv(dgAc=Yky!KerW<+AWWxUs~+E&2dt1Mvqfvb)r{z5dGK5$Y-izEAMvL(8C#5RatRH0$Wnq zT9szE7T^X*>sD%MySdaTcQ)FljgF13;|`YcbGO>L%$4nADUZ1~Ix}6z@%E5gUEhwK zKOLTt_Vu1}NCCh9LO10`SGs@n<#hk8t@HXL=H>X)T1A%yb0Z`dwYP^Y=-17gSNRi< zxxVKMRb9^)I%~Q=rj*hEw#T^=Na=6 ze{CAxtiQP>7jZW`I{M$KvRO5AI{IVE@Sfh8U4@=5p+44eIfByDiWKOrrRFD zwR=QTh&<}px5ErIO3F%d*sC#LAOgDFO<1co7TvIX-qMy}vfqKV@ z*>0A)+hgr!40Hfa)RIQtUZ8lpR-~^(CuJ z-9$rJrfv)0Dw~p`3xv2oj=r77k$))L>`AJ(I5zg5&AbSl!XO;|_uwQay(cSAG#;CI zB&$&Eh-x#~SxPeUqyjbTENT`@Ep;Dv?1Oy7Qj6T#PSmz~mTGq&uU`sDgr&}P=iq;i zdjlka6AeN>O`M+s8DhFyGgIT;pxTx_*FE!fmYM=YmNMWb%<;fvDgCIg;YX>y{sr~* zW4^v#Mt$9nFm}0)*RzxhZgs;(S9SwSIq%*GiR?Ju{?knoPd57Zx7-^W-$eTV4t4va zhuSh>Y=c%2X||QU{^?Asuv-gq=iH9^B5P;0+JQQlbvPg|wjN0>R5wMT9lgaKc9gib zH7#*%XksZ--6xt@>J+!C8SQ7Y5HsXTNY=|^ij&${;#MZ)L=xIl3aeENYnLkyGg_r)mU79xu^Fur-rjSoTiyZZe*)*{JsQ->@B+&J6nq~F<==E-$;sgB zlLoa{xOtcAo}{S%$z7ms%HX+Q4eoOS+|S{;&r)z-szVI)EH%A%2I7$Xoqj-wmoPh& zgub5QHDD9cP>9$2fq1?>`#g6z>V2`3P0DsZj(UFvZA+Fr9PP?X_vU&wX@>hu z{o^h}1DllLF2YD>Gu|e<&wximWAV|V#(3A}Mkz%ZW_hX(Jb;?Ie(;_HM|pk8fgxV6 zIFN0-HpOlwBkqI~4@C6CNh zK2qzpVq~X989_;-Z@7>@s0H3p^@t}GC7{9a0MfVtX}k<+T;ytSX1Vq|Q(a!9_oR9$ zy@`*72fT>u`oRSUQjyl{2MZ50@VfoLeqPT$KzXo!@J9zy8%dvipn=z?AK2fR=9wjq zF6mxri4&pBQ#(%mazIV`)Qx=6%*jvWW0F;9v+osaB$ba;*Yra4N}N!ylI_#@(w2_W zCiP!d`&8a;N}zTo^S8zCLGP4i7f>e@P84eP+NDymTv@AbkbNi#9ryh;(JxIgF@WnRSs@D>00}CSCX^J zA*4=~!|WtmX`Dblq>;iMmE4pNevClt1B6zHe-rQd7C4|jcB0tVq@b;y9cZgF`L;SE zsI5lZq+Ry1*?t@1u9ViP<(BtuLd%RkRP1rkhl)MU#X!saC$!9Nw9IGGGWU8C(a%t9 zCI;HvQcjQ3G}8)OevCmp&pcwCpSlTWL8P|y{z#B)Hr-J)GI!+Pxj7>;N2j)6Ke2jX zdGlS(CC&4i=Qhu1p4yx=%GjLRoY|b!oYP#?yr_8@%P5*!7%Qe?>LzZI+IJ%}wY|(e z8KqJRabi(QfyqG}jV;{kYvVkgB$UiH?qknb$WjB$=NS$2Dej`jT)=&~yY;Fku2A*m z=2hoB2{4~({m?TC=EJMbcuX)4v|jK;!TkQJ6P{?84XtiZ1k9>cM?FTE&8??BVK9$c z^|HqR^R(7up75fO{8*j?aOe&#O0=6C2Rx8lpoGs%^!8na{-NYV(aHGLL z&-1)1%p%5fh>u~Fgz_Bh4LnMx*uU-#P(A}nbAa+0*qeFEog(E{9(gOMP6ep8fog!K zdQzm?B*y7sp8AoX&>sc$G@kkqk$OtoLq!i4vnkerFCVz>{4%W*^|3V22>Fk5is>H7w4ocUW_k#yN5y!#(PyN`to7(G4A)VeO(1U7W!~r z|5?mcrqbB!8Pd%-QM0&c&ye~@ zH%z+PJ4-M+4uS2hc5jGbw3k!gXB+7?sONb@LUL*!uD#q)<7DHx%$9z}?7;3ZA#9e| z*y%i-bJ_$y>QGaTkLmVQ)ii$SyqFXDB{~*REHmwCv_iiaJE8vLD!ds^<@CgYo-=w4 z3>dnqdUG{53$%vQv5hd#&MoQRYS5|oR&Ukm2Ca8x_dltss(w^AuYcrHTmKgIE1Hx3 z2YXKX+sz-ZjCf~Bf^}e5$D)KQE3E@NI>r~mzOu&7Wsa=e_hozGC4bwNOa9H5F)lOz z8M&b0^WZc_U)(P3Q|JRHEWiH9H#LFu5A|Yg?D*IC^w&LkP)L8n_{+ia*ML}MtQ^+Y z;-PbV+VNb*d#~(+^an-0%=qoc@*-6lejk!l(~zH>?wKVyRg3TSTdaGAG>4@8q?CFh z_Ci;_kLfofKefBK89B()4Y9Cc+Ns*7o^$^h`MJG7`;>P38RRERdRITH_vxZv52>f0 zso6$)+83tq+O0*%PYp~na=n_69#gHYJ$9Z~qsy=TdF`fxGYx$?MNT%B%fz?YkQ1h& zs_@25&X#_)8u<`nGQp3!J(lvbsBu$OU(Oll$S;{ipe2e;jTd7n$0F*_RQ2RM9GhPc zAG%RqL&!Y%;bwx;&_lUtsOEF?vFaK4;40+i7FB+AJLTpgYyU4;w!$kYF5FHL~iY8^P-4mWEh`tR*3F3nhZ;>-3NwYN}n_{;W^Fnql|;XR@5 zx%OuJxww(AId-jcW7LJwYrEN=!%GcwgW9gSpc7iQIU?P39*bm<;Z|{4poN>tyG{vmoeB)0T}wub zvpdi}rNCZj#S(d6i9xNG1+GHtl_-X65@R!pr%pha!dLW>@HZ`hItu=TcI=mb2`j9> zGSWV>aOD-ww?$QoFS(p=o2uBeEPDYzmXw!YTH_)08C3464&1Elx5K^*>3y|W@Na1H!aT72LVZPpV$^Xn&-PQ=-PxT@82ki(qb+IgLYR|c}Um)zBu42@lEeLx7 z!hSp!CQdcgIn%0y9JXHj0geq-S=|K05rd!V<6HLG$* z=7z7(B$cNNGAft+K#_GIvm?dP(jOXHmOyzI=?&##E1iyPye~Ah^oNAh+P20nt=#8O z`EF$F1!}%mqd9R^Wpxy&b|M$kq}<@fIZIe#m~W23fDz~$_T|?f^52EjxZAJUv3DqR zYbG3)E)b}CON3J9P<0%jJ42ARUFs+3^%ct(?dV*5j zP>N8w9hlio-AQJ(YAW}nb>Mva^a9MTv17=IcTf&87wjJ5jE_+tsQ%qmoTBA#H=^|( zQYWPqq*QZ0D-+Hd167-CAtQ7o_W> zD{1zKXp-8Z^M~J~0`DQaxK!J~qz<#Je?#^Cj-s_xaz$;yZak;(EXG4BWXGKRP#P)l zUsU<}owPjRt(AH=)oIji^SucnZq#XW^p%W4>Yt5Q(hIM9()srZSJLpFR)~{&#!tGU zn&7;`rD=LkTxE!{D);i0iH=ww7uwR#aZ;(H68DSPdPi&}rCP1+KTP`^_ww&sa>X(? z@8lKLxHCXgc?7gDO26EDJ@)8e37QC;=BLe*9_{z+ag%s|=P{Ou~cX5#VuncbR14c2}MvY}?g z=`OAP6<#*cM4ak+IIn%+^Ns@43zGc4AW0$QHDBn6Kf7OEaJZngf$PtSEbH&B%IG~r zQs2LPU2~B1-;eeh48QYRdoKA;9p5u#*qrTEMcnGu>!9mz^+xFKul+SoPpw3PS7(5| zF2SpZpZuP@ujVDdPXd)z$co%T+v(V1$fUm73|vKg-an^jk8^yZ4sFg8vDHdZEKlX** zW^v$KMhlm*EaGfePXF&lYEx?J2Hn5YT78ur%+ioQ+ODxmZ8p8@ z5$lKqm?q*`|Sc{x9!UspWN(c*WMz5aPkm3Wi>2(td?{uC; z?!`2Qcnw@x)ss$UE{L^ynI8FJfFAN_?2}b@HoBcp*Av2{)pNgSbXP^zFYvL5 zC&Uq9k`#QTyZ<&9kWRz&R)DNeO%1?k8A$(Id=Vhy+T223V?O<-gYG?FvQ@{t zh3c2TWb5~NJJ>PrF|Ph1my2?^zUSKJhtIdvj6S#WEc$%om+dXj;}kWNboNR&m&i*d zA>16aD4O`#ONLKCo&5-PtU*B*Y(p5OZSh9OaTk19Ge4LJQ;6|6tL}l`>yub0X6_>Gw z%puy858O`_q0dQptl){J$DR32CC;y~=0F!l@>5SN{?)wnwEHX589{n7#FO--!#G(_ z{Dn7NKg%v2r=_gQtL z?9oWUhrWe0mW7)0Xy=fAqY3T&a1QM>QChA=4i(V~vfDez%(Ro=cV`u9cJ;Qf#7>;i zzo^Q9oKfvUd1zPr91+a&jC~B{4ds0U@_xy4L)yADK5vNM8(m&LZ%U9is(W@)0+b-gT1cz=Oh_xn?YtLd z>}-xu-p=x+?Q9P9Ead0iSZ?QblrTXOdop*uiOQHN=~87v)zYfBt}xtw!DXE73Q56S zM*QF1$9N9vn;M++hVu&JxcyDYD}EM&;v?i$JRg346Y|O_d^58CH;?v zEyT!ISbuIQ7;*j4!C~`V{;_GQ)Z2O&kM2c#nU9`O=M7W;vR*ZX4K!?AHF`nz0^6;{ z`+OSpM<(@Fd>d4qGijcRF5;eQo8$kmWI!AG2UAwDelP%Cvp^b$54cFPp-? z*wcQS3u|u8A&LLzGB=qG>}v|9IsaU zdw+YW?L$hb$`0#S^+>6>?g~By18Kn-C+hnOv)ho`bMcML`qe|A(sdv6nN=;G*!NgU z><4ismKbkp&ELBcu~gfS7npolg17#k`|f zWgk`TTH@N6t;Q;g&XwEk%^uC!6LFm@PoZ2mkjE@Sm>q>=6CQ6W!ap}lkaog(X@{E~ z<&98vuKaK%&0Us&Lp937Rq*%QH)uCNw(I;=b5vN)hb>__D)+|hGrj+LZfOF|w-Ppx z)a|C-E3@-SD&i8sYZi@ zIK)?tzA|<0;J5=%=FJ^UI-quN8JJ5paGAh3gIKH2cKyvm{x4muL%b)_?gw*~Yq9Go z#2rYbQ|uug&4rzDcsJjd%_!~$E`!=wwA2yjOcZNwCiSr-i;~XGBAJg$%t`;VSY7?R z@h?||_%A5?_Ujpl|3NcCVQ(P~QjiAc(Pq(#NJ?!AWt9C7SHdsEQ;2C;9U&^JBhTXD z(kN`=0%55x`FDTZL#+nwm0(;F=6#KeN7KFqxFT*gevJNP9_Cfz2i$wEaJ%AKe|ZI^ ze)_H}w08X5)zOKxAK@5QT%R&-y8^z_I#+_Dw2$%sJYvwEcBWvV9p4N2uNK@+lmIoC zanR0f9c^FSAEKT+IOq8jg`F)iZP+uS`eQGZ{q5Ln}qcm z`#tv*Xk}@N(8K3SX<@#I`2f@(Zr5?^=UA93;>E=GIe@)z2d@Lx~wwQu3;!nRL1GtHyF@zotK(!AZ>3I8%U@c=J# zCoQI#dGo)Z1(9Z6m&4V30Q0WqZ@QSvSoSk=l)i`ZB7s#v_Iz zLvdWCp@`NVTiV01>Nvc}RLRUF&6ziuT!CHbyv>)gwO#NYP_&k1R`KiwvrCebZqO=K z2l<~_l+hO7wx@nZK1;QIbz@CTH})$Gwok-5^(FYCrZ=IN)98tEYSDQ=yF9tzDXbM_ zN%)T3Rhbuij@Fzf^YiE#KpDrsRXHrYo}CcqwiI!bO_kHcHMGK4ersN6U#L6Wk!8*4 z4^=PlC#7KzQO2L}ecGBgvpd}Jr67Xz(+N$b}B4z}y=Onz-i?8tNIQuxndthEH zbE}%)1F@5p`z>ketu!{lz7Y$?N+Y@L z3z=rC%C5;^kTnwQAzLv+_Kjxe7U2A`y(8anh^Q|4jUREldap7oo1pfo!(Z~v)N_zU zvU1tDi(N0+RbE}_GVIhFYDfED#LdX1IbEii`k7n3YgIvW;i~zuxgonk8x|sb3Oym# z1}S%c{gVy7wKSUDR$I1$nH?FEZYLQDG5MO}q@8-nzkSbd?6vkQn3vN|Sc<-dz9|TE z%4#*u?@&!O#DZrZ^^ZT#{_HFy(JVbuMI8$p_KGiTgx06go_CiOE~FX$1;vHJ`sQIlJ<{E<)6yFvJS}WgXBIFFSVk>D}}%DsyUUngTuFU^Xd9ML#jP-7_Ct5 zaGCS@8UKr2f4#DgrSa)VCH;l`7Zd?f>XNyuCXj69Md(Q?grNYhz7IuVr9}CrcPlwL77l`WwxHL9U(qXX= z+YEUAtsu*ugz<>5@;AnFw4U2Wvm8m4EK%p16v2(d%ueXOF=vs&m~%DYmWIju?Crw0 z>afru!?ip8ldSjpRpz}z8vctG^n~d_IOYYW<`^fIXOtn_eJ-yJM z%uwQ&{A!5tWrN#JqcJMkpVK;o(00rcd>Bi6s9@5(;WLb&ooapVijt?D@A^%b*E?St z(k|{C(*0YEH#8LZ4D*26Smb}MSF3qxNWJK1u~u7*SFc4|(Ggiqc{MqP;ZnHmQZ;Mw=)qC5+fTo#=v{9L#v#Yk;dRdjcu=i)9b@sn` zz;P(IWllcxJ`~PvzvwrMvuZ-A)9_`EyIr;YA?%mK?0S4G*{C&BF^|M9x~Jx&wOP=I zHS$K3R;IP`QsuH(V_iyqF=So1rkBw9@5bAA+JE6do)P04G+wU;aftg_9<@H zE)(`yL+*q0$I%#oOM2~!RPMzhAEZ%TP%1Ml=HRj7K^f(!JnAvmDSW?p6_Q+%TjPsX zn`nRIWHSd*9T~#wt$ni$|K-t=qZAk#sZ;?G#r32EGfu z>f=Vx&Zsh*^bKC)GmE%S0=Hen-OA2-hzkj^*Q3sl!`i%IB(RD-0?j2^SSL(-W>tef0ILK1$&x(e>LS-3D$N=s|~{t zS7DWFVWBaAG84N@irw#A4a45=l!lQx^?3H->Bn;vyHr`~I_ykisjJWr z1?xwh?n)<{Y3k<8&tql$uMkIdebUivN7T^`4%N})j%$eHN7x&3*0sTT94pP^a$*qQ zjfn3W#J2|VU4;1NAikN{QD?!9x{=sX$5PvSI~y-XZ1h}=xZe8{50|`tut_Z}dQ*AFf|Ks>J>yz>BYO>051RtWln1D(8Hc;I7R zw;wRq|H8wWZ8BMo+V3?-<`!$Q)4=QyzE{rSziG~Pf8;bfMsDKl%U<2pW%EbRJ=gY& zws=iWe@M-pKhDgF!i+xNE%6i#P54&7;{;HA?bVd4tI3UzGRM@w`c~wz~fnAEq zFpY-|#ffVS1-l`I>np$Eckw%%v8H7E8Ef&t7@vW`QN`k&`*2M=HIel zTqT=;x?=zW*LM3%`;5wyeofD~s-)_gD&i~6q38Fzr8)dT@i!ih01px1fx^bD^e%m+ zr8>MowX3FDy(_Vjb^>))?@rf%n;+)ISZtgh30_WK#jQRQLUwglV@)m3lWy0H%9-}v zw+mcJJSB@f-JCZ{uTTHB?e2S<7X10CcXj(-hs;0WELH=~=LT(EfT3&#(RbUrfbCwCsREFb@eMSt1ktM15(o4YCZt+u&| zYAt~-N&4Xas>o>zrdKcdWV_w;X;0q2eA<%z7u`L7-}0~Nzf2f0^S!sRDhD#mf8C%T zcmM7eGE<%(+GoWfACh`>_Vw)<-v65R+=fS{>pJaMuVR9_?9A(H#*cl`JuPXNyV&qw zz8a?2zWB>GBP!ZAxX1oV$Jl!*k=Ab>I5d9n|43*kZ&UC7^MsH6kLX@+`|x4&x|6xL zFm|{isono|_54rg4u^aB-dA2L`JHdXh@be5-(u_E^eE0N`utb^9k;xFd9NPRZ<5kT zFEYJq&ZyBLqw}_{zj4p_``7hOdFkp6rQ!pca_zPSYo9Qh_pGZNKlcmwy3a2K$mYu6 z_}9E|J*_`!`f9 zj262VBQeV#!>r7Po!NOwB=gd z?QZ0Z8l%=|G)5YujWI^6(Pqpw<{3+kWyW%21=!*uHIdp#V`OAxbYx7VHPRND8<`hb z8d(-u9$5jVxoAzaHrf~+866!R6K##QMdwE6MVCgGMVCicAWB?}CPo`$jERhij){q} z#@J$VWAb83W6EO6V=53~&Z@C$tww94HQE|uwOVb~Tx*`S)LLdOw^krIIGe_%wHa-Z zwrE?7&1$pRa&39GQd^m=+*X0a;&L^)+FWC9WNvhBOs+N8mYbWKms^@!mRp`%fu!W} zGzf{=1MiC+EQa_WNCD1OsTchR+?LyS6W(H zR$5+Kfo$N)G-cW{V_9TbbXiQ9waiwQTb5T=T2@w8URHrj;>tDU+HzxgWO;OXOu4n( zR-Rj)S6*6PR$g9Sfh^=IG!@zkV?|^|bVW>swZc}BTai~$T2WR}UQtmIZHXB>YFtR@ z|7$ltQMnve8Vr<&O?0M`+?CA3b&u$<%2-YglZMgxWW!3sP{nzavC!%6C%MA+W(B>L zKW~>prG8!o_es#nub_gfoto(s{&oDhlH`9H9u?f>iq5yk;(hIMv`BU@c zR#EI@brTeAg{(qFTAd1i3<8eMirjO zX`WRDcjC{1M^K5<3$Lr0Md9DV)At0zvnc4tDd@-X^uy^lPC-9GK|g_~KNz5z5O|{( zHJhlQpUBe>m+y%R`cwsdDo;OLUQ!kGlNI!ndHUxA^;vL#O=hO_dnM2;PFCPeRp3qK z@hI&DMW^BpE4phdxICo`;Ri_418?*~cUc9~XY%yp15|=p6UeX3fQ#V&c7^}jdH>OY z_z3QmGBd?j6C%L~?pB$Z+y_I0-KPbZ6!4S7gWat%Gx?`;bOj~g_sGoTZVWU_g1bp( zCik&8cUVw@d%4U^?hnQUyKk47$$fXAnGpORl$puB6m6NHl`huec00*v^tX0sIjXYur(1*m2P-snY*o7VzK%e!Rp^mLBBpal1^f&3HP^@02n z+;e4S;_ow=SwbRR&F)ZycLyKdYk~50hnyVra~1S+*=#XAsE<*>oxDMEP({)UudCU7-hJ3|KD$fI3+h8TxXYEAEl|)eVD|*kFOZWX zeM%JcC5-MQAVne#2Y0zrL#pEQGhkWD8iVLd11|KU#%O4*=q}uOSEle^rl4P_a9_yZ zeMdwTF2@!s=ohiaM10aXwn*WBk%GQl;a<+34&uLDL0_Suui)?ABO)PvDirj0D(LTI zFN*k7WjS`Ig8nWA{ax(UAbv<%99C+qwhvDK#q2GSelY^z0;}-_KWer_LBE8(E7DV+ z%E4W()NHAOekuD%q&K6D;ovS;YPL*4zl{A&q(22h4(@WLW_K&-?`GFUdMY^_+~rEm z?orU+!$QQiPe}iJpHjDwZhHQ=7)YU9QxuT0vjU#s|??%gKRXqo9X5h`vTaU#p<6Wf?*AwF>$= z1$`ZxDbfr1Q>UO`p`c&E?hxr0gOXz_6!a?<^eb7mNKYEaRx0QntVDFDV#3KJSt3+3 zC#wo_cPjkXvo%5P^$Pa}_H)tQ2p5huDBK$r{5GKZjy=krxVVHl^RDLQ~e(9l?3_E9w1T5cdG&}^rB{~*(#Of;AB z<|1}4%%mt=BT>E{2r{>@Cxgt*{2BRlxHW%5K3%o9ysEhtC)?xJ(lz|8pKx5>)KW`V zdI<;UlSNHSQ)|`gfcu(t)pVl1ND9v~Q`5Re$<*3{6Z3h$tLxURakex|4r`mMR@}aP zH9~G_TE3>HsM))l{us{o^U=tgfxK3O5LV!?jh_jdi#}pk{3w{jXbnA8r+>#cN{~Zsx3mKe}K* zV4$Wt@akNPt8FFw*46hdN5mO2i4skKT;o9Y)Gn`Hw}K77rpw+lWbc_w2%%KekvnW2 ztFBvHH6@eP)hu7b|E2N&;2stk_^)ZEzjfe)^1a%*wy~~RG>9xMm)WeVCMIuggW|Tl z_WqXDwQJbQs-~u@DH({&8eAiaI~J-}ud8onOS6~f<>V~SE+{X~TR>Oo;(9*Wjk?2k z<`OG)HBHEp;S63=O|^AY7ZvqMaB8kw$=8E`ht)0hbv0}0M&POyNS;9T6_HxjRW~}DS4!jp4N;>y zkVna($=QaYg$4m!57%L3Js3`ZN@^j96{}mS>zbYG_*5k8n^&#neEAj=OUTWjYA#rz zrml51uN#g<3P%Y~U`RoULMWBn(u(ZmMR`k> zqwp>-Sg<_zu9Ahhi)4<)1v!#?z;?G+2(EpJRe3B2yp3b!({k*8toHx0f zNr(MdQI8hGGmAROGlc(3_@nS3q%hSR7(bB?|8%#Q>Mg8{BOT!yMKjG&k-bUOYvF%1 za7coudrnA_3&V8lS`j})j1P@#REQ+a%Mc#*i=&Yqj}aZh=jSE5ggJB73&V6jAv!H5 ze5W`fj5k%i;yo(;;`fJFaDEWzRDTfXe<9Rc$$V7!ra}H`T%ZEJ0Xl^@hs@VSy1$C^ z=tJUs(dT0RL0F;wT7__E1giQ**jG*Ib2ph0kFn4xUnzV_&ur55oRAL4PvSo;QoQdN zbWezM`$YY)NPmj-P>%hX^e~RUtDg8AfSLFnBpvAjmYC`o`~TQ`7x<{Eb8UR@nMpDU z0}M&P5JH?}00Ti7l5i7*+!z8u0WUp>COIz@o0BJ$X zffj0Qt8Id4gSN-C^*BgcJ0y|rBYwyK^Q^tr%$}W4?03%Z`_BLSb;0Ca?|R?$uKVp> zm#rZxngj9XB*XC`%8iiaM%Y8g(SAV0?-{UU!cn9fYHDig8P7~YxEBCYuE;;6oAs0V zl}vh1$%lAzg`Ct&7v<{MFZI}fi^vc6>7;{?`9#<$!#8BSJ}3Moh^Q})PZ3{2;BE<- z4%Qw}cwEBo6CywBC7tz+ zbm~7?Z-)>foIJuLO}n132;Y4sM18Iygxn{k`wyl2aX{wtNkYWq4FzSmqWnM?<%jsc z2Y1%{Ns|5zLWIAa5aF=A7!Ssiat{&0-(f5nU{8^sltD!sO)e<6Hk$(77>E9>mOgH04xsh^$f9f$=j-L=Bod1;YNz|hx6e{-& z7_S#4te24MFOiRgNC*2-hR=SJ@%e}l;e8_AKa=hb^mF86KPciOVJ0E`OGim&k?3zWea!a^8rH0Nn<`C-9rcy z%=VjvO*H0vQeR!{4<;cKXAnpGpCkEL4s7>qC+uHp3IA%gFSh?u;LP`L5+YqsO33nI z{;~csem4O!etQYQ*9$P|3Y;G%MEKQ&eRNIKE5t+eQ-@_gbrStC%8&ht*!M&K&35TP zWfS!cbWz`$WPL;be+R=s{L(2G%sxVdmqUnf#ty4T;SfU51Cl;Yx^rDj|1%{0 zE0R7>y5A+;`R!54-5~KtB>p%d{O^(O&rA0Mgb4ptLd5epA^3hN-CGC|pFa{pF89)y z?o6z9++;VxL1UPcXu^GjD9<+~Y?1Io3AuOY zXu+iG{(+SRa1Z)n!rf>$govky5ar}0WI71inBgq%kt+$Q06LgXv=CLQnMjuc^srtKpH|BDh1!x06_dxQ|_IEfC5 z_$din3E^%G07SlVFO&XnB1C!3k@!3bDfuE(JvvLqF+Khy6u+`f6*@?eWG7NI%4`Iq^FSb0B-;k>k>l5 zr=Ae~{JYYfd(jRQ=C=V^Zf6OHnCl_V2j;PSP?whyqK?)Q!u=76i}?cR&q@5pC_mPh zJ>WB_X~-uJQ+d z;ZOO8dm;EZpDQHe)yXq<@`h6DP0ZyDm1e; z<#hDBq*7HR)zs!^NTr+7RCi&f&bo^uBv5Ny z>cVYPSazXDRhKb&5UarK;>)HDGgWPuwb;S!ZcXivW^^Ce2V zd(mARfK@x&B}ki|whO&FMq}HBY|p1lL^Zbhc8y{zT`GGo8`vdUpe;^aL$j)ay9tC! z;Smc~tr}r&5Jjx{rfX!YND$P1kwEO5M#9nDIZ{@&eI#+q)`oO3OLZYSK1M-pAer^W z>Y}!k1RL6IbYDrhM0b=-K~a2^-67BJAQNiFWR^*ll?|IKBcQ#n95GcwxdUZ7ihZc4 zH6VHDj8KI?b7xA~u|E~Du94Q5y(*JxI$3wDV%#nJR+n(M>|RL@xrb$9wwc_}&BfLogRWGyYhc-I`2X{FxH-4b@xxS67|t;`e^G{WDw?VIS^4Gw z=ln_;m$Z}sCgN8p@v;ic+hJdYAEwV5`H0_&pH*HhaE7gn3U@UetbB)n&r(c)D%@(= zt>Mn9h=$AXRJfRy#mM7aGe-%Ld;r>m_*v!6sla*@ZcGQJ&JlUf!fuV2BN?s0xS>?S6dCU)G zl)OP;vdU|PJeDivrQ)aLmD%LAKwbst$|!lIHhE_ukM)Z3`r)VK&9}*;P9;ML161|& z>o&fdz{mB9GAi7)aI>ak+ydw&z{GH&hKPi_*CuZfGKKSgWt6-P+k^(s@(jD3s@ul+8)T`xh7?lyeq+HEsr-KZ!?%E z&ySyyS7wv96#4=~36p$8OKtLIEz&d}+$nD`eo9`IP2M6jiXVfnjEW!kYOV3BhCG#j zSAki{+iH{NOF=*0O?n@;$vX^r+aQPW8)}jFf=ym28d)Le%BcALz$UM3aWuWTU{>+_ zwN2h8$a}-7q?vrgerc0e1$ncO4#w|l{FFTI`7n8E+?tW5X`6s6qvD6pM#tpe;X9zW z0~6(q#81iVhqzefH9=mz5+?bGCWFsf9^N~n{q88q$M!MSCa)HaySwtpx5+Dmyejx- z{PHdG7TM(Og>I7f#FSC#t+2_fhrBR|ls6hbmEOl~^4!pKuwE&njphym3f}Ds0I|*>BtARWHN7tE?{*Eb{(l zlQ#p`C*J5LejPS>IV+;$!nGE8{g5DQeMv3CIMj{2Wbj$@uLkmVKn}|TQHbQtp8>iu443BTHhIS_@}_}K zKBo7qP2N(-n+11el)MjZ^3FnD08C78IetpsMOY{o)k~P;kVjk@Wsi^ha(sQd;Zt#< zOl80FOY(8vYL6e!Stz5dMcwcXS4@B^+!@{QDH&u}cJ3kC!&NfKr|iqWB;VJ&;d4-s zG|IlM8$J~lS(W{J-SEv(LM(hg>V^+nI1!`d{k$7KpQ;oVdEEQ7=gS)rY0>z7+znrM z_4KoD_*9%IR@oEK$J)bHG%H^}@G*HR>a5Ru$RLgKlWF6tC^h9PK9xneHohwGhB7K0)i%C*@L8%=#J9Fzt%=#wGZ!w(*hlU+Cp0j2C;mkCJ@#$6pi$uFI|B z_vfz&-Ywn&(t~A3@ODt$TOaGe+x)Au@k$ilfB(-f@U9=eLfc}zIP$Y2x%fh=kY(YW zVByt=k7~}XTKJmD({e=HR&1fBwB9Iv2SB;oLV@(j*Wg7lUvS4%E$3HFxm8xqH5N`6 zUszi|Tc$}Qm4Bv|lw9M>nR@-rzM_@Od{dS!SiES_;zhojR;*aMu&Q#&a^I-Hi2SSb z0(qlGj0y}D*oaX+;sIp3FK6ZArHd<9Egq^BaT;E^xN^Y~4WAi;R&4B)tFP1IdnR0$ z=tzoBcJYmyE1YS1e?46vpl9fru56tr9b=8v;lJZ;k}G1wyTn;7EYYMNBdGkilR^p30t8f8ier0tvZU-!1v=o;?;8R|L zxO4tm^D>UfT)AYGI3fSPeP;o2WX^CepLy-*ZN`;*{5f<-e?grO@tY)GA@P+GUn}uP zB)(VTVvimEPZEcGmW?9?IuJsH^AGJ2qwYpGJujV6v3oL>Jo;}?kW-h%^2abDjM)cC z1VHt*S+J8&^{I9~(rB*2k9mJNz5saa;j+#uqgn>%z}9u%Y6xaMg!)nR_2grCoC{dx z%>dqnpE61w%iAh%6XaFFjq;cWN*tc_Awd+>)5CGMvfVqXPMSv-uCzBbz?cX6Xx>mqt*=MpY0>k0pZH!a?B3?p+WMW zZA8^oLhBgvkF=4#s(}D1dGn)n^iq>uap$D|w|9C&4zw@?rHO}z5`1cb_&P{cGeZu<(^xXI}2QywM zKG)(XC@4+ki|W4cQBy|Ws_O^nBQnpF^q+d$yqY>8CGNZ`_xBXqD>Kco51hjL4Q8*&W2`eS2e-{6gB95n-m z-Pl}Q(|_2k<_$H|hh5h^HSJ^uzR;2wcRs1dgaLZ4v*k|%<`mBN$DL2t zQd?g=pWOS3Gc&`zoq0jm`9AuChPEwt<>N9oOJ@1`{t z_k4RdzN*vKpznGE@WY1PhCAS|#tZF2=XZBaU&Ha${*DtJC!Bg`Yo#N1>N!2Z)qGcQ ze9-)E`?aON3#|y3Y9EDs!4E^>Mm$74q(?e)q$Hg=(!aH|##!_4iJ8X+JK{Q97w48} zD3NE|;u6x1G3UQiobZ0;aA$K$L%-_UnpxFn(>_2t!bkt7twy7BFE*h64*eqa1yQ54 z9HtA`r?GUbS1pG6##p-20xAD)8=ab#sBuDT66>E@l&EnE?S>Wih%;#HOG@#he$od> zoO+pL#CN2`d1iaJ{Lx~KS9M_JF6QGD~^VCADOne|^8#dj+l*xm{y!9a6QgB?c% zMHp=TY@wU*v&!2HgkdYAv0i2g`?aKHuzD$F4PBIUKop4izVba*wyFR41RZz@7 zif`nY@z~Xin#;}W$LEih3*O7mUFvbZ3??#nnT*#jjK&?;?I{15p^b6{$2B}PJ-KRc z*7TAzjJX`wx0n6Q@aP2%kCmraCFGrQo37u2>x-^}hOKbD!R^U2UAMwDEopeeLvYoy zbn!*DhvAlyRM4;kh}DhFOsum%93?6hLa)hFv6WA)4f5Ydm>yboD&-+l&9A)%-a4x z@Gl!POkhObhydQ4)5@x+68ARF>|B2XzS&b|=AReeyGs&Zfb`)@kyBTiuIv1pj9=vG zn7w)nnG4!6`c;OK_5ktu@B?I@?7^=VKaQ`2`~@tKbO-*hUr=9afz>qskMDCZPol@1V>%2p=-l{?8h+Cv*1xRSlEsOUD3;EVDQftQ zi&%PWYMok&jm}A7)bN`YvHmfsv=}F-vGiDs-?)f%>1XlH^j~44$DUf?H!ouSbCwb{ z{N_b0oi{Y1#)(r8v2=6LR2=-~MJ$~&!KiWKCP^$kBT9sg-@J&W^VCGtIPoG_EIl(y zgpJ?8h^1d?qx)=hpN*bnqi5OZ**1E%jqbP6{Wkg_8-0+CKG;SdY@-jc(TCXRSJ~)S z+2}boe5ef{X7fMHM(6pRsBz+^er$dZj}l>X;s!%3{c0P1gpEGJMjvUTa}^pj&d4sO z>Betl#D<5l%3_>ao{gSop)$VtHhR8|USOkhg%LH*F5j@R&YmfMtj+(}sAt%m;-!VC z6TkTon;za6h#IGMO%#ER-+W+;=D5hWLb#5%<^X#;)pz@V^g(~jGyXKk(Uh{#f0Uc3 z7)i3=dyd38l4L>RQi-$XW}&^+NSxthp?y9fagHQeXwL^?@Qj$VAB@ktl1@2U=zqcz z=a`g*`h{l(g{c*|H+q*3?pf&X$4ELs7ETe(mN-Y2EW9jJ5knuXeO2Oxf<9RLW(<8y zQAvMJ;C&)@s?7L}5ck4B(&m9L3;p|FB)>_|*Z!Bpy%?jjaMLtFj@4Yp zWpTWaIM;4j=-+cCZu-AE@+LY|FrcSt*GYOS3M32Tg zeNfxu7!Zt!kJtK0+zh`!%a^zr-(0OchK}|L6%F6iU=&H3;_TUp}a*t|DH9A@c^!kA{-+zuB=9cah`Dgs+D+e*L-h!ANmJRY;e45(=)6zPQH5X}al+K_p%=q?L<>Cy_HEw$cF_L7eQt zu^xzBxWLSG@xb%^dm{cPRhHi2M?-HB&XoH{s=r&vGkKG&4No_!?# zvVe;EkaBbstK3j96jN3=sF2k;2t(15?4!j z5A>phE3qd)hW zS&4rQ@6!_EfZJihbxE^PQ2{)MUtvWW!cdIu+A4>NJ<-64=gcjltYufJ! zH$z8BxJAD6_6^*jBfeF>_x1?xZxVl0zW4S``QF>N@E#rAx1q2wRyiJnzLfBBj8TNh zN513gz<@Xde3{5+4oMCSV4Tx1-}_0JE#WxQk$)2j;lGgZNe#1I_^-mB5okPUser3j zny^aQxD8=GXd>QEiG75o`w>pP5rUD?(vm3~R{>%LSm-u_c|OBz^X5jx|HU>hpRhs4 zW7;g;bc}wi9t#^USfiv$X$E(2t|!m5r<1pMnNz) zV#hb-8Z+!h9J>sMiXtZk5md})qO+7(cXNo8&-thkT}&6nL@-L|QjyGIqbozCI(5Sk ztqV3{w?k4ywzaS=bG``OHnFj}+vihJvaAZ$=}DB>?aU%Vj?R@MPBDdNOJB^yE#l)c zLv@tz5_8Z9Lzii1gc38RtG=>x6?ypM+H59%l*ciPrWCU1t_*4XVY(0#?hG5B3K!Fkm_5`Vr<(E@ zE_D+sTnyVW^7zJdDcqD%@-Y0z$U6yn9Cs;?=~MFdz;4Z#9gv6QMvSs&fr;q@S(s;F zp-x5_6>e@fd|dl0!?0*3cEh(vP|QDy@8)j!M1&=;;;Zh4ueKX`Tf5sQ0mlOPz@_ito;D_^9hqM)7ejZkNY)p^W0&^(Fa^cEd-VpfXC{ z2i@=uQcQrV+&Fi($1hS?;8XHAceeA@!ml!lFTESSJ&FlX@r~?;PjncPSMg2jhR@qg zxO2MUE9@p*>b30Y;Cx>h6)x|^(GDOC`wf+6bWrx)HoiR)H+@CZ`>!^>XD`9`fsJo3 za21v{+|O-%`z|3b9iFY}c<~bQuCejeUxM!j8{eTz@ZDqMJA4VgZ`$~N3_eu`Os}%5 zZ}fpI%<)UeJ8qMA@)CT%v+?oGC^$uovbWp#-n;}~I{F-IJ~x3+#hpTxeS(dz`4W6L z+xSjjBHX(rpK1~<;A8z(Muq#Zjj#0*e7htc=N&X>!8hHsiocY{-(K*6RINyP$fq$1 zkvv4ntKvqy3VcoIC%GR|g&*^o!!f%~$cvb9*mAy=L}^qy`T)1`eUACTA;d))#W!;7 zs8K$Px!f71{ITP{^m_$M%?=}ShN-tWk%e?LzBFTVJ zVV83gprSk{D6UUyZ+!3mq$6Kszju$KTn=hkn~Xh4x{rLDjAxU!&7jR+rR5feQ`gfz z4lfn_)PG;Lo~7PHFsX5Z+InPW=bNi$cBZd<>*M&mnVnhp%#_14F(QC{E7&RWMBn*-k!+g8x;3tpSAJLkg|s1l$Db8 zXB*Eog6EAR+0(PjldA?)#Xp`kJ-H@M{B=FnlP|6+UNnZeA5FNq4>XXzV#5)sDU_L_QtE*`ohpr-7pVEz|Me zan9VDA3Rr{Vs!vcT_N?Jrm=KLaNv2MSbpmakn}_w-7=9B{*$C!6Y%^GPmHjy>qMA5 zH=bqTV1H_z6B3_fqu*e|7u#^CaU+KQp;nC;;?G7fv;Tg@hQDURe__MlvEhHR;eWN^ z7j3xOuckBOgU=yE4Dn$${2Ch`wBgn@4gD{-(fJOmGNf;`;ZND{AK368+3+SC{(BpK z-iCW3b<0fe5F4((>CHGYemC0aciHf-*>HYin?Z8O<$f@A{lv+Z%+Xox&&q8T`vxuP zF&j+4&G$>NsY{|j@PSxo6P?yf1WwTo6rJ1qFH>l!}sVtQJ; zFe;4tKC0gQAif~n1tX91x zWpFoM=yM|h+7zS6AUtrtdI<|Trl75kix!Il6S}h`Gzzv0zIlTwqj&=+oe&-KFhV$v zAjCnS0z!1?rGz-zS4Nm-zWbPjj&~Muc)p1cNAKnkX2|a-;V4}Nap)=*5#neZ=ebEf z^Np^gEY19$Q8xAi>F$@`c^qWE*G&9Fx&seOI{P}}?BhreNSwMT;>Co6HSH_XeSvg; zK;pdrK)yW^e^KH;l{nuoCjBFchb7(%ji2GB5rUp4@re>&De<)ue_7%j2OUG?{vU?I zG>23a9Y z7XFgYX`(T2-_waS8Wcy29)xw?Y7`%eL-GU$S`TpeZ}w{M|z(Z6!VYbLw#O~qY`*dXEjb!UH;vpyzyh?!!DPa)^dmE z3e0}Jjjo^;?yZRxTsZ7-w529z1s!FP+X(RR<#_ZUBxT2om2p-uu1w1|W%kyrvKRrY zJYO(Mb>@s~?Ay|#JY$gSqE@iom^gpU5w6H5iWT`uqpJN z=2SPv1#?=`XJibCzo-SDgpVEv8Tz|M;YiK@5bzaYt!QKV*5aIFDd`74-LxY4)WJ_( z>-ymDrgg)QIsCdm!>3)0D|KBcU44_`*9wp5xvu8wqb`4Y$mtJ<^a&lIqi3rN&6_Ib z+Kb`xJ;T01Z;M-`+uguW!5`Pg`}Vy2q&f zcdWTs*Q3TI#%*83!P*K9e%wl+_B9`AP_*Fk;_99UayhC9%yfcBR zjOe?VMxI&5&>J!AgT_ZNQ(8H2mZ`}fug$m7S4cX?2;M!ewb7rJbgqqg_jtd=IW{CC zzm5PZ!|-2M2q5wIZFnni#-|3qWaQs@iJS7gG4I0Dzt2)3iI214Tt-+rNz0K_;mV_H z^KpTBp?I57%-iX{VmbYZS@#+oaI0KexpG-VlIiD;JGywfEKa=9tSlun%?z=Dx6MnV1W+6>$zM+%Z>H?rc4r3$u+9vW_`G$MjJ6_W@?YpYRWa zwVB^I7jt$nvt4nH$vJx_=Dw_BoU5|^(0#ddXDdn?D#JmA50H+zrt<%f%@r;0Robga z%>2+oG;{va)Y$V{7LWK8mi2v1Rg$7Uc1!6dq)V0de|G*aLD336 zHMgBXI)oD$@?K3tnv<7 z9N07H!F>g4_hGz^aWl3XTLOOb9c;{| zw*=JQfnKg>&#f@|^l~j?ca+bm(#EA7(|sn*-N;$3mg6}V^5JcqqbZGjW@HC-f3e}7 z(7U|Om?&QD-gBfU!oF3$x6NIwfAvpo&$~hGVkJ!1{V5d-D>T2q!qM&i#orp!XHKk& z5B3ZWZ%7l|U#)P~hmSgjK5T3*^fX@~?#a8VHa?&YcOP>Oem`N}F{dB2KtR0k;|Lr- zFm9!3*SAUdv?Hk2BsoDR-}MnI2USokZ|0WwP)d2qbS8TYgldk#WJK}M<>=Ez5lC zD83#mm@Fg2)f-~)g>#^@DR9JB?eck#{@L%Z)_k9Z*7-jRq1`uX*>OQn5O>{0iJAU2 z=AYPC)q^=lvV%^nF(a!uk(U40*G24WqQ(`yiwH*tdOl2Zgg(XOQ9ZDUah(+FKVI;& zZ#NA(AdBHTDVEdWjOn#y(Xh8R3aQ|n;za^3r~q?>pzjdK}g z=ync2%A12^S-1oC^Mun-hzR6N`Uu65!42!$3*q`K$nW&$I_!tSc?(ELo zAnoGF>lMo?S1+s*8@cM@E$-+>EDhI{0 ztXdOM7AaY{7}rXXksv80kC|{mMGAQja%JUx(X2AJ#^>L$aDAZoJ8E}MGl%V3Z z(I{u>JxjU?fxcoWBBo}97R?utV1-^IP6Ehh^{VhJA$G)(L`I1oOcqlPNhR!i0H?q&VbHwek%ZM7`%(IvK?r0P z;WTsq+A&?zvdIr3=Nw5;h>$-CgC6;a&n28`&WR|e8aVx}CInsum|2QHgtMi5xZebv ze1qr?I-;ay-UwNMj33<@KZeWr6cWN8MbRJUG{oJ2%nznF^DA%zOv2#dlF*KmpYa#@ zahuGC+a-U6DJN-xq%Sn{H))YMz9%h~y1@ifZ$LQ#q9!hm)#sUYuA8l8 z(UG(Istz+o*=Kr-?Pj}Suy(lJkT2c!cEcRo*LK5T?Haowcj@N3;Snvx(yjd+7S)$s zibXX2Xs^}{TcmS}c4U8#i)CRp>A%ONIHo_L-~UPaUe39cVIM#<96#z{3h|@a*VCLUUky8X_+!7oK9F;@c>HKe@yif4 z^N*5O2GlC=utgsIDtU`wx5}#k&VEW6C9eVwR(Wqg9^=FK5h{5bVYkX#3cNdc>)>vc z*JP2${#D7_Ym-+4yu19{19z*u7K=QFujHM8-5S5mz^(Gw7t>G?W0luxk;i$qk{5>E zDsKmHbnOvCKAJz{XO(vr^2WjKYWx_!lGg{qtnw(IX;wzb>j@^SJRc&(GN(L_8%iF} zT3O{)0Z}q2Q>AyfOZ>LQj&z+L4jFQJSpf&#vLmv4kj~WOi?(qNI6qSIdcp%(BmKc7;N8V95$;xbtrmGc zi@Z@bd3*!7yZBvglXuo4FWVyTW}Cb@z%eC^7@)$;hQ%7cFyyK77z7TL-t{(lPXhOu zBE(-MkLQD}^4vJAr0Vk!i@Y5+c|7|!&LWTD((r8&t2{5{1>ny5!g{FUcL010$B7>e z&-OiHTE$-_?*!agZj?boK1>-ShBW@(ggazaE5bEEzRbQ3?+Nl-x+CC`^HYZF#gA!F zaf4NBg#+)7DZ?;n?E5-}NH5PbDx>(Y6j{!>9@n4zT*T$}b^iH%I+cSg2TR7o*(plN zO2>)9m<(R{kIm)(>!02ddx9)$HQy+RMo-vOmB<1{K9wRnpQgox8!8I=xu`{3J2Sh_}x;$!jgf`Iyz z%H`Te{`dgCic53(bBy)1BDl!D=ML>D&4qo)S@Cto>@n|a&bC@j?T>j6xq|LspI~}0 zz8oj+_nH>{xf=|B znCVu(r(oyLiYvQde>r;a+ z>>lL`y zjNf_G$Ozz$pkIU^_&sb+kvFsr#aEwAcULoagad`ZjydZCIHBoo>@i(y-;nQU+vuoU zdnUni`sswE(s7$Ju=JtXufNm#szJDap*t?Sou(hLe+%yg1jvXi*nRBf0 zstG~I^KorSx+zo3X=^SDUK4ceV_FJF*9KoY@Vk&U2;UJJ)EcU8{MF{n+<5HV_6?3~ z-n!Y7o6?N06V9s35H2vw7cQus+hv94HaiUzcoCT8a_7)Fb z`FFKBJaJF|&Tt){7%rTV*!0|-ZxqjN`bK(oSSv<4XDpa9{nX5`r&q6w&KZZ#C-erV z@9vI)jyC}jKi_lbJxMPb?meTjz6rP? z_=j1WjLnrNjZIn8L$fn>G-7kxdm`PnJ-;eOk-tLFq)u3z*O-?<|D&IQ`uwnW$71BJuURtF`%pw&$)O+0PjomI_9)q2{dTn;cr8>M94GSZ z)rhSz^sbRM1ihy#+3K9^WI^W4T>X-&?jD?1XB|5#0a z&qZy$1N`tZNL_#&aYF&+7{v3N83*W5E{*FR}|I(lRApeE!*za)Q2$uHA>G4Dpi$(dEh zzeR7?@Z8JnbI!`trYDWgxD3DkJoC>LtT>X9t?!R-zcA||&N<=>#!XYV zA$<6Xin5chy3u#t6Gr2d)UeAH9~|5CgfVc^fCSg+!V4pGvv+h>ZP@&dk(T*{ktlX+G2G$2=&iswmlxNz0e#}XCAcxp#mjN-_yN;D!`PLe zpElEtREu$4U=17t#fhF{Zh6uu=ZLd>#{>4U(M+>z`s0wrQFH^K8aGW^9A<6$Slj7_GJVZOib-2M=8A=ZIbUNd{gq2(<`+V|f!wBz*`Kks-s=)9QW+==%klQ80^XRML3fM~O(4Klb^j)3@jlB0>-*xxS{EBz!_<~78vxiT;clwZfVdma` z@4c(EvE^x1V{szyZDV_JkHIeghT^HsyAF8rwbm*~%4!|tzbIzFo9Cwor5h$*#2GcV5YE5-{D3ss@eS+;r?zY)&J{I8gl&2Yqi|JH0_xB zR;VwqrfdHeN&!55ZAYjNV9T|C4aHq_6n%5;g#^bt)7I(@-h4gp1yihTYs$JI{ph=n8g8FvbB$}? zFxu7jpo<}Ww`!MXm#d_+HoqjCC}Fec?dNow@$_y-`;0 z3T_TQ7EC#_0HfdCa$d@}Qh469sQvc*Xn(XKoapM+`hl_NS*`s%{RwNqqV{SF$9th6U*#NqyzGUsra6+-_E6F_ z!B-9MBsE{nd2I~B`fdYy%YxHlTst{wtO0)( z;YC-%zYAfmxaWDyQ=6xxp7IGPr-T$O=hw}A=>_Y_oki_0#Q6G2=*rK&@!5^R;$Xsg zk8Z9XT*2xFukinkNGu+V#NuH7+ECvH&cAYNU&Aa_Z+gMd_N466awm7LdL?CN64p)2 zE&X1&aV*YZkNi!2+cQ@_T%Q0uEVH%QMeXn9s}ZEA z-BDzY^QVpB>wexb(DTTYUZt**$sJ%V^-()E?G$(NNEe-4B)_Sbv zFn`&Gb*4+)0?i7#{Ep{kz81sAG3|?r$XA$51Z_#+zT&EwrD>b zxeY$4R=;0k#ro-a|M zRT{26g%|#SS{Z%i=qJoC=fo@b9@tY{8=Td|SefVZ=NyqeL|Ng5 zFOZgKT)u;F9@%i|aLQgo7+!=?zuB18Z?iG`hYZ6t`PhNO#n3=DZz~^Av$fdu_O}3U zol+alT^|iq56)8It}eW=#L_Y~|2|{Zn7*y+;j0e5YlW2BaH;U!;~;xX&Hw6oNADNF z_hM5jb=Pfc@dBB)iZTi>{7Q`baF2IEPC&{jY#ok0r~>@#hB3dU=0*d1 z0YdMlj~>-JtzoOyV$2ybYM?pKpqAx#FQaZ&YlGhU*j=iRjc#FUjUAv2)e7pbk{by=}^J{h&AAj5I<8ElE z(?$(^A0e9IvAwP9Y~uNZ|qKD@q$yZVmNuF*S-p>MpXd?>4 z->vNdji*bDIR|FW4EIPxc_qPT;M>KC7vpDZr#6Y#2Ie%doC_QFm+9H{#$KoEg+4N* z?@#-FnOls6hXv0bIp)_MalN2tf2WN8Ousw3_*Jv49)8#JX3Td(Yw5&l)!A0;{H?J) zJH6ButXrEB)_XXb3NH+u{hg4h<0KzuLtZOyN~vq#8LY0LQEXf9)Z0pQNXY9i>Y80{ zN~u0(BlLb<-8UME^<7s?rkJWlnBGm5F z_4eyOFg87=UB%q|PVuo$wAA72I_JECybtKPIn6_ZJtOJvIogF<6ixfPBJI@DXTHPM z8f{zTis)i5%)L>yQGM($Ltg0rx!yGM(hHfVL%WRu-pY<(O5IBMR5{~>{N(PDqvY;HLeMz!5L%BHt;cLN*GMh>Zlh1Ynd?A1no#*^NYDNHj1LT>;gMsmF^)0R z)xi(?0qxY44ddkcfj+d{xy^Bq?(&zJZ6-S*7`I=BJLXmB%2O~GN)M!josL^Dp7-%( zAL)hl(u2-NMT*k{4q&>#QU;$kjt`2v=>GJ^+t?Crycu}GZX-?0Ep54nC86a^Y6lkuvbvNk%DtO4+~^BzjbEnSyA7q*jwz!`8D z&RSD$h8G+)l^rg}&T7O3H~%V}zT78}v#9@Jr&G_3Yu;|8=j-{K@OMkdk^3;#1C;lZ zj*WWy+R6^6BYov|V?aJ!U3$Kjom09A7;|@}W!=L*J{;6=htfopg*67{5I$NvGj2B>oeGE;ChyaEvA{ma%DUof znhqf*yV9xW+inccG1EFchg`J{n=w!Jh!#4l;h~7#*RTm=jz`3zcG?Cx{%ARqJ8yag zlAVyeYDe+p&g)+J>a?Ec6U5hUjn}C~THTv(C)xb#k%xV}AvHKeON6M=2v@2v;ZEJ{@lcy;;Qc8h_ z!uFL#w|(T-v{DQN)!6_?dos}+TuRgU&P^+ zaO30|Tk87-6L2!3C$uxvqb1atHTJ5J)S>;T?eQxUcFjEZxVL}PXq%qmDx01ntwfEm zMeUO!dWu0Ke~MkN{l(6gFL67xcDHIy z==Dm@ZE&Kl__D+Cj+7GgKeN#fLC&3Gy$}t>?1v~Heb7DbY`193+l^OKShHS2fAqyr zw*QyVBRQIq1eIZ5J&j`?M?i+1k^dGyrb51U%W>(F;9_-Uu~b(pI2%x)b?vT=cR?fscK$T4Sd}A3?1M z&W2zeV`{-8I)U~9mQ|Oj6X1NqS}!s0m^$Y=Y9lw-XJpr6{-Mi~z#hktxkn(iK)Y&O z@I8#!+~27_=%#+<;l~a4wjgm0eBh92k?_WXa{q!;M6L=_1#- z-;$htOI6SFy+p1Mzjdt>Vi@8L;BjhhW=IVY%@eH=cM2tC08s6VN5x8iK@gd5izHc zSn+h}>)27+VmJa%8_odi*;@?VM{V@$9nJ+Qpg02=WAw4}BYJ<%^R9(P=JP#I8R5}e z>$M?|Li6r`)}&_;Cqf|eQKLtNsOy*=C$wL!~dn3d&%+t@mnJmYuiL` zdFfo_C)3IOB?tDG62$%zcB)IBE*{jJk$p?h9KET-Q)@5!M%-sTUHUUi++mk-PjLRM z!-2TFf+F^#^)W}Gd%M{5l-Qkh%H3Hl=X8??_0Fd2ezNewdgyLckK_wJY;-;-HF9EY z$aYT?ZoF#d!`LG>=euT`ehMqyNAVKEQ&+5@4o7(`~ z`&-N%%~h^i16Lg3$t~(de`{Hbb8Y;`rXHgA`fH^3I;Zq5UzyoC#i9rKw@7)dYV=;O zVOJzB@TidxcoI8dk79Ss+%@BjiX}A%F>(b;8k}t<&Rtskr*AJ9I?$X+afeBrjUqSa z^Hsu6&*`U(oAUjg>sI+ui=Cg=F4XEy8E=lZy6AOxVJ55A+v1E=WPPn&^>Dp6o9Bfb z`^E=9Fg%YHU8g@K>P_}|v0|qkE3@P87~B7d`1!^Md-yIMcxK9gmc$06!RPQlid4D$ zSz<+|^ut^wV3nQ3HQoHrHvjFlV(ma2(xB&^I-qCi zV^4(;N?y{%gp0RgU3Ds9)H}DX{pvwI=#{fUP?K*lS98v!W^;x}AGemiw;6q`Z@}8P zR$p%a=3fyD^jOPUK>DLba`mmHS;1XvPjnQapHD$c@%qiUdJDJ)cs>*(EmCf1XCSwZN~#R?*?>bJ)6)D+)y#r>L{GB1imUYIq>ect7o8BT$| zL38IG?7A zEEAfW?ngV<-k7)BNIb43R&+Q$kHR*qX8vc7e15#6P^;*0WmsJ{z-6j%`PIC~;J1gj z5AtBW6X!DYl5^`Zwk3J9!jttLC68hcude1qhfDN@Zdsl(4I+=eV_6dzjq_*31>d-T zyK&Xz;~ne!)gmqrWBzs3V#Yw;(TlN|`lkd*#9n8$t+MllF2|MqQ(x;wU zu>7gj4?MVa*7UE88$M~?Q&o9S!K~Zx)KiaP?Usd;Tda3wN4{DW*M6d}tLVh8xN@y4}b3-=a_eWS(xwb1k`J(!I%OJ+%|5$Ex~ zCh8~0fUE!F*!ukSFMXT z>xR=)1I6e#aK9M_was7Dihb2!+Ewvw560nSS<=84k}kUP=YO`zxV0)jTv$@tG<1up zf6;O#H6`wQ$rx71GJDtXjCje&(eyl?O*?7~(_V*5;^U;fWDM65MOZfm6S1Rc#=*HW zp)CmybQYFiwzcYtx}!!;px=JaghGsC6=I$>=g1XL?>6RZiP!G|qb8K?F1Wf~W8{-PYN$WfA z&s)2?3ZZ=By{5mP=UEc!c$#CEmWH`pLBNAEXiV|Rj)5+Q-g+bzy@d}aB*LSI25$_y zp=pTQF5=~P)y3Dj+b`Vc{$$%V7`@MX<2D!z{KL&d#aBoUAsvai?w0LF@+6#*!|F77lBp3sWTZ+;KS}8~Nqxg4Kn$rqxE+MltE)Y|a+W)DiK zz&BKuu9owIrlR(nvdlS>Icnn^Rd(SY)fKJAI6FaxClK1`!vIP_rv_gtd$6B zOvY%Z(PP#wF~ix4+1W14!#Km)DrRTV8O~O?k8jljjG5zN3Sy<_yXxvg=KLL{ubDQF z-xIC%y9S2~r%XAwaScoJiYGi1e8GPERgJ$EZ#vBh+4m`n+TXC`HRsgv2r0fUZdd>O zxVle1GUo`)WA+UPv0L3ZIwkCm`%8UN6Vtn0oZxb!Rt%i9OpL{I6Fz%qX6KHTLxZjh z9x-2p)G_Q6h6WS&;iSZJ`djiO|2`LVY9{0lnw?#87&_IID1*-#OY3FQ=cu`(8BPX4Zd8*d5_~f^i(`s z#xL{?oRs(y$I81!`^DVhKeX_g^|@%pTKJyzZD_|XwBxd1v=wXN#p^%DNHp>{!?rXU zN%ecNU;dMh^_g41x!zfc6Rm9Bn?PTJv1#~k*nd=F_x&*TA5Q|0Yq_h;_nG_i49rKU zF&p@6oLBQ8CcpNK|AsN>lV2LX%+rQDlQAB${_OorsuItCf&Pbbj-1czt+ju&{)4mq z!>jZf{W1MR{Ci$Mgulo1*Y$Vw_w-%*llmV0Vf}0RBl`E?{))aqaFO#@dXun!pnITe z)UxJ?UKxGwSnR%|A3m`@?)murrYlcF_in0g=;7aw^xyOF z>ru>kl5%nO6SR^kudbzb`qh>6p`UU-u_LIDPCV~QyfQQb?KrA!r!S>#FKQ1u)y&%r zi>1$c@p|Y-kkcbKxyiZn`QqM9JErt(LR|A%B0n&^-?pC1CBHt}HP*4~?17ENe{4B? zKB;#a&y>fvebf^>P^=+gDX&*kqDv?V>Z=tnsdosY=fsVhI*9LCq4{F|r#9)G#(*7P!G zqleL}H=$F!IS|XUGdJ&Lqya*d}r! zwKDe1T(0P8hXvt36a2kA;*QI?%^5f?;wgW-@co3i(@Y)uA(6W3qm)XCEZd~qH$`v$ z3ppQWo4B&ECr{drzBM8Fom8I3({#+p+yTajI*PyQ=J>0$5}!85nRkQCu|mwYub}>> zRvYxa_RfF#=zzI8+SiaV+}V=znXBXdgx;r3w_d}Ont9?!&K5zi1W~+`vvDFY!N5lT&KC_7AMj+s?*UkJD--V zg=gea&fL~jTYwW}f3b{%cb<+WJ?OZ!$eQ;>gO!#_1oQb;*HZAv8k+u8lk@H|f zELyJDBBx?LRBQV!MeT+ql$Ox9k6Z&;DUjO3^>&1xx2cNSb&IS|LLTInshdbRpX!W5 z$)p#)guNV=jw_hOSo$eWB_c|p%8lgoWDQ^b5-=W@%bh^klA z*}$Uw?}Yf}F)epp=WP~_e~EC6&i`h}j0LqAlRKxqk|g=32!8fIg%R#Dq(IBM*RtlT zZrqGh+vu-ub_HEeFjhN`>74xG_2rfnYdRo*XD7-`Xjh$FbV6N5gwdBHP;LASTA@2aab?- zuwKXzdAb=j{w@7CAyZFdL}J%r#t!Fa{?+-4T=8o;XPd=+fQVj+yDCo?^OSSR^$F07 zjBIk7qcXzJfL27_C78n4C1v48Li`Ns&hs2MJNwVA-dX)#O>sEE@m}@qtp&&(>s%Q< z|Eg%N6t?%5nnOw&R?b@<=Ij=`Wfzk%1}F9UM)9a7+|uE_4-NM|WTyz@P0X6_7ry@)z|qd&If_|pF^#8@FE z=hgMj|2%oxZ27+JZWZGeo%Kij;x3Q*yX&v*gi!h0U&e{%f8y>0^9%zba@!AoQ_C{} zct$9H_gjERnhf!qebZgLkn+sXAYPVpCG08B-|mOtPP}qF(q!ouL3xH~(0`884Hx>~ zk0%6o`j6s~M#^u}ta9IH@ZKw4!Z=YXh#zr24SV8u;0eK<_`Zzf6R?veqF)5%nWVlf zt#X}5@t1fq{c^4J3rh2h(xA)=c*2Qq!YBzr{{_x_aHfBrH4!pO3Vnrf0!dJQlEXWy zD9_)Shv3feD)C6e6H9!Pqigq zE##A)e6{z+m#}k|C4ZKXZ}6nf^4_HUIhOo6LVmd?b&mHY<JsmbFJYVn>Bo&WONG2&s+Q8yGhyd4Oa3w;@5k~oPnIuXoS+rN zUuL;qZnEe{8d6e*Tcsll!gi8CZ(Xhjn0dZ zrFaTY2=1&8Bc7i|?~N~Er`ht~EaYR}{v7GP%;1Svk)dIl^^2fkr^Ui+5qN&9(qhTC zS@LZ{KI(GO!Uu%3}yoH@EOTJ6U^DH=Ny7Y^nVP~x+zgEb<=Si*g-uM!BdMx=KA-~0w z>ha$A5_Z;E^6P}W--@lX$oZu3@3#+<@Atz0q=k2bg?EFKkFrJaB9!@%bA!Np(kpLL{uzU3 z{V4G2#|;+#jTZim0GtVn4@*B|q){y+gmV1-M z_gXy9^V5dov^y+*i^V@-@jtfs-&uT?*EUQ2@+`i>;?J@8T8m$0@poAKL*Q9l`2CiT z@1q@-`)=i4F5JtVR~26%_-W1`6<;Cv3a1ctpLncu`S@O$sdym{LghT)h6_j;a55DDgLl3KTicu{rm9b z<9lJD;+G2kEN7+Sn*@K3bF1Pd{&~*B;I$#%cP;*x7XM!sKRHYLmg(~mi@(C+*IE1* zEdDzd|F7T~KekKx82|q+z+-%$ZMw&unE}4uS*Uo%EgvW0eImd&IG+jd7du}I@JpP3 zQT$WF|0T}rijN6?sdG^AGQBTzGIHRc48xpk@n=~4V(^R~t5rV6v#S)(Ha8!)A#YUt z8^Zlc=kFEIJ~WZ9N95OP=S0PGypxad=-J@4Vg6lW@vD?P z$Ef)jkKV3$iMQ7IhTP6a@y~*1e45ZMe6Mi7 z)wx{pPm28bv~!K(-w^J%JD*j2g>b*q`Lg197IQwvPdgPa`zM?z=^d;ou8PrIV{@{n zaYcJ)YkMayMQL8q(bj`2aywV`CK|7v%j;u~E$EAMw>7r{FextVaKtg5yho$4qYL)D z!~=)k`_eo>Us*Qd?vtK&dC{))#(NSPTX12_HQnvFOkOh7 zleh{7?p>?>5Lyy#Evp-waX*SsHQBtXtufKs-PqdWtVAm72*Xn+F0)x>XtSn$RX48e zX>3{7-HodxELU;cfXo*aydS1Yc0V7rf>+ORf~m2htM%H(71uWQUYl%l%m77bjlEqs zoA??pGghfPg+JiMI^sypF$Kq1(!ibv+3O_xJ=# z?z$vWxUF&hs$^pi?~LwU(ZLIKMw3Z)cl9C7eW6t?jh&+6t!}#(Dc>&cpJ7D=PgYhK z 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 !+xVz4jNhWtNh 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%0AnLH1?|L3X1~X!;)PU|xjNv^AHmkY?b9s}h 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 zb_bdb_finding_binding_init_ctx", (FMT__0)); - ZB_SCHEDULE_ALARM_CANCEL(zb_bdb_finding_binding_initiator_alarm, ZB_ALARM_ANY_PARAM); - ZB_SCHEDULE_ALARM_CANCEL(zb_bdb_finding_binding_target_alarm, ZB_ALARM_ANY_PARAM); - ZB_MEMSET((zb_uint8_t *)&BDB_COMM_CTX(), 0, ZB_OFFSETOF(zb_bdb_comm_ctx_t, FIRST_GENERAL_BDB_FIELD)); - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_finding_binding_init_ctx", (FMT__0)); - - ZCL_SELECTOR().process_identify_query_res = zb_bdb_process_identify_query_res; -} - - -/* -**************************************** -F & B Target -*/ - -/* Starts EZ-Mode Finding and binding mechanism at the target's endpoint internal function */ -static zb_ret_t zb_bdb_finding_binding_target_func(zb_uint8_t endpoint, zb_uint16_t commissioning_time_secs) -{ - zb_ret_t ret = RET_OK; - zb_bool_t bdb_finding_binding_started; - - TRACE_MSG(TRACE_ZCL1, "> bdb_finding_binding_target_func endpoint %hd", (FMT__H, endpoint)); - - bdb_finding_binding_started = zb_zcl_is_identifying(endpoint); - -#ifdef ZB_STACK_REGRESSION_TESTING_API - if (ZB_REGRESSION_TESTS_API().bdb_allow_multiple_fb_targets) - { - bdb_finding_binding_started = ZB_FALSE; - } -#endif - - if (!ZB_JOINED() || bdb_finding_binding_started) - { - ret = RET_INVALID_STATE; - } - - if (ret == RET_OK) - { - /* Clear BDB Commissioning Mode state after identifying has finished */ - ZB_SCHEDULE_ALARM(zb_bdb_finding_binding_target_alarm, endpoint, - ZB_MILLISECONDS_TO_BEACON_INTERVAL(commissioning_time_secs * 1000)); - ret = ( zb_zcl_start_identifying(endpoint, commissioning_time_secs) == ZB_ZCL_STATUS_SUCCESS ? - RET_OK : RET_ERROR ); - } - if (ret == RET_OK) - { - ZB_BDB().bdb_commissioning_step = ZB_BDB_FINDING_N_BINDING; - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - BDB_COMM_CTX().state = ZB_BDB_COMM_FINDING_AND_BINDING_TARGET; - } - - TRACE_MSG(TRACE_ZCL1, "< bdb_finding_binding_target_func ret %hd", (FMT__H, ret)); - - return ret; -} - - -/* Starts EZ-Mode Finding and binding mechanism at the target's endpoint with default time */ -zb_ret_t zb_bdb_finding_binding_target(zb_uint8_t endpoint) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> bdb_finding_binding_target endpoint %hd", (FMT__H, endpoint)); - - /* Check arguments passed */ - if (!ZB_AF_IS_EP_REGISTERED(endpoint)) - { - ret = RET_INVALID_PARAMETER_1; - } - - if (ret == RET_OK) - { - ret = zb_bdb_finding_binding_target_func(endpoint, (zb_uint16_t)ZB_BDB().bdb_commissioning_time); - } - - TRACE_MSG(TRACE_ZCL1, "< bdb_finding_binding_target ret %hd", (FMT__H, ret)); - - return ret; -} - -/* Starts EZ-Mode Finding and binding mechanism at the target's endpoint with time in parameter */ -zb_ret_t zb_bdb_finding_binding_target_ext(zb_uint8_t endpoint, zb_uint16_t commissioning_time_secs) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> bdb_finding_binding_target_ext endpoint %hd commissioning_time_secs %d", (FMT__H_D, endpoint, commissioning_time_secs)); - - /* Check arguments passed */ - if (!ZB_AF_IS_EP_REGISTERED(endpoint)) - { - ret = RET_INVALID_PARAMETER_1; - } - else if (commissioning_time_secs < ZB_BDBC_MIN_COMMISSIONING_TIME_S) - { - ret = RET_INVALID_PARAMETER_2; - } - - if (ret == RET_OK) - { - ret = zb_bdb_finding_binding_target_func(endpoint, commissioning_time_secs); - } - - TRACE_MSG(TRACE_ZCL1, "< bdb_finding_binding_target_ext ret 0x%lx", (FMT__L, ret)); - - return ret; -} - -static void finding_binding_finished_context_update(void) -{ - BDB_COMM_CTX().state = ZB_BDB_COMM_IDLE; - ZB_BDB().bdb_commissioning_step = ZB_BDB_COMMISSIONING_STOP; - TRACE_MSG(TRACE_ZDO3, "ZB_BDB_COMMISSIONING_STOP", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_SUCCESS; -} - -static void raise_target_finished_cancelled_signal(zb_uint8_t param, zb_uint16_t ep) -{ - zb_uint8_t *ptr; - TRACE_MSG(TRACE_ZDO1, "F&B target cancelled calling zb_zdo_startup_complete", (FMT__0)); - ptr = zb_app_signal_pack_with_detailed_status(param, ZB_BDB_SIGNAL_FINDING_AND_BINDING_TARGET_FINISHED, - RET_CANCELLED, sizeof(zb_uint8_t)); - *ptr = (zb_uint8_t)ep; - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - TRACE_MSG(TRACE_ZDO1, "F&B target cancelled calling zb_zdo_startup_complete", (FMT__0)); -} - -void zb_bdb_finding_binding_target_cancel(void) -{ - zb_uint8_t ep_id = 0; - - TRACE_MSG(TRACE_ZCL1, "> zb_bdb_finding_binding_target_cancel", (FMT__0)); - - ZB_SCHEDULE_ALARM_CANCEL(zb_bdb_finding_binding_target_alarm, ZB_ALARM_ALL_CB); - - do - { - ep_id = zb_zcl_get_next_target_endpoint( - ep_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, ZB_ZCL_CLUSTER_SERVER_ROLE, get_profile_id_by_endpoint(ep_id)); - if (ep_id != 0U) - { - zb_zcl_stop_identifying(ep_id); - } - } while (ep_id != 0U); - - /* put ZB_ZCL_BROADCAST_ENDPOINT(0xFF) value to endpoint in this case */ - zb_buf_get_out_delayed_ext(raise_target_finished_cancelled_signal, ZB_ZCL_BROADCAST_ENDPOINT, sizeof(zb_uint16_t)); - - finding_binding_finished_context_update(); - TRACE_MSG(TRACE_ZCL1, "< zb_bdb_finding_binding_target_cancel", (FMT__0)); -} - -void zb_bdb_finding_binding_target_alarm_ep(zb_uint8_t param, zb_uint16_t endpoint) -{ - zb_uint8_t *ptr; - TRACE_MSG(TRACE_ZCL1, "> zb_bdb_finding_binding_target_alarm_ep param %hd endpoint %d", (FMT__H_D, param, endpoint)); - - finding_binding_target_cancel_ep_internal((zb_uint8_t)endpoint, ZB_TRUE); - - TRACE_MSG(TRACE_ZDO1, "F&B target done calling zb_zdo_startup_complete", (FMT__0)); - ptr = zb_app_signal_pack(param, ZB_BDB_SIGNAL_FINDING_AND_BINDING_TARGET_FINISHED, RET_OK, sizeof(zb_uint8_t)); - *ptr = (zb_uint8_t)endpoint; - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_finding_binding_target_alarm_ep", (FMT__0)); -} - -static void finding_binding_target_cancel_ep_internal(zb_uint8_t endpoint, zb_bool_t is_timeout_expired) -{ - zb_uint8_t ep_id = 0; - zb_bool_t is_identifying = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, "> finding_binding_target_cancel_ep_internal endpoint %hd is timeout expired %hd", (FMT__H_H, endpoint, ZB_B2U(is_timeout_expired))); - - /* Let's treat 0xFF endpoint ID as cancel all targets */ - if (endpoint == ZB_ZCL_BROADCAST_ENDPOINT) - { - zb_bdb_finding_binding_target_cancel(); - return; - } - - ZB_SCHEDULE_ALARM_CANCEL(zb_bdb_finding_binding_target_alarm, endpoint); - zb_zcl_stop_identifying(endpoint); - - if (!is_timeout_expired) - { - zb_buf_get_out_delayed_ext(raise_target_finished_cancelled_signal, (zb_uint16_t)endpoint, sizeof(zb_uint16_t)); - } - - /* After Identifying on that EP is stopped we need to iterate through all other endpoints having Identifying cluster server checking if that endpoint is now in identifying mode. - * If no more endpoints are identifying now, update BDB commissioning step, stage, status, as in zb_bdb_finding_binding_target_cancel(). - */ - do - { - ep_id = zb_zcl_get_next_target_endpoint( - ep_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, ZB_ZCL_CLUSTER_SERVER_ROLE, get_profile_id_by_endpoint(endpoint)); - if (ep_id == endpoint) - { - continue; - } - else if (ep_id != 0U) - { - if (zb_zcl_is_identifying(ep_id)) - { - is_identifying = ZB_TRUE; - } - } - } - while(ep_id != 0U && !is_identifying); - - if (!is_identifying) - { - finding_binding_finished_context_update(); - } - - TRACE_MSG(TRACE_ZCL1, "< finding_binding_target_cancel_ep_internal", (FMT__0)); -} - -void zb_bdb_finding_binding_target_cancel_ep(zb_uint8_t endpoint) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_bdb_finding_binding_target_cancel_ep endpoint %hd ", (FMT__H, endpoint)); - - finding_binding_target_cancel_ep_internal(endpoint, ZB_FALSE); - - TRACE_MSG(TRACE_ZCL1, "< zb_bdb_finding_binding_target_cancel_ep", (FMT__0)); -} - -void zb_bdb_finding_binding_target_alarm(zb_uint8_t endpoint) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_bdb_finding_binding_target_alarm endpoint %hd", (FMT__H, endpoint)); - - zb_buf_get_out_delayed_ext(zb_bdb_finding_binding_target_alarm_ep, (zb_uint16_t)endpoint, sizeof(zb_uint16_t)); - - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_finding_binding_target_alarm", (FMT__0)); -} - - -/* -**************************************** -F & B Initiator -*/ - -static void zb_bdb_finding_binding_initiator_stop( - zb_uint8_t param, zb_uint16_t status) -{ - zb_zdo_signal_fb_initiator_finished_params_t *signal_params; - - finding_binding_finished_context_update(); - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED; - - signal_params = (zb_zdo_signal_fb_initiator_finished_params_t *)zb_app_signal_pack( - param, - ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED, - (ZB_BDB_STATUS_SUCCESS == ZB_BDB().bdb_commissioning_status) ? RET_OK : RET_ERROR, - 0 /* data_size */); - - if (signal_params) - { - zb_buf_set_status(param, RET_OK); - signal_params->status = (zb_zdo_fb_initiator_finished_status_t) status; - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - } -} - -void zb_bdb_finding_binding_initiator_cancel(void) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_bdb_finding_binding_initiator_cancel", (FMT__0)); - - ZB_SCHEDULE_ALARM_CANCEL(zb_bdb_finding_binding_initiator_alarm, ZB_ALARM_ALL_CB); - zb_buf_get_out_delayed_ext(zb_bdb_finding_binding_initiator_stop, ZB_ZDO_FB_INITIATOR_STATUS_CANCEL, 0); - - TRACE_MSG(TRACE_ZCL1, "< zb_bdb_finding_binding_initiator_cancel", (FMT__0)); -} - -/* Alarm when finding & binding is invoked but no identify query response got */ -void zb_bdb_finding_binding_initiator_alarm(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_bdb_finding_binding_initiator_alarm %hd", (FMT__H, param)); - - ZVUNUSED(param); - - if (ZB_ZDP_STATUS_SUCCESS == BDB_COMM_CTX().status) - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_SUCCESS; - zb_buf_get_out_delayed_ext(zb_bdb_finding_binding_initiator_stop, ZB_ZDO_FB_INITIATOR_STATUS_SUCCESS, 0); - } - else if (ZB_ZDP_STATUS_TABLE_FULL == BDB_COMM_CTX().status) - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_BINDING_TABLE_FULL; - zb_buf_get_out_delayed_ext(zb_bdb_finding_binding_initiator_stop, ZB_ZDO_FB_INITIATOR_STATUS_ERROR, 0); - } - else - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NO_IDENTIFY_QUERY_RESPONSE; - zb_buf_get_out_delayed_ext(zb_bdb_finding_binding_initiator_stop, ZB_ZDO_FB_INITIATOR_STATUS_ALARM, 0); - } - - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_finding_binding_initiator_alarm", (FMT__0)); -} - -/** - Find record in the F&B respondents table. - Return respondent or NULL if not found. -*/ -static zb_ret_t zb_bdb_find_respondent(zb_uint16_t nwk_addr, zb_uint8_t *resp_index) -{ - zb_ret_t ret = RET_NOT_FOUND; - zb_uindex_t i; - zb_address_ieee_ref_t addr_ref = 0; - - TRACE_MSG(TRACE_ZCL1, "> zb_bdb_find_respondent by addr %d", (FMT__D, nwk_addr)); - - if (zb_address_by_short(nwk_addr, ZB_FALSE, ZB_FALSE, &addr_ref) == RET_OK) - { - for (i = 0 ; i < BDB_COMM_CTX().respondent_number ; i++) - { - if (BDB_COMM_CTX().respondent[i].addr_ref == addr_ref) - { - *resp_index = i; - ret = RET_OK; - TRACE_MSG(TRACE_ZCL2, "Found nwk_addr in the Respondents", (FMT__0)); - break; - } - } - } - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_find_respondent %d", (FMT__D, ret)); - return ret; -} - -static zb_ret_t zb_bdb_find_respondent_by_bind_confirm_buf(zb_bufid_t confirm_buf, - zb_uint8_t *resp_index) -{ - zb_ret_t ret = RET_NOT_FOUND; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL1, ">> zb_bdb_find_respondent_by_bind_confirm_buf, buf %d", - (FMT__D, confirm_buf)); - - ZB_ASSERT(confirm_buf != ZB_BUF_INVALID); - - for (i = 0; i < BDB_COMM_CTX().respondent_number; i++) - { - if (BDB_COMM_CTX().respondent[i].curr_bind_req_buf == confirm_buf) - { - *resp_index = i; - ret = RET_OK; - TRACE_MSG(TRACE_ZCL2, "found confirm_buf in the respondents, index %d", (FMT__D, i)); - break; - } - } - - TRACE_MSG(TRACE_ZCL1, ">> zb_bdb_find_respondent_by_bind_confirm_buf, ret %d", - (FMT__D, ret)); - return ret; -} - -static void process_next_binding_for_respondent(zb_bdb_comm_respondent_info_t *respondent, - zb_bufid_t param); - - -static void handle_bind_confirm(zb_uint8_t param) -{ - zb_apsme_binding_req_t *aps_bind_req = ZB_BUF_GET_PARAM(param, zb_apsme_binding_req_t); - zb_bdb_comm_respondent_info_t *respondent = NULL; - zb_uint8_t resp_idx; - zb_ret_t status; - - TRACE_MSG(TRACE_ZCL2, ">> handle_bind_confirm, param %d", (FMT__D, param)); - - if (zb_bdb_find_respondent_by_bind_confirm_buf(param, &resp_idx) == RET_OK) - { - respondent = &BDB_COMM_CTX().respondent[resp_idx]; - } - - ZB_ASSERT(respondent); - - if (!respondent) - { - TRACE_MSG(TRACE_ERROR, "got bind_confirm (param %d), but didn't send a request", - (FMT__D, param)); - } - else - { - respondent->curr_bind_req_buf = ZB_BUF_INVALID; - - status = zb_buf_get_status(param); - - if (status == RET_OK) - { - BDB_COMM_CTX().status = ZB_ZDP_STATUS_SUCCESS; - } - else - { - /* If status is not success set status ZB_ZDP_STATUS_TABLE_FULL even - * for other retcodes and indicate with ZB_ZDO_FB_INITIATOR_STATUS_ERROR - * by zb_bdb_finding_binding_initiator_alarm() */ - BDB_COMM_CTX().status = ZB_ZDP_STATUS_TABLE_FULL; - } - - /* [AV] - use binding progress cb to report about binding results; - don't break and cry if only one bind request has failed - keep on processing */ - if (status == RET_OK) - { - TRACE_MSG(TRACE_ZCL2, "bind success", (FMT__0)); - BDB_COMM_CTX().was_bound = ZB_TRUE; - status = ZB_BDB_COMM_BIND_SUCCESS; - } - else - { - TRACE_MSG(TRACE_ZCL2, "bind fail status was %d", (FMT__D, status)); - status = ZB_BDB_COMM_BIND_FAIL; - } - - { - zb_ieee_addr_t resp_ext_addr; - - zb_address_ieee_by_ref(resp_ext_addr, respondent->addr_ref); - if (BDB_COMM_CTX().finding_binding_progress_cb) - { - /* Report about binding results */ - BDB_COMM_CTX().finding_binding_progress_cb( - status, - resp_ext_addr, - respondent->ep_list[respondent->eps_checked], - aps_bind_req->clusterid); - } - } - - process_next_binding_for_respondent(respondent, param); - } - - TRACE_MSG(TRACE_ZCL2, "<< handle_bind_confirm", (FMT__0)); -} - -static zb_ret_t bind_respondent_cluster(zb_bdb_comm_respondent_info_t *respondent, - zb_uint8_t ep, - zb_uint16_t cluster, - zb_bufid_t param) -{ - zb_apsme_binding_req_t *aps_bind_req = ZB_BUF_GET_PARAM(param, zb_apsme_binding_req_t); - zb_ret_t status; - - TRACE_MSG(TRACE_ZCL2, ">> bind_respondent_cluster, respondent %p, ep %d, cluster 0x%x, param %d", - (FMT__P_D_D_D, respondent, ep, cluster, param)); - - - /* If finding_binding_progress_cb == NULL, we are Simple device and must - * bound anything that stirs. - * If we are still Simple device but have that collback, bind behavior is - * under application control. - */ - if (BDB_COMM_CTX().finding_binding_progress_cb != NULL) - { - zb_ieee_addr_t resp_ext_addr; - TRACE_MSG(TRACE_ZCL2, "finding_binding_start_cb %p", - (FMT__P, BDB_COMM_CTX().finding_binding_progress_cb)); - - zb_address_ieee_by_ref(resp_ext_addr, respondent->addr_ref); - /* Callback can return RET_IGNORE to skip bind to that cluster. */ - status = BDB_COMM_CTX().finding_binding_progress_cb( - ZB_BDB_COMM_BIND_ASK_USER, - resp_ext_addr, - respondent->ep_list[respondent->eps_checked], - cluster) == ZB_TRUE ? RET_OK : RET_IGNORE; - } - else - { - status = RET_OK; - } - - /* [AV] Skip binding routines if bind was rejected by user */ - if (status == RET_IGNORE) - { - TRACE_MSG(TRACE_ZCL2, "bind rejected by the user", (FMT__0)); - } - - if (status == RET_OK) - { - ZB_BZERO(aps_bind_req, sizeof(zb_apsme_binding_req_t)); - - zb_get_long_address(aps_bind_req->src_addr); - aps_bind_req->src_endpoint = BDB_COMM_CTX().ep; - aps_bind_req->clusterid = cluster; - if (ZB_BDB().bdb_commissioning_group_id == 0xffff) - { - zb_address_ieee_by_ref(aps_bind_req->dst_addr.addr_long, respondent->addr_ref); - aps_bind_req->addr_mode = ZB_APS_ADDR_MODE_64_ENDP_PRESENT; - aps_bind_req->dst_endpoint = respondent->ep_list[respondent->eps_checked]; - TRACE_MSG(TRACE_ZCL2, "F&B: Unicast bind src ep %hd cluster 0x%x dst " TRACE_FORMAT_64 " ep %hd", - (FMT__H_D_A_H, aps_bind_req->src_endpoint, aps_bind_req->clusterid, TRACE_ARG_64(aps_bind_req->dst_addr.addr_long), aps_bind_req->dst_endpoint)); - } - else - { - aps_bind_req->addr_mode = ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; - aps_bind_req->dst_addr.addr_short = ZB_BDB().bdb_commissioning_group_id; - aps_bind_req->dst_endpoint = respondent->ep_list[respondent->eps_checked]; - TRACE_MSG(TRACE_ZCL2, "F&B: Group bind src ep %hd cluster 0x%x dst group %d", - (FMT__H_D_D, aps_bind_req->src_endpoint, aps_bind_req->clusterid, aps_bind_req->dst_addr.addr_short)); - } - - respondent->curr_bind_req_buf = param; - aps_bind_req->confirm_cb = handle_bind_confirm; -#ifdef SNCP_MODE - aps_bind_req->remote_bind = ZB_B2U(ZB_TRUE); -#endif - zb_apsme_bind_request(param); - } - - TRACE_MSG(TRACE_ZCL2, "<< bind_respondent_cluster status %hd", (FMT__H, status)); - - return status; -} - -static void process_binding_for_respondent(zb_bdb_comm_respondent_info_t *respondent, - zb_bufid_t param); - -static void process_next_binding_for_respondent(zb_bdb_comm_respondent_info_t *respondent, - zb_bufid_t param) -{ - respondent->curr_cluster_idx++; - process_binding_for_respondent(respondent, param); -} - -static void process_binding_for_respondent(zb_bdb_comm_respondent_info_t *respondent, - zb_bufid_t param) -{ - zb_zdo_simple_desc_resp_t *resp = NULL; - zb_uint8_t in_cluster_cnt; - zb_uint8_t out_cluster_cnt; - zb_ret_t bind_status = RET_OK; - - TRACE_MSG(TRACE_ZCL2, ">> process_binding_for_respondent, respondent %p, param %d", - (FMT__P_D, respondent, param)); - - ZB_ASSERT(respondent->simple_desc_resp_buf); - resp = (zb_zdo_simple_desc_resp_t*)zb_buf_begin(respondent->simple_desc_resp_buf); - in_cluster_cnt = resp->simple_desc.app_input_cluster_count; - out_cluster_cnt = resp->simple_desc.app_output_cluster_count; - TRACE_MSG(TRACE_ZCL3, "in cluster cnt %d out cluster cnt %d", (FMT__D_D, in_cluster_cnt, out_cluster_cnt)); - - while (respondent->curr_cluster_idx < in_cluster_cnt + out_cluster_cnt) - { - zb_uint8_t role = (respondent->curr_cluster_idx >= in_cluster_cnt ? - ZB_ZCL_CLUSTER_CLIENT_ROLE : ZB_ZCL_CLUSTER_SERVER_ROLE); - - if (zb_bdb_find_cluster_match(resp->simple_desc.app_cluster_list[respondent->curr_cluster_idx], - role)) - { - TRACE_MSG(TRACE_ZCL2, "found cluster match clusterid %d", - (FMT__D, resp->simple_desc.app_cluster_list[respondent->curr_cluster_idx])); - - bind_status = bind_respondent_cluster(respondent, - respondent->ep_list[respondent->eps_checked], - resp->simple_desc.app_cluster_list[respondent->curr_cluster_idx], - param); - break; - } - else - { - respondent->curr_cluster_idx++; - } - } - - if (respondent->curr_cluster_idx == in_cluster_cnt + out_cluster_cnt) - { - TRACE_MSG(TRACE_ZCL3, "check simple desc finished", (FMT__0)); - if (BDB_COMM_CTX().was_bound - && ZB_BDB().bdb_commissioning_group_id != 0xffff) - { - zb_uint16_t resp_short_addr; - - zb_address_short_by_ref(&resp_short_addr, respondent->addr_ref); - TRACE_MSG(TRACE_ZCL3, "Sending ADD_GROUP_REQ", (FMT__0)); - ZB_ZCL_GROUPS_SEND_ADD_GROUP_REQ( - param, resp_short_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - respondent->ep_list[respondent->eps_checked], - BDB_COMM_CTX().ep, ZB_AF_HA_PROFILE_ID, ZB_ZCL_ENABLE_DEFAULT_RESPONSE, NULL, - ZB_BDB().bdb_commissioning_group_id); - } - else - { - zb_buf_free(param); - } - - respondent->eps_checked++; - ZB_SCHEDULE_CALLBACK(zb_bdb_active_eps_check_cb, respondent->simple_desc_resp_buf); - respondent->simple_desc_resp_buf = 0; - } - else - { - if (bind_status != RET_OK) - { - process_next_binding_for_respondent(respondent, param); - } - } - - TRACE_MSG(TRACE_ZCL2, "<< process_binding_for_respondent", (FMT__0)); -} - -/** - Checks simple descriptor received from respondent and - performs binding if cluster match is found -*/ -void zb_bdb_simple_desc_check_cb(zb_uint8_t param, zb_uint16_t param2) -{ - zb_zdo_simple_desc_resp_t *resp = (zb_zdo_simple_desc_resp_t*)zb_buf_begin(param2); - zb_bdb_comm_respondent_info_t *respondent = NULL; - zb_uint8_t resp_idx; - - TRACE_MSG(TRACE_ZCL2, "> zb_bdb_simple_desc_check_cb %hd %d", (FMT__H_D, param, param2)); - - - /*Find record in the F&B identify table */ - /* Check profile id matching for incoming simple_desc before processing it - * (required by test FB-PRE-TC-03B) - */ - if (zb_zcl_is_target_endpoint(BDB_COMM_CTX().ep_desc, resp->simple_desc.app_profile_id)) - { - if (zb_bdb_find_respondent(resp->hdr.nwk_addr, &resp_idx) == RET_OK) - { - respondent = &BDB_COMM_CTX().respondent[resp_idx]; - } - - if (respondent) - { - respondent->curr_cluster_idx = 0; - respondent->simple_desc_resp_buf = param2; - param2 = 0; - process_binding_for_respondent(respondent, param); - param = 0; - } - } - else - { - TRACE_MSG(TRACE_ZCL3, "Simple_desc ignored due to profile_id mismatch", (FMT__0)); - /* Try to skip this descriptor. */ - if (zb_bdb_find_respondent(resp->hdr.nwk_addr, &resp_idx) == RET_OK) - { - respondent = &BDB_COMM_CTX().respondent[resp_idx]; - respondent->eps_checked++; - ZB_SCHEDULE_CALLBACK(zb_bdb_active_eps_check_cb, param2); - param2 = 0; - } - } - - if (param) - { - zb_buf_free(param); - } - if (param2) - { - zb_buf_free(param2); - } - - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_simple_desc_check_cb", (FMT__0)); -} - - -/* Checks whether cluster matches on the initiator's endpoint */ -zb_bool_t zb_bdb_find_cluster_match(zb_uint16_t cluster_id, zb_uint8_t role) -{ - zb_bool_t ret = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, "> zb_bdb_find_cluster_match clusterId %d role %hd", (FMT__D_H, cluster_id, role)); - - if (BDB_COMM_CTX().ep_desc!=NULL) - { - zb_uint8_t cluster_count = BDB_COMM_CTX().ep_desc->cluster_count; - struct zb_zcl_cluster_desc_s *cluster_desc_list = - BDB_COMM_CTX().ep_desc->cluster_desc_list; - zb_int16_t i; - - TRACE_MSG(TRACE_ZCL3, "cluster_id %d local cluster count %hd", (FMT__D_H, cluster_id, cluster_count)); - - for (i=0; i < cluster_count; i++) - { - TRACE_MSG(TRACE_ZCL3, "cluster_id[%d] %d role %hd role_mask %hd", (FMT__D_D_H_H, i, cluster_desc_list[i].cluster_id, role, cluster_desc_list[i].role_mask)); - if (cluster_id == cluster_desc_list[i].cluster_id) - { - if (role != cluster_desc_list[i].role_mask - /* || role == ZB_ZCL_CLUSTER_MIXED_ROLE */ - /* || cluster_desc_list[i].role_mask == ZB_ZCL_CLUSTER_MIXED_ROLE */) - { - TRACE_MSG(TRACE_ZCL3, "Match!", (FMT__0)); - ret = ZB_TRUE; - break; - } - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_bdb_find_cluster_match ret %hd", (FMT__H, ret)); - return ret; -} - -/** - Processes simple descriptor response during EZ Mode commissioning - (finding & binding) -*/ -void zb_bdb_process_simple_desc_res(zb_uint8_t param) -{ - zb_int16_t status = RET_OK; - - zb_zdo_simple_desc_resp_t *resp = (zb_zdo_simple_desc_resp_t*)zb_buf_begin(param); - zb_bdb_comm_respondent_info_t *respondent = NULL; - zb_uint8_t resp_idx; - - TRACE_MSG(TRACE_ZCL2, "> zb_bdb_process_simple_desc_res %hd", (FMT__H, param)); - - status = ( (BDB_COMM_CTX().state == ZB_BDB_COMM_FINDING_AND_BINDING) ? - RET_OK : RET_CANCELLED ); - - if (status == RET_OK) - { - status = resp->hdr.status; - } - - if (status == RET_OK) - { - zb_buf_get_out_delayed_ext(zb_bdb_simple_desc_check_cb, param, 0); - } - else - { - /* Error with this endpoint. Continue f&b process with further endpoints. */ - if (zb_bdb_find_respondent(resp->hdr.nwk_addr, &resp_idx) == RET_OK) - { - respondent = &BDB_COMM_CTX().respondent[resp_idx]; - respondent->eps_checked++; - ZB_SCHEDULE_CALLBACK(zb_bdb_active_eps_check_cb, param); - } - } - - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_process_simple_desc_res", (FMT__0)); -} - -/* - Sends SimpleDescriptor request for all the active endpoints - of the respondent -*/ -void zb_bdb_active_eps_check_cb(zb_uint8_t param) -{ - zb_bdb_comm_respondent_info_t *respondent = NULL; - /* TRICKY HACK: in some cases there is zb_zdo_simple_desc_resp_t instead of zb_zdo_ep_resp_t. - And code below works only because nwk_addr in zb_zdo_ep_resp_t has the same offset - as hdr.nwk_addr in zb_zdo_simple_desc_resp_t... */ - zb_zdo_ep_resp_t *resp = (zb_zdo_ep_resp_t*)zb_buf_begin(param); - zb_uint8_t resp_idx; - zb_uindex_t respondents_to_move; - - TRACE_MSG(TRACE_ZCL2, "> zb_bdb_process_active_ep_check_cb %hd", (FMT__H, param)); - - /*Find record in the F&B identify table by address */ - if (zb_bdb_find_respondent(resp->nwk_addr, &resp_idx) == RET_OK) - { - respondent = &BDB_COMM_CTX().respondent[resp_idx]; - } - - if (respondent) - { - if (respondent->eps_checked < respondent->ep_cnt) - { - zb_zdo_simple_desc_req_t * req; - zb_uint8_t ep = respondent->ep_list[respondent->eps_checked]; - zb_uint16_t resp_short_addr; - - TRACE_MSG(TRACE_ZCL3, "processing ep %hd", (FMT__H, ep)); - - req = zb_buf_initial_alloc(param, sizeof(zb_zdo_simple_desc_req_t)); - ZB_BZERO(req, sizeof(zb_zdo_simple_desc_req_t)); - - zb_address_short_by_ref(&resp_short_addr, respondent->addr_ref); - req->nwk_addr = resp_short_addr; - req->endpoint = ep; - if (zb_zdo_simple_desc_req(param, zb_bdb_process_simple_desc_res) == ZB_ZDO_INVALID_TSN) - { - zb_bdb_error_handle_buf(ZB_ZDP_STATUS_INSUFFICIENT_SPACE, param); - } - - param = 0; - } - else - { - respondent->addr_ref = 0xFF; - - if (resp_idx < ZB_ARRAY_SIZE(BDB_COMM_CTX().respondent) - 1) - { - respondents_to_move = ZB_ARRAY_SIZE(BDB_COMM_CTX().respondent) - resp_idx - 1; - - ZB_MEMMOVE(&BDB_COMM_CTX().respondent[resp_idx], - &BDB_COMM_CTX().respondent[resp_idx + 1], - sizeof(BDB_COMM_CTX().respondent[0]) * respondents_to_move); - } - - BDB_COMM_CTX().respondent_number--; - - if (0 == BDB_COMM_CTX().respondent_number) - { - /* [AV] User already knows, whether binding was performed or not. Just report f&b finished OK - Now it's the only point where EZ-Mode finishes successfully */ - TRACE_MSG(TRACE_ZCL1, "All endpoints are checked. Finding and binding finished", (FMT__0)); - - if (BDB_COMM_CTX().status == ZB_ZDP_STATUS_TABLE_FULL) - { - TRACE_MSG(TRACE_ZCL1, "Binding table is full", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_BINDING_TABLE_FULL; - } - else - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_SUCCESS; - } - } - } - } /* if (respondent) */ - - if (param) - { - zb_buf_free(param); - } - - - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_process_active_ep_check_cb", (FMT__0)); -} - -/* - add ep to respondent and go on -*/ -static void zb_bdb_add_ep_to_respondent(zb_uint8_t param, zb_uint16_t nwk_addr, zb_uint8_t ep) -{ - zb_ret_t status = RET_OK; - zb_zdo_ep_resp_t *resp; - zb_bdb_comm_respondent_info_t *respondent=NULL; - zb_uint8_t resp_idx = 0xff; - zb_bool_t is_new_respondent = ZB_TRUE; - - TRACE_MSG(TRACE_ZCL2, "> zb_bdb_add_ep_to_respondent addr %d ep %hd", (FMT__D_H, nwk_addr, ep)); - status = ( (BDB_COMM_CTX().state == ZB_BDB_COMM_FINDING_AND_BINDING) ? - RET_OK : RET_CANCELLED ); - if(status== RET_OK) - { - if (zb_bdb_find_respondent(nwk_addr, &resp_idx) != RET_OK) - { - if (BDB_COMM_CTX().respondent_number < ZB_ARRAY_SIZE(BDB_COMM_CTX().respondent)) - { - resp_idx = BDB_COMM_CTX().respondent_number; - TRACE_MSG(TRACE_ZCL1, "add new respondent 0x%x (idx %hd)", (FMT__D_H, nwk_addr, resp_idx)); - BDB_COMM_CTX().respondent_number++; - } - else - { - TRACE_MSG(TRACE_ZCL1, "Out of space for Identify Query resp devices", (FMT__0)); - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "respondent 0x%x (idx %hd) is already in the list, continue...", - (FMT__D_H, nwk_addr, resp_idx)); - is_new_respondent = ZB_FALSE; - } - } - if (resp_idx != 0xff) - { - zb_address_ieee_ref_t addr_ref; - - respondent = &BDB_COMM_CTX().respondent[resp_idx]; - - if (is_new_respondent) - { - status = zb_address_by_short(nwk_addr, ZB_FALSE, ZB_FALSE, &addr_ref); - - if (status == RET_OK) - { - respondent->addr_ref = addr_ref; - respondent->ep_cnt = 0; - respondent->eps_checked = 0; - } - } - - if (status == RET_OK) - { - if (respondent->ep_cnt < ZB_BDB_COMM_ACTIVE_ENDP_LIST_LEN) - { - respondent->ep_list[respondent->ep_cnt] = ep; - ++(respondent->ep_cnt); - } - else - { - TRACE_MSG(TRACE_ERROR, "Too many active endpoints for EZ-Mode to serve %hd, drop this ep", - (FMT__H, respondent->ep_cnt)); - } - } - - if (status == RET_OK && is_new_respondent) - { - resp = zb_buf_initial_alloc(param, sizeof(zb_zdo_ep_resp_t)); - ZB_BZERO(resp, sizeof(zb_zdo_ep_resp_t)); - resp->nwk_addr = nwk_addr; - resp->status = 0; - resp->ep_count = respondent->ep_cnt; - TRACE_MSG(TRACE_ERROR, "start zb_bdb_active_eps_check_cb", (FMT__0)); - ZB_SCHEDULE_CALLBACK(zb_bdb_active_eps_check_cb, param); - } - else if (status == RET_OK) - { - /* Do not need to start anything or indicate the error, free the buf */ - zb_buf_free(param); - } - else - { - /*zb_bdb_error_handle_param(status, param);*/ - zb_bdb_error_handle_buf(status, param); - } - } - else - { - /*zb_bdb_error_handle_param(status, param);*/ - zb_bdb_error_handle_buf(status, param); - } - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_add_ep_to_respondent", (FMT__0)); -} - -/* - Processes active endpoints response during finding & binding -*/ -void zb_bdb_process_active_eps_res(zb_uint8_t param) -{ - zb_int16_t status = RET_OK; - zb_zdo_ep_resp_t *resp = (zb_zdo_ep_resp_t*)zb_buf_begin(param); - zb_uint8_t *ep_list = (zb_uint8_t *)resp + sizeof(zb_zdo_ep_resp_t); - zb_bdb_comm_respondent_info_t *respondent=NULL; - zb_uint8_t resp_idx; - - TRACE_MSG(TRACE_ZCL2, "> zb_bdb_process_active_eps_res from addr %d %hd", (FMT__D_H, resp->nwk_addr, param)); - - - status = ( (BDB_COMM_CTX().state == ZB_BDB_COMM_FINDING_AND_BINDING) ? - RET_OK : RET_CANCELLED ); - - /*Find record in the F&B identify table */ - if ((status == RET_OK) && (zb_bdb_find_respondent(resp->nwk_addr, &resp_idx) == RET_OK)) - { - zb_uindex_t i = 0; - zb_uint16_t resp_short_addr; - respondent = &BDB_COMM_CTX().respondent[resp_idx]; - zb_address_short_by_ref(&resp_short_addr, respondent->addr_ref); - TRACE_MSG(TRACE_ZCL3, "Active endpoints response got from addr %d ep_cnt %hd", - (FMT__H_D, resp_short_addr, resp->ep_count)); - - respondent->ep_cnt = resp->ep_count; - respondent->eps_checked = 0; - - if (respondent->ep_cnt > ZB_BDB_COMM_ACTIVE_ENDP_LIST_LEN) - { - TRACE_MSG(TRACE_ERROR, "Too many active endpoints for EZ-Mode to serve %hd", - (FMT__H, respondent->ep_cnt)); - TRACE_MSG(TRACE_ERROR, "Serve first %hd endpoints", - (FMT__H, ZB_BDB_COMM_ACTIVE_ENDP_LIST_LEN)); - respondent->ep_cnt = ZB_BDB_COMM_ACTIVE_ENDP_LIST_LEN; - } - /* Save active endpoints list to context to reuse buffer */ - for (; i < respondent->ep_cnt; i++) - { - respondent->ep_list[i] = ep_list[i]; - } - ZB_SCHEDULE_CALLBACK(zb_bdb_active_eps_check_cb, param); - } - else - { - /*zb_bdb_error_handle_param(status, param);*/ - zb_bdb_error_handle_buf(status, param); - } - - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_process_active_eps_res", (FMT__0)); -} - -/* - Processes identify query response during EZ Mode commissioning - (finding & binding) -*/ -void zb_bdb_process_identify_query_res(zb_uint8_t param) -{ - zb_int16_t status = RET_OK; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL2, "> zb_bdb_process_identify_query_res %hd", (FMT__H, param)); - - status = ( (BDB_COMM_CTX().state == ZB_BDB_COMM_FINDING_AND_BINDING) ? - RET_OK : RET_CANCELLED ); - - /* It is not data confirm, so seems like we should not check u.hdr.status. - TODO: Check other cases - sometimes we are in data confirm, sometimes - in data indication! */ - - if (status == RET_OK) - { - zb_ieee_addr_t ext_addr; - - if (BDB_COMM_CTX().status == RET_NOT_FOUND) - { - BDB_COMM_CTX().status = RET_OK; - } - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - TRACE_MSG(TRACE_ZCL2, "Identify query response got from addr 0x%x", - (FMT__D, cmd_info.addr_data.common_data.source.u.short_addr)); - - if (zb_address_ieee_by_short(cmd_info.addr_data.common_data.source.u.short_addr, ext_addr) != RET_OK -#ifdef ZB_CERTIFICATION_HACKS - /* We probably know ext address, but tests like FB-PRE-TC-01A require ieee_addr_req */ - || ZB_CERT_HACKS().force_ext_addr_req -#endif - ) - { - /* All we need in this buffer is respondent_addr which we know - * already. So reuse it for addr_req. */ - zb_zdo_ieee_addr_req_param_t *req; - req = ZB_BUF_GET_PARAM(param, zb_zdo_ieee_addr_req_param_t); - req->nwk_addr = cmd_info.addr_data.common_data.source.u.short_addr; - req->dst_addr = req->nwk_addr; - req->start_index = 0; - req->request_type = 0; /* 0x00 Single device response */ - TRACE_MSG(TRACE_ZCL2, "Have no ext address for short 0x%x. Sending ieee_addr_req.", - (FMT__D, cmd_info.addr_data.common_data.source.u.short_addr)); - if (zb_zdo_ieee_addr_req(param, zb_bdb_process_ext_addr_resp) == ZB_ZDO_INVALID_TSN) - { - zb_bdb_error_handle_buf(ZB_ZDP_STATUS_INSUFFICIENT_SPACE, param); - } - } - else - { -#ifdef USE_ACTIVE_EP_REQ - zb_bdb_fb_send_active_ep_req(param, cmd_info.addr_data.common_data.source.u.short_addr); -#else - zb_bdb_add_ep_to_respondent(param, cmd_info.addr_data.common_data.source.u.short_addr, cmd_info.addr_data.common_data.src_endpoint); -#endif - } - } - else - { - TRACE_MSG(TRACE_ZCL2, "Device is not in F&B state, so skip F&B resp, current_state 0x%hx", (FMT__H, BDB_COMM_CTX().state)); - - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_process_identify_query_res", (FMT__0)); -} - - -void zb_bdb_fb_send_active_ep_req(zb_uint8_t param, zb_uint16_t src_addr) -{ - zb_bdb_comm_respondent_info_t *respondent = NULL; - zb_uint8_t resp_idx = 0xff; - - TRACE_MSG(TRACE_ZCL2, "> zb_bdb_fb_send_active_ep_req param %hd src_addr 0x%x", (FMT__H_D, param, src_addr)); - if (zb_bdb_find_respondent(src_addr, &resp_idx) != RET_OK) - { - if (BDB_COMM_CTX().respondent_number < ZB_ARRAY_SIZE(BDB_COMM_CTX().respondent)) - { - resp_idx = BDB_COMM_CTX().respondent_number; - BDB_COMM_CTX().respondent_number++; - } - else - { - TRACE_MSG(TRACE_ZCL1, "Out of space for Identify Query resp devices", (FMT__0)); - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "F&B is already busy dealing with remote %x. Drop this Identify Req Resp", - (FMT__D, src_addr)); - resp_idx = 0xff; - } - if (resp_idx != 0xff) - { - zb_zdo_active_ep_req_t *req; - zb_address_ieee_ref_t addr_ref = 0; - respondent = &BDB_COMM_CTX().respondent[resp_idx]; - - if (zb_address_by_short(src_addr, ZB_FALSE, ZB_FALSE, &addr_ref) == RET_OK) - { - respondent->addr_ref = addr_ref; - req = zb_buf_initial_alloc(param, sizeof(zb_zdo_active_ep_req_t)); - ZB_BZERO(req, sizeof(zb_zdo_active_ep_req_t)); - req->nwk_addr = src_addr; - TRACE_MSG(TRACE_ZCL3, "F&B sending active ep req to 0x%x", (FMT__D, src_addr)); - if (zb_zdo_active_ep_req(param, zb_bdb_process_active_eps_res) == ZB_ZDO_INVALID_TSN) - { - zb_bdb_error_handle_buf(ZB_ZDP_STATUS_INSUFFICIENT_SPACE, param); - } - param = 0; - } - } - - if (param) - { - zb_buf_free(param); - } - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_fb_send_active_ep_req", (FMT__0)); -} - - -void zb_bdb_process_ext_addr_resp(zb_uint8_t param) -{ - zb_address_ieee_ref_t addr_ref; - zb_zdo_nwk_addr_resp_head_t *resp = (zb_zdo_nwk_addr_resp_head_t*)zb_buf_begin(param); - - if (zb_buf_get_status(param) == RET_OK) - { - TRACE_MSG(TRACE_ZCL1, "Got long address " TRACE_FORMAT_64 " for 0x%x", - (FMT__A_D, TRACE_ARG_64(resp->ieee_addr), resp->nwk_addr)); - zb_address_update(resp->ieee_addr, resp->nwk_addr, ZB_FALSE, &addr_ref); - zb_bdb_fb_send_active_ep_req(param, resp->nwk_addr); - } - else - { - TRACE_MSG(TRACE_ZCL1, "Failed to get long address for 0x%x", - (FMT__D, resp->nwk_addr)); - zb_buf_free(param); - } -} - - -/* - Checks whether identify_query request - was sent successfully -*/ -void zb_bdb_identify_query_sent_cb(zb_uint8_t param) -{ - - TRACE_MSG(TRACE_ZCL2, "> zb_bdb_identify_query_sent_cb %hd", (FMT__H, param)); - - if (zb_buf_get_status(param) == RET_OK) - { -//[AM] Do not send Identify Query multiply times. 8.6 Finding & binding procedure for an initiator endpoint. - zb_buf_free(param); - } - else - { - /* Report error - can't send command */ - zb_bdb_error_handle_buf(zb_buf_get_status(param), param); - } - - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_identify_query_sent_cb", (FMT__0)); -} - -/** -Repeat Identify query -*/ - -/** - Sends Identify Query request during - EZ-Mode finding & binding initiator -*/ -void zb_bdb_send_identify_query_req(zb_uint8_t param) -{ - zb_addr_u addr; - TRACE_MSG(TRACE_ZCL2, "> zb_bdb_identify_query_req %hd", (FMT__H, param)); - - addr.addr_short = ZB_NWK_BROADCAST_ALL_DEVICES; - ZB_ZCL_IDENTIFY_SEND_IDENTIFY_QUERY_REQ - (param, addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT/*ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT*/, - ZB_ZCL_BROADCAST_ENDPOINT, BDB_COMM_CTX().ep, get_profile_id_by_endpoint(BDB_COMM_CTX().ep), - ZB_ZCL_DISABLE_DEFAULT_RESPONSE, /* don't need ZCL_STATUS_FAIL in response */ - zb_bdb_identify_query_sent_cb); - /* - wait for response for ZB_NWK_BROADCAST_DELIVERY_TIME() - */ - ZB_SCHEDULE_ALARM(zb_bdb_finding_binding_initiator_alarm, 0, ZB_NWK_EXPIRY_BROADCAST * ZB_TIME_ONE_SECOND); - - TRACE_MSG(TRACE_ZCL2, "< zb_bdb_identify_query_req", (FMT__0)); -} - - -/** - Starts EZ-Mode Finding and binding mechanism at the initiator's endpoint - - Summary: Finding and binding as initiator zb_bdb_finding_binding_initiator() - returns RET_OK if procedure was started successfully, error code otherwise. To report procedure - status, user callback is called. It may be called several times with Success status and only once - with error status. If any error appears, finding and binding stops. - - Finding and binding algorithm: - 1. Check that operation may be started and tx command Identify Query zb_bdb_send_identify_query_req() - Error status is reported with finding_binding_cb() - 2. After command is send, start 180 sec timer zb_bdb_finding_binding_initiator_alarm() - 3*. If timeout fires, call user finding_binding_cb with RET_TIMEOUT status - 4. If Identify query response is received, request active endpoints from the responder - (zb_zdo_active_ep_req(), callback zb_bdb_process_active_eps_res()). - Error status is reported with finding_binding_cb() - Note: the 1st responder device is treated as "target device", others are ignored - 5. On receiving active EP list, store it and start this list analysis: zb_bdb_active_eps_check_cb() - Error status is reported with finding_binding_cb() - 6*. Go through each EP and request simple descriptor for it. If no more EP - call user callback - finding_binding_cb with RET_NO_BOUND_DEVICE status - 7. On receiving simple descriptor response, zb_bdb_process_simple_desc_res() calls - zb_bdb_simple_desc_check_cb() to handle response. - Error status is reported with finding_binding_cb() - 8. zb_bdb_simple_desc_check_cb() checks clusters and performs binding. - Use user callback to ask if binding is needed or not. - Status (error or success) is reported with finding_binding_cb() - 9. After binding is finished, go to p.6, call zb_bdb_active_eps_check_cb() to - check another EP - - - */ -zb_ret_t zb_bdb_finding_binding_initiator(zb_uint8_t endpoint, - zb_bdb_comm_binding_callback_t user_binding_cb) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> zb_bdb_finding_binding_initiator endpoint %d", (FMT__D, endpoint)); - - /* Check endpoint is registered */ - BDB_COMM_CTX().ep_desc = zb_af_get_endpoint_desc(endpoint); - - /* Check endpoint is registered */ - ret = ( BDB_COMM_CTX().ep_desc ? RET_OK : RET_INVALID_PARAMETER_1 ); - - /* Check NWK steering complete */ - if (ret == RET_OK) - { - ret = ( zb_zdo_joined() ? - RET_OK : RET_INVALID_STATE); - } - - /* Check commissioning is not in progress */ - if (ret == RET_OK) - { - ret = ( (BDB_COMM_CTX().state == ZB_BDB_COMM_IDLE && - ZB_BDB().bdb_commissioning_step == ZB_BDB_COMMISSIONING_STOP) ? - RET_OK : RET_BUSY ); - } - - if (ret == RET_OK) - { - ZB_BDB().bdb_commissioning_step = ZB_BDB_FINDING_N_BINDING; - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - - BDB_COMM_CTX().state = ZB_BDB_COMM_FINDING_AND_BINDING; - BDB_COMM_CTX().status = RET_NOT_FOUND; - BDB_COMM_CTX().ep = endpoint; - /* [AV] - No need if f&b finished specific callback: store it in user_cb field */ - BDB_COMM_CTX().finding_binding_progress_cb = user_binding_cb; - BDB_COMM_CTX().respondent_number = 0; - ZB_BZERO(BDB_COMM_CTX().respondent, sizeof(zb_bdb_comm_respondent_info_t) * BDB_MAX_IDENTIFY_QUERY_RESP_NUMBER); - BDB_COMM_CTX().was_bound = ZB_FALSE; - - zb_buf_get_out_delayed(zb_bdb_send_identify_query_req); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_bdb_finding_binding_initiator ret %hd", (FMT__H, ret)); - - return ret; -} - - -/* Pushes error message up via user callback in buffer's header */ -void zb_bdb_error_handle_buf(zb_int16_t status, zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_bdb_error_handle_buf status %d, param %hd", (FMT__D_H, status, param)); - - zb_buf_set_status(param, status); - if (status == ZB_ZDP_STATUS_TABLE_FULL) - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_BINDING_TABLE_FULL; - } - else if (status == RET_OK) - { - TRACE_MSG(TRACE_ZCL1, "F&B finished ok", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_SUCCESS; - } - else - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NO_IDENTIFY_QUERY_RESPONSE; - } - - if (ZB_BDB_COMM_FINDING_AND_BINDING_TARGET == BDB_COMM_CTX().state) - { - zb_app_signal_pack(param, - ZB_BDB_SIGNAL_FINDING_AND_BINDING_TARGET_FINISHED, - ZB_BDB().bdb_commissioning_status, 0); - } - - BDB_COMM_CTX().state = ZB_BDB_COMM_IDLE; - TRACE_MSG(TRACE_ZDO1, "F&B done, status %d, app signal %d. Calling zb_zdo_startup_complete_int status %hd", - (FMT__D_D_H, ZB_BDB().bdb_commissioning_status, ZB_BDB().bdb_application_signal, zb_buf_get_status(param))); - - /* bdb commissioning is finished */ - ZB_BDB().bdb_commissioning_step = ZB_BDB_COMMISSIONING_STOP; - TRACE_MSG(TRACE_ZDO3, "ZB_BDB_COMMISSIONING_STOP", (FMT__0)); - - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - - TRACE_MSG(TRACE_ZCL1, "< zb_bdb_error_handle_buf", (FMT__0)); -} - -#endif /* defined(ZB_BDB_ENABLE_FINDING_BINDING) */ diff --git a/zboss/development/src/commissioning/bdb/zdo_commissioning_bdb.c b/zboss/development/src/commissioning/bdb/zdo_commissioning_bdb.c deleted file mode 100644 index 420cf8d5e3..0000000000 --- a/zboss/development/src/commissioning/bdb/zdo_commissioning_bdb.c +++ /dev/null @@ -1,2957 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: BDD specific commissioning -*/ - -#define ZB_TRACE_FILE_ID 62 - -#include "zb_common.h" -#include "zb_scheduler.h" -#include "zb_bufpool.h" -#include "zb_nwk.h" -#include "zb_nwk_nib.h" -#include "zb_aps.h" -#include "zb_zdo.h" -#include "zb_secur.h" -#include "zb_secur_api.h" -#include "zb_nvram.h" -#include "zb_bdb_internal.h" -#include "zdo_wwah_stubs.h" - -#define BDB_COMMISSIONING_DEBUG - -#if defined ZB_BDB_MODE && !defined BDB_OLD - -zb_bdb_comm_ctx_t g_bdb_ctx; - -void bdb_commissioning_machine(zb_uint8_t param); -static void bdb_initialization_machine(zb_uint8_t param); -static void bdb_touchlink_machine(zb_uint8_t param); -static void bdb_network_steering_machine(zb_uint8_t param); -static void bdb_network_formation_machine(zb_uint8_t param); -#if defined(ZB_BDB_ENABLE_FINDING_BINDING) -static void bdb_finding_n_binding_machine(zb_uint8_t param); -#endif -void bdb_initialization_procedure(zb_uint8_t param); -static void bdb_precomm_rejoin_over_all_channels(zb_uint8_t param, zb_uint16_t secure); -void bdb_network_steering_on_network(zb_uint8_t param); -#ifdef ZB_JOIN_CLIENT -void bdb_network_steering_not_on_network(zb_uint8_t param); -static void bdb_force_rejoin_if_not_in_progress(zb_bufid_t param); -#ifndef NCP_MODE_HOST -static void bdb_initiate_key_exchange_if_needed(void); -#endif /* NCP_MODE_HOST */ -#endif /* ZB_JOIN_CLIENT */ -void bdb_after_mgmt_permit_joining_cb(zb_uint8_t param); -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER -static void bdb_rejoin_machine(zb_uint8_t param); -static void schedule_wwah_rejoin_backoff_attempt(zb_uint8_t param); -#endif -#ifndef NCP_MODE_HOST -static void nwk_cancel_network_discovery_response(zb_bufid_t buf); -#endif /* NCP_MODE_HOST */ - -zb_bool_t bdb_not_ever_joined() -{ - zb_ext_pan_id_t curr_ext_pan_id = {0}; - zb_get_extended_pan_id(curr_ext_pan_id); - - return (zb_bool_t)(ZB_EXTPANID_IS_ZERO(curr_ext_pan_id) - && !zb_zdo_authenticated() - && !zb_zdo_tclk_valid()); -} - - -zb_bool_t bdb_is_in_tc_rejoin(void) -{ - return ZB_U2B(ZB_BDB().bdb_tc_rejoin_active); -} - - -#ifdef ZB_FORMATION - -static zb_bool_t bdb_can_do_network_formation() -{ - return (zb_bool_t)(!zb_zdo_joined() - && ( -#ifdef ZB_DISTRIBUTED_SECURITY_ON - (ZB_IS_DEVICE_ZR() - && FORMATION_SELECTOR().start_formation != NULL - /* ZR can do formation in Distributed only */ - && zb_tc_is_distributed()) -#else - 0 -#endif - /* Do Formation as ZC */ - || ZB_IS_DEVICE_ZC()) - ); -} - -#endif /* ZB_FORMATION */ - -static void bdb_initiate_commissioning(zb_uint8_t param) -{ - /* ZB_BDB().bdb_commissioning_step = ZB_BDB_INITIALIZATION; */ - /* TRACE_MSG(TRACE_ZDO1, "bdb mode - initiate bdb commissioning", (FMT__0)); */ - /* ZB_SCHEDULE_CALLBACK(bdb_commissioning_machine, param); */ - -#if 0//def ZB_BDB_TOUCHLINK - if (ZB_BDB().bdb_commissioning_mode == ZB_BDB_TOUCHLINK_TARGET) - { - ZB_BDB().bdb_commissioning_step = ZB_BDB_TOUCHLINK_TARGET; - ZB_SCHEDULE_CALLBACK(bdb_touchlink_machine, param); - } - else -#endif - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - ZB_BDB().v_do_primary_scan = ZB_BDB_JOIN_MACHINE_PRIMARY_SCAN; - ZB_BDB().v_scan_channels = 0; /* Will be set from scan routines. */ - TRACE_MSG(TRACE_ZDO1, "Start BDB Initialization procedure", (FMT__0)); - ZB_SCHEDULE_CALLBACK(bdb_initialization_procedure, param); - } -} - -zb_bool_t bdb_start_top_level_commissioning(zb_uint8_t mode_mask) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_start_top_level_commissioning mode_mask 0x%hx", (FMT__H, mode_mask)); - if ((ZB_BDB().bdb_commissioning_step != ZB_BDB_INITIALIZATION && - ZB_BDB().bdb_commissioning_step != ZB_BDB_COMMISSIONING_STOP) || - ZB_BDB().bdb_commissioning_status == ZB_BDB_STATUS_IN_PROGRESS) - { - TRACE_MSG(TRACE_ZDO1, "bdb_commissioning in progress (step=%hd), return ZB_FALSE", - (FMT__H,ZB_BDB().bdb_commissioning_step)); - return ZB_FALSE; - } - ZB_BDB().bdb_commissioning_mode = mode_mask; - ZB_BDB().bdb_commissioning_step = ZB_BDB_INITIALIZATION; - /* Do stack init and startup */ - if (!zb_zdo_joined()) - { - zboss_start_continue(); - } - else - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - ZB_BDB().bdb_commissioning_step = ZB_BDB_INITIALIZATION; - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_START, 0); - } - return ZB_TRUE; -} - -void bdb_commissioning_signal(bdb_commissioning_signal_t sig, zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO3, "bdb_commissioning_signal sig %hd param %hd", (FMT__H_H, sig, param)); - BDB_COMM_CTX().signal = sig; - - if (param) - { - ZB_SCHEDULE_CALLBACK(bdb_commissioning_machine, param); - } - else - { - zb_buf_get_out_delayed(bdb_commissioning_machine); - } -} - -#ifdef ZB_BDB_TOUCHLINK -void bdb_check_fn() -{ - if (!ZB_AIB().aps_use_nvram) - { - TRACE_MSG(TRACE_ZDO1, "No nvram - factory new", (FMT__0)); - ZB_ZLL_SET_FACTORY_NEW(); - } - else - { - /* TODO: recheck this condition */ - if (bdb_not_ever_joined()) - { - TRACE_MSG(TRACE_ZDO1, "Factory new", (FMT__0)); - ZB_ZLL_SET_FACTORY_NEW(); - } - else - { - TRACE_MSG(TRACE_ZDO1, "Not factory new", (FMT__0)); - ZB_ZLL_CLEAR_FACTORY_NEW(); - } - } -} -#endif - - -static void bdb_init(void) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_init", (FMT__0)); - ZB_BDB().bdb_commissioning_step = ZB_BDB_INITIALIZATION; - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_SUCCESS; - ZB_BDB().bdb_commissioning_group_id = (zb_uint16_t)-1; - /* ZBOSS "autostart" mode: - - ZC, not on a network: Formation - - ZC, on a network: Init + Steering - - non-D ZR/ZED, not on a network: Steering (not on a network) - - non-D ZR/ZED, on a network: Init + Steering (on a network) - */ - ZB_BDB().bdb_commissioning_mode = ZB_BDB_NETWORK_STEERING | ZB_BDB_NETWORK_FORMATION | ZB_BDB_FINDING_N_BINDING; - ZB_BDB().bdb_commissioning_time = ZB_BDBC_MIN_COMMISSIONING_TIME_S; - ZB_BDB().bdb_scan_duration = ZB_DEFAULT_SCAN_DURATION; - - /* init to zero: channel sets will be set to correct values during commissioning start - (see bdb_init_channel_sets()) or if the app sets them directly using - zb_set_bdb_primary_channel_set() or zb_set_bdb_secondary_channel_set() */ - ZB_BDB().bdb_primary_channel_set = ZB_BDB().bdb_secondary_channel_set = 0u; - - zb_aib_tcpol_set_update_trust_center_link_keys_required(ZB_TRUE); - -#if defined(ZB_BDB_ENABLE_FINDING_BINDING) - zb_bdb_finding_binding_init_ctx(); -#endif -} - -zb_bool_t bdb_joined(void) -{ - zb_bool_t joined; - zb_ext_pan_id_t ext_pan_id = {0}; - - zb_get_extended_pan_id(ext_pan_id); - joined = (zb_bool_t)(!ZB_EXTPANID_IS_ZERO(ext_pan_id) && - zb_zdo_authenticated()); - - if (zb_aib_get_coordinator_version() >= 21) - { - joined = (zb_bool_t)(joined && zb_zdo_tclk_valid()); - } - - return joined; -} - - -static void bdb_init_channel_sets(void) -{ - zb_uint8_t used_page; - - TRACE_MSG(TRACE_ZDO1, ">> bdb_init_channel_sets", (FMT__0)); - - TRACE_MSG(TRACE_ZDO1, "primary: 0x%x; secondary: 0x%x", - (FMT__D_D, zb_get_bdb_primary_channel_set(), zb_get_bdb_secondary_channel_set())); - /* DD: this logic is moved from zb_set_nwk_role_mode_common_ext() and - zb_production_config_load_ver_2_0(). - Not sure it is correct for MULTIMAC case though. */ - - used_page = zb_aib_channel_page_list_get_first_filled_page(); - - /* if SubGHz support is disabled, the first filled page should be 0, 2.4GHz, - so we don't need to check if we support SubGHz. */ - if (used_page != ZB_CHANNEL_PAGES_NUM) - { - if (zb_get_bdb_primary_channel_set() == 0u) - { - zb_set_bdb_primary_channel_set(zb_aib_channel_page_list_get_mask(used_page)); - TRACE_MSG(TRACE_ZDO1, "new primary channel set: 0x%x", - (FMT__D, zb_get_bdb_primary_channel_set())); - } - if (zb_get_bdb_secondary_channel_set() == 0u) - { - /* TODO (ZBS-428): This needs to be fixed according to stack documentation, primary and - secondary channel masks should follow the BDB spec default values (5.3 Attributes), - and secondary channel set should not be changed if it has been manually set to 0 (5.3.12 bdbSecondaryChannelSet attribute) */ - TRACE_MSG(TRACE_ZDO1, "secondary channel set unused: 0x%x", - (FMT__D, zb_get_bdb_secondary_channel_set())); - } - } - - TRACE_MSG(TRACE_ZDO1, "<< bdb_init_channel_sets", (FMT__0)); -} - - -void bdb_preinit(void) -{ - zb_bool_t joined; - zb_ext_pan_id_t ext_pan_id = {0}; - - TRACE_MSG(TRACE_ZDO1, ">> bdb_preinit", (FMT__0)); - -#ifdef ZB_BDB_TOUCHLINK - bdb_check_fn(); -#endif - - ZB_ASSERT(zb_get_device_type() != ZB_NWK_DEVICE_TYPE_NONE); - - zb_get_extended_pan_id(ext_pan_id); - joined = bdb_joined(); - -#if defined ZB_DISTRIBUTED_SECURITY_ON - if (joined) - { - zb_sync_distributed(); - } -#endif - - if (joined) - { - TRACE_MSG(TRACE_ZDO1, "Not factory new", (FMT__0)); -#ifdef ZB_BDB_TOUCHLINK - /* just in case */ - ZB_ZLL_CLEAR_FACTORY_NEW(); -#endif - } - -#ifdef ZB_BDB_TOUCHLINK - /* 8.7 Touchlink procedure for an initiator: - The touchlink procedure for an initiator can perform a "normal" channel scan or an "extended" - channel scan; the latter is used if a reset to factory new is required (see sub-clause 9.2) or - if the target could be operating on a channel other than those defined in - bdbcTLPrimaryChannelSet. - */ - ZB_BDB().bdb_ext_channel_scan = 1; /* ZB_ZLL_IS_FACTORY_NEW() */ -#endif - - bdb_init_channel_sets(); - - TRACE_MSG(TRACE_INFO1, "dev type %hd, joined %hd, ext_pan_id %hd, authenticated %hd, tclk_valid %hd", - (FMT__H_H_H_H_H, - zb_get_device_type(), - joined, - !ZB_EXTPANID_IS_ZERO(ext_pan_id), - zb_zdo_authenticated(), - zb_zdo_tclk_valid())); -} - - -/** - BDB Initialization procedure according to 7.1 Initialization procedure - */ -void bdb_initialization_procedure(zb_uint8_t param) -{ - zb_ext_pan_id_t ext_pan_id = {0}; - zb_get_extended_pan_id(ext_pan_id); - - bdb_preinit(); -/* Can do rejoin if ZED and if authenticated: only secured rejoin is - * allowed by BDB. - * Seems, ZR must continue its work without a rejoin (hmm?) - */ - if (bdb_joined()) - { -#if defined ZB_COORDINATOR_ROLE - if (ZB_IS_DEVICE_ZC()) - { - TRACE_MSG(TRACE_ZDO2, "Start ZC without formation", (FMT__0)); - ZB_SCHEDULE_CALLBACK(zb_nwk_cont_without_formation, param); - param = 0; - } - else -#endif -#if defined ZB_ROUTER_ROLE - if (ZB_IS_DEVICE_ZR() && !ZB_BDB().bdb_force_router_rejoin) - { - TRACE_MSG(TRACE_ZDO2, "Initiate start router for ZR", (FMT__0)); - ZB_SCHEDULE_CALLBACK(zb_zdo_start_router, param); - param = 0; - } - else -#endif - { - /* Perform secure rejoin */ - TRACE_MSG(TRACE_ZDO2, "Perform secure rejoin", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_SECURE_REJOIN, param); - param = 0; - } - - /* Reset steering to avoid network opening - * (permit join request command) */ - ZB_BDB().bdb_commissioning_mode = ZB_BDB_NETWORK_FORMATION | ZB_BDB_FINDING_N_BINDING; - - /* We are NFN - indicate ZB_BDB_SIGNAL_DEVICE_REBOOT */ - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_DEVICE_REBOOT; - } - else if (bdb_not_ever_joined()) - { - /* Nothing to do, just continue */ - TRACE_MSG(TRACE_ERROR, "Nothing to do, just continue", (FMT__0)); - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_DEVICE_FIRST_START; - } - else if (!ZB_EXTPANID_IS_ZERO(ext_pan_id) - && ((zb_aib_get_coordinator_version() < 21) || - ((zb_aib_get_coordinator_version() >= 21) && zb_zdo_tclk_valid()))) - { - /* Perform TC rejoin */ - TRACE_MSG(TRACE_ERROR, "Perform TC rejoin", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_TC_REJOIN, param); - - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_DEVICE_REBOOT; - param = 0; - } -#ifndef ZB_COORDINATOR_ONLY - else - { - TRACE_MSG(TRACE_ERROR, "Strange configuration, leave", (FMT__0)); - zdo_commissioning_leave(param, ZB_FALSE, ZB_FALSE); - param = 0; - } -#endif /* #ifndef ZB_COORDINATOR_ONLY */ - - if (param) - { - /* No additional actions are needed, finish initialization */ - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_FINISH, param); - } -} - -static void bdb_post_commissioning_actions(void) -{ -#if (defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && defined ZB_ZCL_ENABLE_WWAH_SERVER) - wwah_post_commissioning_actions(); -#endif -} - -static void bdb_send_tc_rejoin_done_after_reboot(zb_uint8_t param, zb_uint16_t status) -{ - TRACE_MSG(TRACE_ZDO1, ">> bdb_send_tc_rejoin_done_after_reboot, param %hd, status %d", - (FMT__H_D, param, status)); - - zb_app_signal_pack(param, ZB_BDB_SIGNAL_TC_REJOIN_DONE, -status, 0); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - - TRACE_MSG(TRACE_ZDO1, "<< bdb_send_tc_rejoin_done_after_reboot", (FMT__0)); -} - -void bdb_commissioning_machine(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_commissioning_machine param %hd signal %hd state %hd", - (FMT__H_H_H, param, BDB_COMM_CTX().signal, ZB_BDB().bdb_commissioning_step)); - - TRACE_MSG(TRACE_ZDO1, ">> bdb_commissioning_machine param %hd step 0x%x bdb_commissioning_mode 0x%x bdb_commissioning_status %d joined %d", - (FMT__H_D_D_D_D, param, ZB_BDB().bdb_commissioning_step, ZB_BDB().bdb_commissioning_mode, ZB_BDB().bdb_commissioning_status, zb_zdo_joined())); - - /* Run machines specific to the current SE device state */ - switch (ZB_BDB().bdb_commissioning_step) - { - case ZB_BDB_INITIALIZATION: - ZB_SCHEDULE_CALLBACK(bdb_initialization_machine, param); - break; - - case ZB_BDB_TOUCHLINK_COMMISSIONING: - /* FIXME: Do we really need separate step for target? Do not touch it for now, but need to - * refactor during Touchlink commissioning refactoring/extension. */ - case ZB_BDB_TOUCHLINK_TARGET: - ZB_SCHEDULE_CALLBACK(bdb_touchlink_machine, param); - break; - - case ZB_BDB_NETWORK_STEERING: - ZB_SCHEDULE_CALLBACK(bdb_network_steering_machine, param); - break; - - case ZB_BDB_NETWORK_FORMATION: - ZB_SCHEDULE_CALLBACK(bdb_network_formation_machine, param); - break; - -#if defined(ZB_BDB_ENABLE_FINDING_BINDING) - case ZB_BDB_FINDING_N_BINDING: - ZB_SCHEDULE_CALLBACK(bdb_finding_n_binding_machine, param); - break; -#endif - -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER - case ZB_BDB_REJOIN: - ZB_SCHEDULE_CALLBACK(bdb_rejoin_machine, param); - break; -#endif /* ZB_ZCL_ENABLE_WWAH_SERVER */ - - case ZB_BDB_COMMISSIONING_STOP: - if (BDB_COMM_CTX().signal == BDB_COMM_SIGNAL_FINISH -#ifdef NCP_MODE_HOST - /* Need it only to send signal to app about rejoin. - Maybe need to implement it correctly.*/ - || BDB_COMM_CTX().signal == BDB_COMM_SIGNAL_NWK_START_ROUTER_CONF -#endif /* NCP_MODE_HOST */ - ) - { - /* commissioning done */ - if (ZB_BDB().bdb_commissioning_status == ZB_BDB_STATUS_IN_PROGRESS) - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_SUCCESS; - /* Reset "force rejoin" flag */ - ZB_BDB().bdb_force_router_rejoin = ZB_FALSE; - } - - TRACE_MSG(TRACE_INFO1, "COMMISSIONING_STOP: app signal %hd comm status %hd", (FMT__H_H, ZB_BDB().bdb_application_signal, ZB_BDB().bdb_commissioning_status)); - ZB_BDB().bdb_op_cancelled = ZB_FALSE; - if (ZB_BDB().bdb_commissioning_status == ZB_BDB_STATUS_CANCELLED) - { - zb_app_signal_pack_with_detailed_status(param, - ZB_BDB().bdb_application_signal, - RET_INTERRUPTED, - 0); - - } - else - { - zb_app_signal_pack(param, ZB_BDB().bdb_application_signal, - -ZB_BDB().bdb_commissioning_status, 0); - } - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - - if (ZB_BDB().bdb_tc_rejoin_after_reboot == ZB_TRUE && - ZB_BDB().bdb_application_signal == ZB_BDB_SIGNAL_DEVICE_REBOOT) - { - zb_buf_get_out_delayed_ext(bdb_send_tc_rejoin_done_after_reboot, ZB_BDB().bdb_commissioning_status, 0U); - ZB_BDB().bdb_tc_rejoin_after_reboot = ZB_FALSE; - } - - /* FIXME: Not sure when to start WWAH and other activities */ - if (ZB_BDB().bdb_commissioning_status == ZB_BDB_STATUS_SUCCESS && - (ZB_BDB().bdb_application_signal == ZB_BDB_SIGNAL_DEVICE_FIRST_START || - ZB_BDB().bdb_application_signal == ZB_BDB_SIGNAL_DEVICE_REBOOT || - ZB_BDB().bdb_application_signal == ZB_BDB_SIGNAL_STEERING)) - { - bdb_post_commissioning_actions(); - } - -#if defined ZB_JOIN_CLIENT - if (ZB_BDB().bdb_commissioning_status == ZB_BDB_STATUS_DEV_ANNCE_SEND_FAILURE && - (ZB_BDB().bdb_application_signal == ZB_BDB_SIGNAL_DEVICE_FIRST_START || - ZB_BDB().bdb_application_signal == ZB_BDB_SIGNAL_DEVICE_REBOOT)) - { - ZB_SCHEDULE_CALLBACK(bdb_force_rejoin_if_not_in_progress, ZB_BUF_INVALID); - } -#endif /* defined ZB_JOIN_CLIENT */ - } - /* else ignore anything we can receive (for instance, LEAVE_DONE etc) */ - else - { - TRACE_MSG(TRACE_ZDO1, "commissioning is not in progress, ignore", (FMT__0)); - zb_buf_free(param); - } - break; - - default: - TRACE_MSG(TRACE_ERROR, "Unknown commissioning state %d", (FMT__D, ZB_BDB().bdb_commissioning_mode)); -#ifdef BDB_COMMISSIONING_DEBUG - ZB_ASSERT(0); -#else - if (param) - { - zb_buf_free(param); - } -#endif - break; - } -} - -static void bdb_initialization_machine(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_initialization_machine param %hd signal %hd state %hd", - (FMT__H_H_H, param, BDB_COMM_CTX().signal, ZB_BDB().bdb_commissioning_step)); - switch (BDB_COMM_CTX().signal) - { - case BDB_COMM_SIGNAL_INIT_START: - { -#ifdef ZB_BDB_TOUCHLINK - if (ZB_BDB().bdb_commissioning_mode == ZB_BDB_TOUCHLINK_TARGET) - { - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_FINISH, param); - } - else -#endif - { - if (bdb_joined() && zb_zdo_joined()) - { - TRACE_MSG(TRACE_ZDO1, "Already inited, skip initialization", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_FINISH, param); - } - else - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - ZB_BDB().v_do_primary_scan = ZB_BDB_JOIN_MACHINE_PRIMARY_SCAN; - ZB_BDB().v_scan_channels = 0; /* Will be set from scan routines. */ - TRACE_MSG(TRACE_ZDO1, "Start BDB Initialization procedure", (FMT__0)); - ZB_SCHEDULE_CALLBACK(bdb_initialization_procedure, param); - } - } - } - break; - - case BDB_COMM_SIGNAL_INIT_SECURE_REJOIN: - bdb_precomm_rejoin_over_all_channels(param, 1); - break; - - case BDB_COMM_SIGNAL_INIT_TC_REJOIN: - if (ZB_BDB().bdb_application_signal == ZB_BDB_SIGNAL_DEVICE_REBOOT) - { - ZB_BDB().bdb_tc_rejoin_after_reboot = ZB_TRUE_U; - } - - ZB_BDB().bdb_tc_rejoin_active = ZB_TRUE; - bdb_precomm_rejoin_over_all_channels(param, 0); - break; - - case BDB_COMM_SIGNAL_NWK_AUTH_FAILED: - /* ZG->aps.authenticated = ZB_FALSE; */ - /* FALLTHROUGH */ - case BDB_COMM_SIGNAL_NWK_JOIN_FAILED: - { - TRACE_MSG(TRACE_ZDO1, "Rejoin failed, secured %hd", (FMT__H, bdb_is_in_tc_rejoin())); - -#if 0 - /* TC rejoin should be invoked only if we have unique TCLK or if it is directly allowed in - * application to perform TC rejoin with legacy ZC. - * To prevent infinite rejoins loop here, TC rejoin will be performed only once, but application - * will receive ZB_BDB_SIGNAL_TC_REJOIN_DONE to choose a next action */ - if (!bdb_is_in_tc_rejoin() && ((zb_zdo_tclk_valid() && (zb_aib_get_coordinator_version() >= 21)) - || zb_aib_tcpol_get_allow_unsecure_tc_rejoins()) -#ifdef ZB_REJOIN_BACKOFF - && !zb_zdo_rejoin_backoff_is_running() -#endif - ) - { - /* Perform TC rejoin */ - TRACE_MSG(TRACE_ZDO1, "Perform TC rejoin", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_TC_REJOIN, param); - } - else -#endif - { - TRACE_MSG(TRACE_ZDO1, "Can't find network", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NO_NETWORK; - ZB_BDB().bdb_tc_rejoin_active = ZB_FALSE_U; - - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_FINISH, param); - } - } - break; - - case BDB_COMM_SIGNAL_NWK_JOIN_DONE: - TRACE_MSG(TRACE_ZDO1, "Device is joined", (FMT__0)); -#ifdef ZB_JOIN_CLIENT -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER - if (!ZB_PIBCACHE_RX_ON_WHEN_IDLE() - && zb_zcl_wwah_check_if_wwah_rejoin_enabled() - && !BDB_COMM_CTX().rejoin.rr_global_retries) - { - TRACE_MSG(TRACE_ZDO1, "Cancel any scheduled rejoin attempts", (FMT__0)); - ZB_SCHEDULE_ALARM_CANCEL(zdo_commissioning_initiate_rejoin, ZB_ALARM_ANY_PARAM); - } -#endif - - if (!zdo_secur_waiting_for_tclk_update()) -#endif - { - /* Join is finished - can reset the blacklist. */ -#ifdef ZB_NWK_BLACKLIST - zb_nwk_blacklist_reset(); -#endif - } - - ZB_BDB().bdb_tc_rejoin_active = ZB_FALSE_U; - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_FINISH, param); - break; - - case BDB_COMM_SIGNAL_NWK_FORMATION_OK: - TRACE_MSG(TRACE_ZDO1, "Network is started OK", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_FINISH, param); - break; - - case BDB_COMM_SIGNAL_NWK_START_ROUTER_CONF: - TRACE_MSG(TRACE_ZDO1, "Network is started OK (router)", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_FINISH, param); - break; - - case BDB_COMM_SIGNAL_LEAVE_DONE: - TRACE_MSG(TRACE_ZDO1, "Left from the network", (FMT__0)); - /* ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NO_NETWORK; */ - /* We left from the network (probably because of wrong network configuration). - Try to continue commissioning as FN device. */ - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_DEVICE_FIRST_START; - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_FINISH, param); - break; - - case BDB_COMM_SIGNAL_INIT_FINISH: - TRACE_MSG(TRACE_ZDO1, "Initialization finished, next step - Touchlink", (FMT__0)); - /* Go to next commissioning step - Touchlink procedure */ - ZB_BDB().bdb_commissioning_step = ZB_BDB_TOUCHLINK_COMMISSIONING; - bdb_commissioning_signal(BDB_COMM_SIGNAL_TOUCHLINK_START, param); - break; - - case BDB_COMM_SIGNAL_NETWORK_STEERING_DISCOVERY_FAILED: - - break; - - - default: - TRACE_MSG(TRACE_ERROR, "Unknown signal %d", (FMT__D, BDB_COMM_CTX().signal)); -#ifdef BDB_COMMISSIONING_DEBUG - ZB_ASSERT(0); -#else - if (param) - { - zb_buf_free(param); - } -#endif - break; - } -} - -static void bdb_precomm_rejoin_over_all_channels(zb_uint8_t param, zb_uint16_t secure) -{ - if (!param) - { - zb_buf_get_out_delayed_ext(bdb_precomm_rejoin_over_all_channels, secure, 0); - } - else - { - zb_channel_list_t rejoin_ch_list; - zb_ext_pan_id_t ext_pan_id; - - - TRACE_MSG(TRACE_ZDO1, "bdb_precomm_rejoin_over_all_channels %hd", (FMT__H, param)); - zb_channel_list_init(rejoin_ch_list); -#if defined ZB_SUBGHZ_BAND_ENABLED - zb_channel_page_list_copy(rejoin_ch_list, ZB_AIB().aps_channel_mask_list); -#else - zb_channel_page_list_set_2_4GHz_mask(rejoin_ch_list, - zb_aib_channel_page_list_get_2_4GHz_mask()); -#endif /* !ZB_SUBGHZ_BAND_ENABLED */ - zb_get_extended_pan_id(ext_pan_id); - zdo_initiate_rejoin(param, ext_pan_id, - rejoin_ch_list, - (zb_bool_t)secure); - } -} - -#ifdef ZB_BDB_TOUCHLINK -static void bdb_touchlink_target_timeout(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_touchlink_target_timeout: finish Touchlink Target", (FMT__0)); - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_TOUCHLINK_TARGET_FINISHED; - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_SUCCESS; - bdb_commissioning_signal(BDB_COMM_SIGNAL_TOUCHLINK_FINISH, param); -} -#endif - -/* TODO: Split on Touchlink Target and Touchlink Initiator */ -static void bdb_touchlink_machine(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_touchlink_machine param %hd signal %hd state %hd", - (FMT__H_H_H, param, BDB_COMM_CTX().signal, ZB_BDB().bdb_commissioning_step)); - switch (BDB_COMM_CTX().signal) - { - case BDB_COMM_SIGNAL_TOUCHLINK_START: - { -#ifdef ZB_BDB_TOUCHLINK - if (ZB_BDB().bdb_commissioning_mode & ZB_BDB_TOUCHLINK_TARGET) - { - /* TODO: Fix this correctly after discussion about signals. */ - if (ZB_BDB().bdb_commissioning_mode == ZB_BDB_TOUCHLINK_TARGET) - { - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_TOUCHLINK_TARGET; - } - - TRACE_MSG(TRACE_ZDO1, "Start Touchlink Target", (FMT__0)); - /* Now if touchlink compiled, force formation compile (need for distributed). */ - /* TODO: a) check for touchlink enabled; b) call touchlink indirectly */ -#ifdef ZB_FORMATION - zdo_formation_force_link(); -#endif - ZB_SCHEDULE_CALLBACK(bdb_touchlink_target_start, param); - } - else if (ZB_BDB().bdb_commissioning_mode & ZB_BDB_TOUCHLINK_COMMISSIONING) - { - /* TODO: Fix this correctly after discussion about signals. */ - if (ZB_BDB().bdb_commissioning_mode == ZB_BDB_TOUCHLINK_COMMISSIONING) - { - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_TOUCHLINK; - } - - TRACE_MSG(TRACE_ZDO1, "Start Touchlink initiator", (FMT__0)); - TRACE_MSG(TRACE_ZDO1, "Running BDB Touchlink initiator v_do_primary_scan %hd", (FMT__H, ZB_BDB().v_do_primary_scan)); - ZB_SCHEDULE_CALLBACK(bdb_touchlink_initiator, param); - } - else -#endif - { - TRACE_MSG(TRACE_ZDO1, "Skip Touchlink", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_TOUCHLINK_FINISH, param); - } - } - break; - -#ifdef ZB_BDB_TOUCHLINK - case BDB_COMM_SIGNAL_TOUCHLINK_INITIATOR_DONE: - TRACE_MSG(TRACE_ZDO1, "Touchlink initiator succeeded, continue", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_SUCCESS; - bdb_commissioning_signal(BDB_COMM_SIGNAL_TOUCHLINK_FINISH, param); - break; - - case BDB_COMM_SIGNAL_TOUCHLINK_INITIATOR_FAILED: - TRACE_MSG(TRACE_ZDO1, "Touchlink initiator failed", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_TARGET_FAILURE; - bdb_commissioning_signal(BDB_COMM_SIGNAL_TOUCHLINK_FINISH, param); - break; - - case BDB_COMM_SIGNAL_NETWORK_STEERING_DISCOVERY_FAILED: - if (ZB_BDB().bdb_commissioning_mode & ZB_BDB_TOUCHLINK_TARGET) - { - /* Touchlink Target: We are asked to start the network, no other networks discovered - - * continue */ - /* TODO: Manipulating with status this way only because of bdb_touchlink implementation, - * remove when it will be fixed! */ - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NO_NETWORK; - ZB_SCHEDULE_CALLBACK(bdb_touchlink_target_start, param); - } - else - { - ZB_ASSERT(0); /* Debug */ - } - break; - - case BDB_COMM_SIGNAL_NWK_JOIN_FAILED: - if (ZB_BDB().bdb_commissioning_mode & ZB_BDB_TOUCHLINK_COMMISSIONING && - !(ZB_BDB().bdb_commissioning_mode & ZB_BDB_TOUCHLINK_TARGET)) - { - TRACE_MSG(TRACE_ZDO1, "Touchlink Initiator: Failed to rejoin to the formed network", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NO_NETWORK; - bdb_commissioning_signal(BDB_COMM_SIGNAL_TOUCHLINK_FINISH, param); - } - else - { - ZB_ASSERT(0); /* Debug */ - } - break; - - case BDB_COMM_SIGNAL_NWK_START_ROUTER_CONF: - { - TRACE_MSG(TRACE_ZDO1, "Touchlink Target: successfully formed the network", (FMT__0)); - - /* Inform the application about Touchlink Target formation */ - zb_app_signal_pack(param, ZB_BDB_SIGNAL_TOUCHLINK_NWK, - ZB_BDB_STATUS_SUCCESS, - 0); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - - ZB_SCHEDULE_ALARM_CANCEL(bdb_touchlink_target_timeout, ZB_ALARM_ANY_PARAM); - bdb_touchlink_target_timeout(0); - } - break; - - case BDB_COMM_SIGNAL_NWK_JOIN_DONE: - TRACE_MSG(TRACE_ZDO1, "Touchlink Initiator: successfully joined the network", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_TOUCHLINK_FINISH, 0); - break; - - case BDB_COMM_SIGNAL_TOUCHLINK_NOTIFY_TASK_RESULT: - { - zb_ret_t status = zb_buf_get_status(param); - if (ZB_BDB().bdb_commissioning_mode & ZB_BDB_TOUCHLINK_TARGET) - { - if (status == ZB_ZLL_TASK_STATUS_OK) - { - /* Touchlink Target started */ - - /* FIXME: BDB spec does not define the timeout for Touchlink Target. Let's assume device - * will be in the Target mode for 1 min by default. */ - /* TODO: Stop Touchlink Target if device finishes Touchlink Target procedure before - * timeout. */ - TRACE_MSG(TRACE_ZDO1, "Touchlink target started, wait for Touchlink Target timeout", (FMT__0)); - ZB_SCHEDULE_ALARM(bdb_touchlink_target_timeout, 0, ZB_TIME_ONE_SECOND * 60); - - /* Inform the application that Touchlink Target is started */ - zb_app_signal_pack(param, ZB_BDB_SIGNAL_TOUCHLINK_TARGET, ZB_BDB_STATUS_SUCCESS, 0); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - } - else - { - TRACE_MSG(TRACE_ZDO1, "Touchlink target start failed", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_TARGET_FAILURE; - bdb_commissioning_signal(BDB_COMM_SIGNAL_TOUCHLINK_FINISH, param); - } - } - else /* Touchlink Initiator */ - { - if (status == ZB_ZLL_TASK_STATUS_FINISHED) - { - TRACE_MSG(TRACE_ZDO1, "Some device discovered: continue with touchlink_initiator", (FMT__0)); - /* TODO: Refactor this function! Similar to bdb_commissioning_machine() there is a lot of - * unclear manipulations with flags there etc. */ - ZB_SCHEDULE_CALLBACK(bdb_touchlink_initiator, param); - } - else - { - ZB_ASSERT(0); /* debug */ - } - } - } - break; -#endif /* ZB_BDB_TOUCHLINK */ - case BDB_COMM_SIGNAL_TOUCHLINK_FINISH: - if (ZB_BDB().bdb_commissioning_status != ZB_BDB_STATUS_IN_PROGRESS) - { - ZB_BDB().bdb_commissioning_step = ZB_BDB_COMMISSIONING_STOP; - TRACE_MSG(TRACE_ZDO3, "ZB_BDB_COMMISSIONING_STOP", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_FINISH, param); - } - else - { - TRACE_MSG(TRACE_ZDO1, "Touchlink finished, next step - Network Steering", (FMT__0)); - /* Go to next commissioning step - Network Steering procedure */ - ZB_BDB().bdb_commissioning_step = ZB_BDB_NETWORK_STEERING; - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_START, param); - } - break; - - default: - TRACE_MSG(TRACE_ERROR, "Unknown signal %d", (FMT__D, BDB_COMM_CTX().signal)); -#ifdef BDB_COMMISSIONING_DEBUG - ZB_ASSERT(0); -#else - if (param) - { - zb_buf_free(param); - } -#endif - break; - } -} - -#ifndef ZB_COORDINATOR_ONLY -void bdb_network_steering_auth_failure(zb_uint8_t param) -{ - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NO_NETWORK; -#ifdef ZB_CERTIFICATION_HACKS - if (ZB_CERT_HACKS().stay_on_network_after_auth_failure && zb_zdo_joined()) - { - /* special hack for bdb tests - do not leave network if authentication failed */ - ZB_BDB().bdb_commissioning_step = ZB_BDB_COMMISSIONING_STOP; - TRACE_MSG(TRACE_ZDO3, "ZB_BDB_COMMISSIONING_STOP", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_FINISH, param); - } - else -#endif - { - TRACE_MSG(TRACE_ZDO1, "Authentication failure. Leave.", (FMT__0)); - zdo_commissioning_leave(param, ZB_FALSE, ZB_FALSE); - } -} - -void bdb_network_steering_tclk_ex_failure(zb_uint8_t param) -{ - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_TCLK_EX_FAILURE; - - /* Joined but failed to update it's TC link key - leave network and complete steering - * with status ZB_BDB_STATUS_TCLK_EX_FAILURE */ - - TRACE_MSG(TRACE_ZDO1, "TC link key update failure. Leave.", (FMT__0)); - /* ZB_BDB().bdb_commissioning_step = ZB_BDB_LAST_COMMISSIONING_STEP; */ - -#ifdef ZB_CERTIFICATION_HACKS - if (ZB_CERT_HACKS().stay_on_network_after_auth_failure) - { - /* special hack for bdb tests - do not leave network if tclk update failed */ - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); - } - else -#endif - { - zdo_commissioning_leave(param, ZB_FALSE, ZB_FALSE); - } -} -#endif /* !ZB_COORDINATOR_ONLY */ - -void bdb_network_steering_start(zb_uint8_t param) -{ -#ifdef ZB_JOIN_CLIENT - if (zdo_secur_waiting_for_tclk_update()) - { - TRACE_MSG(TRACE_ZDO1, "We are waiting for TCLK update. What to do? Lets free the buf at least. buf %hd", (FMT__H, param)); - zb_buf_free(param); - } - else -#endif - { - if (zb_zdo_joined()) - { - /* - The node then sets bdbCommissioningStatus to SUCCESS. If the node supports - touchlink, it sets the values of the aplFreeNwkAddrRangeBegin, - aplFreeNwkAddrRangeEnd, aplFreeGroupID-RangeBegin and - aplFreeGroupIDRangeEnd attributes all to 0x0000 (indicating the node 1045 having - joined the network using MAC association). - */ - TRACE_MSG(TRACE_ZDO1, "Start BDB network steering when on network", (FMT__0)); - ZB_SCHEDULE_CALLBACK(bdb_network_steering_on_network, param); - } - else - { - /* If we are NFN and join failed - finish and pass it up to application. */ - if (!zb_bdb_is_factory_new()) - { - TRACE_MSG(TRACE_ZDO1, "Not ZB_JOINED and NFN - finish BDB", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NO_NETWORK; - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); - } - else - { - TRACE_MSG(TRACE_ZDO1, "Start BDB network steering when NOT on network", (FMT__0)); -#ifdef ZB_JOIN_CLIENT - /* call directly to simplify cancellation logic */ - bdb_network_steering_not_on_network(param); -#endif - } - } - } -} - -#ifdef ZB_JOIN_CLIENT -void bdb_network_steering_start_scan(zb_uint8_t param) -{ - zb_nlme_network_discovery_request_t *req = ZB_BUF_GET_PARAM(param, zb_nlme_network_discovery_request_t); - - ZB_BZERO(req, sizeof(zb_nlme_network_discovery_request_t)); - - TRACE_MSG(TRACE_ZDO3, "bdb_network_steering_start_scan param %hd", (FMT__H, param)); - /* MMDEVSTUBS */ - -#if defined ZB_SUB_GHZ_ZB30_SUPPORT - { - zb_uint8_t used_page; - - used_page = zb_aib_channel_page_list_get_first_filled_page(); - zb_channel_page_list_set_mask(req->scan_channels_list, used_page, ZB_BDB().v_scan_channels); - } -#else - zb_channel_page_list_set_2_4GHz_mask(req->scan_channels_list, ZB_BDB().v_scan_channels); -#endif /* !ZB_SUB_GHZ_ZB30_SUPPORT */ - - req->scan_duration = ZB_BDB().bdb_scan_duration; - COMM_CTX().discovery_ctx.disc_count = COMM_CTX().discovery_ctx.nwk_scan_attempts; - - /* That finishes in zdo_app.c zb_nlme_network_discovery_confirm */ - ZB_SCHEDULE_CALLBACK(zb_nlme_network_discovery_request, param); -} - - -void bdb_network_steering_not_on_network(zb_uint8_t param) -{ -#if !defined NCP_MODE_HOST - zb_uint8_t used_page; -#endif /* !NCP_MODE_HOST */ - - if (ZB_BDB().v_do_primary_scan == ZB_BDB_JOIN_MACHINE_PRIMARY_SCAN - && ZB_BDB().bdb_primary_channel_set != 0 - && !ZB_IS_DEVICE_ZC()) - { - ZB_BDB().v_do_primary_scan = ZB_BDB_JOIN_MACHINE_SECONDARY_SCAN_START; - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - -#ifdef ZB_REJOIN_BACKOFF - if (zb_zdo_rejoin_backoff_is_running() && (ZDO_CTX().zdo_rejoin_backoff.rjb_cnt == 1) && !ZB_BDB().v_scan_channels) - { - /* the first attempt - do secure rejoin using the current channel */ - ZB_BDB().v_scan_channels = (1l << ZB_PIBCACHE_CURRENT_CHANNEL()); - /* TRICKY: Set primary_scan again - we will do 2 PRIMARY_SCANs (first on current channel, - * second on bdb_primary_channel_set), then SECONDARY_SCAN. */ - ZB_BDB().v_do_primary_scan = ZB_BDB_JOIN_MACHINE_PRIMARY_SCAN; - } - else - { - /* We done rejoin_backoff specific attempt, now reset v_scan_channels and use usual scheme - * (bdb_primary_channel_set, then bdb_secondary_channel_set). */ - ZB_BDB().v_scan_channels = 0; - - /* the second and further attempts - do secure rejoin using ALL channels */ - - /* 01/27/2017 EE Why having already 2 channel sets we introduce - another one - rejoin backoff channels mask? Can't we go thru - primary/secondary like we do for usual start? ok, after first attempt at - the current channel. - Do we need default_channel_mask parameter in zb_zdo_rejoin_backoff_start? - Isn't product_cfg.aps_channel_mask == bdb_primary_channel_set? - */ - /* NK: Seems like it is ok. Lets update bdb_channel_mask on rejoin_backoff start instead of - * using rjb_chan_mask (in the case when application wants to use custom channel mask for rjb). - * - * Currently will not remove rjb_chan_mask because it is used in legacy (non-BDB) - * variant. It is a hack because in this variant we overwrite original - * ZB_AIB().aps_channel_mask on 1st rjb attempt, then restore it from rjb_chan_mask (in all known - * cases production_mask == ZB_AIB().aps_channel_mask == rjb_chan_mask). - * Not sure about supporting legacy (non-BDB) rejoin_backoff, for me it looks like it may be - * completely removed. - */ - - /* Implement insecure rejoin via BDB if needed. */ - } -#endif - - if (!ZB_BDB().v_scan_channels) - { - /* 01/30/2017 EE In case of rejoin backoff you substitute primary - channel set by current channel, then use secondary channel set. - Not sure this is what you want to do. - Probably need to go in 2 steps: current, primary, secondary. - As an alternative (simpler, but a bit further from BDB : current, primary | secondary. - BTW I do not know why they ever invented primary and secondary... - */ - ZB_BDB().v_scan_channels = ZB_BDB().bdb_primary_channel_set; - } - TRACE_MSG(TRACE_ZDO1, "Doing primary scan channel mask 0x%lx", (FMT__L, ZB_BDB().v_scan_channels)); - /* call directly to simplify cancellation logic */ - bdb_network_steering_start_scan(param); - } - else if (!ZB_IS_DEVICE_ZC() - && ((ZB_BDB().v_do_primary_scan == ZB_BDB_JOIN_MACHINE_SECONDARY_SCAN_START - && ZB_BDB().bdb_secondary_channel_set != 0) - || - (ZB_BDB().v_do_primary_scan == ZB_BDB_JOIN_MACHINE_PRIMARY_SCAN - && ZB_BDB().bdb_secondary_channel_set != 0 - && ZB_BDB().bdb_primary_channel_set == 0))) - { - ZB_BDB().v_do_primary_scan = ZB_BDB_JOIN_MACHINE_SECONDARY_SCAN_DONE; - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - ZB_BDB().v_scan_channels = ZB_BDB().bdb_secondary_channel_set; - TRACE_MSG(TRACE_ZDO1, "Doing secondary scan channel mask 0x%lx", (FMT__L, ZB_BDB().v_scan_channels)); - /* call directly to simplify cancellation logic */ - bdb_network_steering_start_scan(param); - } - else - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NO_NETWORK; - TRACE_MSG(TRACE_ZDO1, "BDB: Could not join or authorize - run next bdb machine step", (FMT__0)); - ZB_BDB().v_do_primary_scan = ZB_BDB_JOIN_MACHINE_PRIMARY_SCAN; - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); - } - -/* TODO (ZBS-429): sync the channel mask values in ZDO that will be used for retries */ -#if !defined NCP_MODE_HOST - used_page = zb_aib_channel_page_list_get_first_filled_page(); - zb_channel_page_list_set_mask(ZB_AIB().aps_channel_mask_list, used_page, ZB_BDB().v_scan_channels); -#endif /* !NCP_MODE_HOST */ - -} -#endif /* ZB_JOIN_CLIENT */ - -void bdb_network_steering_finish(zb_uint8_t param) -{ - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); -} - -void bdb_network_steering_on_network(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO3, "bdb_network_steering_on_network param %hd", (FMT__H, param)); - /* - Send Permit Joining. - - If I am ZR or ZC, open myself for connects (permit joining). - */ - { - /* - Continues EZ-Mode Nwk steering after network has been formed or device has joined to the nwk: - invokes permit_joining routines for ZC & ZR, pushes the results of Nwk steering up - via user callback for ZED -*/ - /* Send mgmt permit joining broadcast */ - zb_zdo_mgmt_permit_joining_req_param_t *req_param = ZB_BUF_GET_PARAM(param, zb_zdo_mgmt_permit_joining_req_param_t); - - ZB_BZERO(req_param, sizeof(zb_zdo_mgmt_permit_joining_req_param_t)); - req_param->dest_addr = ZB_NWK_BROADCAST_ROUTER_COORDINATOR; - req_param->permit_duration = ZB_BDBC_MIN_COMMISSIONING_TIME_S; - req_param->tc_significance = ZB_TRUE; - zb_zdo_mgmt_permit_joining_req(param, bdb_after_mgmt_permit_joining_cb); - } -} - -/* - Called when broadcasting PermitJoining finished - during EZ-Mode Nwk Steering for ZC or ZR: - schedules local nlme.permit_joining request -*/ -void bdb_after_mgmt_permit_joining_cb(zb_uint8_t param) -{ - - TRACE_MSG(TRACE_ZDO2, "> bdb_after_mgmt_permit_joining_cb %hd", (FMT__H, param)); - - if (zb_buf_get_status(param) == RET_OK) - { -#ifdef ZB_ROUTER_ROLE - if (ZB_IS_DEVICE_ZC_OR_ZR()) - { - zb_zdo_mgmt_permit_joining_req_param_t *req = ZB_BUF_GET_PARAM(param, - zb_zdo_mgmt_permit_joining_req_param_t); - - ZB_BZERO(req, sizeof(zb_zdo_mgmt_permit_joining_req_param_t)); - req->permit_duration = ZB_BDBC_MIN_COMMISSIONING_TIME_S; - req->dest_addr = ZB_PIBCACHE_NETWORK_ADDRESS(); - - zb_zdo_mgmt_permit_joining_req(param, bdb_network_steering_finish); - param = 0; - } -#endif - } - else - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NOT_PERMITTED; - } - - if (param) - { - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); - } - - TRACE_MSG(TRACE_ZCL2, "< bdb_after_mgmt_permit_joining_cb", (FMT__0)); -} - -static void bdb_network_steering_machine(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_network_steering_machine param %hd signal %hd state %hd", - (FMT__H_H_H, param, BDB_COMM_CTX().signal, ZB_BDB().bdb_commissioning_step)); - switch (BDB_COMM_CTX().signal) - { - case BDB_COMM_SIGNAL_NETWORK_STEERING_START: - { - if (ZB_BDB().bdb_commissioning_mode & ZB_BDB_NETWORK_STEERING) - { - /* TODO: Fix this correctly after discussion about signals. */ - if (ZB_BDB().bdb_commissioning_mode == ZB_BDB_NETWORK_STEERING) - { - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_STEERING; - } - - /* For ZC steering means "open net for join". Meaningful only after formation complete. */ - if (!ZB_IS_DEVICE_ZC() || zb_zdo_joined()) - { - TRACE_MSG(TRACE_ZDO1, "Start Network Steering", (FMT__0)); - if (ZB_BDB().bdb_op_cancelled == ZB_TRUE) - { - TRACE_MSG(TRACE_ZDO1, "steering cancelled", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_CANCELLED; - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); - } - else - { - /* call directly to simplify cancellation logic */ - bdb_network_steering_start(param); - } - } - else - { - TRACE_MSG(TRACE_ZDO1, "Skip Network Steering: meaningless before formation", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); - } - } - else - { - TRACE_MSG(TRACE_ZDO1, "Skip Network Steering", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); - } - } - break; - - case BDB_COMM_SIGNAL_NETWORK_STEERING_DISCOVERY_FAILED: - if (zb_buf_get_status(param) == RET_INTERRUPTED) - { - TRACE_MSG(TRACE_ZDO1, "discovery was cancelled", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_CANCELLED; - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); - break; - } - if(ZB_BDB().bdb_commissioning_status == ZB_BDB_STATUS_IN_PROGRESS) - { - /* If commissioning is in progress, steering state machine should handle NWK discovery failed signal, - since a secondary channel scan is supposed to happen after a failed scan of primary channels */ - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_START, param); - break; - } - - /* FALLTHROUGH */ - case BDB_COMM_SIGNAL_NWK_JOIN_FAILED: - TRACE_MSG(TRACE_ZDO1, "No networks found", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_NO_NETWORK; - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); - break; - -#ifndef ZB_COORDINATOR_ONLY - case BDB_COMM_SIGNAL_NWK_AUTH_FAILED: - ZB_SCHEDULE_CALLBACK(bdb_network_steering_auth_failure, param); - break; - - case BDB_COMM_SIGNAL_NETWORK_STEERING_TCLK_EX_FAILURE: - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_TCLK_EX_FAILURE; - ZB_SCHEDULE_CALLBACK(bdb_network_steering_tclk_ex_failure, param); - break; -#endif /* !ZB_COORDINATOR_ONLY */ - - case BDB_COMM_SIGNAL_NWK_START_ROUTER_CONF: - case BDB_COMM_SIGNAL_NWK_JOIN_DONE: -#ifdef ZB_JOIN_CLIENT - if (!zdo_secur_waiting_for_tclk_update()) - { - /* Join is finished - can reset the blacklist. */ - TRACE_MSG(TRACE_ZDO1, "Router started/ED join done, TCLK is not needed - continue", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - /* Join is finished - can reset the blacklist. */ -#ifdef ZB_NWK_BLACKLIST - zb_nwk_blacklist_reset(); -#endif - /* TRICKY: Run steering one more time - to broadcast Permit Joining. This time it will be - * steering for device on network. */ - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_START, param); - } - else -#endif - { - TRACE_MSG(TRACE_ZDO1, "Router started/ED join done, wait for TCLK", (FMT__0)); - zb_buf_free(param); - } - break; - - case BDB_COMM_SIGNAL_LEAVE_DONE: - if (ZB_BDB().bdb_commissioning_status != ZB_BDB_STATUS_NO_NETWORK) - { - /* Probably bdb device failed to update tclk exchange */ - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, param); - } - else - { - /* Will be here after bdb device failed authentication - lets join to - * other networks */ -#ifdef ZB_JOIN_CLIENT - ZB_SCHEDULE_CALLBACK(zdo_retry_joining, 0); -#endif - } - break; - - case BDB_COMM_SIGNAL_NETWORK_STEERING_TCLK_DONE: - TRACE_MSG(TRACE_ZDO1, "TCLK succeeded", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - /* Join is finished - can reset the blacklist. */ -#ifdef ZB_NWK_BLACKLIST - zb_nwk_blacklist_reset(); -#endif - /* TRICKY: Run steering one more time - to broadcast Permit Joining. This time it will be - * steering for device on network. */ - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_START, param); - break; - - case BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH: - /* Do not stop even if steering is failed - may continue with Formation if it is allowed - * (Distributed ZR case) */ - - /* if (ZB_BDB().bdb_commissioning_status != ZB_BDB_STATUS_IN_PROGRESS) */ - /* { */ - /* ZB_BDB().bdb_commissioning_step = ZB_BDB_COMMISSIONING_STOP; */ - /* bdb_commissioning_signal(BDB_COMM_SIGNAL_FINISH, param); */ - /* } */ - /* else */ - { - /* Go to next commissioning step - Network Steering procedure */ - TRACE_MSG(TRACE_ZDO1, "Network Steering finished, next step - Network Formation", (FMT__0)); - ZB_BDB().bdb_commissioning_step = ZB_BDB_NETWORK_FORMATION; - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_FORMATION_START, param); - } - break; - - default: - TRACE_MSG(TRACE_ERROR, "Unknown signal %d", (FMT__D, BDB_COMM_CTX().signal)); -#ifdef BDB_COMMISSIONING_DEBUG - ZB_ASSERT(0); -#else - if (param) - { - zb_buf_free(param); - } -#endif - break; - } -} - - -static void bdb_network_formation_machine(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_network_formation_machine param %hd signal %hd state %hd", - (FMT__H_H_H, param, BDB_COMM_CTX().signal, ZB_BDB().bdb_commissioning_step)); - switch (BDB_COMM_CTX().signal) - { - case BDB_COMM_SIGNAL_NETWORK_FORMATION_START: - { - if (ZB_BDB().bdb_commissioning_mode & ZB_BDB_NETWORK_FORMATION) - { - /* TODO: Fix this correctly after discussion about signals. */ - if (ZB_BDB().bdb_commissioning_mode == ZB_BDB_NETWORK_FORMATION) - { - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_FORMATION; - } - -#ifdef ZB_FORMATION - if (bdb_can_do_network_formation()) - { - TRACE_MSG(TRACE_ZDO1, "Start Network Formation", (FMT__0)); - TRACE_MSG(TRACE_ZDO1, "Start BDB formation for device type %d", (FMT__D, zb_get_device_type())); - if (ZB_BDB().bdb_op_cancelled == ZB_TRUE) - { - TRACE_MSG(TRACE_ZDO1, "formation cancelled", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_CANCELLED; - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_FORMATION_FINISH, param); - } - else - { - ZB_ASSERT(FORMATION_SELECTOR().start_formation != NULL); - /* call directly to simplify cancellation logic */ - FORMATION_SELECTOR().start_formation(param); - } - } - else -#endif /* ZB_FORMATION */ - { - TRACE_MSG(TRACE_ZDO1, "Can not do Network Formation, skip", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_FORMATION_FINISH, param); - } - } - else - { - TRACE_MSG(TRACE_ZDO1, "Skip Network Formation", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_FORMATION_FINISH, param); - } - } - break; - - case BDB_COMM_SIGNAL_NWK_FORMATION_OK: - TRACE_MSG(TRACE_ZDO1, "Network is successfully formed", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_FORMATION_FINISH, param); - break; - - case BDB_COMM_SIGNAL_NETWORK_FORMATION_FINISH: - default: - if (ZB_BDB().bdb_commissioning_status != ZB_BDB_STATUS_IN_PROGRESS) - { - ZB_BDB().bdb_commissioning_step = ZB_BDB_COMMISSIONING_STOP; - TRACE_MSG(TRACE_ZDO3, "ZB_BDB_COMMISSIONING_STOP", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_FINISH, param); - } - else - { - TRACE_MSG(TRACE_ZDO1, "Network Formation finished, next step - Finding & Binding", (FMT__0)); - /* Go to next commissioning step - finish */ -#if defined(ZB_BDB_ENABLE_FINDING_BINDING) - ZB_BDB().bdb_commissioning_step = ZB_BDB_FINDING_N_BINDING; - bdb_commissioning_signal(BDB_COMM_SIGNAL_FINDING_N_BINDING_START, param); -#endif - } - break; - } -} - - -#if defined(ZB_BDB_ENABLE_FINDING_BINDING) -static void bdb_finding_n_binding_machine(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_finding_n_binding_machine param %hd signal %hd state %hd", - (FMT__H_H_H, param, BDB_COMM_CTX().signal, ZB_BDB().bdb_commissioning_step)); - switch (BDB_COMM_CTX().signal) - { - case BDB_COMM_SIGNAL_FINDING_N_BINDING_START: - { - /* if (ZB_BDB().bdb_commissioning_mode & ZB_BDB_FINDING_N_BINDING) */ - /* { */ - /* TRACE_MSG(TRACE_ZDO1, "TODO: Start Finding & Binding", (FMT__0)); */ - /* } */ - /* else */ - { - TRACE_MSG(TRACE_ZDO1, "Skip Finding & Binding", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_FINDING_N_BINDING_FINISH, param); - } - } - break; - - case BDB_COMM_SIGNAL_FINDING_N_BINDING_FINISH: - TRACE_MSG(TRACE_ZDO1, "Finding & Binding finished, finish BDB commissioning", (FMT__0)); - /* Go to next commissioning step - finish */ - ZB_BDB().bdb_commissioning_step = ZB_BDB_COMMISSIONING_STOP; - TRACE_MSG(TRACE_ZDO3, "ZB_BDB_COMMISSIONING_STOP", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_FINISH, param); - break; - - case BDB_COMM_SIGNAL_LEAVE_DONE: - TRACE_MSG(TRACE_ZDO1, "Leave done, abort BDB commissioning", (FMT__0)); - - switch (BDB_COMM_CTX().state) - { - case ZB_BDB_COMM_IDLE: - /* Do nothing in this case, BDB_COMM_CTX should be already reset */ - break; - - case ZB_BDB_COMM_FINDING_AND_BINDING: - zb_bdb_finding_binding_initiator_cancel(); - break; - - case ZB_BDB_COMM_FINDING_AND_BINDING_TARGET: - zb_bdb_finding_binding_target_cancel(); - break; - - default: - /* NOTE: other COMM states are not currently used, so handle them when it will be needed */ - ZB_ASSERT(ZB_FALSE); - break; - } - - break; - - default: - TRACE_MSG(TRACE_ERROR, "Unknown signal %d", (FMT__D, BDB_COMM_CTX().signal)); - - TRACE_MSG(TRACE_ERROR, "Ignore (F&B implemented separately)", (FMT__0)); - if (param) - { - zb_buf_free(param); - } - break; - } -} -#endif - -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER -static zb_bool_t bdb_ds_filter_cb(zb_uint16_t i) -{ - switch (i) - { - case ZB_NVRAM_COMMON_DATA: - return ZB_TRUE; - default: - return ZB_FALSE; - } -} - -/* Savepoint logic for SE R&R and WWAH Rejoin could be unified and moved into a separate module. - For NCP case it could be put at SoC side */ -static void bdb_savepoint_before_rr() -{ - TRACE_MSG(TRACE_ZDO1, "bdb_savepoint_before_rr", (FMT__0)); - - BDB_COMM_CTX().rejoin.rr_sv_authenticated = ZB_B2U(ZG->aps.authenticated); - BDB_COMM_CTX().rejoin.rr_sv_device_type = zb_get_device_type(); - - /* Save parent info. We do not want to reload it from nvram because neighbor table load supposes clear neighbor table. */ - BDB_COMM_CTX().rejoin.rr_sv_parent_short = 0xffff; - if (ZG->nwk.handle.parent != (zb_uint8_t)-1) - { - zb_neighbor_tbl_ent_t *nent = NULL; - zb_uint16_t addr = BDB_COMM_CTX().rejoin.rr_sv_parent_short; - zb_address_by_ref(BDB_COMM_CTX().rejoin.rr_sv_parent_long, &addr, ZG->nwk.handle.parent); - if (zb_nwk_neighbor_get(ZG->nwk.handle.parent, ZB_FALSE, &nent) == RET_OK) - { - BDB_COMM_CTX().rejoin.rr_sv_parent_nent = *nent; - } - } - /* All other information is now in our nvram. We can restore it from there. */ -} - -static void bdb_restore_cont(zb_uint8_t param) -{ - /* Undo effect of zdo_rejoin_clear_prev_join(). */ - /* If ZED, start poll again */ - if (ZB_IS_DEVICE_ZED()) - { - if (!ZB_U2B(ZB_PIBCACHE_RX_ON_WHEN_IDLE())) - { - zb_zdo_pim_start_poll(0); - } - zb_buf_free(param); - } - else - { - BDB_COMM_CTX().rejoin.rr_ignore_start_router_conf = 1; - ZB_SCHEDULE_CALLBACK(zb_zdo_start_router, param); - } -} - -static void bdb_restore_saved_rr(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_restore_saved_rr param %hd", (FMT__H, param)); - -#ifdef ZB_USE_NVRAM - /* get common dataset from nvram */ - ZB_NVRAM().ds_filter_cb = bdb_ds_filter_cb; - zb_nvram_load(); - ZB_NVRAM().ds_filter_cb = NULL; -#endif - - if (BDB_COMM_CTX().rejoin.rr_sv_parent_short != 0xffff) - { - /* Create and lock parent */ - zb_address_update(BDB_COMM_CTX().rejoin.rr_sv_parent_long, BDB_COMM_CTX().rejoin.rr_sv_parent_short, ZB_FALSE, &ZG->nwk.handle.parent); - } - else - { - /* Restore ZG->nwk.handle.parent from BDB_COMM_CTX().rejoin.rr_sv_parent_long */ - zb_address_by_ieee(BDB_COMM_CTX().rejoin.rr_sv_parent_long, ZB_FALSE, ZB_FALSE, &ZG->nwk.handle.parent); - } - - { - zb_neighbor_tbl_ent_t *nent = NULL; - - /* TODO: [Multi-MAC] set iface_id */ - if (zb_nwk_neighbor_get(ZG->nwk.handle.parent, ZB_TRUE, &nent) == RET_OK) - { - nent->relationship = ZB_NWK_RELATIONSHIP_PARENT; - } - } - - { - zb_address_ieee_ref_t ref; - zb_address_update(ZB_PIBCACHE_EXTENDED_ADDRESS(), - ZB_PIBCACHE_NETWORK_ADDRESS(), - ZB_TRUE, &ref); - } - ZB_NIB().device_type = (zb_nwk_device_type_t)BDB_COMM_CTX().rejoin.rr_sv_device_type; - ZG->aps.authenticated = ZB_U2B(BDB_COMM_CTX().rejoin.rr_sv_authenticated); - ZB_SET_JOINED_STATUS(ZB_TRUE); -#ifdef ZB_USE_NVRAM - zb_nvram_store_addr_n_nbt(); -#endif - - /* Now pibcache is filled by right values, but values are not pushed to MAC. Switch MAC channel etc. */ - zb_nwk_sync_pibcache_with_mac(param, bdb_restore_cont); -} -#endif /* #ifdef ZB_ZCL_ENABLE_WWAH_SERVER */ - -/* WWAH Rejoin procedure: - 1. Store existing network settings. - [Continue if Sleepy ED and join was NOT caused by Poll Control Check-in failure, else go to step - 5] - 2. Secure Rejoin on the Current Channel. - 3. TC Rejoin on the Current Channel. - 4. (optional, now skip) TC Rejoin on preferred channel list - [<<<] - [Continue if device is using unique TCLK, else go to step 8] - 5. TC Rejoin on all channels - 6. Back to previous network settings and - Wait for X seconds or until additional triggers (example: user button push) - a. Non-sleepy ED: X seconds will be equal to the Keepalive cluster value or 24 hours if - Keepalive cluster is not Implemented - b. Sleepy ED: if WWAH rejoin algorithm is implemented then the wait will be determined by the - WWAH rejoin algorithm, else 15 minutes - 7. Non-sleepy ED or ZR - back to step 3. - [These steps are only for Sleepy ED] - 8. Secure Rejoin on all channels. - 9. Back to previous network settings and - Wait for X seconds or until additional triggers - 10. Go to step 1. - - *When performing a rejoin on multiple channels, the device shall first perform a beacon survey on - the given set of channels, sort the resulting beacons using the WWAH prioritized parent - algorithm and prefer beacons with a higher network update ID when more than one share the same - WWAH parent priority. - */ -/* TODO: implement all rejoin triggers for ZR and ZED */ -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER -static void bdb_retry_rejoin_recovery(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_retry_rejoin_recovery param %hd", (FMT__H, param)); - if (!param) - { - zb_buf_get_out_delayed(bdb_retry_rejoin_recovery); - } - else - { - BDB_COMM_CTX().rejoin.waiting = 0; - bdb_commissioning_signal(BDB_COMM_CTX().rejoin.next_rejoin_signal, param); - } -} - -static void bdb_rejoin_machine(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_rejoin_machine param %hd signal %hd state %hd", - (FMT__H_H_H, param, BDB_COMM_CTX().signal, ZB_BDB().bdb_commissioning_step)); - - switch (BDB_COMM_CTX().signal) - { - case BDB_COMM_SIGNAL_REJOIN_START: - { - TRACE_MSG(TRACE_ZDO1, "Start Rejoin", (FMT__0)); - - /* Double-check this should be stopped during Rejoin */ - zb_zcl_wwah_stop_periodic_checkin(); - zb_zcl_wwah_stop_bad_parent_recovery(); - - if (!BDB_COMM_CTX().rejoin.rr_skip_savepoint) - { - bdb_savepoint_before_rr(); - } - - BDB_COMM_CTX().rejoin.rr_have_unique_tclk = (zb_secur_get_link_key_by_address(ZB_PIBCACHE_EXTENDED_ADDRESS(), ZB_SECUR_VERIFIED_KEY) != NULL); - -#ifdef ZB_NWK_BLACKLIST - zb_nwk_blacklist_reset(); -#endif - - if (!ZB_U2B(ZB_PIBCACHE_RX_ON_WHEN_IDLE()) && - !BDB_COMM_CTX().rejoin.rejoin_by_checkin_failure) - { - bdb_commissioning_signal(BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_CURRENT_CHANNEL, 0); - BDB_COMM_CTX().rejoin.last_rejoin_signal = BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_CURRENT_CHANNEL; - } - else - { - bdb_commissioning_signal(BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_ALL_CHANNELS, 0); - BDB_COMM_CTX().rejoin.last_rejoin_signal = BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_ALL_CHANNELS; - } - - /* Inform application that rejoin is started */ - zb_app_signal_pack(param, ZB_BDB_SIGNAL_WWAH_REJOIN_STARTED, - RET_OK, - 0); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - } - break; - - case BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_CURRENT_CHANNEL: - case BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_CURRENT_CHANNEL: - case BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_ALL_CHANNELS: - case BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_ALL_CHANNELS: - { - zb_channel_list_t channel_list; - zb_bool_t current_channel = - (zb_bool_t)(BDB_COMM_CTX().signal == BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_CURRENT_CHANNEL || - BDB_COMM_CTX().signal == BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_CURRENT_CHANNEL); - zb_bool_t secure = - (zb_bool_t)(BDB_COMM_CTX().signal == BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_CURRENT_CHANNEL || - BDB_COMM_CTX().signal == BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_ALL_CHANNELS); - - if (current_channel) - { - TRACE_MSG(TRACE_ZDO1, "Try rejoin over current page %hd channel %hd", - (FMT__H_H, ZB_PIBCACHE_CURRENT_PAGE(), ZB_PIBCACHE_CURRENT_CHANNEL())); - zb_channel_list_init(channel_list); - zb_channel_page_list_set_logical_channel(channel_list, ZB_PIBCACHE_CURRENT_PAGE(), - ZB_PIBCACHE_CURRENT_CHANNEL()); - } - else - { - /* FIXME: do we need to use preferred channels here? */ - TRACE_MSG(TRACE_ZDO1, "Try rejoin over all channels", (FMT__0)); - zb_channel_page_list_copy(channel_list, ZB_AIB().aps_channel_mask_list); - } - - if (secure) - { - ZG->aps.authenticated = ZB_TRUE; - } - - TRACE_MSG(TRACE_ZDO1, "rejoin secure %d", (FMT__D, secure)); - BDB_COMM_CTX().rejoin.last_rejoin_signal = BDB_COMM_CTX().signal; - -#if defined ZB_DISTRIBUTED_SECURITY_ON - if (!secure && IS_DISTRIBUTED_SECURITY()) - { - /* WWAH spec, 11.4 Parent and Hub Connectivity Recovery Procedure - Please note that for Distributed security networks, TC Rejoin is not supported. As a - result, for a device rejoining a Distributed security network, all steps involving TC - Rejoin shall be skipped. - */ - /* Skip rejoin by imitation that current step is failed */ - bdb_commissioning_signal(BDB_COMM_SIGNAL_NWK_JOIN_FAILED, param); - } - else -#endif - { - zb_ext_pan_id_t ext_pan_id; - zb_get_extended_pan_id(ext_pan_id); - - zdo_initiate_rejoin(param, ext_pan_id, - channel_list, - (zb_bool_t)secure); - } - } - break; - - case BDB_COMM_SIGNAL_NWK_AUTH_FAILED: - TRACE_MSG(TRACE_ZDO1, "Failed NWK authentication", (FMT__0)); - /* FALLTHROUGH */ - case BDB_COMM_SIGNAL_LEAVE_DONE: /* Is it possible? */ - case BDB_COMM_SIGNAL_NWK_JOIN_FAILED: - { - zb_bool_t need_to_wait = ZB_FALSE; - - TRACE_MSG(TRACE_ZDO1, "Failed rejoin", (FMT__0)); - - switch (BDB_COMM_CTX().rejoin.last_rejoin_signal) - { - case BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_CURRENT_CHANNEL: /* Step 2 */ - /* -> Step 3 */ - BDB_COMM_CTX().rejoin.next_rejoin_signal = - BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_CURRENT_CHANNEL; - break; - case BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_CURRENT_CHANNEL: /* Step 3 */ - { - if (BDB_COMM_CTX().rejoin.rr_have_unique_tclk) - { - /* Have unique TCLK: -> Step 5 */ - BDB_COMM_CTX().rejoin.next_rejoin_signal = - BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_ALL_CHANNELS; - } - else - { - /* Do not have unique TCLK */ - need_to_wait = ZB_TRUE; - - if (ZB_U2B(ZB_PIBCACHE_RX_ON_WHEN_IDLE())) - { - /* RX-ON: Wait, than back to step 3 */ - BDB_COMM_CTX().rejoin.next_rejoin_signal = - BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_CURRENT_CHANNEL; - } - else - { - /* Non-sleepy ED: Continue to step 8 */ - BDB_COMM_CTX().rejoin.next_rejoin_signal = - BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_ALL_CHANNELS; - } - } - } - break; - case BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_ALL_CHANNELS: /* Step 5 */ - { - /* -> Step 6 */ - need_to_wait = ZB_TRUE; - - if (ZB_U2B(ZB_PIBCACHE_RX_ON_WHEN_IDLE())) - { - /* Non-sleepy ED: Back to step 3 */ - BDB_COMM_CTX().rejoin.next_rejoin_signal = - BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_CURRENT_CHANNEL; - } - else - { - /* Non-sleepy ED: Continue to step 8 */ - BDB_COMM_CTX().rejoin.next_rejoin_signal = - BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_ALL_CHANNELS; - } - } - break; - case BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_ALL_CHANNELS: /* Step 8 */ - { - /* -> Step 9-10 */ - need_to_wait = ZB_TRUE; - BDB_COMM_CTX().rejoin.next_rejoin_signal = - BDB_COMM_SIGNAL_REJOIN_START; - } - break; - default: - ZB_ASSERT(0); /* debug */ - break; - } - - if (need_to_wait) - { - zb_time_t time_to_wait = 0; - - TRACE_MSG(TRACE_ZDO1, "skip savepoint %hd", (FMT__H, !BDB_COMM_CTX().rejoin.rr_skip_savepoint)); - - if (ZB_U2B(ZB_PIBCACHE_RX_ON_WHEN_IDLE())) - { - /* FIXME: TODO: remove direct access to WWAH ctx from commissioning level! */ - /* For Routers and Non-Sleepy End Devices, X seconds will be equal to the Keepalive - * cluster value of 24 hours if Keepalive cluster is not implemented. */ - if (WWAH_CTX().periodic_checkins.poll_method == ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_KEEPALIVE) - { - time_to_wait = (WWAH_CTX().periodic_checkins.keepalive_base + - ZB_RANDOM_VALUE(WWAH_CTX().periodic_checkins.keepalive_jitter)) * ZB_TIME_ONE_SECOND; - } - else - { - time_to_wait = ZB_ZCL_WWAH_REJOIN_NON_SLEEPY_ED_ROUTER_TIMEOUT; - } - } - else - { - ++BDB_COMM_CTX().rejoin.rr_global_retries; - -#ifdef ZB_JOIN_CLIENT - if (zb_zcl_wwah_get_rejoin_tmo(BDB_COMM_CTX().rejoin.rr_global_retries, &time_to_wait) == RET_EXIT) - { - /* Wait for next Full Rejoin cycle */ - BDB_COMM_CTX().rejoin.rr_global_retries = 0; - } -#endif - } - - if (!BDB_COMM_CTX().rejoin.rr_skip_savepoint) - { - ZB_SCHEDULE_CALLBACK(bdb_restore_saved_rr, param); - } - TRACE_MSG(TRACE_ZDO1, "retry rejoin, time_to_wait=%ld", (FMT__L, time_to_wait)); - BDB_COMM_CTX().rejoin.waiting = 1; - ZB_SCHEDULE_ALARM(bdb_retry_rejoin_recovery, 0, time_to_wait); - } - else - { - ZB_SCHEDULE_CALLBACK(bdb_retry_rejoin_recovery, param); - } - } - break; - - case BDB_COMM_SIGNAL_NWK_START_ROUTER_CONF: - if (BDB_COMM_CTX().rejoin.waiting) - { - /* Ignore START_ROUTER_CONF when it is triggered by bdb_restore_saved_rr(). */ - break; - } - /* FALLTHROUGH */ - case BDB_COMM_SIGNAL_NWK_JOIN_DONE: - TRACE_MSG(TRACE_ZDO1, "Device is joined", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_REJOIN_FINISH, param); - break; - - case BDB_COMM_SIGNAL_REJOIN_FINISH: - TRACE_MSG(TRACE_ZDO1, "Rejoin finished, finish BDB commissioning", (FMT__0)); - /* Go to next commissioning step - finish */ - ZB_BDB().bdb_commissioning_step = ZB_BDB_COMMISSIONING_STOP; - TRACE_MSG(TRACE_ZDO3, "ZB_BDB_COMMISSIONING_STOP", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_FINISH, param); - break; - - default: - TRACE_MSG(TRACE_ERROR, "Unknown signal %d", (FMT__D, BDB_COMM_CTX().signal)); - - TRACE_MSG(TRACE_ERROR, "Ignore (F&B implemented separately)", (FMT__0)); - if (param) - { - zb_buf_free(param); - } - break; - } -} - -#endif /* ZB_ZCL_ENABLE_WWAH_SERVER */ - -void bdb_start_rejoin_recovery(zb_uint8_t param, zb_uint16_t user_param) -{ -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER - TRACE_MSG(TRACE_ZDO1, ">> bdb_start_rejoin_recovery: param %hd user_param %d", (FMT__H_D, param, user_param)); - if (!param) - { - zb_buf_get_out_delayed_ext(bdb_start_rejoin_recovery, user_param, 0); - } - else - { - zb_uint8_t rejoin_reason = ZB_GET_LOW_BYTE(user_param); - - BDB_COMM_CTX().rejoin.rejoin_by_checkin_failure = - (rejoin_reason == BDB_COMM_REJOIN_REASON_POLL_CONTROL_CHECK_IN); - - BDB_COMM_CTX().rejoin.rr_global_retries = 0; - - ZB_BDB().bdb_commissioning_step = ZB_BDB_REJOIN; - bdb_commissioning_signal(BDB_COMM_SIGNAL_REJOIN_START, param); - } - TRACE_MSG(TRACE_ZDO1, "<< bdb_start_rejoin_recovery", (FMT__0)); -#else - ZVUNUSED(user_param); - TRACE_MSG(TRACE_ERROR, "bdb_start_rejoin_recovery: not supported!", (FMT__0)); - if (param) - { - zb_buf_free(param); - } -#endif -} - -#ifdef ZB_JOIN_CLIENT - -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER -void schedule_wwah_rejoin_backoff_attempt(zb_uint8_t param) -{ - if (!param) - { - zb_buf_get_out_delayed(schedule_wwah_rejoin_backoff_attempt); - } - else - { - zb_time_t backoff_interval = 0; - zb_uint8_t *rejoin_reason = NULL; - - TRACE_MSG(TRACE_ZDO1, ">>schedule_wwah_rejoin_backoff_attempt", (FMT__0)); - - TRACE_MSG(TRACE_ZDO1, "WWAH rejoin is enabled, scheduling next rejoin attempt", (FMT__0)); - - ++BDB_COMM_CTX().rejoin.rr_global_retries; - if (zb_zcl_wwah_get_rejoin_tmo(BDB_COMM_CTX().rejoin.rr_global_retries, &backoff_interval) == RET_EXIT) - { - BDB_COMM_CTX().rejoin.rr_global_retries = 0; - } - - TRACE_MSG(TRACE_ZDO1, "Next rejoin attempt in %hd", (FMT__H_H, backoff_interval)); - rejoin_reason = ZB_BUF_GET_PARAM(param, zb_uint8_t); - *rejoin_reason = ZB_REJOIN_REASON_BACKOFF_REJOIN; - ZB_SCHEDULE_ALARM(zdo_commissioning_initiate_rejoin, param, backoff_interval); - - TRACE_MSG(TRACE_ZDO1, "<> bdb_handle_initiate_rejoin_signal, param %d", (FMT__H, param)); - TRACE_MSG(TRACE_ZDO1, "Handle init rejoin, reason: %d", (FMT__D, rejoin_reason)); - - if (rejoin_reason == ZB_REJOIN_REASON_DEV_ANNCE_SENDING_FAILED) - { - /* manually stop commissioning and rejoin*/ - ZB_BDB().bdb_commissioning_step = ZB_BDB_COMMISSIONING_STOP; - BDB_COMM_CTX().signal = BDB_COMM_SIGNAL_FINISH; - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_DEV_ANNCE_SEND_FAILURE; - - ZB_SCHEDULE_CALLBACK(bdb_commissioning_machine, param); - } - else - { - bdb_force_rejoin_if_not_in_progress(param); - } - - TRACE_MSG(TRACE_ZDO1, "<< bdb_handle_initiate_rejoin_signal", (FMT__0)); -} - - -static void bdb_handle_dev_annce_sent_signal(zb_bufid_t param) -{ - /* This function is called in case when device_annce has been successfully sent. - Otherwise ZB_COMM_SIGNAL_INITIATE_REJOIN will be raised (bdb_handle_initiate_rejoin_signal). - */ -#ifndef NCP_MODE_HOST - bdb_initiate_key_exchange_if_needed(); -#endif /* NCP_MODE_HOST */ -#if !defined SNCP_MODE && defined ZB_ROUTER_ROLE - if (ZB_IS_DEVICE_ZR()) - { - ZB_SCHEDULE_CALLBACK(zb_zdo_start_router, param); - } - else -#endif /* !defined SNCP_MODE && defined ZB_ROUTER_ROLE */ - { - bdb_commissioning_signal(BDB_COMM_SIGNAL_NWK_JOIN_DONE, param); - } -} - - -static void bdb_handle_leave_done_signal(zb_bufid_t param) -{ - /* In r21 all case changed to bdb_commissioning_leave_done(). - * But it is not 100% equivalent. - * There is no zdo_retry_joining() call but is zb_zdo_reset_inform_user_app() call. - * Let's leave r22 behavior for now, but not sure it has no problems which fixed in r21. */ - - /* VP: Moved from zdo (zb_nlme_reset_confirm) to prevent races between reset_confirm_cb - * and bdb_commissioning_machine. */ - - /* FIXME: not very good check, but anyway. We need to differentiate 2 cases: - * 1st case: join is not complete - * 2nd case: join is complete and control was already passed to application - * If join is not complete (key exchange failed etc), schedule bdb iterations etc. - * If join is already completed, application may already initiate new steering etc, so do not - * touch bdb at all. */ - - /* TODO: Send special ZDO signal (LEAVE_DONE or so) - it will allow to avoid manual join - * restarting after leave (from application). */ - if (ZB_BDB().bdb_commissioning_step == ZB_BDB_COMMISSIONING_STOP) - { - TRACE_MSG(TRACE_NWK1, "BDB commissioning machine is already finished, do nothing", - (FMT__0)); - } - else - { - TRACE_MSG(TRACE_NWK1, "Scheduling BDB after leave step %d status %d", - (FMT__D_D, ZB_BDB().bdb_commissioning_step, ZB_BDB().bdb_commissioning_status)); - if (ZB_BDB().bdb_commissioning_status != ZB_BDB_STATUS_NO_NETWORK) - { - /* Probably bdb device failed to update tclk exchange */ - bdb_commissioning_signal(BDB_COMM_SIGNAL_LEAVE_DONE, 0); - } - else - { - /* Will be here after bdb device failed authentication - lets join to - * other networks */ - ZB_SCHEDULE_CALLBACK(zdo_retry_joining, 0); - } - } - - if (param != ZB_BUF_INVALID) - { - zb_buf_free(param); - } -} - - -#ifndef NCP_MODE_HOST - -static void bdb_initiate_key_exchange_if_needed(void) -{ - if (!IS_DISTRIBUTED_SECURITY() - && ZB_TCPOL().update_trust_center_link_keys_required - && !ZB_TCPOL().waiting_for_tclk_exchange) /* TCLK is not already in progress */ - { - zb_uint16_t aps_key_idx = (zb_uint16_t)-1; - - if (!ZB_IEEE_ADDR_IS_ZERO(ZB_AIB().trust_center_address)) - { - aps_key_idx = zb_aps_keypair_get_index_by_addr(ZB_AIB().trust_center_address, - ZB_SECUR_VERIFIED_KEY); - } - if (aps_key_idx == (zb_uint16_t)-1) - { - TRACE_MSG(TRACE_SECUR3, "BDB & !distributed - get TCLK over APS", (FMT__0)); - zdo_initiate_tclk_gen_over_aps(0); - } - } -} - - -static void bdb_handle_auth_ok_signal(zb_bufid_t param) -{ - /* Logic from this function has been moved to bdb_initiate_key_exchange_if_needed */ - if (param != ZB_BUF_INVALID) - { - zb_buf_free(param); - } -} - - -static void bdb_handle_rejoin_after_secur_failed_signal(zb_bufid_t param) -{ - zb_ext_pan_id_t ext_pan_id; - /* rejoin to current pan */ - zb_get_extended_pan_id(ext_pan_id); - zdo_initiate_rejoin(param, ext_pan_id, ZB_AIB().aps_channel_mask_list, ZB_FALSE); -} -#endif /* !NCP_MODE_HOST */ - - -static void bdb_handle_leave_with_rejoin_signal(zb_bufid_t param) -{ -#ifndef NCP_MODE_HOST - zb_uint8_t *rejoin_reason = NULL; -#endif - /* [MM]: 01/15/2018: Left this logic unchanged after - * refactoring. However, explained above is tricky and is required to be - * checked */ - - /* VP: currently we have both bdb join/rejoin and old-style join/rejoin logic and they are mixed. - In some case BDB device receives nwk leave (with rejoin in our case), then performing usual rejoin (without using BDB machine), - after join failure/success stack uses BDB commissioning machine to complete join process. This leads to calling bdb_commissioning_machine - without reset it's logic - then stack silently completes process without notifying application or further join attempts. - Temporarily fix: use BDB logic for rejoin on receiving leave (locally or remotely). - */ - zdo_inform_app_leave(ZB_NWK_LEAVE_TYPE_REJOIN); - -#ifndef NCP_MODE_HOST - rejoin_reason = ZB_BUF_GET_PARAM(param, zb_uint8_t); - *rejoin_reason = ZB_REJOIN_REASON_LEAVE_WITH_REJOIN; - ZB_SCHEDULE_CALLBACK(zdo_commissioning_initiate_rejoin, param); -#else - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_DEVICE_REBOOT; - zb_buf_free(param); -#endif - -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER - if (!ZB_PIBCACHE_RX_ON_WHEN_IDLE() - && zb_zcl_wwah_check_if_wwah_rejoin_enabled()) - { - BDB_COMM_CTX().rejoin.rr_global_retries = 0; - } -#endif -} - -#endif /* ZB_JOIN_CLIENT */ - - -#ifndef NCP_MODE_HOST -#ifdef ZB_COORDINATOR_ROLE - -static void bdb_handle_secured_rejoin_signal(zb_bufid_t param) -{ - zb_apsme_transport_key_req_t *req = ZB_BUF_GET_PARAM(param, zb_apsme_transport_key_req_t); - zb_address_ieee_ref_t ref_to_addr; - /* r21 doesn't use empty keys - * In r21 setup alarm waiting for unique TCLK request. - * Note: param must hold transport key request even while we do not - * actually send it there! - */ - /* - It IS possible to work not in BDB but require TCLK update (use case: certification tests). - But update_trust_center_link_keys_required flag is always presend and initialized to 1 during BDB init. - */ - /* Note: is somewhere in time we put update_trust_center_link_keys_required under ifdef, need to check for ZB_IN_BDB() here. - Remember ZB_IN_BDB() can be just 1 (BDB-only build). */ - if (ZB_TCPOL().update_trust_center_link_keys_required - && !IS_DISTRIBUTED_SECURITY() - && !zb_secur_get_link_key_by_address(req->dest_address.addr_long, ZB_SECUR_VERIFIED_KEY)) - { - /* Try to close link_key_alarm if address is found. - It's needed to remove possibility of - 'bdb_link_key_refresh_alarm' duplication - */ - if (zb_address_by_ieee(req->dest_address.addr_long, ZB_FALSE, ZB_FALSE, &ref_to_addr) == RET_OK) - { - bdb_cancel_link_key_refresh_alarm(bdb_link_key_refresh_alarm, ref_to_addr); - } - - ZB_SCHEDULE_ALARM(bdb_link_key_refresh_alarm, param, ZB_TCPOL().trust_center_node_join_timeout); - } - else - { - zb_buf_free(param); - } -} - - -static void bdb_handle_tclk_verified_remote_signal(zb_address_ieee_ref_t param) -{ - ZVUNUSED(param); -} - - -static void bdb_handle_device_left_signal(zb_address_ieee_ref_t param) -{ - ZVUNUSED(param); -} - - -#endif /* ZB_COORDINATOR_ROLE */ - -#endif /* !NCP_MODE_HOST */ - - -#ifdef ZB_FORMATION - -static void bdb_handle_formation_failed_signal(zb_bufid_t param) -{ - if (zb_buf_get_status(param) == RET_INTERRUPTED) - { - TRACE_MSG(TRACE_ZDO1, "formation was cancelled", (FMT__0)); - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_CANCELLED; - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_FORMATION_FINISH, param); - } - else - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_FORMATION_FAILURE; - ZB_SCHEDULE_CALLBACK(bdb_commissioning_machine, param); - } -} - -#endif /* ZB_FORMATION */ - - - -static void bdb_handle_comm_signal(zb_commissioning_signal_t signal, zb_bufid_t param) -{ - TRACE_MSG(TRACE_ZDO1, ">> bdb_handle_comm_signal, signal %d, param %d", - (FMT__D_D, signal, param)); - - switch(signal) - { - case ZB_COMM_SIGNAL_INIT: - bdb_force_link(); - if (param != ZB_BUF_INVALID) - { - zb_buf_free(param); - } - break; - case ZB_COMM_SIGNAL_START: - bdb_initiate_commissioning(param); - break; -#ifdef ZB_JOIN_CLIENT - case ZB_COMM_SIGNAL_NWK_DISC_FAILED: - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_DISCOVERY_FAILED, param); - break; - case ZB_COMM_SIGNAL_JOIN_FAILED: - bdb_handle_join_failed_signal(param); - break; - case ZB_COMM_SIGNAL_AUTH_FAILED: - bdb_commissioning_signal(BDB_COMM_SIGNAL_NWK_AUTH_FAILED, param); - break; - case ZB_COMM_SIGNAL_INITIATE_REJOIN: - bdb_handle_initiate_rejoin_signal(param); - break; - case ZB_COMM_SIGNAL_DEV_ANNCE_SENT: - bdb_handle_dev_annce_sent_signal(param); - break; - case ZB_COMM_SIGNAL_ROUTER_STARTED: - bdb_commissioning_signal(BDB_COMM_SIGNAL_NWK_START_ROUTER_CONF, param); - break; - case ZB_COMM_SIGNAL_TCLK_UPDATE_COMPLETE: - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_TCLK_DONE, param); - break; - case ZB_COMM_SIGNAL_TCLK_UPDATE_FAILED: - bdb_commissioning_signal(BDB_COMM_SIGNAL_NETWORK_STEERING_TCLK_EX_FAILURE, param); - break; - case ZB_COMM_SIGNAL_LEAVE_DONE: - bdb_handle_leave_done_signal(param); - break; - -#ifndef NCP_MODE_HOST - case ZB_COMM_SIGNAL_AUTH_OK: - bdb_handle_auth_ok_signal(param); - break; - case ZB_COMM_SIGNAL_SECUR_FAILED: - bdb_update_tclk_failed(param); - break; - case ZB_COMM_SIGNAL_REJOIN_AFTER_SECUR_FAILED: - bdb_handle_rejoin_after_secur_failed_signal(param); - break; -#endif /* !NCP_MODE_HOST */ - - case ZB_COMM_SIGNAL_LEAVE_WITH_REJOIN: - bdb_handle_leave_with_rejoin_signal(param); - break; -#endif /* ZB_JOIN_CLIENT */ - -#ifndef NCP_MODE_HOST - -#ifdef ZB_COORDINATOR_ROLE - case ZB_COMM_SIGNAL_SECURED_REJOIN: - bdb_handle_secured_rejoin_signal(param); - break; - case ZB_COMM_SIGNAL_TCLK_VERIFIED_REMOTE: - bdb_handle_tclk_verified_remote_signal(param); - break; - case ZB_COMM_SIGNAL_DEVICE_LEFT: - bdb_handle_device_left_signal(param); - break; -#endif /* ZB_COORDINATOR_ROLE */ - -#ifdef ZB_FORMATION - case ZB_COMM_SIGNAL_AUTHENTICATE_REMOTE: - zb_buf_free(param); - break; -#endif /* ZB_FORMATION */ - -#endif /* !NCP_MODE_HOST */ - -#ifdef ZB_FORMATION - case ZB_COMM_SIGNAL_FORMATION_DONE: - bdb_commissioning_signal(BDB_COMM_SIGNAL_NWK_FORMATION_OK, param); - break; - case ZB_COMM_SIGNAL_FORMATION_FAILED: - bdb_handle_formation_failed_signal(param); - break; -#endif /* ZB_FORMATION */ - - - default: - TRACE_MSG(TRACE_ERROR, "unknown commissioning signal: %d", (FMT__D, signal)); - ZB_ASSERT(0); - if (param != ZB_BUF_INVALID) - { - zb_buf_free(param); - } - } - - TRACE_MSG(TRACE_ZDO1, "<< bdb_handle_comm_signal", (FMT__0)); -} - -#ifdef ZB_ROUTER_ROLE - -static zb_uint8_t bdb_get_permit_join_duration(void) -{ - /* The network is closed by default */ - return 0; -} - -#if !defined ZB_COORDINATOR_ONLY && !defined NCP_MODE_HOST -static void bdb_handle_no_active_links_left_signal(zb_bufid_t param) -{ - if (ZB_BDB().bdb_commissioning_mode != ZB_BDB_TOUCHLINK_TARGET) - { - zb_send_no_active_links_left_signal(param); - } -} -#endif /* !ZB_COORDINATOR_ONLY && !NCP_MODE_HOST */ - -#endif /* #ifdef ZB_ROUTER_ROLE */ - - -#ifndef NCP_MODE_HOST - -static zb_bool_t bdb_must_use_installcode(zb_bool_t is_client) -{ - ZVUNUSED(is_client); -#ifdef ZB_SECURITY_INSTALLCODES - return (zb_bool_t)ZB_TCPOL().require_installcodes; -#else - return ZB_FALSE; -#endif /* ZB_SECURITY_INSTALLCODES */ -} - -#ifdef ZB_BDB_TOUCHLINK - -static zb_bool_t bdb_should_accept_frame_before_join(zb_bufid_t param) -{ - zb_bool_t ret; - - ZVUNUSED(param); - - TRACE_MSG(TRACE_ZDO2, "bdb_should_accept_frame_before_join, param %d", (FMT__D, param)); - - ret = ((ZB_BDB().bdb_commissioning_mode == ZB_BDB_TOUCHLINK_TARGET - || ZB_BDB().bdb_commissioning_mode == ZB_BDB_TOUCHLINK_COMMISSIONING) - && ZB_BDB().bdb_commissioning_status == ZB_BDB_STATUS_IN_PROGRESS); - - TRACE_MSG(TRACE_ZDO2, "<< bdb_should_accept_frame_before_join, ret %d", (FMT__D, ret)); - - return ret; -} - -#endif /* ZB_BDB_TOUCHLINK */ - -#endif /* !NCP_MODE_HOST */ - - -zb_uint8_t bdb_get_scan_duration(void) -{ - return ZB_BDB().bdb_scan_duration; -} - - -void bdb_set_scan_duration(zb_uint8_t duration) -{ - ZB_BDB().bdb_scan_duration = duration; -} - - -void zb_bdb_initiate_tc_rejoin(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - - if (param == ZB_UNDEFINED_BUFFER) - { - zb_buf_get_out_delayed(zb_bdb_initiate_tc_rejoin); - return; - } - - TRACE_MSG(TRACE_ZDO1, ">> zb_bdb_initiate_tc_rejoin, param %hd", (FMT__H, param)); - - if ((!zb_zdo_tclk_valid() || (zb_aib_get_coordinator_version() < 21)) - && !zb_aib_tcpol_get_allow_unsecure_tc_rejoins()) - { - TRACE_MSG(TRACE_ERROR, "TC rejoin is not allowed", (FMT__0)); - ret = RET_INVALID_STATE; - } - - if (ret == RET_OK) - { - TRACE_MSG(TRACE_ZDO1, "Start TC rejoin", (FMT__0)); - - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - ZB_BDB().bdb_commissioning_step = ZB_BDB_INITIALIZATION; - ZB_BDB().bdb_application_signal = ZB_BDB_SIGNAL_TC_REJOIN_DONE; - - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_TC_REJOIN, param); - } - else - { - (void)zb_app_signal_pack(param, ZB_BDB_SIGNAL_TC_REJOIN_DONE, ret, 0); - ZB_SCHEDULE_CALLBACK(zboss_signal_handler, param); - } - - TRACE_MSG(TRACE_ZDO1, "<< zb_bdb_initiate_tc_rejoin, ret %d", (FMT__D, ret)); -} - - -zb_ret_t zb_bdb_start_secured_rejoin(void) -{ - zb_ret_t ret; - - TRACE_MSG(TRACE_ZDO1, ">> zb_bdb_start_secured_rejoin, prev_comm_signal %hd", (FMT__H, BDB_COMM_CTX().signal)); - - ret = BDB_COMM_CTX().signal == BDB_COMM_SIGNAL_NWK_JOIN_FAILED ? RET_OK : RET_INVALID_STATE; - - if (ret == RET_OK) - { - TRACE_MSG(TRACE_ZDO2, "Start secured rejoin", (FMT__0)); - bdb_commissioning_signal(BDB_COMM_SIGNAL_INIT_SECURE_REJOIN, ZB_BUF_INVALID); - } - - TRACE_MSG(TRACE_ZDO1, "<< zb_bdb_start_secured_rejoin, ret %d", (FMT__D, ret)); - - return ret; -} - - -void bdb_force_link(void) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_force_link", (FMT__0)); - bdb_init(); - -#if defined ZB_BDB_TOUCHLINK && !defined NCP_MODE_HOST - ZG->nwk.selector.should_accept_frame_before_join = bdb_should_accept_frame_before_join; -#endif /* ZB_BDB_TOUCHLINK && !NCP_MODE_HOST */ -#if !defined NCP_MODE_HOST && defined ZB_JOIN_CLIENT - /* introduce some kind of setter? To be solved in the scope of ZBS-241 */ - ZG->nwk.selector.nwk_cancel_nwk_disc_resp = nwk_cancel_network_discovery_response; -#endif /* !defined NCP_MODE_HOST && defined ZB_JOIN_CLIENT */ - - COMM_SELECTOR().signal = bdb_handle_comm_signal; - COMM_SELECTOR().is_in_tc_rejoin = bdb_is_in_tc_rejoin; - -#ifdef ZB_JOIN_CLIENT - COMM_SELECTOR().get_scan_duration = bdb_get_scan_duration; -#endif - -#ifdef ZB_ROUTER_ROLE - COMM_SELECTOR().get_permit_join_duration = bdb_get_permit_join_duration; - -#if !defined ZB_COORDINATOR_ONLY && !defined NCP_MODE_HOST - ZG->nwk.selector.no_active_links_left_cb = bdb_handle_no_active_links_left_signal; -#endif /* !ZB_COORDINATOR_ONLY && !NCP_MODE_HOST */ - -#endif /* #ifdef ZB_ROUTER_ROLE */ - -#ifndef NCP_MODE_HOST - COMM_SELECTOR().must_use_install_code = bdb_must_use_installcode; -#endif /* !NCP_MODE_HOST */ -} - - -#ifdef ZB_ROUTER_ROLE - -void zb_set_network_router_role(zb_uint32_t channel_mask) -{ - bdb_force_link(); - - zb_set_network_router_role_with_mode(channel_mask, ZB_COMMISSIONING_BDB); -} - -#ifndef NCP_MODE_HOST -void zb_set_network_router_role_ext(zb_channel_list_t channel_list) -{ - bdb_force_link(); - zb_set_nwk_role_mode_common_ext(ZB_NWK_DEVICE_TYPE_ROUTER, - channel_list, - ZB_COMMISSIONING_BDB); -} -#endif /* !NCP_MODE_HOST */ - -#endif /* ZB_ROUTER_ROLE */ - - -#ifdef ZB_ED_FUNC - -void zb_set_network_ed_role(zb_uint32_t channel_mask) -{ - bdb_force_link(); - zb_set_network_ed_role_with_mode(channel_mask, ZB_COMMISSIONING_BDB); -} - - -#ifndef NCP_MODE_HOST -void zb_set_network_ed_role_ext(zb_channel_list_t channel_list) -{ - bdb_force_link(); - zb_set_nwk_role_mode_common_ext(ZB_NWK_DEVICE_TYPE_ED, - channel_list, - ZB_COMMISSIONING_BDB); -} -#endif /* !NCP_MODE_HOST */ - -#endif /* ZB_ED_FUNC */ - -/*! \addtogroup zboss_bdb_api */ -/*! @{ */ - -void zb_set_bdb_primary_channel_set(zb_uint32_t channel_mask) -{ - ZB_BDB().bdb_primary_channel_set = channel_mask; -} - -zb_uint32_t zb_get_bdb_primary_channel_set() -{ - return ZB_BDB().bdb_primary_channel_set; -} - -void zb_set_bdb_secondary_channel_set(zb_uint32_t channel_mask) -{ - ZB_BDB().bdb_secondary_channel_set = channel_mask; -} - -zb_uint32_t zb_get_bdb_secondary_channel_set() -{ - return ZB_BDB().bdb_secondary_channel_set; -} - -void zb_bdb_set_legacy_device_support(zb_uint8_t enable) -{ - /* WARNING: Turn off link key exchange if legacy device support (= ZB_BDB_NETWORK_STEERING - Actions: return RET_PENDING, it is too late to cancel - 10. Steering is in progress, but already cancelled - Conditions: ZB_BDB().bdb_commissioning_step == ZB_BDB_NETWORK_STEERING - ZB_BDB().bdb_op_cancelled == ZB_TRUE - Actions: return RET_IGNORE - */ - - zb_ret_t ret; - - TRACE_MSG(TRACE_ZDO1, ">> bdb_cancel_joining, buf %d", (FMT__P, buf)); - - if (buf == 0U) - { - TRACE_MSG(TRACE_ERROR, "no buffer provided, ignore this request", (FMT__0)); - return; - } - - do - { - if (ZB_IS_DEVICE_ZC()) - { - ret = RET_ILLEGAL_REQUEST; - break; - } - - if (zb_zdo_joined()) - { - ret = RET_INVALID_STATE; - break; - } - - if (ZB_BDB().bdb_op_cancelled == ZB_TRUE) - { - ret = RET_IGNORE; - break; - } - - if (ZB_BDB().bdb_commissioning_mode != ZB_BDB_NETWORK_STEERING) - { - ret = RET_INVALID_STATE; - break; - } - - if (ZB_BDB().bdb_commissioning_step > ZB_BDB_NETWORK_STEERING) - { - ret = RET_PENDING; - break; - } - - ZB_BDB().bdb_op_cancelled = ZB_TRUE; - - if (ZB_BDB().bdb_commissioning_step < ZB_BDB_NETWORK_STEERING) - { - ret = RET_OK; - break; - } - - if (try_to_cancel_nwk_discovery_alarm()) - { - TRACE_MSG(TRACE_ZDO1, "discovery alarm cancelled", (FMT__0)); - ret = RET_OK; - break; - } - - ZB_SCHEDULE_CALLBACK(zb_nwk_cancel_network_discovery, buf); - ret = RET_BUSY; - - } while(0); - - if (ret != RET_BUSY) - { - TRACE_MSG(TRACE_ZDO1, "status %d, calling a cb", (FMT__D, ret)); - bdb_send_steering_cancelled_signal(buf, ret); - } - - TRACE_MSG(TRACE_ZDO1, "<< bdb_cancel_joining, ret %d", (FMT__D, ret)); -} - - -static void nwk_cancel_network_discovery_response(zb_bufid_t buf) -{ - zb_ret_t status; - - TRACE_MSG(TRACE_ZDO1, ">> nwk_cancel_network_discovery_response, buf %d", (FMT__D, buf)); - - ZB_ASSERT(buf != 0U); - - status = *ZB_BUF_GET_PARAM(buf, zb_ret_t); - - TRACE_MSG(TRACE_ZDO1, "status %d", (FMT__D, status)); - - switch(status) - { - case RET_OK: - case RET_IGNORE: - /* pass the status to the app */ - break; - case RET_INVALID_STATE: - if (try_to_cancel_nwk_discovery_alarm()) - { - TRACE_MSG(TRACE_ZDO1, "discovery alarm cancelled", (FMT__0)); - status = RET_OK; - break; - } - else - { - status = RET_PENDING; - } - break; - default: - TRACE_MSG(TRACE_ERROR, "unexpected status: %d", (FMT__D, status)); - ZB_ASSERT(0); - break; - } - - bdb_send_steering_cancelled_signal(buf, status); - - TRACE_MSG(TRACE_ZDO1, "<< nwk_cancel_network_discovery_response", (FMT__0)); -} - -#endif /* ZB_JOIN_CLIENT */ - -#endif /* NCP_MODE_HOST */ - -static void zb_bdb_close_network_local(zb_bufid_t buf) -{ - zb_zdo_mgmt_permit_joining_req_param_t *req_param; - - req_param = ZB_BUF_GET_PARAM(buf, zb_zdo_mgmt_permit_joining_req_param_t); - - ZB_BZERO(req_param, sizeof(zb_zdo_mgmt_permit_joining_req_param_t)); - req_param->dest_addr = ZB_PIBCACHE_NETWORK_ADDRESS(); - req_param->permit_duration = 0; - req_param->tc_significance = 1; - - (void)zb_zdo_mgmt_permit_joining_req(buf, NULL); -} - - -zb_ret_t zb_bdb_close_network(zb_bufid_t buf) -{ - zb_ret_t ret = RET_OK; - zb_uint8_t tsn = ZB_ZDO_INVALID_TSN; - - if (buf == ZB_BUF_INVALID) - { - buf = zb_buf_get_out(); - } - - if (buf != ZB_BUF_INVALID) - { - zb_zdo_mgmt_permit_joining_req_param_t *req_param; - - - TRACE_MSG(TRACE_ZDO3, ">> zb_bdb_close_network", (FMT__0)); - - req_param = ZB_BUF_GET_PARAM(buf, zb_zdo_mgmt_permit_joining_req_param_t); - - ZB_BZERO(req_param, sizeof(zb_zdo_mgmt_permit_joining_req_param_t)); - req_param->dest_addr = ZB_NWK_BROADCAST_ROUTER_COORDINATOR; - req_param->permit_duration = 0; - req_param->tc_significance = 1; - - if (zb_get_device_type() == ZB_NWK_DEVICE_TYPE_COORDINATOR || - zb_get_device_type() == ZB_NWK_DEVICE_TYPE_ROUTER) - { - tsn = zb_zdo_mgmt_permit_joining_req(buf, zb_bdb_close_network_local); - } - else - { - tsn = zb_zdo_mgmt_permit_joining_req(buf, NULL); - } - - if (tsn == ZB_ZDO_INVALID_TSN) - { - TRACE_MSG(TRACE_ERROR, "Failed to create permit request", (FMT__0)); - ret = RET_ERROR; - } - } - else - { - TRACE_MSG(TRACE_ERROR, "Unable to get buffer", (FMT__0)); - ret = RET_NO_MEMORY; - } - - TRACE_MSG(TRACE_ZDO3, "<< zb_bdb_close_network", (FMT__0)); - return ret; -} - - -/*! @} */ - -#endif /* ZB_BDB_MODE && !BDB_OLD */ diff --git a/zboss/development/src/commissioning/bdb/zdo_commissioning_bdb_formation.c b/zboss/development/src/commissioning/bdb/zdo_commissioning_bdb_formation.c deleted file mode 100644 index 4ee56afb5a..0000000000 --- a/zboss/development/src/commissioning/bdb/zdo_commissioning_bdb_formation.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: BDD specific commissioning. Formation part. -*/ - -#define ZB_TRACE_FILE_ID 99 - -#include "zb_common.h" -#include "zb_scheduler.h" -#include "zb_bufpool.h" -#include "zb_nwk.h" -#include "zb_nwk_nib.h" -#include "zb_aps.h" -#include "zb_zdo.h" -#include "zb_secur.h" -#include "zb_secur_api.h" -#include "zb_nvram.h" -#include "zb_bdb_internal.h" - - -#if defined ZB_FORMATION - -#ifndef NCP_MODE_HOST -static void nwk_cancel_network_formation_response(zb_bufid_t buf); -#endif /* NCP_MODE_HOST */ - -static void bdb_formation(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZDO3, "bdb_formation param %hd", (FMT__H, param)); - - /* See Figure 5 - Network formation procedure */ - - if (ZB_BDB().v_do_primary_scan == ZB_BDB_JOIN_MACHINE_PRIMARY_SCAN - && ZB_BDB().bdb_primary_channel_set != 0) - { - ZB_BDB().v_do_primary_scan = ZB_BDB_JOIN_MACHINE_SECONDARY_SCAN_START; - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - ZB_BDB().v_scan_channels = ZB_BDB().bdb_primary_channel_set; - TRACE_MSG(TRACE_ZDO1, "Doing formation channel mask 0x%lx", (FMT__L, ZB_BDB().v_scan_channels)); - /* call directly to simplify cancellation logic */ - zdo_start_formation(param); - } - else if ((ZB_BDB().v_do_primary_scan == ZB_BDB_JOIN_MACHINE_SECONDARY_SCAN_START - && ZB_BDB().bdb_secondary_channel_set != 0) - || - (ZB_BDB().v_do_primary_scan == ZB_BDB_JOIN_MACHINE_PRIMARY_SCAN - && ZB_BDB().bdb_secondary_channel_set != 0 - && ZB_BDB().bdb_primary_channel_set == 0)) - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_IN_PROGRESS; - ZB_BDB().v_do_primary_scan = ZB_BDB_JOIN_MACHINE_SECONDARY_SCAN_DONE; - ZB_BDB().v_scan_channels = ZB_BDB().bdb_secondary_channel_set; - TRACE_MSG(TRACE_ZDO1, "Doing formation channel mask 0x%lx", (FMT__L, ZB_BDB().v_scan_channels)); - /* call directly to simplify cancellation logic */ - zdo_start_formation(param); - } - else - { - ZB_BDB().bdb_commissioning_status = ZB_BDB_STATUS_FORMATION_FAILURE; - TRACE_MSG(TRACE_ZDO1, "BDB: Formation failed run next bdb machine step", (FMT__0)); - ZB_BDB().v_do_primary_scan = ZB_BDB_JOIN_MACHINE_PRIMARY_SCAN; - ZB_BDB().bdb_commissioning_step <<= 1; - ZB_SCHEDULE_CALLBACK(bdb_commissioning_machine, param); - } -} - - -static void bdb_commissioning_formation_channels_mask(zb_channel_list_t list) -{ - zb_uint32_t mask; - -#if defined ZB_SUB_GHZ_ZB30_SUPPORT - zb_uint8_t used_page; -#endif /* ZB_SUB_GHZ_ZB30_SUPPORT */ - - mask = ZB_BDB().v_scan_channels; - - zb_channel_list_init(list); - -#if defined ZB_SUB_GHZ_ZB30_SUPPORT - used_page = zb_aib_channel_page_list_get_first_filled_page(); - zb_channel_page_list_set_mask(list, used_page, mask); -#else - zb_channel_page_list_set_mask(list, ZB_CHANNEL_LIST_PAGE0_IDX, mask); -#endif /* !ZB_SUB_GHZ_ZB30_SUPPORT */ - -} - - -static void bdb_formation_force_link(void) -{ -#ifndef NCP_MODE_HOST - /* introduce some kind of setter? To be solved in the scope of ZBS-241 */ - ZG->nwk.selector.nwk_cancel_nwk_form_resp = nwk_cancel_network_formation_response; -#endif /* NCP_MODE_HOST */ - zdo_formation_force_link(); - - FORMATION_SELECTOR().start_formation = bdb_formation; - FORMATION_SELECTOR().get_formation_channels_mask = bdb_commissioning_formation_channels_mask; - FORMATION_SELECTOR().get_scan_duration = bdb_get_scan_duration; -} - -#ifdef ZB_COORDINATOR_ROLE - -void zb_set_network_coordinator_role(zb_uint32_t channel_mask) -{ - bdb_force_link(); - bdb_formation_force_link(); - zb_set_network_coordinator_role_with_mode(channel_mask, ZB_COMMISSIONING_BDB); -} - -#ifndef NCP_MODE_HOST -void zb_set_network_coordinator_role_ext(zb_channel_list_t channel_list) -{ - bdb_force_link(); - bdb_formation_force_link(); - zb_set_nwk_role_mode_common_ext(ZB_NWK_DEVICE_TYPE_COORDINATOR, - channel_list, - ZB_COMMISSIONING_BDB); -} -#endif /* !NCP_MODE_HOST */ - -#endif /* ZB_COORDINATOR_ROLE */ - - -#ifdef ZB_DISTRIBUTED_SECURITY_ON - -void zb_enable_distributed(void) -{ - bdb_formation_force_link(); -} - -void zb_disable_distributed(void) -{ - FORMATION_SELECTOR().start_formation = NULL; - FORMATION_SELECTOR().get_formation_channels_mask = NULL; - ZB_IEEE_ADDR_COPY(ZB_AIB().trust_center_address, g_zero_addr); -} - -#endif /* ZB_DISTRIBUTED_SECURITY_ON */ - -#ifndef NCP_MODE_HOST -/* these functions are not supported for NCP now. - Will be resolved in scope of ZBS-241 */ - -static void bdb_send_formation_cancelled_signal(zb_bufid_t buf, zb_ret_t status) -{ - TRACE_MSG(TRACE_ZDO1, "bdb_send_formation_cancelled_signal, buf %d, status %d", - (FMT__D_D, buf, status)); - - (void)zb_app_signal_pack_with_detailed_status(buf, ZB_BDB_SIGNAL_FORMATION_CANCELLED, status, 0); - ZB_SCHEDULE_CALLBACK(zboss_signal_handler, buf); -} - - -void bdb_cancel_formation(zb_bufid_t buf) -{ - /* The states this function can be called: - 1. No formation (initiated by bdb_start_top_level_commissioning) is in progress - Conditions: ZB_BDB().bdb_commissioning_mode != ZB_BDB_NETWORK_FORMATION - Actions: return RET_INVALID_STATE - 2. Formation is in progress, network formation is not sent yet - Conditions: ZB_BDB().bdb_commissioning_step <= ZB_BDB_NETWORK_FORMATION - Actions: set ZB_BDB().bdb_op_cancelled flag - return RET_OK - 3. Formation is in progress, network formation is scheduled - Conditions: ZB_BDB().bdb_commissioning_step == ZB_BDB_NETWORK_FORMATION - Actions: call zb_nwk_cancel_network_formation() - zb_nwk_cancel_network_formation will return RET_OK - return RET_OK - 4. Formation is in progress, NWK layer formation is in progress - Conditions: ZB_BDB().bdb_commissioning_step == ZB_BDB_NETWORK_FORMATION - Actions: call zb_nwk_cancel_network_formation() - zb_nwk_cancel_network_formation will return RET_OK (if it possible to cancel) - or RET_INVALID_STATE (if it is too late to cancel a formation) - return RET_OK or RET_PENDING - 5. Formation is in progress, formation confirm is scheduled - Conditions: ZB_BDB().bdb_commissioning_step == ZB_BDB_NETWORK_FORMATION - Actions: call zb_nwk_cancel_network_formation() - zb_nwk_cancel_network_formation will return RET_INVALID_STATE - return RET_PENDING - 6. Formation is in progress, formation confirm is scheduled - Conditions: ZB_BDB().bdb_commissioning_step == ZB_BDB_NETWORK_FORMATION - Actions: call zb_nwk_cancel_network_formation() - zb_nwk_cancel_network_formation will return RET_INVALID_STATE - return RET_PENDING - 7. Formation is in progress, NWK layer formation is already cancelled - Conditions: ZB_BDB().bdb_commissioning_step == ZB_BDB_NETWORK_FORMATION - Actions: call zb_nwk_cancel_network_formation() - zb_nwk_cancel_network_formation() will return RET_IGNORE - return RET_IGNORE - 8. Formation is in progress, but already cancelled - Conditions: ZB_BDB().bdb_commissioning_step == ZB_BDB_NETWORK_FORMATION - ZB_BDB().bdb_op_cancelled == ZB_TRUE - Actions: return RET_IGNORE - */ - - zb_ret_t ret; - - TRACE_MSG(TRACE_ZDO1, ">> bdb_cancel_formation, buf %d", (FMT__D, buf)); - - if (buf == 0U) - { - TRACE_MSG(TRACE_ERROR, "no buffer provided, ignore this request", (FMT__0)); - return; - } - - do - { - if (ZB_BDB().bdb_op_cancelled == ZB_TRUE) - { - ret = RET_IGNORE; - break; - } - - if (ZB_BDB().bdb_commissioning_mode != ZB_BDB_NETWORK_FORMATION) - { - ret = RET_INVALID_STATE; - break; - } - - if (ZB_BDB().bdb_commissioning_step > ZB_BDB_NETWORK_FORMATION) - { - ret = RET_PENDING; - break; - } - - ZB_BDB().bdb_op_cancelled = ZB_TRUE; - - if (ZB_BDB().bdb_commissioning_step < ZB_BDB_NETWORK_FORMATION) - { - ret = RET_OK; - break; - } - - ZB_SCHEDULE_CALLBACK(zb_nwk_cancel_network_formation, buf); - ret = RET_BUSY; - } while (0); - - if (ret != RET_BUSY) - { - TRACE_MSG(TRACE_ZDO1, "status %d, calling a cb", (FMT__D, ret)); - bdb_send_formation_cancelled_signal(buf, ret); - } - - TRACE_MSG(TRACE_ZDO1, "<< bdb_cancel_formation", (FMT__0)); -} - - -static void nwk_cancel_network_formation_response(zb_bufid_t buf) -{ - zb_ret_t status; - - TRACE_MSG(TRACE_ZDO1, ">> nwk_cancel_network_formation_response, buf %d", (FMT__D, buf)); - - ZB_ASSERT(buf != 0U); - - status = *ZB_BUF_GET_PARAM(buf, zb_ret_t); - - TRACE_MSG(TRACE_ZDO1, "status %d", (FMT__D, status)); - - switch(status) - { - case RET_OK: - case RET_IGNORE: - /* pass the status to the app */ - break; - case RET_INVALID_STATE: - /* it is too late to cancel formation */ - status = RET_PENDING; - break; - default: - TRACE_MSG(TRACE_ERROR, "unexpected status: %d", (FMT__D, status)); - ZB_ASSERT(0); - break; - } - - bdb_send_formation_cancelled_signal(buf, status); - - TRACE_MSG(TRACE_ZDO1, "<< nwk_cancel_network_formation_response", (FMT__0)); -} - -#endif /* NCP_MODE_HOST */ - -#endif /* ZB_FORMATION */ diff --git a/zboss/development/src/commissioning/legacy/zdo_commissioning_classic.c b/zboss/development/src/commissioning/legacy/zdo_commissioning_classic.c deleted file mode 100644 index 6391e73f01..0000000000 --- a/zboss/development/src/commissioning/legacy/zdo_commissioning_classic.c +++ /dev/null @@ -1,761 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Classic ZB commissioning: defined in Core specification and HA -*/ - - -#define ZB_TRACE_FILE_ID 67 -#include "zb_common.h" - -#ifdef ZB_COMMISSIONING_CLASSIC_SUPPORT -#include "zb_scheduler.h" -#include "zb_bufpool.h" -#include "zb_nwk.h" -#include "zb_nwk_nib.h" -#include "zb_aps.h" -#include "zb_zdo.h" -#include "zb_secur.h" -#include "zb_secur_api.h" -#include "zb_nvram.h" -#include "zb_bdb_internal.h" - -static void zdo_classic_commissioning_force_link(void); - -#ifdef ZB_FORMATION -static void zdo_classic_formation_force_link(void); -#endif /* ZB_FORMATION */ - -#ifdef ZB_JOIN_CLIENT -static void zdo_restart_association(zb_uint8_t param); -#endif /* ZB_JOIN_CLIENT */ - - -void zdo_classic_initiate_commissioning(zb_uint8_t param) -{ - zb_ext_pan_id_t use_ext_pan_id; - - TRACE_MSG(TRACE_ZDO1, "zdo_classic_initiate_commissioning param %hd device type %d", - (FMT__H_D_D, param, zb_get_device_type())); - - ZB_ASSERT(zb_get_device_type() != ZB_NWK_DEVICE_TYPE_NONE); - - zb_get_use_extended_pan_id(use_ext_pan_id); - - /* a. Maybe Formation */ - /*cstat -MISRAC2012-Rule-2.1_b*/ - if (ZB_IS_DEVICE_ZC() -#if defined ZB_ROUTER_ROLE && defined ZB_DISTRIBUTED_SECURITY_ON - /* Not joined ZR with TC addr -1 means: start Distributed formation.*/ - || (zb_tc_is_distributed() - && ZB_IS_DEVICE_ZR() - && !zb_zdo_joined()) -#endif - ) - { - BDB_COMM_CTX().bdb_application_signal = ZB_ZDO_SIGNAL_DEFAULT_START; - - /** @mdr{00012,44} */ - /*cstat +MISRAC2012-Rule-2.1_b*/ -#if defined ZB_FORMATION - ZB_ASSERT(FORMATION_SELECTOR().start_formation); - ZB_SCHEDULE_CALLBACK(FORMATION_SELECTOR().start_formation, param); -#else - TRACE_MSG(TRACE_MAC1, "Coordinator role is not supported", (FMT__0)); - zb_buf_free(param); -#endif - } - /* Rejoin after reboot? */ -#ifdef ZB_JOIN_CLIENT - else if (!ZB_EXTPANID_IS_ZERO(ZB_NIB_EXT_PAN_ID())) - { - /* try to rejoin the current network: - use apsChannelMask as channel mask and do unsecure rejoin - if we are not authenticated. - */ - BDB_COMM_CTX().bdb_application_signal = ZB_BDB_SIGNAL_DEVICE_REBOOT; - (void)zdo_initiate_rejoin(param, ZB_NIB_EXT_PAN_ID(), - ZB_AIB().aps_channel_mask_list, - zb_zdo_authenticated()); - } - /* Rejoin to the net defined by aps_use_extended_pan_id */ - else if (!ZB_EXTPANID_IS_ZERO(use_ext_pan_id)) - { - BDB_COMM_CTX().bdb_application_signal = ZB_BDB_SIGNAL_DEVICE_REBOOT; - /* If the device is not the designated coordinator and apsUseExtendedPANID - has a non-zero value, the device should attempt to rejoin the network - specified in apsUseExtendedPANID. To do this, it should use NLME-JOIN.request - with the ExtendedPANID parameter equal to the value of apsUseExtendedPANID, the - ScanChannels parameter of the primitive equal to the value of the apsChannelMask - configuration attribute. The RejoinNetwork parameter of the NLME-JOIN.request - primitive should have a value of 0x02 indicating rejoin. */ - (void)zdo_initiate_rejoin(param, use_ext_pan_id, - ZB_AIB().aps_channel_mask_list, - ZB_FALSE); - } - else - { - /* ZR: discovery, then join */ - zb_nlme_network_discovery_request_t *req = ZB_BUF_GET_PARAM(param, zb_nlme_network_discovery_request_t); - - zb_channel_page_list_copy(req->scan_channels_list, ZB_AIB().aps_channel_mask_list); - req->scan_duration = ZB_DEFAULT_SCAN_DURATION; /* TODO: configure it somehow? */ - TRACE_MSG(TRACE_APS1, "discovery, then join by association, scan attempts %hd", (FMT__H, COMM_CTX().discovery_ctx.nwk_scan_attempts)); - - COMM_CTX().discovery_ctx.disc_count = COMM_CTX().discovery_ctx.nwk_scan_attempts; - ZB_SCHEDULE_CALLBACK(zb_nlme_network_discovery_request, param); - } -#endif /* ZB_JOIN_CLIENT */ -} - -#ifdef ZB_JOIN_CLIENT -static void zdo_restart_association(zb_uint8_t param) -{ - zb_nlme_network_discovery_request_t *req = ZB_BUF_GET_PARAM(param, zb_nlme_network_discovery_request_t); - TRACE_MSG(TRACE_ERROR, "rejoin failed - try association", (FMT__0)); - - ZB_ASSERT(zb_get_device_type() != ZB_NWK_DEVICE_TYPE_NONE); - - TRACE_MSG(TRACE_ZDO1, "Dev type %hd", (FMT__H, zb_get_device_type())); - ZG->zdo.handle.rejoin = ZB_FALSE; - - zb_channel_page_list_copy(req->scan_channels_list, ZB_AIB().aps_channel_mask_list); - req->scan_duration = ZB_DEFAULT_SCAN_DURATION; /* TODO: configure it somehow? */ - COMM_CTX().discovery_ctx.disc_count = COMM_CTX().discovery_ctx.nwk_scan_attempts; - ZB_SCHEDULE_CALLBACK(zb_nlme_network_discovery_request, param); -} - - -static void zdo_classic_handle_nwk_disc_failed_signal(zb_bufid_t param) -{ - TRACE_MSG(TRACE_ZDO2, "Calling zb_zdo_startup_complete_int to indicate nwk discovery failure", - (FMT__0)); - (void)zb_app_signal_pack(param, ZB_ZDO_SIGNAL_DEFAULT_START, (zb_int16_t)ZB_NWK_STATUS_NOT_PERMITTED, 0U); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); -} - - -static void zdo_classic_handle_join_failed_signal(zb_bufid_t param) -{ - if (ZB_U2B(ZG->zdo.handle.rejoin) && ZB_U2B(ZB_AIB().aps_insecure_join) && !ZB_U2B(ZB_AIB().always_rejoin)) - { - /* FIXME: Do we really need to mix rejoin - Association - rejoin - Association - ... ? - Also - if we dropped to association, looks like we need to erase network data before. It - is really strange case when we do unsuccessful association attempt (no more children - available), and then successful rejoin attempt to the same network. - */ - TRACE_MSG(TRACE_ZDO1, "rejoin failed - try nwk search & association", (FMT__0)); - ZB_SCHEDULE_CALLBACK(zdo_restart_association, param); - } - else - { - if (ZB_U2B(COMM_CTX().discovery_ctx.scanlist_ref)) - { - zb_buf_free(param); - TRACE_MSG(TRACE_ZDO1, "{re}join failed", (FMT__0)); - ZB_SCHEDULE_CALLBACK(zdo_retry_joining, 0); - } - else - { - TRACE_MSG(TRACE_ZDO1, "{re}join totally failed - inform user", (FMT__0)); - (void)zb_app_signal_pack(param, ZB_ZDO_SIGNAL_DEFAULT_START, (zb_int16_t)ZB_NWK_STATUS_NOT_PERMITTED, 0U); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - } - } -} - - -static void zdo_classic_handle_authentication_failed_signal(zb_bufid_t param) -{ -/* - 2.1 Standard Security Mode - - If the joining device - did not receive the key via the APSME-TRANSPORT-KEY.indication within the - apsSecurityTimeOutPeriod since receiving the NLME-JOIN.confirm primitive, it - shall reset and may choose to start the joining procedure again. - - In - - 11.29 TP/SEC/BV-29 -I Security NWK Remove II-ZR - Objective: DUT as ZR removes - (DUT ZED2 performs silent leave). - - So it is unclear: do we need to just leave or join again? - Let's leave to satisfy TC. -*/ -/* NK: If we are in rejoin procedure, do "silent" rejoin, else - do "silent" leave */ - if (ZG->zdo.handle.rejoin -#ifdef ZB_CERTIFICATION_HACKS - && !ZB_CERT_HACKS().disable_cyclic_tc_rejoin -#endif - ) - { -#ifdef ZB_REJOIN_BACKOFF - if (zb_zdo_rejoin_backoff_is_running()) - { - /* Go to new rejoin backoff iteration */ - zb_zdo_rejoin_backoff_iteration_done(); - ZB_SCHEDULE_CALLBACK(zb_zdo_rejoin_backoff_continue, 0); - zb_buf_free(param); - } - else -#endif - { - zb_ext_pan_id_t ext_pan_id; - zb_get_extended_pan_id(ext_pan_id); - /* force unsecure (AKA Trust Center) rejoin to current pan */ - (void)zdo_initiate_rejoin(param, ext_pan_id, - ZB_AIB().aps_channel_mask_list, ZB_FALSE); - } - } - else - { - TRACE_MSG(TRACE_ERROR, "zdo_authentication_failed - Leave", (FMT__0)); -#ifndef ZB_MULTILEAVE_HACK - zdo_commissioning_leave(param, ZB_FALSE, ZB_FALSE); - ZB_ZDO_SET_UNAUTH(); /* Call unauth_delayed after leave */ -#else - ZB_SET_JOINED_STATUS(ZB_FALSE); - zb_buf_free(param); - (void)zb_buf_get_out_delayed_ext(zb_zdo_startup_complete_int_delayed, ZB_NWK_STATUS_NO_KEY); -#endif - } -} - -static void zdo_classic_rejoin(zb_bufid_t param) -{ - zb_ext_pan_id_t ext_pan_id; - - zb_get_extended_pan_id(ext_pan_id); - (void)zdo_initiate_rejoin(param, ext_pan_id, - ZB_AIB().aps_channel_mask_list, zb_zdo_authenticated()); -} - - -static void zdo_classic_handle_initiate_rejoin_signal(zb_bufid_t param) -{ - zb_uint8_t *p = zb_buf_get_tail(param, sizeof(zb_uint8_t)); - zb_uint8_t rejoin_reason = *p; - - if (rejoin_reason == ZB_REJOIN_REASON_DEV_ANNCE_SENDING_FAILED) - { - TRACE_MSG(TRACE_ZDO1, "DEV_ANNCE_SENDING_FAILED, buf status: %d", (FMT__D, zb_buf_get_status(param))); - (void)zb_app_signal_pack(param, BDB_COMM_CTX().bdb_application_signal, (zb_int16_t)zb_buf_get_status(param), 0U); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - } - - BDB_COMM_CTX().bdb_application_signal = ZB_BDB_SIGNAL_DEVICE_REBOOT; - - zb_buf_get_out_delayed(zdo_classic_rejoin); -} - - -static void zdo_classic_handle_dev_annce_sent_signal(zb_bufid_t param) -{ - zb_uint16_t aps_key_idx = (zb_uint16_t)-1; - - if (!ZB_IEEE_ADDR_IS_ZERO(ZB_AIB().trust_center_address)) - { - aps_key_idx = zb_aps_keypair_get_index_by_addr(ZB_AIB().trust_center_address, - ZB_SECUR_VERIFIED_KEY); - } - - if (!IS_DISTRIBUTED_SECURITY() - && ZB_TCPOL().update_trust_center_link_keys_required - && !ZB_TCPOL().waiting_for_tclk_exchange - && aps_key_idx == (zb_uint16_t)-1) /* TCLK is not already in progress */ - { - - TRACE_MSG(TRACE_SECUR3, "Found key idx %d", (FMT__D, aps_key_idx)); - - if (aps_key_idx == (zb_uint16_t)-1) - { - TRACE_MSG(TRACE_SECUR3, "BDB & !distributed - get TCLK over APS", (FMT__0)); - zdo_initiate_tclk_gen_over_aps(0); - } - } - else - { - if (ZB_IS_DEVICE_ZR()) - { - ZB_SCHEDULE_CALLBACK(zb_zdo_start_router, param); - } - else - { - (void)zb_app_signal_pack(param, BDB_COMM_CTX().bdb_application_signal, (zb_int16_t)zb_buf_get_status(param), 0U); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - } - } -} - - -static void zdo_classic_handle_router_started_signal(zb_bufid_t param) -{ - zb_bool_t is_waiting = zdo_secur_waiting_for_tclk_update(); - - if (ZB_NIB_SECURITY_LEVEL() == 0U - || !is_waiting - || ZB_IS_DEVICE_ZC_OR_ZR()) - { - TRACE_MSG(TRACE_ZDO1, "calling zdo_startup_complete", (FMT__0)); - (void)zb_app_signal_pack(param, BDB_COMM_CTX().bdb_application_signal, (zb_int16_t)zb_buf_get_status(param), 0U); - /* Router start is last step in join. */ - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - } - else - { - zb_buf_free(param); - } -} - - -static void zdo_classic_handle_tclk_update_complete_signal(zb_bufid_t param) -{ -#ifdef ZB_NWK_BLACKLIST - zb_nwk_blacklist_reset(); -#endif - - if (ZB_IS_DEVICE_ZR()) - { - ZB_SCHEDULE_CALLBACK(zb_zdo_start_router, param); - } - else - { - (void)zb_app_signal_pack(param, BDB_COMM_CTX().bdb_application_signal, (zb_int16_t)zb_buf_get_status(param), 0U); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); - } -} - - -static void zdo_classic_handle_leave_done_signal(zb_bufid_t param) -{ - if (ZB_U2B(ZB_ZDO_GET_UNAUTH())) - { - ZB_ZDO_CLEAR_UNAUTH(); - if (param != ZB_BUF_INVALID) - { - ZB_SCHEDULE_CALLBACK2(zb_zdo_startup_complete_int_delayed, param, ZB_NWK_STATUS_NO_KEY); - } - else - { - (void)zb_buf_get_out_delayed_ext(zb_zdo_startup_complete_int_delayed, ZB_NWK_STATUS_NO_KEY, 0); - } - } - else - { - if (param != ZB_BUF_INVALID) - { - zb_buf_free(param); - } - } -} - - -static void zdo_classic_handle_auth_ok_signal(zb_bufid_t param) -{ - if (param != ZB_BUF_INVALID) - { - zb_buf_free(param); - } -} - - -static void zdo_classic_handle_secur_failed_signal(zb_bufid_t param) -{ - zb_apsme_confirm_key_ind_t *ind = ZB_BUF_GET_PARAM(param, zb_apsme_confirm_key_ind_t); - - TRACE_MSG(TRACE_ZDO1, "report error status %hd, zb_app_signal_pack", (FMT__H, ind->status)); - (void)zb_app_signal_pack(param, ZB_ZDO_SIGNAL_DEFAULT_START, (zb_int16_t)ind->status, 0U); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); -} - - -static void zdo_classic_handle_rejoin_after_secur_failed_signal(zb_bufid_t param) -{ - zb_ext_pan_id_t ext_pan_id; - /* rejoin to current pan */ - zb_get_extended_pan_id(ext_pan_id); - (void)zdo_initiate_rejoin(param, ext_pan_id, ZB_AIB().aps_channel_mask_list, ZB_FALSE); -} - - -static void zdo_classic_handle_leave_with_rejoin_signal(zb_bufid_t param) -{ -#ifdef ZB_USE_NVRAM - /* If we fail, trace is given and assertion is triggered */ - (void)zb_nvram_write_dataset(ZB_NVRAM_COMMON_DATA); -#endif - -#ifdef ZB_NWK_BLACKLIST - zb_nwk_blacklist_reset(); -#endif - - zdo_inform_app_leave(ZB_NWK_LEAVE_TYPE_REJOIN); - - zb_nwk_do_rejoin_after_leave(param); - - BDB_COMM_CTX().bdb_application_signal = ZB_BDB_SIGNAL_DEVICE_REBOOT; -} - -#endif /* ZB_JOIN_CLIENT */ - -#ifdef ZB_COORDINATOR_ROLE - -static void zdo_classic_handle_secured_rejoin_signal(zb_bufid_t param) -{ - zb_apsme_transport_key_req_t *req = ZB_BUF_GET_PARAM(param, zb_apsme_transport_key_req_t); - zb_aps_device_key_pair_set_t *key_pair = zb_secur_get_link_key_by_address(req->dest_address.addr_long, ZB_SECUR_VERIFIED_KEY); - zb_address_ieee_ref_t ref_to_addr; - - /* Try to close link_key_alarm if address is found. - It's needed to remove possibility of - 'bdb_link_key_refresh_alarm' duplication - */ - if (zb_address_by_ieee(req->dest_address.addr_long, ZB_FALSE, ZB_FALSE, &ref_to_addr) == RET_OK) - { - bdb_cancel_link_key_refresh_alarm(bdb_link_key_refresh_alarm, ref_to_addr); - } - - /* r21 doesn't use empty keys - * In r21 setup alarm waiting for unique TCLK request. - * Note: param must hold transport key request even while we do not - * actually send it there! - */ - /* - It IS possible to work not in BDB but require TCLK update (use case: certification tests). - But update_trust_center_link_keys_required flag is always presend and initialized to 1 during BDB init. - */ - /* Note: is somewhere in time we put update_trust_center_link_keys_required under ifdef, need to check for ZB_IN_BDB() here. - Remember ZB_IN_BDB() can be just 1 (BDB-only build). */ - if (ZB_TCPOL().update_trust_center_link_keys_required - && !IS_DISTRIBUTED_SECURITY() - && (key_pair == NULL)) - { - ZB_SCHEDULE_ALARM(bdb_link_key_refresh_alarm, param, ZB_TCPOL().trust_center_node_join_timeout); - } - else - { - zb_buf_free(param); - } -} - - -static void zdo_classic_handle_tclk_verified_remote_signal(zb_address_ieee_ref_t param) -{ - ZVUNUSED(param); -} - - -static void zdo_classic_handle_device_left_signal(zb_address_ieee_ref_t param) -{ - ZVUNUSED(param); -} - -#endif /* ZB_COORDINATOR_ROLE */ - -#ifdef ZB_FORMATION -static void zdo_classic_handle_formation_done_signal(zb_bufid_t param) -{ - (void)zb_app_signal_pack(param, ZB_ZDO_SIGNAL_DEFAULT_START, zb_buf_get_status(param), 0); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); -} - - -static void zdo_classic_handle_formation_failed_signal(zb_bufid_t param) -{ - (void)zb_app_signal_pack(param, ZB_ZDO_SIGNAL_DEFAULT_START, zb_buf_get_status(param), 0); - ZB_SCHEDULE_CALLBACK(zb_zdo_startup_complete_int, param); -} -#endif /* ZB_FORMATION */ - -static void zdo_classic_handle_comm_signal(zb_commissioning_signal_t signal, zb_bufid_t param) -{ - TRACE_MSG(TRACE_ZDO1, ">> zdo_classic_handle_comm_signal, signal %d, param %d", - (FMT__D_D, signal, param)); - - switch(signal) - { - case ZB_COMM_SIGNAL_INIT: - zdo_classic_commissioning_force_link(); - if (param != ZB_BUF_INVALID) - { - zb_buf_free(param); - } - break; - case ZB_COMM_SIGNAL_START: - zdo_classic_initiate_commissioning(param); - break; -#ifdef ZB_JOIN_CLIENT - case ZB_COMM_SIGNAL_NWK_DISC_FAILED: - zdo_classic_handle_nwk_disc_failed_signal(param); - break; - case ZB_COMM_SIGNAL_JOIN_FAILED: - zdo_classic_handle_join_failed_signal(param); - break; - case ZB_COMM_SIGNAL_AUTH_FAILED: - zdo_classic_handle_authentication_failed_signal(param); - break; - case ZB_COMM_SIGNAL_INITIATE_REJOIN: - zdo_classic_handle_initiate_rejoin_signal(param); - break; - case ZB_COMM_SIGNAL_DEV_ANNCE_SENT: - zdo_classic_handle_dev_annce_sent_signal(param); - break; - case ZB_COMM_SIGNAL_ROUTER_STARTED: - zdo_classic_handle_router_started_signal(param); - break; - case ZB_COMM_SIGNAL_TCLK_UPDATE_COMPLETE: - zdo_classic_handle_tclk_update_complete_signal(param); - break; - case ZB_COMM_SIGNAL_TCLK_UPDATE_FAILED: - zdo_authentication_failed(param); - break; - case ZB_COMM_SIGNAL_LEAVE_DONE: - zdo_classic_handle_leave_done_signal(param); - break; - case ZB_COMM_SIGNAL_AUTH_OK: - zdo_classic_handle_auth_ok_signal(param); - break; - case ZB_COMM_SIGNAL_SECUR_FAILED: - zdo_classic_handle_secur_failed_signal(param); - break; - case ZB_COMM_SIGNAL_REJOIN_AFTER_SECUR_FAILED: - zdo_classic_handle_rejoin_after_secur_failed_signal(param); - break; - case ZB_COMM_SIGNAL_LEAVE_WITH_REJOIN: - zdo_classic_handle_leave_with_rejoin_signal(param); - break; -#endif /* ZB_JOIN_CLIENT */ - -#ifdef ZB_COORDINATOR_ROLE - case ZB_COMM_SIGNAL_SECURED_REJOIN: - zdo_classic_handle_secured_rejoin_signal(param); - break; - case ZB_COMM_SIGNAL_TCLK_VERIFIED_REMOTE: - zdo_classic_handle_tclk_verified_remote_signal(param); - break; - case ZB_COMM_SIGNAL_DEVICE_LEFT: - zdo_classic_handle_device_left_signal(param); - break; -#endif /* ZB_COORDINATOR_ROLE */ - -#ifdef ZB_FORMATION - case ZB_COMM_SIGNAL_FORMATION_DONE: - zdo_classic_handle_formation_done_signal(param); - break; - case ZB_COMM_SIGNAL_FORMATION_FAILED: - zdo_classic_handle_formation_failed_signal(param); - break; - case ZB_COMM_SIGNAL_AUTHENTICATE_REMOTE: - zb_buf_free(param); - break; -#endif /* ZB_FORMATION */ - - default: - TRACE_MSG(TRACE_ERROR, "unknown commissioning signal: %d", (FMT__D, signal)); - ZB_ASSERT(0); - if (param != ZB_BUF_INVALID) - { - zb_buf_free(param); - } - break; - } - - TRACE_MSG(TRACE_ZDO1, "<< zdo_classic_handle_comm_signal", (FMT__0)); -} - - -#ifdef ZB_ROUTER_ROLE - -static zb_uint8_t zdo_classic_get_permit_join_duration(void) -{ - zb_uint8_t duration; - - if ((ZB_NIB().max_children != 0U) -#ifdef ZB_CERTIFICATION_HACKS - && (ZB_CERT_HACKS().max_joins != 0U) -#endif /* ZB_CERTIFICATION_HACKS */ - ) - { - duration = ZDO_CTX().conf_attr.permit_join_duration; - } - else - { - duration = 0U; - } - - return duration; -} - -#endif /* #ifdef ZB_ROUTER_ROLE */ - -static zb_bool_t zdo_classic_must_use_installcode(zb_bool_t is_client) -{ - ZVUNUSED(is_client); -#ifdef ZB_SECURITY_INSTALLCODES - return (zb_bool_t)ZB_TCPOL().require_installcodes; -#else - return ZB_FALSE; -#endif /* ZB_SECURITY_INSTALLCODES */ -} - - -static void zdo_classic_init(void) -{ - ZB_TCPOL().update_trust_center_link_keys_required = ZB_TRUE; -} - - -static void zdo_classic_commissioning_force_link(void) -{ - zdo_classic_init(); - - COMM_SELECTOR().signal = zdo_classic_handle_comm_signal; - -#ifdef ZB_ROUTER_ROLE - COMM_SELECTOR().get_permit_join_duration = zdo_classic_get_permit_join_duration; -#endif /* ZB_ROUTER_ROLE */ - - COMM_SELECTOR().must_use_install_code = zdo_classic_must_use_installcode; -} - - -#ifdef ZB_FORMATION - -/* It is possible to move these functions to a separate object module if needed - for size optimization */ - - -static void zdo_classic_commissioning_formation_channels_mask(zb_channel_list_t list) -{ - zb_channel_page_list_copy(list, ZB_AIB().aps_channel_mask_list); -} - - -static void zdo_classic_formation_force_link(void) -{ - zdo_formation_force_link(); - - FORMATION_SELECTOR().start_formation = zdo_start_formation; - FORMATION_SELECTOR().get_formation_channels_mask = zdo_classic_commissioning_formation_channels_mask; -} - -#endif /* ZB_FORMATION */ - - -#ifdef ZB_COORDINATOR_ROLE - -void zb_set_network_coordinator_role_legacy(zb_uint32_t channel_mask) -{ - zdo_classic_commissioning_force_link(); -#ifdef ZB_FORMATION - /* [VK]: it's impossible to explain to MISRA that ZB_FORMATION is defined with ZB_COORDINATOR_ROLE always */ - zdo_classic_formation_force_link(); -#endif /* ZB_FORMATION */ - zb_set_network_coordinator_role_with_mode(channel_mask, ZB_COMMISSIONING_CLASSIC); -} - - -void zb_set_nwk_coordinator_role_legacy_ext(zb_channel_list_t channel_list) -{ - zdo_classic_commissioning_force_link(); -#ifdef ZB_FORMATION - /* [VK]: it's impossible to explain to MISRA that ZB_FORMATION is defined with ZB_COORDINATOR_ROLE always */ - zdo_classic_formation_force_link(); -#endif /* ZB_FORMATION */ - zb_set_nwk_role_mode_common_ext(ZB_NWK_DEVICE_TYPE_COORDINATOR, - channel_list, - ZB_COMMISSIONING_CLASSIC); -} - -#endif /* ZB_COORDINATOR_ROLE */ - - -#ifdef ZB_ROUTER_ROLE - -void zb_set_network_router_role_legacy(zb_uint32_t channel_mask) -{ - zdo_classic_commissioning_force_link(); -#if defined ZB_FORMATION && defined ZB_DISTRIBUTED_SECURITY_ON - /* enable distributed security, not optimal, but no need to optimize legacy commissioning */ - /* [VK]: it's impossible to explain to MISRA that ZB_FORMATION is defined with ZB_ROUTER_ROLE always */ - zdo_classic_formation_force_link(); -#endif /* ZB_FORMATION && ZB_DISTRIBUTED_SECURITY_ON */ - zb_set_network_router_role_with_mode(channel_mask, ZB_COMMISSIONING_CLASSIC); -} - - -void zb_set_nwk_router_role_legacy_ext(zb_channel_list_t channel_list) -{ - zdo_classic_commissioning_force_link(); -#if defined ZB_FORMATION && defined ZB_DISTRIBUTED_SECURITY_ON - /* enable distributed security, not optimal, but no need to optimize legacy commissioning */ - /* [VK]: it's impossible to explain to MISRA that ZB_FORMATION is defined with ZB_ROUTER_ROLE always */ - zdo_classic_formation_force_link(); -#endif /* ZB_FORMATION && ZB_DISTRIBUTED_SECURITY_ON */ - zb_set_nwk_role_mode_common_ext(ZB_NWK_DEVICE_TYPE_ROUTER, - channel_list, - ZB_COMMISSIONING_CLASSIC); -} - -#endif /* ZB_ROUTER_ROLE */ - - -#ifdef ZB_ED_FUNC - -void zb_set_network_ed_role_legacy(zb_uint32_t channel_mask) -{ - zdo_classic_commissioning_force_link(); - - zb_set_network_ed_role_with_mode(channel_mask, ZB_COMMISSIONING_CLASSIC); -} - -void zb_set_nwk_ed_role_legacy_ext(zb_channel_list_t channel_list) -{ - zdo_classic_commissioning_force_link(); - - zb_set_nwk_role_mode_common_ext(ZB_NWK_DEVICE_TYPE_ED, - channel_list, - ZB_COMMISSIONING_CLASSIC); -} - -#endif /* ZB_ED_FUNC */ -#endif /* ZB_COMMISSIONING_CLASSIC_SUPPORT */ diff --git a/zboss/development/src/include/hw_crypto_api.h b/zboss/development/src/include/hw_crypto_api.h deleted file mode 100644 index 7c75d05e39..0000000000 --- a/zboss/development/src/include/hw_crypto_api.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: HW crypto API -*/ - -#ifndef HW_CRYPTO_API_H -#define HW_CRYPTO_API_H 1 - -#ifndef ZB_SOFT_SECURITY - -extern zb_ret_t -hw_encrypt_n_auth( - zb_uint8_t *key, - zb_uint8_t *nonce, - zb_uint8_t *string_a, - zb_ushort_t string_a_len, - zb_uint8_t *string_m, - zb_ushort_t string_m_len, - zb_bufid_t crypted_text); - -extern zb_ret_t -hw_decrypt_n_auth( - zb_uint8_t *key, - zb_uint8_t *nonce, - zb_bufid_t buf, - zb_ushort_t string_a_len, - zb_ushort_t string_c_len); - - -#define zb_ccm_encrypt_n_auth hw_encrypt_n_auth - -#define zb_ccm_decrypt_n_auth hw_decrypt_n_auth - -#define zb_ccm_decrypt_n_auth_stdsecur zb_ccm_decrypt_n_auth - -#endif /* ZB_SOFT_SECURITY */ - -#ifdef ZB_HW_ZB_AES128 -void hw_aes128(zb_uint8_t *key, zb_uint8_t *msg, zb_uint8_t *c); - -#define zb_aes128 hw_aes128 -#endif - -#ifdef ZB_HW_ZB_AES128_DEC -void hw_aes128_dec(zb_uint8_t *key, zb_uint8_t *msg, zb_uint8_t *c); - -#define zb_aes128_dec hw_aes128_dec -#endif - -#endif /* HW_CRYPTO_API_H */ diff --git a/zboss/development/src/include/zb_addr_globals.h b/zboss/development/src/include/zb_addr_globals.h deleted file mode 100644 index 5abadc3ba7..0000000000 --- a/zboss/development/src/include/zb_addr_globals.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Address compression, hash and etc. -*/ - -#ifndef ZB_ADDR_GLOBALS_H -#define ZB_ADDR_GLOBALS_H 1 - -/*! @cond internals_doc */ -/*! \addtogroup ZB_NWK */ -/*! @{ */ - -/** - \par Define 'global address context' - common place to store and manage - various ZigBee addresses. It contains array of Pan ID, IEEE(64-bit) and 16 - -bit address pairs. Protocol tables contains only 1 byte reference to the - corresponding array. These arrays are hashes indeed, this speed up address - search. To minimize memory usage open address hash is used. - - Address context consists of: - - Pan ID's array - open addressing hash contains known Pan IDs. Seems MAC or NWK - should clear it before new scan operation. - - IEEE/16-bits address pair hash. Array of IEEE/16bit address pair. IEEE - address is the key in this hash. - - 16-bits address hash. The key of this hash is 16-bit address, used for 16 - -bits address and corresponding IEEE address search. This array contains - reference to IEEE array. - - Clear and reuse elements in IEEE/16bit address map: - Each IEEE/16-bits address pair has lock counter. Lock counter is zero when - this address is not used in any table, those not used addresses organized in - lru list. Head of lru list contains address elements that's not used for a - long time. -*/ - -#include "zb_pooled_list.h" -#include "zb_address.h" - - -/** - Manufacturer part of IEEE address -*/ -typedef ZB_PACKED_PRE struct zb_dev_manufacturer_s -{ - zb_uint8_t device_manufacturer[3]; /*!< Manufacturer identifier - 3 octets */ -} -ZB_PACKED_STRUCT -zb_dev_manufacturer_t; - -/** - * @name Address redirect type - * @anchor mac_command_frame_id - * - * Note: These values were members of `enum zb_addr_redirect_type_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -/** Regular record */ -#define ZB_ADDR_REDIRECT_NONE 0x00U -/** Entry contains only short address and redirects to regular record with both addresses */ -#define ZB_ADDR_REDIRECT_SHORT 0x01U -/** Entry contains only IEEE address and redirects to regular record with both addresses*/ -#define ZB_ADDR_REDIRECT_IEEE 0x02U -/** @} */ - - -/* redirect/direct data structures are killed: they are the same actually. */ -/* zb_address_map_t is moved to zb_address.h */ - - -/** - ext Pan ID and short Pan ID -> pan ref map - */ -typedef ZB_PACKED_PRE struct zb_pan_id_map_s -{ - zb_ext_pan_id_t long_panid; /*!< 64-bit Pan ID */ - zb_uint16_t short_panid; /*!< 16-bit Pan ID */ -} ZB_PACKED_STRUCT zb_pan_id_map_t; - - -/* EE: do not pack that data structure: will not win - * significantly on RAM, but can get slower/bigger code. */ -/** - Global address context -*/ -typedef struct zb_addr_globals_s -{ - zb_uint8_t used_manufacturer[ZB_DEV_MANUFACTURER_TABLE_SIZE / 8U + 1U]; /*!< - * dev_manufacturer - * usage mask */ - zb_dev_manufacturer_t dev_manufacturer[ZB_DEV_MANUFACTURER_TABLE_SIZE]; /*!< - * Manufacturers - * array */ - - zb_pan_id_map_t pan_map[ZB_PANID_TABLE_SIZE]; /*!< Pan ID's hash */ - zb_uint8_t used_pan_addr[ZB_PANID_TABLE_SIZE / 8U + 1U]; /*!< pan_addr usage mask */ - -#ifndef ZB_CONFIGURABLE_MEM - zb_address_map_t addr_map[ZB_IEEE_ADDR_TABLE_SIZE]; /*!< Address map - open - * hash by 64-bit address */ - zb_uint8_t short_sorted[ZB_IEEE_ADDR_TABLE_SIZE]; /*!< 16-bits address sort array */ -#else - zb_address_map_t *addr_map; - zb_uint8_t *short_sorted; -#endif - zb_ushort_t n_elements; /*!< # of elements in the - * address translation table */ - zb_ushort_t n_sorted_elements; /*!< # of elements in the short_sorted[] */ - zb_ushort_t clock_i; /*!< # of elements in the addr_map[] */ -} zb_addr_globals_t; - - -/*! @} */ -/*! @endcond */ - -#endif /* ZB_ADDR_GLOBALS_H */ diff --git a/zboss/development/src/include/zb_aps.h b/zboss/development/src/include/zb_aps.h deleted file mode 100644 index 1fe7c4c754..0000000000 --- a/zboss/development/src/include/zb_aps.h +++ /dev/null @@ -1,601 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: APS layer API -*/ - -#ifndef ZB_APS_H -#define ZB_APS_H 1 - -#include "zb_config.h" - -/*! \addtogroup aps_ib */ -/*! @{ */ - -/* APS Information Base default values. */ - -/** @brief Default value for AIB non-member radius attribute */ -#define ZB_APS_AIB_DEFAULT_NONMEMBER_RADIUS 0x02U - -/** @brief Default value for AIB maximum non-member radius attribute. - * - * Possible values from 0x00 to 0x06. - */ -#define ZB_APS_AIB_DEFAULT_MAX_NONMEMBER_RADIUS 0x06U - -/** @brief Value of non-member radius that means infinity non-member transmission. */ -#define ZB_APS_AIB_INFINITY_NONMEMBER_RADIUS 0x07U - -/** @cond internals_doc */ - -/** @brief APSME GET common message header. */ -typedef ZB_PACKED_PRE struct zb_aps_command_header_s -{ - zb_uint8_t fc; /*!< Frame control */ - zb_uint8_t aps_counter; /*!< APS counter */ - zb_uint8_t aps_command_id; /*!< APS command */ -} ZB_PACKED_STRUCT zb_aps_command_header_t; - -/** @brief APSME GET common packet header. */ -typedef ZB_PACKED_PRE struct zb_aps_command_pkt_header_s -{ - zb_uint8_t fc; /*!< Frame control */ - zb_uint8_t aps_counter; /*!< APS counter */ -} ZB_PACKED_STRUCT zb_aps_command_pkt_header_t; - -/** @endcond */ /* internals_doc */ - -/*! @} */ - -/*! \addtogroup aps_api */ -/*! @{ */ - -/** @name APS data service structures and API. - * @{ - */ - -/** @brief APSDE data request structure. - * - * This data structure passed to @ref zb_apsde_data_request() in the packet buffer (in its tail). - */ -typedef struct zb_apsde_data_req_s -{ - zb_addr_u dst_addr; /*!< Destination address */ - zb_uint16_t profileid; /*!< The identifier of the profile for which this - frame is intended. */ - zb_uint16_t clusterid; /*!< The identifier of the object for which this - frame is intended. */ - zb_uint8_t dst_endpoint; /*!< either the number of the individual endpoint - of the entity to which the ASDU is being - transferred or the broadcast endpoint (0xff). */ - zb_uint8_t src_endpoint; /*!< The individual endpoint of the entity from - which the ASDU is being transferred. */ - zb_uint8_t radius; /*!< The distance, in hops, that a frame will be - allowed to travel through the network. */ - zb_uint8_t addr_mode; /*!< The type of destination address supplied by - the DstAddr parameter - see @ref aps_addr_mode */ - zb_uint8_t tx_options; /*!< The transmission options for the ASDU to be - transferred. These are a bitwise OR of one or - more of the following: - 0x01 = Security enabled transmission - 0x02 = Use NWK key - 0x04 = Acknowledged transmission - 0x08 = Fragmentation permitted. - See @ref apsde_tx_opt */ - /*2.2.4.1.1.1 spec r21*/ - zb_uint8_t use_alias; /*!< The next higher layer may use the UseAlias parameter - to request alias usage by NWK layer for the current frame. - If the UseAlias parameter has a value of FALSE, - meaning no alias usage, then the parameters - AliasSrcAddr and AliasSeqNumb will be ignored. - Otherwise, a value of TRUE denotes that the values supplied in - AliasSrcAddr and AliasSeqNumb are to be used - Values: TRUE or FALSE */ - zb_uint16_t alias_src_addr;/*!< The source address to be used for this NSDU. - If the UseAlias parameter has a value of FALSE, - the AliasSrcAddr parameter is ignored. - Values: Any valid device address except broadcast address */ - zb_uint8_t alias_seq_num; /*!< The sequence number to be used for this NSDU. - If the UseAlias parameter has a value of FALSE, - the AliasSeqNumb parameter is ignored. - Values: 0x00-0xff */ -#ifdef APS_FRAGMENTATION -#define NCP_APSDE_PARAM_SIZE ZB_OFFSETOF(zb_apsde_data_req_t, extended_fc) - zb_uint8_t extended_fc; /* Extended Frame Control - internal use only */ - zb_uint8_t block_num; /* Fragmentation: for the first segment - total payload len */ -#else -#define NCP_APSDE_PARAM_SIZE sizeof(zb_apsde_data_req_t) -#endif -} zb_apsde_data_req_t; - -/** @brief Parameters of the APSDE-DATA.confirm primitive. */ -typedef ZB_PACKED_PRE struct zb_apsde_data_confirm_s -{ - zb_addr_u dst_addr; /*!< The destination address for the binding entry. */ - zb_uint8_t dst_endpoint; /*!< The destination endpoint for the binding entry. */ - zb_uint8_t src_endpoint; /*!< The source endpoint for the binding entry. */ - /* FIXME: Do we use this field?? */ - zb_time_t tx_time; /*!< A time indication for the transmitted packet based on the - local clock, as provided by the NWK layer. */ - zb_uint8_t addr_mode; /*!< The type of destination address supplied by - the DstAddr parameter - see @ref aps_addr_mode */ -#define FIRST_INTERNAL_APSDE_CONF_FIELD status - zb_ret_t status; /*!< The status of corresponding request. */ - zb_bool_t need_unlock; -} ZB_PACKED_STRUCT zb_apsde_data_confirm_t; - -/** - * @name Transmission options - * @brief The transmission options for the ASDU to be transferred. - * - * Note: These values were members of `enum zb_apsde_tx_opt_e` type but were converted to a - * set of macros due to MISRA violations. - * - * These are a bitwise OR of one or more. - * @anchor apsde_tx_opt - */ -/** @{ */ -#define ZB_APSDE_TX_OPT_SECURITY_ENABLED 0x01U /*!< Security enabled transmission */ -#define ZB_APSDE_TX_OPT_USE_NWK_KEY_R21OBSOLETE 0x02U /*!< Use NWK key */ -#define ZB_APSDE_TX_OPT_ACK_TX 0x04U /*!< Acknowledged transmission */ -#define ZB_APSDE_TX_OPT_FRAG_PERMITTED 0x08U /*!< Fragmentation permitted */ -#define ZB_APSDE_TX_OPT_INC_EXT_NONCE 0x10U /*!< Include extended nonce in APS security frame */ - -#ifdef ZB_APSDE_REQ_ROUTING_FEATURES -#define ZB_APSDE_TX_OPT_FORCE_MESH_ROUTE_DISC 0x20U /* Non-spec extension: Force mesh route discovery */ -#define ZB_APSDE_TX_OPT_FORCE_SEND_ROUTE_REC 0x40U /* Non-spec extension: Force send route record */ -#endif /* ZB_APSDE_REQ_ROUTING_FEATURES */ - -/** @} */ - -/** @brief NLDE-DATA.request primitive - - This function can be called via scheduler, returns immediately. - Later zb_nlde_data_confirm will be called to pass NLDE-DATA.request result up. - - @param param - packet to send (\ref zb_buf_t) and parameters at buffer tail - \ref zb_nlde_data_req_t - - @b Example: -@code - { - zb_apsde_data_req_t *req; - zb_ushort_t i; - - buf = ZB_BUF_FROM_REF(param); - ZB_BUF_INITIAL_ALLOC(buf, 10, ptr); - for (i = 0 ; i < 10 ; ++i) - { - ptr[i] = i % 32 + '0'; - } - - req = ZB_GET_BUF_TAIL(buf, sizeof(zb_apsde_data_req_t)); - req->dst_addr.addr_short = 0; /-- ZC --/ - req->addr_mode = ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - req->tx_options = ZB_APSDE_TX_OPT_ACK_TX; - req->radius = 5; - req->profileid = 2; - req->src_endpoint = 10; - req->dst_endpoint = 10; - buf->u.hdr.handle = 0x11; - TRACE_MSG(TRACE_APS3, "Sending apsde_data.request", (FMT__0)); - ZB_SCHEDULE_CALLBACK(zb_apsde_data_request, ZB_REF_FROM_BUF(buf)); - } -@endcode - - */ -void zb_apsde_data_request(zb_uint8_t param); - -/** @brief APSDE-DATA.confirm primitive. - * - * The primitive reports the results of a request to transfer a data PDU (ASDU) from NHLE. - * - * @note zb_apsde_data_confirm must be defined in the APS layer! APS layer just calls this - * function. - * @param param - sent packet - see @ref zb_buf_t. APS must free or reuse it. Following packet - * fields are used: - * @li status - The status of the corresponding request. Can take value of: INVALID_REQUEST, - * MAX_FRM_COUNTER, NO_KEY, BAD_CCM_OUTPUT, ROUTE_ERROR, BT_TABLE_FULL, FRAME_NOT_BUFFERED or any - * status values returned from security suite or the MCPS-DATA.confirm primitive. - * @li handle - The handle associated with the NSDU being confirmed. - */ -void zb_apsde_data_confirm(zb_uint8_t param); - -/** @brief NLDE-DATA.indication primitive. - * - * This function called via scheduler by the NWK layer to pass incoming data packet to the APS - * layer. - * @note zb_nlde_data_indication() must be defined in the APS layer! NWK layer just - * calls this function. - * @param param - The set of octets comprising the NSDU to be transferred (with length). - * - * Other fields got from MAC nsdu by macros. - */ -void zb_apsde_data_indication(zb_uint8_t param); - -/** @} */ /* APS data service structures and API. */ - -/** @cond internals_doc */ - -/** @brief Remove APS header from the packet. - - @param packet - APS packet - @param ptr - (out) pointer to the APS data begin - - */ -#define ZB_APS_HDR_CUT_P(packet, ptr) \ - ptr = zb_buf_cut_left(packet, zb_aps_full_hdr_size(zb_buf_begin(packet))) - - -/** @brief Remove APS header from the packet. - - @param packet - APS packet - - @b Example: -@code -void data_indication(zb_uint8_t param) -{ - zb_ushort_t i; - zb_bufid_t asdu = (zb_bufid_t )ZB_BUF_FROM_REF(param); - - ZB_APS_HDR_CUT(asdu); - - TRACE_MSG(TRACE_APS3, "data_indication: packet %p len %d handle 0x%x", (FMT__P_D_D, - asdu, (int)zb_buf_len(asdu), asdu->u.hdr.status)); - - zb_free_buf(asdu); -} -@endcode - */ -#define ZB_APS_HDR_CUT(packet) \ - (void)zb_buf_cut_left(packet, zb_aps_full_hdr_size(zb_buf_begin(packet))) - -/** @endcond */ /* internals_doc */ - -/** @cond internals_doc */ - -/** @brief Structure for Get Group Membership Command. - * @see ZCL8 spec, subclause 3.6.2.3.4. - */ -typedef ZB_PACKED_PRE struct zb_apsme_get_group_membership_req_s -{ - zb_callback_t confirm_cb; /*!< The callback to be called when the operation is completed. */ - zb_ushort_t n_groups; /*!< Group addresses amount. */ - zb_uint8_t endpoint; /*!< The endpoint which the groups are assigned to. */ - zb_uint8_t align[1]; - zb_uint16_t groups[1]; /*!< First element if list with group addresses. */ -} ZB_PACKED_STRUCT zb_apsme_get_group_membership_req_t; - -/* - * 'groups' array member is passed as a function parameter (e.g. zb_aps_group_table_get_membership()), it should be - * properly aligned. - */ -ZB_ASSERT_IF_NOT_ALIGNED(ZB_OFFSETOF(zb_apsme_get_group_membership_req_t, groups), sizeof(zb_uint16_t)); - -/** @brief Structure for Get Group Membership Response Command - * @see ZCL spec, subclause 3.6.2.3.3. - */ -typedef struct zb_apsme_get_group_membership_conf_s -{ - zb_uint16_t groups[ZB_APS_GROUP_TABLE_SIZE]; /*!< List with group addresses. */ - zb_ushort_t n_groups; /*!< Group addresses amount. */ - zb_ushort_t capacity; /*!< Group table capacity */ -} zb_apsme_get_group_membership_conf_t; - -/** @endcond */ /* internals_doc */ - -/*! @} */ - - -/*! @cond internals_doc */ -/*! \addtogroup ZB_APS */ -/*! @{ */ - -/** @brief Signals user that data is sent and acknowledged. - * @param param - reference to the buffer containing ASDU sent. - */ -void zb_apsde_data_acknowledged(zb_uint8_t param); - -/** @brief Initialize APS subsystem. */ -void zb_aps_init(void); - - - -/** @brief APS command codes constants. - * @note APS_CMD_TUNNEL should be last one, or you should change logic. - */ - -/** - * @name APS command codes constants. - * @note APS_CMD_TUNNEL should be last one, or you should change logic. - * @anchor aps_commands - * - * Note: These values were members of `enum zb_aps_commands_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define APS_CMD_SKKE_1 0x01U -#define APS_CMD_SKKE_2 0x02U -#define APS_CMD_SKKE_3 0x03U -#define APS_CMD_SKKE_4 0x04U -#define APS_CMD_TRANSPORT_KEY 0x05U -#define APS_CMD_UPDATE_DEVICE 0x06U -#define APS_CMD_REMOVE_DEVICE 0x07U -#define APS_CMD_REQUEST_KEY 0x08U -#define APS_CMD_SWITCH_KEY 0x09U -#define APS_CMD_EA_INIT_CHLNG 0x0AU -#define APS_CMD_EA_RSP_CHLNG 0x0BU -#define APS_CMD_EA_INIT_MAC_DATA 0x0CU -#define APS_CMD_EA_RSP_MAC_DATA 0x0DU -#define APS_CMD_TUNNEL 0x0EU -#define APS_CMD_VERIFY_KEY 0x0FU -#define APS_CMD_CONFIRM_KEY 0x10U -/** @} */ - -zb_uint8_t aps_find_src_ref( - zb_address_ieee_ref_t src_addr_ref, zb_uint8_t src_end, zb_uint16_t cluster_id); - -#ifdef ZB_COORDINATOR_ROLE -/** @brief APSME-UPDATE-DEVICE.indication primitive. - * @param param - reference to the buffer containing indication data. - */ -void zb_apsme_update_device_indication(zb_uint8_t param); -#endif /* ZB_COORDINATOR_ROLE */ - -/** @internal @brief Send APS command. - * - * Internal routine to be used to send APS command frame. - * @see ZB spec, subclause 2.2.5.2.2 - APS Command Frame Format. - * @param param - buffer with command body. - * @param dest_addr - address of device to send to. - * @param command - command id. - * @param secure - if true, secure transfer at NWK level. - */ -void zb_aps_send_command(zb_uint8_t param, zb_uint16_t dest_addr, zb_uint8_t command, zb_bool_t secure - /** @param secure_aps_i - if true, secure APS level.*/ - , zb_uint8_t secure_aps_i - ); - -/** \par Macros for APS FC parse-compose */ - -#define ZB_APS_FC_GET_FRAME_TYPE(fc) ((fc) & 3U) -#define ZB_APS_FC_SET_FRAME_TYPE(fc, t) ((fc) |= (t)) - -#define ZB_APS_FC_GET_DELIVERY_MODE(fc) (((fc)>>2U) & 3U) -#define ZB_APS_FC_SET_DELIVERY_MODE(fc, m) ((fc) |= (m) << 2U) - -#define ZB_APS_FC_GET_ACK_FORMAT(fc) (((fc)>>4U) & 1U) -#define ZB_APS_FC_SET_ACK_FORMAT(fc, f) ((fc) |= ((f) << 4U)) - -#define ZB_APS_FC_GET_SECURITY(fc) (((fc)>>5U) & 1U) -#define ZB_APS_FC_IS_SECURE(fc) (ZB_APS_FC_GET_SECURITY(fc) != 0U) -#define ZB_APS_FC_SET_SECURITY(fc, f) ((fc) |= ((f) << 5U)) - -#define ZB_APS_FC_GET_ACK_REQUEST(fc) (((fc)>>6U) & 1U) -#define ZB_APS_FC_SET_ACK_REQUEST(fc, f) ((fc) |= ((f) << 6U)) - -#define ZB_APS_FC_GET_EXT_HDR_PRESENT(fc) (((fc)>>7U) & 1U) -#define ZB_APS_FC_SET_EXT_HDR_PRESENT(fc, f) ((fc) |= ((f) << 7U)) - -#define ZB_APS_FIRST_FRAGMENT 0x01U -#define ZB_APS_NOT_FIRST_FRAGMENT 0x02U -/* Limit to 4 fragments as maximum available. - If need to use more, extend bitfield in zb_aps_dup_tbl_ent_t. */ -#define ZB_APS_MAX_FRAGMENT_BLOCK_NUM ZB_APS_MAX_FRAGMENT_NUM - 1 -#define ZB_APS_FC_GET_EXT_HDR_FRAG(fc) ((fc) & 3U) -#define ZB_APS_FC_SET_EXT_HDR_FRAG(fc, f) ((fc) |= (f)) - -/** @brief Setup FC for APS command: frame type, ack request, ack format. */ -#define ZB_APS_FC_SET_COMMAND(fc, need_ack) \ - (fc) |= ( /*frame type*/ZB_APS_FRAME_COMMAND \ - | /*ack req*/(((need_ack)) << 6U) \ - | /*ack format*/(1U << 4U)) - -/** - * @name APS frame type - * @anchor aps_frame_type - * - * Note: These values were members of `enum zb_aps_frame_type_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_APS_FRAME_DATA 0U -#define ZB_APS_FRAME_COMMAND 1U -#define ZB_APS_FRAME_ACK 2U -/** @} */ - -/** - * @name APS frame delivery mode values - * @anchor aps_frame_delivery_mode - * - * Note: These values were members of `enum zb_aps_frame_delivery_mode_e` type but were converted to - * a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_APS_DELIVERY_UNICAST 0U /*!< Unicast frame delivery. */ -/*! Reserved value, see Zigbee spec, subclause 2.2.5.1.1.2 */ -#define ZB_APS_DELIVERY_RESERVED 1U -#define ZB_APS_DELIVERY_BROADCAST 2U /*!< Broadcast frame delivery. */ -#define ZB_APS_DELIVERY_GROUP 3U /*!< Group frame delivery. */ -/** @} */ - - -/** @brief Ger APS header size (not include AUX security hdr). */ -zb_uint8_t zb_aps_hdr_size(zb_uint8_t fc); -#define ZB_APS_HDR_SIZE(fc) \ - zb_aps_hdr_size(fc) -/* #define ZB_APS_HDR_SIZE(fc) \ */ -/* (2 + /\* fc + aps counter *\/ \ */ -/* ((ZB_APS_FC_GET_FRAME_TYPE(fc) == ZB_APS_FRAME_COMMAND) ? 0 : ( \ */ -/* /\* Packet either has dest endpoint (1) or group address (2) *\/ \ */ -/* 1 + \ */ -/* (ZB_APS_FC_GET_DELIVERY_MODE(fc) == ZB_APS_DELIVERY_GROUP) + \ */ -/* /\* cluster id, profile id *\/ \ */ -/* 2 + 2 + \ */ -/* /\* src endpoint *\/ \ */ -/* 1 + \ */ -/* (ZB_APS_FC_GET_EXT_HDR_PRESENT(fc) ? \ */ -/* /\* extended hdr + block number (+ block ack) *\/ \ */ -/* ((ZB_APS_FC_GET_FRAME_TYPE(fc) == ZB_APS_FRAME_ACK) ? 3 : 2) \ */ -/* : 0) \ */ -/* ))) */ - - -/** @brief Return APS header + APS aux hdr size. - * @param pkt - packet for calculate size. - * @return packet APS full head size. - */ -zb_ushort_t zb_aps_full_hdr_size(const zb_uint8_t *pkt); - - -/* #define APS_CONFIRM_STATUS(buf, s, func) \ */ -/* do \ */ -/* { \ */ -/* (buf)->u.hdr.status = (s); \ */ -/* ZB_SCHEDULE_CALLBACK((func), ZB_REF_FROM_BUF((buf))); \ */ -/* } \ */ -/* while(0) */ - - -/** @brief Get Group Membership Command (For Zigbee cluster library). - * - * @param param - buffer with parameter. See @ref zb_apsme_get_group_membership_req_s. - * @see ZCL spec, subclause 3.6.2.2.5. - */ -void zb_apsme_get_group_membership_request(zb_uint8_t param); - -#define ZDO_MGMT_APS_LEAVE_RESP_CLID 0x8034U /* it is from zdo for leave callback*/ - -/** @internal - * @brief Parse APS header - * - * @param packet - buffer with APS command - * @param aps_hdr - APS header see @ref zb_aps_hdr_s - * @param cut_nwk_hdr - flag "cut HWK header before parse" - * */ -void zb_aps_hdr_parse(zb_bufid_t packet, zb_aps_hdr_t *aps_hdr, zb_bool_t cut_nwk_hdr); - -/** @internal - * @brief Check element in the group array by GroupID. - * - * */ -zb_bool_t zb_aps_is_in_group(zb_uint16_t grp_id); - -zb_aps_group_table_ent_t* zb_aps_get_group_table_entry(zb_uint16_t group_addr); - -/** @brief Filling Nlde request. - * @param param - buffer for fill request. - * @param addr - destination address. - * @param secure - Is ASP secure. - */ -void fill_nldereq(zb_uint8_t param, zb_uint16_t addr, zb_uint8_t secure); - -/** @brief Set predefined TC key. */ -void zb_aps_set_preconfigure_security_key(zb_uint8_t *key); - -zb_ret_t zb_aps_get_ieee_source_from_cmd_frame(zb_uint8_t cmd_id, zb_uint8_t cmd_buf_param, zb_ieee_addr_t ieee_addr); - -void zb_aps_clear_after_leave(zb_uint16_t address); - -void zb_apsme_remove_all_groups_internal(void); -void apsme_forget_device(void); -void aps_send_fail_confirm(zb_uint8_t param, zb_ret_t status); - -/*! @} */ -/*! @endcond */ - -/** @cond internals_doc */ - -void zb_apsme_unbind_by_ref(zb_address_ieee_ref_t addr_ref); - -zb_ret_t zb_check_binding_table_whitelist(zb_apsme_binding_req_t *apsreq); - -/* Functions for accessing and modifying a group table */ -zb_ret_t zb_aps_group_table_add(zb_aps_group_table_t *table, zb_uint16_t group, zb_uint8_t ep); -zb_ret_t zb_aps_group_table_remove(zb_aps_group_table_t *table, zb_uint16_t group, zb_uint8_t ep); -void zb_aps_group_table_remove_all(zb_aps_group_table_t *table); -zb_bool_t zb_aps_group_table_is_endpoint_in_group(zb_aps_group_table_t *table, - zb_uint16_t group_id, - zb_uint8_t endpoint); -void zb_apsme_internal_get_group_membership_request(zb_aps_group_table_t *table, zb_uint8_t param); - - -/* Internal function for binding APS-groups to ZCL endpoints, - * called from zb_apsme_add_group_request or elsewhere from any layer - */ -zb_ret_t zb_apsme_add_group_internal(zb_uint16_t group, zb_uint8_t ep); - -/* Internal function for unbinding APS-groups to ZCL endpoints, - * called from zb_apsme_remove_group_request or elsewhere from any layer - */ -zb_ret_t zb_apsme_remove_group_internal(zb_uint16_t group, zb_uint8_t ep); - -/** @endcond */ /* internals_doc */ - -/** @brief APSME GET request primitive. - * @param param reference to the buffer containing request data. - * - * @par Example - * @snippet start_ze.c zb_apsme_get_request - * @par - */ -void zb_apsme_get_request(zb_uint8_t param); - -/** @brief APSME SET request primitive. - * @param param reference to the buffer containing request data. - * - * @par Example - * @snippet start_ze.c zb_apsme_set_request - * @par - * - */ -void zb_apsme_set_request(zb_uint8_t param); - -/*! - * @brief Add entry to binding whitelist table - * - * @param ep_id - endpoint ID - * @param cluster_id - endpoint ID - * @param cluster_role - endpoint ID - * @param ieee_addr - IEEE addr - */ -zb_ret_t zb_aps_add_binding_whitelist_entry(zb_uint8_t ep_id, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_ieee_addr_t ieee_addr); - -#endif /* ZB_APS_H */ diff --git a/zboss/development/src/include/zb_aps_globals.h b/zboss/development/src/include/zb_aps_globals.h deleted file mode 100644 index dd01e37092..0000000000 --- a/zboss/development/src/include/zb_aps_globals.h +++ /dev/null @@ -1,615 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Globals data definitionfor APS subsystem -*/ - -#ifndef ZB_APS_GLOBALS_H -#define ZB_APS_GLOBALS_H 1 - -/*! @cond internals_doc */ -/*! \addtogroup ZB_APS */ -/*! @{ */ - -#include "zb_secur.h" - -/* I don't know why aliases for addr mode were declared, but setting it to 0 and 1 causes - need to convert it back to "normal" addr mode. So, let's declare this aliaces equal to - common addr mode values. - According to 2.2.4.3.1 APSME-BIND.request addr mode values 0x00 and 0x02 are reserved, - only 0x01 and 0x03 are used */ -#define ZB_APS_BIND_DST_ADDR_GROUP ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT -#define ZB_APS_BIND_DST_ADDR_LONG ZB_APS_ADDR_MODE_64_ENDP_PRESENT - -/** - Binding table search result for dst request - */ -typedef ZB_PACKED_PRE struct zb_aps_bind_dst_record_s -{ - zb_uint8_t dst_addr_mode; /*!< destination address mode flag, 0 - * - group address, otherwise long - * address plus dest endpoint */ - ZB_PACKED_PRE union - { - zb_uint16_t group_addr; /*!< group address */ - zb_aps_bind_long_dst_addr_t long_addr; /*!< @see zb_asp_long_dst_addr_t */ - } u; - -} ZB_PACKED_STRUCT zb_aps_bind_dst_record_t; - -#define ZB_APS_IS_TRANS_INDEX(dtbli, tansi) \ - (ZG->aps.binding.dst_table[(dtbli)].trans_index[(tansi)/8U] & (1U << ((tansi)%8U))) - -#define ZB_APS_BINDING_TABLE_WHITELIST_SIZE 4U -/** - Binding table whitelist - */ -typedef ZB_PACKED_PRE struct zb_aps_binding_table_whitelist_s -{ - zb_uint8_t ep_id; /*!< Endpoint ID */ - zb_uint16_t cluster_id; /*!< Cluster ID */ - zb_uint8_t cluster_role; /*!< Cluster role */ - zb_ieee_addr_t addr; /*!< Whitelist address */ -} ZB_PACKED_STRUCT zb_aps_binding_table_whitelist_t; - -/** - Global binding table -*/ -typedef ZB_PACKED_PRE struct zb_aps_binding_table_s -{ - zb_uint8_t src_n_elements; /*!< Count elements in source table */ - zb_uint8_t dst_n_elements; /*!< Count elements in destination table */ - zb_uint8_t whitelist_n_elements; /*!< Count elements in whitelist table */ -#ifdef SNCP_MODE - zb_uint8_t remote_bind_offset; /*!< Offset to attribute id's to remote binding requests */ -#else - /* FIXME: why align here? */ - zb_uint8_t align[1]; -#endif -#ifndef ZB_CONFIGURABLE_MEM - zb_uint8_t trans_table[ZB_APS_BIND_TRANS_TABLE_SIZE]; /*!< Buffers for simultaneous sendings */ - zb_aps_bind_src_table_t src_table[ZB_APS_SRC_BINDING_TABLE_SIZE]; /*!< Source table */ - zb_aps_bind_dst_table_t dst_table[ZB_APS_DST_BINDING_TABLE_SIZE]; /*!< Destination table */ -#else - zb_uint8_t *trans_table; - zb_aps_bind_src_table_t *src_table; - zb_aps_bind_dst_table_t *dst_table; -#endif - zb_aps_binding_table_whitelist_t whitelist_table[ZB_APS_BINDING_TABLE_WHITELIST_SIZE]; /*!< Whitelist table */ - -} ZB_PACKED_STRUCT zb_aps_binding_table_t; - -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_aps_binding_table_t); - -/** - Group table entry - */ -typedef ZB_PACKED_PRE struct zb_aps_group_table_ent_s -{ - zb_uint16_t group_addr; /*!< Group address */ - zb_uint8_t endpoints[ZB_APS_ENDPOINTS_IN_GROUP_TABLE]; /*!< Endpoints table */ - zb_uint8_t n_endpoints; /*!< Count elements in endpoints - * table */ - zb_uint8_t aligned[1]; -} ZB_PACKED_STRUCT zb_aps_group_table_ent_t; - - -ZB_RING_BUFFER_DECLARE(zb_aps_grp_up_q, zb_uint8_t, ZB_APS_GROUP_UP_Q_SIZE); - -/** - Group addressing data structure - */ -typedef struct zb_aps_group_table_s -{ - zb_aps_group_table_ent_t groups[ZB_APS_GROUP_TABLE_SIZE]; /*!< APS group table */ - zb_uint8_t n_groups; /*!< # of entries in APS group table */ -#ifndef ZB_LITE_APS_DONT_TX_PACKET_TO_MYSELF - zb_aps_grp_up_q_t local_dup_q; /*!< queue to be used to pass sending - group addresses packets to myself */ -#endif -} zb_aps_group_table_t; - - -/** - r21 Table 4.33 Trust Center Policy Values - */ -typedef struct zb_tc_policy_s -{ - /* TC policy attributes */ - zb_bitbool_t allow_joins:1; - zb_bitbool_t use_white_list:1; -#ifdef ZB_SECURITY_INSTALLCODES - zb_bitbool_t require_installcodes:1; /*!< bdbJoinUsesInstallCodeKey - * is equal to TRUE, the Trust - * Center only permits a node - * to join its network if - * a corresponding install - * code derived preconfigured - * link key associated - * with the node has been - * preinstalled */ -#endif -#ifndef ZB_LITE_NO_TRUST_CENTER_REQUIRE_KEY_EXCHANGE - zb_bitbool_t update_trust_center_link_keys_required:1; -#endif - zb_bitbool_t ignore_unsecure_tc_rejoins:1; /*nwk.handle.joined. */ - - /*not used zb_bitfield_t bdb_node_join_link_key_type:2;*/ /*!< the type of link key (see - * sub-clause 6.3) with which - * the node was able to decrypt - * the network key. @see bdb_node_join_link_key_type */ - - zb_time_t trust_center_node_join_timeout; - zb_bitfield_t tclk_exchange_attempts:4; /*!< the number of key establishment attempts that have been made to establish a new link key after joining. */ - zb_bitfield_t tclk_exchange_attempts_max:4; /*!< the maximum number of key establishment attempts that will be made before giving up on the key establishment. */ - - /* node-side security policy */ - zb_bitbool_t accept_new_unsolicited_trust_center_link_key:1; - zb_bitbool_t accept_new_unsolicited_application_link_key:1; - zb_bitbool_t waiting_for_tclk_exchange:1; /*!< Set to 1 when node start Link Key exchange - * procedure. Reset to zero when TC LK exchange - * successfully completes or failed */ - zb_bitbool_t is_distributed:1; - -#ifdef ZB_CONTROL4_NETWORK_SUPPORT -#ifdef ZB_ED_FUNC - zb_bitbool_t permit_control4_network:1; /*!< if 1, Joining Control4 Network is permitted */ -#endif - zb_bitbool_t control4_network_emulator:1; /*!< if 1, Emulates Control4 Network behaviour: Transport Key ext src= 0xff,0xff(...) */ -#endif /* defined ZB_ED_FUNC && defined ZB_CONTROL4_NETWORK_SUPPORT */ - zb_bitbool_t aps_unencrypted_transport_key_join:1; /*for joining the devices requiring APS unencrypted Transport key*/ - zb_bitbool_t tc_swapped:1; /*!< 1 if TC is just swapped. */ - zb_bitfield_t authenticate_always:1; /*!< If 1, then zb_authenticate_dev() - * ignore permit_join value */ - zb_bitbool_t allow_unsecure_tc_rejoins:1; /*aps.zdo_ed_scan = 1; -#define ZB_APS_CLEAR_ZDO_ED_SCAN_FLAG() ZG->aps.zdo_ed_scan = 0; -#define ZB_APS_GET_ZDO_ED_SCAN_FLAG() ZG->aps.zdo_ed_scan - -#define ZB_APS_SET_CHANNEL_MANAGER_ED_SCAN_FLAG() ZG->aps.chm_ed_scan = 1; -#define ZB_APS_CLEAR_CHANNEL_MANAGER_ED_SCAN_FLAG() ZG->aps.chm_ed_scan = 0; -#define ZB_APS_GET_CHANNEL_MANAGER_ED_SCAN_FLAG() ZG->aps.chm_ed_scan - -/* zb_aps_dup_tbl_ent_t moved to zboss_api_core.h */ - -typedef struct zb_aps_duplicate_s -{ -#ifndef ZB_CONFIGURABLE_MEM - zb_aps_dup_tbl_ent_t dups_table[ZB_APS_DUPS_TABLE_SIZE]; /*!< Duplicates table */ -#else - zb_aps_dup_tbl_ent_t *dups_table; -#endif -} zb_aps_duplicate_t; - -/** - * @name APS input fragmentation stages - * @anchor aps_in_frag_states - * - * Note: These values were members of `enum zb_aps_in_frag_states_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define APS_IN_FRAG_EMPTY 0x00U -#define APS_IN_FRAG_RECEIVING 0x01U -#define APS_IN_FRAG_WINDOW_RECEIVED 0x02U -#define APS_IN_FRAG_WINDOW_MERGED_NO_ACK 0x03U -#define APS_IN_FRAG_WINDOW_MERGED 0x04U -#define APS_IN_FRAG_COMPLETE 0x05U -/** @} */ - -typedef ZB_PACKED_PRE struct zb_aps_in_fragmented_frame_s -{ -#define ZB_APS_IN_FRAGMENTED_FRAME_EMPTY 0xFFFFu -/* 07/31/2019 EE CR:MINOR Why not addr ref? */ - zb_uint16_t src_addr; /* 0xFFFF for empty entries */ - zb_uint8_t aps_counter; - zb_uint8_t total_blocks_num; - zb_uint8_t current_window; - zb_bufid_t window_buffers[ZB_APS_MAX_FRAGMENT_NUM_IN_WINDOW]; - zb_bufid_t buffer; - ZB_PACKED_PRE struct - { - zb_bitbool_t assemble_in_progress:1; /* probably, we don't need that */ - zb_bitbool_t ack_timer_scheduled:1; - zb_bitfield_t state:3; - zb_bitfield_t aps_ack_retry_cnt:3; - } ZB_PACKED_STRUCT flags; -} ZB_PACKED_STRUCT zb_aps_in_fragment_frame_t; - -/** - * @name APS output fragmentation stages - * @anchor aps_out_frag_stages - * - * These values were members of `enum zb_aps_out_frag_stages_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define APS_FRAG_INACTIVE 0x00U /*!< Fragmentation queue empty */ -#define APS_FRAG_RECEIVED 0x01U /*!< apsde_data received */ -#define APS_FRAG_GET_MAX_TRANSFER 0x02U /*!< Send node descriptor and receive max transfer size */ -#define APS_FRAG_CHAIN_PREPARED 0x03U /*!< Prepare chain */ -#define APS_FRAG_BUFFERS_PREPARED 0x04U /*!< Prepare buffers */ -#define APS_FRAG_TRANSMISSION 0x05U /*!< Fragmented transmission in progress */ -#define APS_FRAG_FINALIZING 0x06U /*!< Transmission completed, to free chains */ -/** @} */ - -#define ZB_APS_BLOCK_REF_SIZE 32U -#define ZB_APS_BLOCK_MASK_SIZE (ZB_APS_BLOCK_REF_SIZE/8U) -typedef struct zb_aps_out_fragmented_frame_s -{ - zb_uint8_t aps_counter; - zb_uint8_t total_blocks_num; - zb_uint8_t blocks_sent_mask[ZB_APS_BLOCK_MASK_SIZE]; - zb_uint8_t blocks_retry_mask[ZB_APS_BLOCK_MASK_SIZE]; - zb_uint8_t current_window; - zb_uint8_t block_ref[ZB_APS_BLOCK_REF_SIZE]; - - zb_uint8_t retry_count; - /* ZB_APS_RETRANS_ENT_SENT_MAC_NOT_CONFIRMED_ALRM_RUNNING case: block_num and block_ack of - * received ack */ - zb_uint8_t wait_block_ack; - zb_uint8_t wait_block_num; - zb_uint8_t state; - /* 2019-03-06 CR:MAJOR What is the reason of this field? It is not used anywhere in - * the code. */ - zb_uint8_t dst_max_in; - zb_uint8_t data_param; - zb_bool_t transmission_is_scheduled; - zb_uint8_t addr_mode; -} zb_aps_out_fragment_frame_t; - -#ifdef APS_FRAGMENTATION -#define ZB_APS_INVALID_MAX_TRANS_SIZE 0U -#define ZB_APS_INVALID_MAX_BUFFER_SIZE 0U -#define ZB_APS_MAX_TRANS_SIZE_TABLE_SIZE 10U -//#define ZB_APS_MAX_TRANS_SIZE_TABLE_SIZE 30 -/* FIXME: Is 1000 sec enough? Looks like we do not need to update it too frequently. */ -/* Timeouts changed to reduce the number of extra sleep/awake pairs on hardware */ -#define ZB_APS_MAX_TRANS_SIZE_CLOCK 20U -#define ZB_APS_MAX_TRANS_SIZE_TMO (50U * ZB_TIME_ONE_SECOND) - -typedef struct zb_aps_max_trans_size_s -{ - zb_uint8_t addr_ref; - zb_uint16_t max_in_trans_size; - zb_uint8_t max_buffer_size; - zb_uint8_t clock; -} zb_aps_max_trans_size_t; -#endif - -typedef void (*zb_aps_binding_added_handler_t)(zb_uint16_t bind_tbl_idx); - -typedef struct zb_aps_func_selector_s -{ - zb_callback_t authhenticate_child_directly; - zb_aps_binding_added_handler_t new_binding_handler; -} zb_aps_func_selector_t; - -#define APS_OUT_FRAG_QUEUE_SIZE 2U -ZB_RING_BUFFER_DECLARE(zb_aps_out_frag_q, zb_bufid_t, APS_OUT_FRAG_QUEUE_SIZE); - - -/** - APS subsystem globals - */ -typedef struct zb_aps_globals_s -{ - zb_apsib_t aib; /*!< AIB parameters */ - zb_aps_binding_table_t binding; /*!< Binding table */ - zb_aps_retrans_t retrans; /*!< Retrans table */ - - zb_aps_group_table_t group; /*!< Group table */ - zb_aps_tmp_t tmp; /*!< */ - zb_aps_duplicate_t dups; - zb_aps_func_selector_t selector; - - /* Lets use 1 simultaneous fragment rx and 1 simultaneous fragment tx (does not affect - non-fragment frames). Specification allows that: - - 2.2.8.4.5 Fragmented Transmissions - Reception and Rejection, and Acknowledgements - If an incoming fragmented transaction is already in progress but the addressing and APS - counter fields do not match those of the received frame, then the received frame may - optionally be rejected or handled independently as a further transaction. - - TODO: May extend to 1 fragmented transaction from 1 neighbor (if needed). - */ -#ifdef APS_FRAGMENTATION - zb_aps_in_fragment_frame_t in_frag[ZB_APS_MAX_IN_FRAGMENT_TRANSMISSIONS]; - zb_aps_out_fragment_frame_t out_frag; - zb_aps_max_trans_size_t max_trans_size[ZB_APS_MAX_TRANS_SIZE_TABLE_SIZE]; - zb_aps_out_frag_q_t out_frag_q; -#endif - - zb_bitbool_t authenticated:1; /*!< if ZB_TRUE, the device is authenticated */ - zb_bitbool_t dups_alarm_running:1; /*!< if ZB_TRUE, the dups packet is processed */ - zb_bitbool_t max_trans_size_alarm_running:1; /*!< if ZB_TRUE, we are process dups packet */ - zb_time_t dups_alarm_start; -#ifdef ZB_APS_USER_PAYLOAD - zb_aps_user_payload_callback_t aps_user_payload_cb; -#endif -} zb_aps_globals_t; - -#ifdef APS_FRAGMENTATION -#define ZB_INVALID_FRAG_ID 0xFFU -ZB_ASSERT_COMPILE_DECL(ZB_APS_MAX_IN_FRAGMENT_TRANSMISSIONS < ZB_INVALID_FRAG_ID); -#endif - -#ifdef ZB_APS_USER_PAYLOAD -zb_bool_t zb_aps_call_user_payload_cb(zb_uint8_t param); - -#define ZB_APS_CALL_USER_PAYLOAD_CB(param) zb_aps_call_user_payload_cb(param) -#else -#define ZB_APS_CALL_USER_PAYLOAD_CB(param) ZB_FALSE -#endif /* ZB_APS_USER_PAYLOAD */ - -/** - Get APS counter field from AIB. - - @return APS counter - */ -#define ZB_AIB_APS_COUNTER() ZG->aps.aib.aps_counter - -/** - Increment APS counter AIB field. -*/ -#define ZB_AIB_APS_COUNTER_INC() ZG->aps.aib.aps_counter++ - -#define ZB_AIB() ZG->aps.aib - -#define APS_SELECTOR() ZG->aps.selector - -#define ZB_AIB_APS_CHANNEL_MASK(idx) ZG->aps.aib.aps_channel_mask_list[(idx)] - -/** - Macro to access TC policy implemented according to r21 - */ -#define ZB_TCPOL() ZG->aps.aib.tcpolicy - -void zb_aib_tcpol_set_update_trust_center_link_keys_required(zb_bool_t enable); -zb_bool_t zb_aib_tcpol_get_update_trust_center_link_keys_required(void); -zb_bool_t zb_aib_tcpol_get_allow_unsecure_tc_rejoins(void); - -#ifdef ZB_DISTRIBUTED_SECURITY_ON -void zb_aib_tcpol_set_is_distributed_security(zb_bool_t enable); -void zb_aib_tcpol_clear_is_distributed_security(void); -zb_bool_t zb_aib_tcpol_get_is_distributed_security(void); -#endif /* ZB_DISTRIBUTED_SECURITY_ON */ - -void zb_aib_set_trust_center_address(const zb_ieee_addr_t address); -void zb_aib_get_trust_center_address(zb_ieee_addr_t address); -zb_uint16_t zb_aib_get_trust_center_short_address(void); -zb_bool_t zb_aib_trust_center_address_zero(void); -zb_bool_t zb_aib_trust_center_address_unknown(void); -zb_bool_t zb_aib_trust_center_address_cmp(const zb_ieee_addr_t address); - -void zb_aib_set_coordinator_version(zb_uint8_t version); -zb_uint8_t zb_aib_get_coordinator_version(void); - -void zb_aib_get_channel_page_list(zb_channel_list_t list); - -void zb_aib_tcpol_set_authenticate_always(zb_bool_t authenticate_always); - -/** - Macro to access BDB attributes. - - Partially shared with TC policy, so use same data structure and sometimes - fields aliases - */ - -/* ZB_BDB was an alias to TCPOLICY. To divide ZBOSS by NCP Host and SoC let's - * put commissioning-related BDB context into ZCL while keep security-related - * fields in TCPOL trying to make BDB security more generic. */ -#define ZB_BDB() BDB_COMM_CTX() - -#ifdef ZB_BDB_MODE - -#ifndef ZB_LITE_BDB_ONLY_COMMISSIONING -#define ZB_IN_BDB() (ZB_COMMISSIONING_TYPE() == ZB_COMMISSIONING_BDB) -#else -#define ZB_IN_BDB() ZB_TRUE -#endif - -#else -#define ZB_IN_BDB() ZB_FALSE -#endif - -#define ZG_APS_BIND_DST_TABLE( _p ) ZG->aps.binding.dst_table[ _p ] - -#define ZB_APS_DUPS() ZG->aps.dups - -/** @def ZB_SE_MODE - * @brief if 1, then SE mode is enabled - */ -#if defined ZB_ENABLE_SE || defined SNCP_MODE -#define ZB_SE_MODE() (ZB_COMMISSIONING_TYPE() == ZB_COMMISSIONING_SE) -#else -#define ZB_SE_MODE() ZB_FALSE -#endif - -/*! @} */ -/*! @endcond */ - -#endif /* ZB_APS_GLOBALS_H */ diff --git a/zboss/development/src/include/zb_bdb_internal.h b/zboss/development/src/include/zb_bdb_internal.h deleted file mode 100644 index 32f0796c0d..0000000000 --- a/zboss/development/src/include/zb_bdb_internal.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Internal BDB header file. -*/ - -#ifndef ZB_BDB_COMMISSIONING_H -#define ZB_BDB_COMMISSIONING_H 1 - -#ifdef ZB_BDB_MODE -/** - * \addtogroup bdb_mode_commissioning - * @{ - * @details - * - */ - -#define ZB_BDB_COMM_QUERY_TIME 4U - -typedef enum bdb_join_machine_e -{ - ZB_BDB_JOIN_MACHINE_SECONDARY_SCAN_START = 0, - ZB_BDB_JOIN_MACHINE_PRIMARY_SCAN = 1, - ZB_BDB_JOIN_MACHINE_SECONDARY_SCAN_DONE = 3, - ZB_BDB_JOIN_MACHINE_DEVINFO_GATHER = 4, - ZB_BDB_JOIN_MACHINE_ADDING_TO_NETWORK = 5, -} bdb_join_machine_t; - - -/** @cond internals_doc */ -typedef ZB_PACKED_PRE struct zb_bdb_comm_respondent_info_s -{ - zb_address_ieee_ref_t addr_ref; /*!< Address reference in Translation Table for "respondent" */ - zb_uint8_t ep_list[ZB_BDB_COMM_ACTIVE_ENDP_LIST_LEN]; /*!< Respondent's active endpoints list */ -#if defined(ZB_BDB_ENABLE_FINDING_BINDING) - zb_uint8_t ep_cnt; /*!< Count of endpoints received during finding and binding */ -#endif - - zb_uint8_t eps_checked; /*!< Count of the currently checked endpoints */ - zb_bufid_t simple_desc_resp_buf; - zb_bufid_t curr_bind_req_buf; - zb_uindex_t curr_cluster_idx; -} ZB_PACKED_STRUCT zb_bdb_comm_respondent_info_t; - -typedef enum bdb_commissioning_signal_e -{ - BDB_COMM_SIGNAL_BAD, /* 0 */ - - BDB_COMM_SIGNAL_INIT_START, /* 1 */ - BDB_COMM_SIGNAL_INIT_SECURE_REJOIN, - BDB_COMM_SIGNAL_INIT_TC_REJOIN, - BDB_COMM_SIGNAL_INIT_FINISH, - - BDB_COMM_SIGNAL_TOUCHLINK_START, /* 5 */ - BDB_COMM_SIGNAL_TOUCHLINK_INITIATOR_DONE, - BDB_COMM_SIGNAL_TOUCHLINK_INITIATOR_FAILED, - BDB_COMM_SIGNAL_TOUCHLINK_NOTIFY_TASK_RESULT, - BDB_COMM_SIGNAL_TOUCHLINK_FINISH, - - BDB_COMM_SIGNAL_NETWORK_STEERING_START, /* 10 */ - BDB_COMM_SIGNAL_NETWORK_STEERING_DISCOVERY_FAILED, - BDB_COMM_SIGNAL_NETWORK_STEERING_TCLK_EX_FAILURE, - BDB_COMM_SIGNAL_NETWORK_STEERING_TCLK_DONE, - /* TODO: BDB_COMM_SIGNAL_NETWORK_STEERING_LEAVE, */ - BDB_COMM_SIGNAL_NETWORK_STEERING_FINISH, - - BDB_COMM_SIGNAL_NETWORK_FORMATION_START, /* 15 */ - BDB_COMM_SIGNAL_NETWORK_FORMATION_FINISH, - - BDB_COMM_SIGNAL_FINDING_N_BINDING_START, /* 17 */ - BDB_COMM_SIGNAL_FINDING_N_BINDING_FINISH, - - BDB_COMM_SIGNAL_REJOIN_START, /* 19 */ - BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_CURRENT_CHANNEL, - BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_CURRENT_CHANNEL, - BDB_COMM_SIGNAL_REJOIN_TRY_TC_REJOIN_ON_ALL_CHANNELS, - BDB_COMM_SIGNAL_REJOIN_TRY_SECURE_REJOIN_ON_ALL_CHANNELS, - BDB_COMM_SIGNAL_REJOIN_FINISH, - - BDB_COMM_SIGNAL_FINISH, /* 25 */ - - BDB_COMM_SIGNAL_NWK_FORMATION_OK, /* 26 */ - BDB_COMM_SIGNAL_NWK_START_ROUTER_CONF, - BDB_COMM_SIGNAL_LEAVE_DONE, - BDB_COMM_SIGNAL_NWK_JOIN_FAILED, - BDB_COMM_SIGNAL_NWK_JOIN_DONE, - BDB_COMM_SIGNAL_NWK_AUTH_FAILED, - - BDB_COMM_N_SIGNALS -} bdb_commissioning_signal_t; - -enum bdb_commissioning_rejoin_reason_e -{ - BDB_COMM_REJOIN_REASON_UNSPECIFIED = 0, - BDB_COMM_REJOIN_REASON_POLL_CONTROL_CHECK_IN, -}; - -/*! -* @ brief BDB Commissioning rejoin context -*/ -typedef ZB_PACKED_PRE struct bdb_commissioning_rejoin_ctx_t -{ - zb_bitfield_t rejoin_by_checkin_failure:1; - zb_bitfield_t rr_have_unique_tclk:1; - zb_bitfield_t waiting:1; - zb_bitfield_t reserved:5; - - zb_uint8_t rr_sv_device_type; /* zb_nwk_device_type_t */ - zb_uint16_t rr_sv_parent_short; - zb_ieee_addr_t rr_sv_parent_long; - zb_neighbor_tbl_ent_t rr_sv_parent_nent; - zb_uint8_t rr_sv_authenticated; - zb_uint8_t rr_retries; - zb_uint8_t rr_ignore_start_router_conf; - zb_uint16_t rr_global_retries; - zb_uint8_t rr_skip_savepoint; - - bdb_commissioning_signal_t last_rejoin_signal; - bdb_commissioning_signal_t next_rejoin_signal; -} -ZB_PACKED_STRUCT bdb_commissioning_rejoin_ctx_t; - -/** - * BDB commissioning context - */ -typedef ZB_PACKED_PRE struct zb_bdb_comm_ctx_s -{ - /** State of commissioning */ - zb_bdb_comm_state_t state; - zb_ret_t status; - /** Callback function invoked when factory fresh or network steering operations finish */ - zb_callback_t user_cb; - -#if defined(ZB_BDB_ENABLE_FINDING_BINDING) - /** Callback function invoked when binding operation start */ - zb_bdb_comm_binding_callback_t finding_binding_progress_cb; -/* [AV] After having separated binding user callbacks from f&b complete callback - the last one can be stored in the user_cb field. */ -#endif - - /** Duration of PermitJoining and IdentifyTime */ - zb_uint16_t duration; -/*Data array to store info from Identity_Query_Resp */ - zb_bdb_comm_respondent_info_t respondent[BDB_MAX_IDENTIFY_QUERY_RESP_NUMBER]; - zb_uint8_t respondent_number; - -#if defined(ZB_BDB_ENABLE_FINDING_BINDING) - /** Endpoint which participate in finding and binding*/ - zb_uint8_t ep; -#endif - - /** Endpoint descriptor*/ - zb_af_endpoint_desc_t *ep_desc; - -#if defined(ZB_BDB_ENABLE_FINDING_BINDING) - /** Count of endpoints received during finding and binding */ - zb_uint8_t ep_cnt; - - /** Signals that at least one endpoint was bound during finding and binding; - * it is used to invoke user callback if no endpoint was bound - */ - zb_bool_t was_bound; -#endif - /*EZ mode in progress flag. Sets for EZScanTimeout*/ - zb_bool_t ez_scan_inprogress; - /** Reference to the buffer holding simple descriptor response */ - zb_uint8_t simple_desc_buf_ref; - - /* ------------- */ - bdb_commissioning_signal_t signal; - bdb_commissioning_rejoin_ctx_t rejoin; - - /* Moved here from BDB_CTX */ -#define FIRST_GENERAL_BDB_FIELD bdb_commissioning_group_id - /* BDB attributes */ - zb_uint16_t bdb_commissioning_group_id; /*!< specifies the identifier of the group on which the initiator applies finding & binding. */ - zb_uint8_t bdb_commissioning_mode; /*!< @see zb_bdb_commissioning_mode_mask_t See Table 4 Bits of the bdbCommissioningMode attribute: -0 -Touchlink: 0 = Do not attempt Touchlink commissioning 1 = Attempt Touchlink commissioning -1 -Network steering: 0 = Do not attempt network steering 1 = Attempt network steering -2 -Network formation: 0 = Do not attempt to form a network 1 = Attempt to form a network, according to device type2 -3 -Finding & binding: 0 = Do not attempt finding & binding 1 = Attempt finding & binding - */ - zb_uint8_t bdb_commissioning_status; /*!< see zb_bdb_error_codes_e */ - - zb_uint32_t bdb_primary_channel_set; - zb_uint32_t bdb_secondary_channel_set; - zb_uint32_t v_scan_channels; - zb_uint32_t bdb_commissioning_time; - zb_uint8_t bdb_scan_duration; - zb_uint8_t bdb_commissioning_step; - - zb_bitfield_t v_do_primary_scan:3; /*!< a bit more than vDoPromaryScan in - * BDB: really scan & join machine - * state. @see enum bdb_join_machine_e */ - - zb_bitfield_t bdb_ext_channel_scan:1; /*!< Touchlink performs ext scan if 1 */ - zb_bitfield_t ignore_aps_channel_mask:1; /*!< Non standard, but useful: if 1, - * use hard-coded channels set. if 0, - * mask channels sets by - * aps_channel_mask. To be used to - * debug at single channel, or 2 - * channels etc */ - - - zb_uint8_t bdb_application_signal; /* Application signal code to be passed into - * zb_zdo_startup_complete */ -#ifdef ZB_BDB_TOUCHLINK - zb_uint8_t tl_first_channel_rpt; - zb_uint8_t tl_channel_i; -#endif /* ZB_BDB_TOUCHLINK */ - zb_bitfield_t bdb_force_router_rejoin:1; /* Force rejoin for the router */ - zb_bitfield_t bdb_tc_rejoin_after_reboot:1; /* Is TC rejoin started when reboot signal is scheduled */ - zb_bitfield_t bdb_tc_rejoin_active:1; /* Is TC rejoin active */ - zb_bitfield_t bdb_op_cancelled:1; /* if the BDB operation (steering or formation) is cancelled */ - } ZB_PACKED_STRUCT zb_bdb_comm_ctx_t; -/** @endcond */ /* internals_doc */ - -extern zb_bdb_comm_ctx_t g_bdb_ctx; - -#define BDB_COMM_CTX() g_bdb_ctx - -#if defined ZB_BDB_MODE && !defined BDB_OLD -void bdb_commissioning_machine(zb_uint8_t param); -void bdb_commissioning_signal(bdb_commissioning_signal_t sig, zb_uint8_t param); -#endif /* ZB_BDB_MODE && !BDB_OLD */ - -#if defined ZB_BDB_ENABLE_FINDING_BINDING -void zb_bdb_finding_binding_init_ctx(void); - -void zb_bdb_process_identify_query_res(zb_uint8_t param); -#endif /* ZB_BDB_ENABLE_FINDING_BINDING */ - -/** @cond touchlink */ - -#if defined ZB_BDB_MODE && defined ZB_BDB_TOUCHLINK && !defined ZB_COORDINATOR_ONLY && defined ZB_DISTRIBUTED_SECURITY_ON -void bdb_touchlink_target_start(zb_uint8_t param); -void bdb_touchlink_initiator(zb_uint8_t param); -#endif /* ZB_BDB_MODE && ZB_BDB_TOUCHLINK && !ZB_COORDINATOR_ONLY && ZB_DISTRIBUTED_SECURITY_ON */ - -/** @endcond */ /* touchlink */ - -#ifdef ZB_COORDINATOR_ROLE -#ifdef ZB_ROUTER_ROLE -void bdb_remove_joiner(zb_uint8_t param); -#endif /* ZB_ROUTER_ROLE */ -#endif /* ZB_COORDINATOR_ROLE */ - -#if defined ZB_BDB_MODE && !defined BDB_OLD -#ifdef ZB_BDB_TOUCHLINK -void bdb_check_fn(void); -#endif /* ZB_BDB_TOUCHLINK */ - -void bdb_start_rejoin_recovery(zb_uint8_t param, zb_uint16_t user_param); - -zb_bool_t bdb_joined(void); - -void bdb_force_link(void); - -zb_uint8_t bdb_get_scan_duration(void); - -#endif /* ZB_BDB_MODE && !BDB_OLD */ - - -/** @} */ /* bdb_mode_commissioning */ - -/** @} */ /* bdb_mode_commissioning */ - -#endif /* ZB_BDB_MODE */ - -#endif /* ZB_BDB_COMMISSIONING_H */ diff --git a/zboss/development/src/include/zb_bufpool.h b/zboss/development/src/include/zb_bufpool.h deleted file mode 100644 index 4640022df7..0000000000 --- a/zboss/development/src/include/zb_bufpool.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Packet buffers pool - internal legacy API -*/ - -#ifndef ZB_BUFPOOL_H -#define ZB_BUFPOOL_H 1 - -#include "zb_config.h" -#include "zb_types.h" -#include "zboss_api_core.h" -#include "zboss_api_buf.h" - -/* Definitions common to both implementations */ - -#define ZB_BPOOL_USAGES_RB_SIZE 2U - -#define ZB_BUFS_LIMIT (ZB_IOBUF_POOL_SIZE / 2U) -#define ZB_BUFS_HI_PRIOR_RESERVE (2U) -#ifdef ZB_REDUCE_NWK_LOAD_ON_LOW_MEMORY -#define ZB_BUFS_RESERVE 3U -#endif - -#define ZB_BUF_IS_OOM_STATE_IN() (ZG->bpool.bufs_allocated[1] >= (ZB_BUFS_LIMIT - ZB_BUFS_HI_PRIOR_RESERVE)) - -#define ZB_BUF_IS_OOM_STATE_OUT() (ZG->bpool.bufs_allocated[0] >= (ZB_BUFS_LIMIT - ZB_BUFS_HI_PRIOR_RESERVE)) - -#define ZB_BUF_IS_OOM_STATE() (ZB_BUF_IS_OOM_STATE_IN() || ZB_BUF_IS_OOM_STATE_OUT()) - -#if !defined ZB_MACSPLIT_DEVICE && !defined ZB_MINIMAL_CONTEXT && !defined ZB_ZGPD_ROLE -#define ZB_NWK_UNLOCK_IN(bufid) zb_nwk_unlock_in((bufid)) -#else -#define ZB_NWK_UNLOCK_IN(bufid) -#endif - -#define ZB_BUF_GET_MULTIPLICITY(buf_hdr) ((buf_hdr)->multiplicity) - -/* Differing definitions */ - -#if defined ZB_LEGACY_BUFS /* old buffer implementation */ - -#include "zb_bufpool_legacy.h" - -#else /* new buffer implementation */ - -/* Storage functions */ - -/** - Buffer storage initialization - */ -void zb_bufpool_storage_init(void); - -/** - Allocate a new buffer entry of specified multiplicity: - the allocated buffer's maximum size will equal at least that of buf_cnt buffers - - @param buf_cnt - required buffer multiplicity - @return pointer to the allocated buffer or NULL - */ -zb_buf_ent_t *zb_bufpool_storage_allocate(zb_uint8_t buf_cnt); - -/** - Release a previously allocated buffer back to the storage - - @param buf - pointer to the buffer - */ -void zb_bufpool_storage_free(zb_buf_ent_t *buf); - -/* Even if we return buf ids from zb_bufpool_storage_allocate, we would still need the conversion - from the buffer ptr to the buffer id: zb_buf_from_data0 -*/ -/** - Convert a buffer pointer to its index in the global buffer array - - @param buf - pointer to the buffer - @return zero-based numerical index of the buffer - */ -zb_bufid_t zb_bufpool_storage_buf_to_bufid(zb_buf_ent_t *buf); - -/** - Convert a zero-based buffer index to the corresponding pointer - - @param buf_id - zero-based buffer index - @return pointer to the corresponding zb_buf_ent_t structure - */ -zb_buf_ent_t *zb_bufpool_storage_bufid_to_buf(zb_bufid_t buf_id); - -/* we need this function from zb_bufpool_mult.c only since it needs to calculate and know - the required number of buffers for each buffer allocation. -*/ -/** - Calculate minimal buffer multiplicity required to store packet of the specified size - - @param payload_size - target payload size - @return required buffer multiplicity - */ -zb_uint8_t zb_bufpool_storage_calc_multiplicity(zb_uint16_t payload_size); - -/** - Calculate the maximum payload size that a buffer of the specified multiplicity can hold. - - @param buf_cnt - buffer multiplicity - @return maximum payload size - */ -zb_size_t zb_bufpool_storage_calc_payload_size(zb_uint8_t buf_cnt); - -#ifdef ZB_BUF_SHIELD - -zb_bool_t zb_bufpool_storage_is_buf_corrupted(zb_buf_ent_t *buf); - -#define ZB_BUF_IS_BUSY(param) (ZG->bpool.buf_in_use[(param) / 8U] & (1U<<((param) % 8U))) - -#endif /* #ifdef ZB_BUF_SHIELD */ - -#endif /* #if defined ZB_LEGACY_BUFS */ - - -/* API functions common to both buffer implementations */ - -/** - Set length and data_offset fields in the buffer's header - - @param buf - buffer id - @param len - new length - @param offset - new offset - */ -void zb_buf_set_len_and_offset_func(TRACE_PROTO zb_bufid_t buf, zb_uint16_t len, zb_uint16_t offset); -#define zb_buf_set_len_and_offset(a,b,c) zb_buf_set_len_and_offset_func(TRACE_CALL (a), (b), (c)) - -/** - Return pointer to the first element of buffer array. - - @param buf - buffer id - - @return pointer to the buffer array - */ -zb_uint8_t *zb_buf_data0_func(TRACE_PROTO zb_bufid_t buf); -#define zb_buf_data0(a) zb_buf_data0_func(TRACE_CALL (a)) - -/** - Convert buffer pointer into bufid. - ptr can be obtained from zb_buf_data0() function. - - @param ptr - pointer to the buffer array - @return buffer id - */ -zb_bufid_t zb_buf_from_data0_func(TRACE_PROTO void *ptr); -#define zb_buf_from_data0(a) zb_buf_from_data0_func(TRACE_CALL (a)); - - -#ifdef ZB_TH_ENABLED -/** - Set length field in the buffer's header - - @param buf - buffer id - @param len - new length - */ -void zb_buf_set_len_func(TRACE_PROTO zb_bufid_t buf, zb_uint16_t len); -#define zb_buf_set_len(a,b) zb_buf_set_len_func(TRACE_CALL (a),(b)) -#endif -/** - Return pointer to the data by offset off from data section start. - - @param buf - buffer id - @param off - offset from the data section begin - - @return pointer to the data - */ -void *zb_buf_data_func(TRACE_PROTO zb_bufid_t buf, zb_uint_t off); -#define zb_buf_data(a, b) zb_buf_data_func(TRACE_CALL (a),(b)) - -#ifdef ZB_TH_ENABLED -/** - Get 'data_offset' field of the buffer's header - - @param buf - buffer id - @return data_offset field value - */ -zb_uint16_t zb_buf_get_offset_func(TRACE_PROTO zb_bufid_t buf); -#define zb_buf_get_offset(a) zb_buf_get_offset_func(TRACE_CALL (a)) -#endif /* ZB_TH_ENABLED */ - - -/** - * @brief Changes buffer type from "in" to "out" when "in" buffers count is greater then "out" buffers count. - * - * Buffer type requalification can be needed in cases when "in" buffers is reused to send response for some incoming - * packet. - * - * @param buf - buffer id to change type. - * @return RET_OK or error code. - */ -zb_ret_t zb_buf_requalify_in_to_out_func(TRACE_PROTO zb_bufid_t buf); -#define zb_buf_requalify_in_to_out(buf) zb_buf_requalify_in_to_out_func(TRACE_CALL (buf)) - -/** - Initialize packet buffers pool. - - To be called at start time. - - @return nothing - - Note: internal call. - */ -void zb_init_buffers(void); - -#endif /* ZB_BUFPOOL_H */ diff --git a/zboss/development/src/include/zb_bufpool_globals.h b/zboss/development/src/include/zb_bufpool_globals.h deleted file mode 100644 index 7642058857..0000000000 --- a/zboss/development/src/include/zb_bufpool_globals.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Buffer pool globals declaration -*/ - -#ifndef ZB_BUFPOOL_GLOBALS_H -#define ZB_BUFPOOL_GLOBALS_H 1 - -/*! @cond internals_doc */ -/*! \addtogroup ZB_BASE */ -/*! @{ */ - -#include "zboss_api_buf_legacy.h" -#include "zb_bufpool.h" - -#ifdef ZB_BIGBUF -#define ZB_BUF_SET_BUSY_BIG(param) ZB_ASSERT(!ZB_BUF_CHECK_BUSY_BIG(param));ZG->bpool.big_buf_in_use[(ZB_BIGBUF_ID_FROM_REF(param)) / 8U] |= (1U<<((ZB_BIGBUF_ID_FROM_REF(param)) % 8U)) -#define ZB_BUF_CLEAR_BUSY_BIG(param) ZB_ASSERT(ZB_BUF_CHECK_BUSY_BIG(param)); ZG->bpool.big_buf_in_use[(ZB_BIGBUF_ID_FROM_REF(param)) / 8U] &= ~(1U<<((ZB_BIGBUF_ID_FROM_REF(param)) % 8U)) -#endif - - -#ifdef ZB_BUF_SHIELD - -#define ZB_BUF_HDR_SIGNATURE 0xbbU -#define ZB_BUF_TAIL_SIGNATURE 0xbeU - -#ifdef ZB_BIGBUF - -#define ZB_BUF_SET_BUSY_SM(param) ZB_ASSERT(!ZB_BUF_IS_BUSY(param)); ZG->bpool.buf_in_use[(param) / 8U] |= (1U<<((param) % 8U)) -#define ZB_BUF_SET_BUSY(param) ((ZB_IS_BIGBUF(param))?ZB_BUF_SET_BUSY_BIG(param):ZB_BUF_SET_BUSY(param)) - -#define ZB_BUF_CLEAR_BUSY_SM(param) ZB_ASSERT(ZB_BUF_IS_BUSY(param)); ZG->bpool.buf_in_use[(param) / 8U] &= ~(1U<<((param) % 8U)) -#define ZB_BUF_CLEAR_BUSY(param) ((ZB_IS_BIGBUF(param))?ZB_BUF_CLEAR_BUSY_BIG(param):ZB_BUF_CLEAR_BUSY(param)) - -#else - -#define ZB_BUF_SET_BUSY(param) \ -ZB_ASSERT(!ZB_BUF_IS_BUSY(param));\ -ZG->bpool.buf_in_use[(param) / 8U] |= (1U<<((param) % 8U)) -#define ZB_BUF_CLEAR_BUSY(param) \ -ZB_ASSERT(ZB_BUF_IS_BUSY(param));\ -ZG->bpool.buf_in_use[(param) / 8U] &= ~(1U<<((param) % 8U)) - -#endif - -#else - -#define ZB_BUF_SET_BUSY(param) - -#define ZB_BUF_CLEAR_BUSY(param) - -#endif - - - - -/** - Buffers pool - */ -typedef struct zb_buf_pool_s -{ -#ifdef ZB_USE_STD_MALLOC - zb_buf_t *pool[ZB_IOBUF_POOL_SIZE]; /*!< Buffers pointers array*/ -#else - -#ifndef ZB_CONFIGURABLE_MEM - zb_buf_ent_t pool[ZB_IOBUF_POOL_SIZE]; /*!< Buffers array (static memory configuration case)*/ -#else - zb_buf_ent_t *pool; /*!< Pointer to buffers array allocated elsewhere. @see configurable_mem_internals */ -#endif - -#ifdef ZB_LEGACY_BUFS - zb_buf_t ZB_XDATA *head; /*!< First free buffer*/ -#endif - -#endif /* else #ifdef ZB_USE_STD_MALLOC */ -#ifdef ZB_BIGBUF - zb_bigbuf_t bpool[ZB_BIGBUF_POOL_SIZE/*ZB_IOBUF_POOL_SIZE*/]; - zb_uint8_t bigbufs_allocated; - //zb_uint8_t bigbufs_allocated[2]; /*!< Count used buffers for in/out packet */ -#endif - zb_uint_t reserved; /*!< reserved bytes at buf pool tail */ - zb_uint8_t bufs_allocated[2]; /*!< Count used buffers for in/out packet */ - zb_bool_t mac_rx_need_buf; /*!< Flag 'buffer need for mac read cmd'. - Mac read cmd is first in queue to buffer always' */ - -#ifndef ZB_CONFIGURABLE_MEM -#define ZB_BUF_POOL_BITMAP_SIZE ((ZB_IOBUF_POOL_SIZE + 7U) / 8U) - zb_uint8_t busy_bufs_bitmap[ZB_BUF_POOL_BITMAP_SIZE]; /* Bitmap storing the state of each - * buffer: - * '1' - currently allocated - * '0' - currently free - * It is different from buf_in_use since - * 1 allocated buffer may occupy the span - * of multiple actual buffers. - */ -#else - zb_uint8_t *busy_bufs_bitmap; -#endif - -#ifdef ZB_BUF_SHIELD -#ifndef ZB_CONFIGURABLE_MEM - zb_uint8_t buf_in_use[(ZB_IOBUF_POOL_SIZE + 7)/8]; /*!< bitmap of allocated - buffers */ -#else - zb_uint8_t *buf_in_use; -#endif -#endif -} zb_buf_pool_t; - - -/*! @} */ -/*! @endcond */ - -#endif /* ZB_BUFPOOL_GLOBALS_H */ diff --git a/zboss/development/src/include/zb_commissioning.h b/zboss/development/src/include/zb_commissioning.h deleted file mode 100644 index 1dcbf84887..0000000000 --- a/zboss/development/src/include/zb_commissioning.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: commissioning layer definitions -*/ - -#ifndef ZB_COMMISSIONING_H -#define ZB_COMMISSIONING_H 1 - -#include "zb_common.h" - -typedef zb_uint8_t zb_commissioning_signal_t; - -typedef void (*zb_commissioning_signal_func_t)(zb_commissioning_signal_t, zb_bufid_t); -typedef zb_uint8_t (*zb_commissioning_get_permit_join_duration_func_t)(void); -typedef zb_bool_t (*zb_commissioning_must_use_installcode_func_t)(zb_bool_t is_client); -typedef void (*zb_commissioning_formation_channels_mask_t)(zb_channel_list_t list); -typedef zb_uint8_t (*zb_commissioning_get_scan_duration_func_t)(void); -typedef void (*zb_commissioning_get_scan_channel_mask_func_t)(zb_channel_list_t channel_mask); -typedef zb_bool_t (*zb_commissioning_is_in_tc_rejoin_func_t)(void); - -#define ZB_COMM_SIGNAL_START 1u -#define ZB_COMM_SIGNAL_NWK_DISC_FAILED 2u -#define ZB_COMM_SIGNAL_JOIN_FAILED 3u -#define ZB_COMM_SIGNAL_AUTH_FAILED 4u -#define ZB_COMM_SIGNAL_INITIATE_REJOIN 5u -#define ZB_COMM_SIGNAL_DEV_ANNCE_SENT 6u -#define ZB_COMM_SIGNAL_ROUTER_STARTED 7u -#define ZB_COMM_SIGNAL_TCLK_UPDATE_COMPLETE 8u -#define ZB_COMM_SIGNAL_TCLK_UPDATE_FAILED 9u -#define ZB_COMM_SIGNAL_LEAVE_DONE 10u -#define ZB_COMM_SIGNAL_AUTH_OK 11u -#define ZB_COMM_SIGNAL_SECUR_FAILED 12u /* do we need it? Isn't it the same as TCLK_UPDATE_FAILED? */ -#define ZB_COMM_SIGNAL_REJOIN_AFTER_SECUR_FAILED 13u /* key switch failure */ -#define ZB_COMM_SIGNAL_LEAVE_WITH_REJOIN 14u -#define ZB_COMM_SIGNAL_SECURED_REJOIN 15u -#define ZB_COMM_SIGNAL_FORMATION_DONE 16u -#define ZB_COMM_SIGNAL_FORMATION_FAILED 17u -#define ZB_COMM_SIGNAL_AUTHENTICATE_REMOTE 18u -#define ZB_COMM_SIGNAL_TCLK_VERIFIED_REMOTE 19u -#define ZB_COMM_SIGNAL_DEVICE_LEFT 20u -#define ZB_COMM_SIGNAL_INIT 21u - - -typedef struct zb_formation_func_selector_s -{ - zb_callback_t start_formation; - zb_commissioning_formation_channels_mask_t get_formation_channels_mask; - zb_commissioning_get_scan_duration_func_t get_scan_duration; -} zb_formation_func_selector_t; - - -typedef struct zb_commissioning_func_selector_s -{ - zb_commissioning_signal_func_t signal; - -#ifdef ZB_ROUTER_ROLE - zb_commissioning_get_permit_join_duration_func_t get_permit_join_duration; -#endif /* ZB_ROUTER_ROLE */ - -#ifndef NCP_MODE_HOST - zb_commissioning_must_use_installcode_func_t must_use_install_code; -#endif /* !NCP_MODE_HOST */ - -#ifdef ZB_JOIN_CLIENT - zb_commissioning_get_scan_duration_func_t get_scan_duration; - zb_commissioning_get_scan_channel_mask_func_t get_scan_channel_mask; -#endif /* ZB_JOIN_CLIENT */ - - zb_commissioning_is_in_tc_rejoin_func_t is_in_tc_rejoin; -} zb_commissioning_func_selector_t; - -typedef struct zb_commissioning_ctx_s -{ - zb_commissioning_type_t commissioning_type; - struct zb_discovery_ctx_s - { - zb_uint8_t scanlist_ref; /* Buffer with scanlist */ - zb_ushort_t scanlist_idx; /* nwk descriptor index in scanlist */ - zb_uint8_t scanlist_join_attempt_n; /* Indicates the current joining - * attempt number */ - zb_uint8_t disc_count; /*!< */ - zb_uint16_t nwk_time_btwn_scans; /* Integer value representing the - * time duration (in milliseconds) - * between each NWK discovery - * attempt. This attribute has a - * default value of 100 (milliseconds) */ - zb_uint8_t nwk_scan_attempts; /* Integer value representing the - * number of scan attempts to make - * before the NWK layer decides which - * Zigbee coordinator or router to - * associate with (see sub-clause - * 2.5.5.5). This attribute has - * default value of 5 */ - - zb_callback_t active_scan_complete_cb; - } discovery_ctx; - -#ifdef ZB_FORMATION - zb_formation_func_selector_t formation_selector; -#endif /* ZB_FORMATION */ - - zb_commissioning_func_selector_t commissioning_selector; -} zb_commissioning_ctx_t; - -#define COMM_CTX() ZG->commissioning_ctx -#define FORMATION_SELECTOR() COMM_CTX().formation_selector -#define COMM_SELECTOR() COMM_CTX().commissioning_selector - -void zdo_commissioning_init(void); -void zdo_commissioning_start(zb_uint8_t param); -#if !defined NCP_MODE_HOST && defined ZB_SECURITY_INSTALLCODES && !defined ZB_SECURITY_INSTALLCODES_ONLY -zb_bool_t zdo_secur_must_use_installcode(zb_bool_t is_client); -#endif /* !NCP_MODE_HOST && ZB_SECURITY_INSTALLCODES && !ZB_SECURITY_INSTALLCODES_ONLY */ -void zdo_comm_set_permit_join_after_router_start(zb_uint8_t param); -void zdo_handle_nlme_network_discovery_confirm(zb_uint8_t param); -void zdo_join_to_nwk_descr(zb_uint8_t param); -void zdo_authenticated_send_device_annce(zb_uint8_t param); -void zdo_reset_scanlist(zb_bool_t do_free); -void zdo_call_nlme_reset(zb_uint8_t param, zb_bool_t warm_start, zb_callback_t cb); -void zdo_next_nwk_discovery_req(zb_uint8_t param); -zb_bool_t zb_distributed_security_enabled(void); -#if !defined NCP_MODE_HOST && defined ZB_COORDINATOR_ROLE -void zdo_commissioning_secure_rejoin_setup_lk_alarm(zb_uint8_t param); -void zdo_commissioning_tclk_verified_remote(zb_address_ieee_ref_t param); -void zdo_commissioning_device_left(zb_address_ieee_ref_t param); -#endif /* !NCP_MODE_HOST && ZB_COORDINATOR_ROLE */ -#ifdef ZB_FORMATION -void zdo_commissioning_send_nwk_key_to_joined_dev(zb_uint8_t param, zb_uint16_t user_param); -void zdo_commissioning_authenticate_remote(zb_bufid_t param); -#endif /* ZB_FORMATION */ -void zdo_commissioning_leave_with_rejoin(zb_uint8_t param); - -#ifdef ZB_ROUTER_ROLE -void zdo_commissioning_start_router_confirm(zb_uint8_t param); -#endif - -#ifdef ZB_JOIN_CLIENT -void zdo_commissioning_join_via_scanlist(zb_uint8_t param); -void zdo_commissioning_nwk_discovery_failed(zb_uint8_t param); -void zdo_commissioning_join_failed(zb_uint8_t param); -void zdo_commissioning_authentication_failed(zb_uint8_t param); -void zdo_commissioning_handle_dev_annce_sent_event(zb_uint8_t param); -void zdo_commissioning_initiate_rejoin(zb_uint8_t param); -zb_bool_t zdo_secur_waiting_for_tclk_update(void); -void zdo_retry_joining(zb_uint8_t param); -void zdo_commissioning_tclk_upd_complete(zb_uint8_t param); -void zdo_commissioning_tclk_upd_failed(zb_uint8_t param); -void zdo_commissioning_authenticated(zb_uint8_t param); -void zdo_commissioning_dev_annce_sent(zb_uint8_t param); -void zdo_commissioning_secur_failed(zb_uint8_t param); -void zdo_commissioning_leave_done(zb_uint8_t param); -void zdo_inform_app_leave(zb_uint8_t leave_type); -#endif - - - -#endif /* ZB_COMMISSIONING_H */ diff --git a/zboss/development/src/include/zb_common.h b/zboss/development/src/include/zb_common.h deleted file mode 100644 index 79e9d7e305..0000000000 --- a/zboss/development/src/include/zb_common.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Common include file for ZigBee -*/ -#ifndef ZB_COMMON_H -#define ZB_COMMON_H 1 - -#include "zb_config.h" - -#ifdef ZB_MINIMAL_CONTEXT - -#include "zb_g_context_min.h" - -#else - -#include "zboss_api.h" -#include "zb_types.h" -#include "zb_errors.h" -#include "zb_debug.h" -#include "zb_g_context.h" -#include "zb_trace.h" -#include "zb_hash.h" -#ifdef ZB_TH_ENABLED -#include "zb_th_internal.h" -#else -#include "zb_th_dummy.h" -#endif /* ZB_TH_ENABLED */ -#include "zb_common_u.h" - -#include "zb_nvram.h" - -/*! \addtogroup init_api */ -/*! @{ */ - -void zb_globals_init(void); - -#if defined ENABLE_USB_SERIAL_IMITATOR -#define USB_SERIAL_IMITATOR_RX_PIPE "usbc_rx" -#define USB_SERIAL_IMITATOR_TX_PIPE "usbc_tx" -#endif /* defined ENABLE_USB_SERIAL_IMITATOR */ - -/*! @} */ - -/*! \internal \addtogroup ZB_BASE */ -/*! @{ */ - -/** - Set Informational Bases defaults. - - @param rx_pipe - rx pipe name (for Unix) or node number (for ns build - in 8051 simulator) - */ -void zb_ib_set_defaults(zb_char_t *rx_pipe); - -enum zb_dev_specific_e -{ - /*! Standard device */ - ZB_STANDARD_SPECIFIC_DEVICE = 0x00, - /*! Manufactured device */ - ZB_MANUFACTURED_SPECIFIC_DEVICE = 0x01 -}; - -/* Definitions for multiple tests in the same FW image / same Linux binary */ -#ifdef ZB_MULTI_TEST -extern zb_int_t g_argc; -extern char** g_argv; -#define ZB_ARGV g_argv -#define ZB_ARGC g_argc -#undef MAIN -#undef ARGV_UNUSED -#define ARGV_UNUSED -#undef MAIN_RETURN -#define MAIN_RETURN(x) -#define TN_CAT0(x,y) x ## y -#define TN_CAT(x,y) TN_CAT0(x,y) -#define MAIN void TN_CAT(ZB_TEST_NAME,_main) -#define ZB_ZDO_STARTUP_COMPLETE void TN_CAT(ZB_TEST_NAME,_zb_zdo_startup_complete) -#define ZGPD_STARTUP_COMPLETE void TN_CAT(ZB_TEST_NAME,_zgpd_startup_complete) - -/* List of MAC primitives' callbacks */ -#define ZB_MLME_ASSOCIATE_INDICATION void TN_CAT(ZB_TEST_NAME,_zb_mlme_associate_indication) -#define ZB_MLME_ASSOCIATE_CONFIRM void TN_CAT(ZB_TEST_NAME,_zb_mlme_associate_confirm) -#define ZB_MLME_BEACON_NOTIFY_INDICATION void TN_CAT(ZB_TEST_NAME,_zb_mlme_beacon_notify_indication) -#define ZB_MLME_COMM_STATUS_INDICATION void TN_CAT(ZB_TEST_NAME,_zb_mlme_comm_status_indication) -#define ZB_MLME_ORPHAN_INDICATION void TN_CAT(ZB_TEST_NAME,_zb_mlme_orphan_indication) -#define ZB_MLME_RESET_CONFIRM void TN_CAT(ZB_TEST_NAME,_zb_mlme_reset_confirm) -#define ZB_MLME_SCAN_CONFIRM void TN_CAT(ZB_TEST_NAME,_zb_mlme_scan_confirm) -#define ZB_MLME_START_CONFIRM void TN_CAT(ZB_TEST_NAME,_zb_mlme_start_confirm) -#define ZB_MLME_POLL_CONFIRM void TN_CAT(ZB_TEST_NAME,_zb_mlme_poll_confirm) -#define ZB_MLME_PURGE_CONFIRM void TN_CAT(ZB_TEST_NAME,_zb_mlme_purge_confirm) -#define ZB_MCPS_DATA_INDICATION void TN_CAT(ZB_TEST_NAME,_zb_mcps_data_indication) -#define ZB_MCPS_DATA_CONFIRM void TN_CAT(ZB_TEST_NAME,_zb_mcps_data_confirm) -#define ZB_MLME_DUTY_CYCLE_MODE_INDICATION void TN_CAT(ZB_TEST_NAME,_zb_mlme_duty_cycle_mode_indication) -#define ZB_PLME_CCA_CONFIRM void TN_CAT(ZB_TEST_NAME,_zb_plme_cca_confirm) - -#else /* ZB_MULTI_TEST */ - -#define ZB_ZDO_STARTUP_COMPLETE void zb_zdo_startup_complete -#define ZGPD_STARTUP_COMPLETE void zgpd_startup_complete - - /* List of MAC primitives' callbacks */ -#define ZB_MLME_ASSOCIATE_INDICATION void zb_mlme_associate_indication -#define ZB_MLME_ASSOCIATE_CONFIRM void zb_mlme_associate_confirm -#define ZB_MLME_BEACON_NOTIFY_INDICATION void zb_mlme_beacon_notify_indication -#define ZB_MLME_COMM_STATUS_INDICATION void zb_mlme_comm_status_indication -#define ZB_MLME_ORPHAN_INDICATION void zb_mlme_orphan_indication -#define ZB_MLME_RESET_CONFIRM void zb_mlme_reset_confirm -#define ZB_MLME_SCAN_CONFIRM void zb_mlme_scan_confirm -#define ZB_MLME_START_CONFIRM void zb_mlme_start_confirm -#define ZB_MLME_POLL_CONFIRM void zb_mlme_poll_confirm -#define ZB_MLME_PURGE_CONFIRM void zb_mlme_purge_confirm -#define ZB_MCPS_DATA_INDICATION void zb_mcps_data_indication -#define ZB_MCPS_DATA_CONFIRM void zb_mcps_data_confirm -#define ZB_MLME_DUTY_CYCLE_MODE_INDICATION void zb_mlme_duty_cycle_mode_indication -#define ZB_PLME_CCA_CONFIRM void zb_plme_cca_confirm - -#define ZB_ARGV argv -#define ZB_ARGC argc - -#endif /* ZB_MULTI_TEST */ - -/** - * @brief Implements "if (a) then (b)" logical operation. - * - * @b Example: - * Instead of: - * @code - * { - * if(ret == RET_OK) - * ZB_ASSERT(*p != NULL); - * } - * @endcode - * It is possible to write as: - * @code - * { - * ZB_ASSERT(ZB_THEREFORE(ret == RET_OK, *p != NULL)); - * } - * @endcode - * This approach avoid dead code when ZB_ASSERT is not defined - */ -#define ZB_THEREFORE(a, b) (!(a) || (b)) - -/** - * @brief Assert using #ZB_THEREFORE macro - */ -#define ZB_ASSERT_IF(cond, assert) (ZB_ASSERT(ZB_THEREFORE((cond), (assert)))) - -#ifndef ZB_CONFIGURABLE_MEM -#define ZB_RESYNC_CFG_MEM() -#else /* ZB_CONFIGURABLE_MEM */ -void zb_init_configurable_mem(int clear); -#define ZB_RESYNC_CFG_MEM() zb_init_configurable_mem(0) -#endif /* ZB_CONFIGURABLE_MEM */ - -#if !defined ZB_LEGACY_BUFS -#ifdef zb_buf_t -#undef zb_buf_t -#undef ZB_BUF_ALLOC_LEFT -#undef ZB_BUF_ALLOC_RIGHT -#undef ZB_BUF_BEGIN_FROM_REF -#undef ZB_BUF_BEGIN -#undef ZB_BUF_CLEAR_PARAM -#undef ZB_BUF_COPY -#undef ZB_BUF_CUT_LEFT2 -#undef ZB_BUF_CUT_LEFT -#undef ZB_BUF_CUT_RIGHT -#undef ZB_BUF_FROM_REF -#undef ZB_BUF_GET_ARRAY_PTR -#undef ZB_BUF_INITIAL_ALLOC -#undef ZB_BUF_LEN_BY_REF -#undef ZB_BUF_LEN -#undef ZB_BUF_OFFSET -#undef ZB_BUF_REUSE -#undef ZB_FREE_BUF -#undef ZB_FREE_BUF_BY_REF -#undef ZB_GET_BUF_PARAM -#undef ZB_GET_BUF_TAIL -#undef ZB_GET_IN_BUF -#undef ZB_GET_IN_BUF_DELAYED -#undef ZB_GET_OUT_BUF -#undef ZB_GET_OUT_BUF_DELAYED2 -#undef ZB_GET_OUT_BUF_DELAYED -#undef ZB_REF_FROM_BUF -#undef ZB_REF_FROM_BUF_PTR -#undef ZB_SET_BUF_PARAM_PTR -#undef ZB_SET_BUF_PARAM -#undef ZB_SWITCH_BUF - -#endif /*zb_buf_t */ - -#define ZB_BUF_ALLOC_LEFT(zbbuf, size, ptr) No old buf API -#define ZB_BUF_ALLOC_RIGHT(zbbuf, size, ptr) No old buf API -#define ZB_BUF_BEGIN_FROM_REF(_ref) No old buf API -#define ZB_BUF_BEGIN(zbbuf) No old buf API -#define ZB_BUF_CLEAR_PARAM(zbbuf) No old buf API -#define ZB_BUF_COPY(dst_buf, src_buf) No old buf API -#define ZB_BUF_CUT_LEFT2(zbbuf, size) No old buf API -#define ZB_BUF_CUT_LEFT(zbbuf, size, ptr) No old buf API -#define ZB_BUF_CUT_RIGHT(zbbuf, size) No old buf API -#define ZB_BUF_FROM_REF(ref) No old buf API -#define ZB_BUF_GET_ARRAY_PTR(zbbuf) No old buf API -#define ZB_BUF_INITIAL_ALLOC(zbbuf, size, ptr) No old buf API -#define ZB_BUF_LEN_BY_REF(param) No old buf API -#define ZB_BUF_LEN(zbbuf) No old buf API -#define ZB_BUF_OFFSET(zbbuf) No old buf API -#define ZB_BUF_REUSE(zbbuf) No old buf API -#define ZB_FREE_BUF(buf) No old buf API -#define ZB_FREE_BUF_BY_REF(param) No old buf API -#define ZB_GET_BUF_PARAM(zbbuf, type) No old buf API -#define ZB_GET_BUF_TAIL(zbbuf, size) No old buf API -#define ZB_GET_IN_BUF() No old buf API -#define ZB_GET_IN_BUF_DELAYED(callback) No old buf API -#define ZB_GET_OUT_BUF() No old buf API -#define ZB_GET_OUT_BUF_DELAYED2(callback, user_param) No old buf API -#define ZB_GET_OUT_BUF_DELAYED(callback) No old buf API -#define ZB_REF_FROM_BUF(buf) No old buf API -#define ZB_REF_FROM_BUF_PTR(ptr) No old buf API -#define ZB_SET_BUF_PARAM_PTR(zbbuf, param, type) No old buf API -#define ZB_SET_BUF_PARAM(zbbuf, param, type) No old buf API -#define ZB_SWITCH_BUF(buf, to_in) No old buf API -#endif /* !defined ZB_LEGACY_BUFS */ - -/* - * Static compile time assertion to make sure that 'zb_bool_t' has the size - * of exactly one byte, regardless of the used platform. - */ -ZB_ASSERT_TYPE_SIZE_NOT_GREATER(zb_bool_t, 1); - -#endif /* ZB_MINIMAL_CONTEXT */ - -#endif /* ZB_COMMON_H */ diff --git a/zboss/development/src/include/zb_common_u.h b/zboss/development/src/include/zb_common_u.h deleted file mode 100644 index cd915cf5c6..0000000000 --- a/zboss/development/src/include/zb_common_u.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Common utilities include file for ZigBee -*/ -#ifndef ZB_COMMON_U_H -#define ZB_COMMON_U_H 1 - -#include "zboss_api_core.h" - -/** - Generate random value between 0 to 0xffffffff (32 bit) for jitters - */ -zb_uint32_t zb_random_jitter(void); - -/** - Used only for jitters. Need to add a premonition to randoms - */ -#define ZB_RANDOM_JTR(max_value) (zb_random_jitter() / (ZB_RAND_MAX / (zb_uint32_t)(max_value))) - -/*! @} */ - -/*! \internal \addtogroup ZB_BASE */ -/*! @{ */ - -/** - Generate CRC8 hash - */ -zb_uint8_t zb_crc8(const zb_uint8_t *p, zb_uint8_t crc, zb_uint_t len); - -/** - Generate CRC16 hash for string - */ -zb_uint16_t zb_crc16(const zb_uint8_t *p, zb_uint16_t crc, zb_uint_t len); - - -/** - Generate CRC32 hash - */ -zb_uint32_t zb_crc32(const zb_uint8_t *p, zb_uint_t len); - -zb_uint32_t zb_crc32_next(zb_uint32_t prev_crc, zb_uint8_t *p, zb_uint_t len); - -zb_uint32_t zb_crc32_next_v2(zb_uint32_t prev_crc, zb_uint8_t *p, zb_uint16_t len); - -/** - * Calculates number of '1' in 16bit bitmask - */ -zb_uint8_t zb_bit_cnt16(zb_uint16_t a); - -void zb_inverse_bytes(zb_uint8_t *ptr, zb_uint32_t len); - -zb_uint_t zb_high_bit_number(zb_uint32_t mask); - -zb_uint_t zb_low_bit_number(zb_uint32_t mask); - -/*! @} */ - -#ifdef ZB_TOOL -void zb_init_tool(void); -#endif - -#endif /* ZB_COMMON_U_H */ diff --git a/zboss/development/src/include/zb_error_indication.h b/zboss/development/src/include/zb_error_indication.h deleted file mode 100644 index 7e51792a03..0000000000 --- a/zboss/development/src/include/zb_error_indication.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Error indication globals definition -*/ - -#ifndef ZB_ERROR_INDICATION_H -#define ZB_ERROR_INDICATION_H 1 - -#include "zb_types.h" -#include "zb_errors.h" -#include "zboss_api_error.h" - -/** - * Raise an error. Use ZB_ERROR_RAISE macro instead of this function. - * - * @param severity - a severity level of the error - * @param err_code - an error code (@see zb_ret_t), consists of an error category and code, - * @see ERROR_CODE. - * @param additional_info - any additional error-dependent info - */ -void zb_error_raise(zb_uint8_t severity, zb_ret_t err_code, void *additional_info); - -#ifdef HAVE_TOP_LEVEL_ERROR_HANDLER -/** - * Top-level handler which is called before an application handler - * if HAVE_TOP_LEVEL_ERROR_HANDLER is defined. - */ -zb_bool_t zb_error_top_level_handler(zb_uint8_t severity, zb_ret_t err_code, void *additional_info); -#endif /* HAVE_TOP_LEVEL_ERROR_HANDLER */ - -#define ZB_ERROR_RAISE(severity, err_code, additional_info) \ - zb_error_raise((severity), (err_code), (additional_info)) - -#endif /* ZB_ERROR_INDICATION_H */ diff --git a/zboss/development/src/include/zb_g_context.h b/zboss/development/src/include/zb_g_context.h deleted file mode 100644 index 960f9f1e63..0000000000 --- a/zboss/development/src/include/zb_g_context.h +++ /dev/null @@ -1,736 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Global context definition -*/ - -#ifndef ZB_G_CONTEXT_H -#define ZB_G_CONTEXT_H 1 - -#include "zb_osif.h" - -#ifdef ZB_MINIMAL_CONTEXT -#error "This header should not be used with ZB_MINIMAL_CONTEXT macro" -#endif /* ZB_MINIMAL_CONTEXT */ - -#if defined ZB_CONFIGURABLE_MEM || defined DOXYGEN -/* - When configuring some memory object sizes at application link time - instead of ZBOSS library compile time, use variables instead of - constants in ZBOSS. - - Keep old macros to prevent massive ZBOSS - sources change and to be able to switch off configurable memory - feature. - - Declarations of variables defining parameters sizes. - Also redefinitions of constants used in ZBOSS normally. - */ - -/** -@internal -@{ -@addtoroup configurable_mem_internals -@{ - */ -/** - Redefinition of ZB_IOBUF_POOL_SIZE: use variable gc_pool_size inside the stack kernel. - */ -extern zb_uint_t gc_pool_size; -#define ZB_IOBUF_POOL_SIZE gc_pool_size - -extern zb_uint8_t gc_buf_pool_bitmap_size; -#define ZB_BUF_POOL_BITMAP_SIZE gc_buf_pool_bitmap_size - -extern zb_uint_t gc_mac_pending_queue_size; -#define ZB_MAC_PENDING_QUEUE_SIZE gc_mac_pending_queue_size - -extern zb_uint_t gc_n_aps_retrans_entries; -#define ZB_N_APS_RETRANS_ENTRIES gc_n_aps_retrans_entries - -extern zb_uint_t gc_sched_q_size; -#define ZB_SCHEDULER_Q_SIZE gc_sched_q_size - -extern zb_uint_t gc_n_aps_key_pair; -#define ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE gc_n_aps_key_pair - -extern zb_uint_t gc_addr_table_size; -#define ZB_IEEE_ADDR_TABLE_SIZE gc_addr_table_size - -#ifdef ZB_MAC_SOFTWARE_PB_MATCHING -extern zb_uint_t gc_child_hash_table_size; -#define ZB_CHILD_HASH_TABLE_SIZE gc_child_hash_table_size -#endif /* ZB_MAC_SOFTWARE_PB_MATCHING */ - -extern zb_uint_t gc_neighbor_table_size; -#define ZB_NEIGHBOR_TABLE_SIZE gc_neighbor_table_size - -extern zb_uint_t gc_routing_table_size; -#define ZB_NWK_ROUTING_TABLE_SIZE gc_routing_table_size - -extern zb_uint_t gc_aps_dups_table_size; -#define ZB_APS_DUPS_TABLE_SIZE gc_aps_dups_table_size - -extern zb_uint8_t gc_aps_bind_src_table_size; -#define ZB_APS_SRC_BINDING_TABLE_SIZE gc_aps_bind_src_table_size - -extern zb_uint8_t gc_aps_bind_dst_table_size; -#define ZB_APS_DST_BINDING_TABLE_SIZE gc_aps_bind_dst_table_size - -extern zb_uint8_t gc_trans_table_size; -#define ZB_APS_BIND_TRANS_TABLE_SIZE gc_trans_table_size - -extern zb_uint8_t gc_single_trans_index_size; -#define ZB_SINGLE_TRANS_INDEX_SIZE gc_single_trans_index_size - -extern zb_uint_t gc_sched_stack_unprotected_q_size; -#define ZB_SCHEDULER_Q_SIZE_PROTECTED_STACK_POOL gc_sched_stack_unprotected_q_size - -extern zb_uint8_t gc_nwk_max_source_routes; -#define ZB_NWK_MAX_SRC_ROUTES gc_nwk_max_source_routes - -/** - @} - @} -*/ - -#endif /* ZB_CONFIGURABLE_MEM */ - - -/*! @cond internals_doc */ -/*! \addtogroup ZB_BASE */ -/*! @{ */ - -/** - \par Define 'global context' - common global data structure. - Vladimir got strange problems in Keil with accessing global variables - implemented in another modules. - Also, wants to easily track memory usage. - So, unite it all into global context. - - Initially suppose global context will be defined here and implemented in the - single .c module and passed to all functions by pointer. - To be able to exclude such pointer pass let's define global context access by - a macro. The macro can be easily substituted by the global variable access - or parameter access. - - Globals can be accessed using ZG macro in constructions like ZG->foo. - - Some subsystems has its own structures in the globals (for example, APS - globals). It can be accesses by special macros, like APSG->bar. - */ - -struct zb_globals_s; -typedef struct zb_globals_s zb_globals_t; - -struct zb_intr_globals_s; -typedef ZB_VOLATILE struct zb_intr_globals_s zb_intr_globals_t; - -extern zb_globals_t g_zb; -extern zb_intr_globals_t g_izb; - -/** - Macro to access globals - */ -/* Hope compiler can optimize &g_zb-> to g_zb. */ -#define ZG (&g_zb) -#define ZIG (&g_izb) - -/* - Per-subsystem globals files are named like zb_xxx_globals.h and included here. - */ -#include "zb_scheduler.h" -#include "zb_sleep.h" -#include "zb_bufpool_globals.h" -#include "zb_addr_globals.h" -#include "zb_nwk_globals.h" -#include "zb_aps_globals.h" -#include "zb_zdo_globals.h" -#include "zb_commissioning.h" - - -#include "zb_ha.h" -#include "zb_zcl.h" - - -#include "zb_time.h" - -#ifdef ZB_USE_NVRAM -#include "zb_nvram_globals.h" -#endif - -#ifdef ZB_USE_BUTTONS -#include "zb_led_button.h" -#endif - -#include "zb_error_indication.h" - -#ifdef USE_ZB_WATCHDOG -#include "zb_watchdog.h" -#endif - -#ifdef ZB_ENABLE_SE_MIN_CONFIG -#include "zb_se.h" -#endif - -#ifdef ZB_TH_ENABLED -#include "zb_th_internal.h" -#endif - -/* Declaration of zb_io_ctx_t on some MAC platforms, like nsng */ -#include "zb_mac.h" - - -/* Alien MAC connected via some serial protocol: not our MAC split, - * but similar concept. In Linux it shares some i/o logic with our - * macsplit. Need it here for for zb_io_ctx_t. */ -#if defined ZB_ALIEN_SERIAL_MAC -#include "zb_alien_mac_transport.h" -#endif - -#if defined TC_SWAPOUT && defined ZB_COORDINATOR_ROLE -#include "zb_tcswap.h" -#endif - - -typedef struct zb_sec_globals_s -{ - zb_bufid_t encryption_buf[ZB_NWK_MAC_IFACE_TBL_SIZE]; /* buffer used for NWK encryption */ - -/* 08/22/2018 EE CR:MINOR APS_FRAME_SECURITY is never used now. */ -/* MAC-split host is not considered as alien MAC in multi-MAC configuration, but - * it also requires second encryption buffer */ -#if defined ZB_ALIEN_MAC || defined ZB_ENABLE_ZGP_SECUR || defined APS_FRAME_SECURITY || !defined ZB_MAC_INTERFACE_SINGLE - zb_bufid_t encryption_buf2[ZB_NWK_MAC_IFACE_TBL_SIZE]; /* buffer used for APS encryption */ -#endif -#if defined TC_SWAPOUT && defined ZB_COORDINATOR_ROLE - zb_tcswap_t tcswap; -#endif -#ifdef SNCP_MODE - zb_bitbool_t accept_partner_lk:1; /**!< enable/disable acceptance of partner LK establishment procedure */ -#endif -} zb_sec_globals_t; - -#define SEC_CTX() ZG->sec - - - -/* CR: 04/13/2016 CR:MINOR EE: change comments documenting this structure and - * its fields to be used by Doxygen */ - -#ifdef ZB_CERTIFICATION_HACKS -/* Flags and attributes for tests, allows to switch stack behavior in run-time. - * Used to simulate legacy device behavior, error behavior e.t.c. - * By default set to zero and does not affect stack behavior. - */ - -/** @brief Informs application that Request Key is received during TCLK update - @param param - buffer index - @param keypair_i - index in apsLinkKeyPairSet corresponding to device - from which the current command is received - @returns ZB_TRUE if apsme_request_key.indication will be dropped - ZB_FALSE if command will be proceeded as usual -*/ -typedef zb_bool_t (*zb_req_key_ind_cb_t) (zb_uint8_t param, zb_uint16_t keypair_i); - -/** @brief Informs application that CCM was calculated (before frame will be encrypted) - @param ccm_p - pointer to calculated ccm (16 bytes in length) - @param hdr - pointer to APS or NWK hdr - @param hdr_len - size of hdr in bytes - @returns ZB_TRUE if application does not wants to call this callback in future - ZB_FALSE otherwise -*/ -typedef zb_bool_t (*zb_ccm_check_cb_t) (zb_uint8_t *ccm_p, - zb_uint8_t *hdr, - zb_ushort_t hdr_len); - -/** @brief Called when APS adds security header (before adding counter to packet) - to outgoing packet. - @param p_sec_counter - pointer to counter that will be added to packet, - change if needed -*/ -typedef void (*zb_aps_secur_counter_hack_cb_t) (zb_uint32_t *p_sec_counter); - -/** @brief Called on joiner (in BDB) before apsme_request_key or apsme_verify_key request. - @param param - buffer index - @returns ZB_TRUE if request primitive will be dropped - ZB_FALSE otherwise -*/ -typedef zb_bool_t (*zb_req_call_cb_t) (zb_uint8_t param); - -/** @brief Called on ZDO CLI command receiving. - @param param - buffer index - @returns ZB_TRUE if the command was handled by application side - ZB_FALSE otherwise -*/ -typedef zb_bool_t (*zb_zdo_af_handler_cb) (zb_uint8_t param, zb_uint16_t cb_param); - -/** - Flags, callbacks and attributes for tests, allows to switch stack behavior in run-time. - Note: some customers express their concern regarding existing of hacks in ZBOSS. - Don't worry, please: that 'hacks' are flags forcing some Test Harness behavior in the stack core: - to simulate legacy device behavior, error behavior e.t.c. - By default set to zero and does not affect stack behavior. - */ -typedef struct zb_cert_hacks_s -{ - zb_uint8_t src_binding_table_size; /*!< Use variables instead of ZB_APS_SRC_BINDING_TABLE_SIZE - and ZB_APS_DST_BINDING_TABLE_SIZE. - @see test PRO_R21/certification/TP_APS_BV-20-I: - limit binding table size. By default both are set to - ZB_APS_SRC_BINDING_TABLE_SIZE and - ZB_APS_DST_BINDING_TABLE_SIZE correspondingly. */ - zb_uint8_t dst_binding_table_size; /*!< see comment for src_binding_table_size */ - zb_ieee_addr_t auth_excluded_dev_addr; /*!< Exclude authentication for this device. Simple - special feature for test TP/SEC/BV-29-I. - "gZC causes DUT ZED2 to be removed from the network - via APS Remove by including ZED2 in the exclusion list - of the trust center". - This is not full-features exclusion list. */ - zb_uint8_t override_nwk_protocol_version; /*!< Override protocol version in nwk header - debug feature for 13.68 NWK Unknown NWK - Protocol Version. */ - zb_int16_t send_update_device_unencrypted; /*!< Debug stuff to send next update_device unsecured. - If <= 0 (default), switch off this debug trick. - If > 0, send send_update_device_unencrypted times - encrypted, then once unencrypted, then always - encrypted. - @see tp_r20_bv-01_zr.c */ - - zb_req_key_ind_cb_t req_key_ind_cb; /*!< This callback is called on TC when - TC receives Request Key command - during TC LK update. - @ee tests CS-ICK-TC-02 and - CS-ICK-TC-03 */ - zb_req_call_cb_t req_key_call_cb; /*!< This callback called on joiner - device before it calls - APSME.REQUEST.KEY primitive. - Passed up with buffer in params. - @see test CS-ICK-TC-02. */ - zb_req_call_cb_t verify_key_call_cb; /*!< This callback called on joiner - device before it calls - APSME.VERIFY.KEY primitive. - Passed up with buffer in params. - @see test CS-ICK-TC-02. */ - zb_callback_t deliver_nwk_key_cb; /*!< This callback called before TC - initiates transporting nwk key to - joiner (in bdb mode). - Passed up with buffer in params. - @see test CS-ICK-TC-03. */ - zb_callback2_t deliver_conf_key_cb; /*!< This callback called before TC - sends confirm key to joiner (TC - link key). - Passed up with buffer and keypair_i - (for joiners apsDeviceKeyPairSet entry) - in params. - @see test CS-NFS-TC-01. */ - zb_ccm_check_cb_t ccm_check_cb; /*!< Called before frame encryption. - @see cs-nfs-tc-01 */ - zb_aps_secur_counter_hack_cb_t secur_aps_counter_hack_cb; /*!< Called before APS frame security - counter will be added to packet. - @see cs-nfs-tc-01 */ - zb_zdo_af_handler_cb zdo_af_handler_cb; /*!< Callback that will be called when - device receives ZDO command. - Pass buffer param and Cluster_Id - in arguments. - @see fb-pre-tc-03a */ - - zb_callback_t mcps_data_confirm_handler_cb; /*!< Callback that will be called - when handling confirmation after - completion of request. - @see rtp_bdb_23 */ - - zb_bitfield_t override_tc_significance_flag: 1; /*!< Allows to override default value - of tc_significance in MgmtPermitJoin; - Default value is 0 - - tc_significance can - not be overwritten by application. - @see cn-nst-tc-10 */ - zb_bitfield_t disable_end_device_timeout_request_at_join: 1; /*!< Disable sending End Device - Timeout Request to parent when - ED joining.Used to simulate - legacy end device in - tp_r21_bv-19 test. */ - zb_bitfield_t enable_leave_to_router_hack: 1; /*!< This flag is used in r20 and - earlier tests to allow sending - nwk leave to router. - According to 3.2.2.16.3 - (NLME-LEAVE.request: Effect on - Receipt) of r21 Router and - Coordinator can send nwk leave - only to End Device childrens. */ - zb_bitfield_t disable_association_response: 1; /*!< Toggle this flag to disable/enable - sending association response - in run-time. See cn-nsa-tc-03. - If set to 1 buffer with - association indication primitive - will be dropped in - zb_mlme_associate_indication. - @see cn-nsa-tc-03. */ - zb_bitfield_t report_legacy_stack_revision_in_node_descr: 1; /*!< Simulate legacy device: stack - revision field in server flags - will be set to 0. */ - zb_bitfield_t force_ext_addr_req: 1; /*!< force ext addr req for BDB - certification tests - @see test FB-PRE-TC-01A (dutzr). */ - zb_bitfield_t disable_aps_acknowledgements: 1; /*!< Disable APS acks for incoming - aps-data frames. */ - zb_bitfield_t disable_in_out_cost_updating: 1; /*!< For TP_PRO_BV_04 need not change in/out - costs by LQI */ - zb_bitfield_t aps_security_off: 1; /*!< run-time APS security switch off. - If TRUE, does not encrypt APS commands */ - zb_bitfield_t enable_alldoors_key: 1; /*!< All APS keys will be the same as default - including pre-configured */ - zb_bitfield_t allow_nwk_encryption_for_aps_frames: 1; /*!< Returns r20 and earlier behavior for - encryption: allows to encrypt APS frame - by nwk key (if set to 1). - @see cs-nf-tc-01 */ - zb_bitfield_t drop_verify_key_indication: 1; /*!< Drops apsme_verify_key,indication when - set to 1 - @see cs-nfs-tc-01 */ - zb_bitfield_t stay_on_network_after_auth_failure: 1; /*!< If set to 1 router device (in bdb) - will not leave network after - authentication failure and/or - tclk exchange failure. - @see cs-nfs-tc-02 */ - zb_bitfield_t pass_incoming_zdo_cmd_to_app: 1; /*!< If set to 1 stack will pass incoming - ZDO clients commands to application. - Use zdo_af_handler_cb to handle them. - @see fp-bpre-tc-03a */ - zb_bitfield_t disable_frame_retransmission: 1; /*!< If set to 1 device will not retransmit - packet from to another devices. - @see fp-bpre-tc-03a */ - zb_bitfield_t force_frame_indication: 1; /*!< If set to 1 device will deliver all - frames ato APS (including frames destined - to another devices). - @see fp-bpre-tc-03a */ - zb_bitfield_t delay_pending_tx_on_rresp: 1; /*!< If set to 1, delay send NWK - data when route established: - wait for better route. Specially - for the test TP_PRO_BV-04 */ - zb_bitfield_t use_route_for_neighbor:1; /*!< if 1, when forwarding nwk, - * check for route better than - * direct tx to the neighbor. Specially - * for the test - * TP_PRO_BV-04. */ - zb_bitfield_t disable_cyclic_tc_rejoin: 1; /*!< If 1, device will not rejoin after Trust Center - * rejoin failure - but leave network instead */ - zb_bitfield_t allow_entry_for_unregistered_ep: 1; /*!< If 1, device will be allowed to create - entry for unregistered endpoint - in APS group table */ - zb_bitfield_t disable_addr_req_on_neighbor_move:1; /*!< If set to 1, disable nwk - * addr req if neighbor moved - * out of us */ - zb_bitfield_t disable_unencrypted_update_device:1; /*!< If set to 1, disable unencrypted Update device - * (simulating a legacy device) - required by TP/R20/BV-03 */ - zb_bitfield_t disable_encrypted_update_device:1; /*!< If set to 1, disable unencrypted Update device - * (simulating a legacy device) - required by TP/R20/BV-04 */ - zb_bitfield_t check_zc_long_addr_is_visible:1; /*!< If set to 1, upon receipt frame from ZC (addr = 0x0000) - * device will check that ZC long address is visible looking up to nwk header. - * Used in TP/PRO/BV-29 and TP/PRO/BV-30. */ - zb_bitfield_t disable_pan_id_conflict_detection:1; /*!< If set to 1, device will not discover PAN - * ID conflict */ - zb_bitfield_t frag_drop_1st_block_1st_time:1; /*!< If set to 1, device will drop 1st block of - * fragmented tx 1st time (TP/PRO/BV-43) */ - zb_bitfield_t frag_skip_0_and_2nd_block_1st_time:1; /*!< If set to 1, device will not send 0 and - 3rd block of fragmented tx 1st time (TP/PRO/BV-44) */ - zb_bitfield_t frag_skip_node_descr:1; /*!< If set to 1, device will not send Node Descriptor - * request to clarify max buffer size and max in/out - * transfer size, it is already set to maximum possible */ - zb_bitfield_t frag_disable_custom_ack_timer:1; /*!< If set to 1, ZBOSS does sends APS acks for - fragmented transmissions only in the cases - required by the specs. */ - zb_bitfield_t aps_counter_custom_setup:1; //replace APS counter - zb_uint8_t aps_counter_custom_value; //custom value of APS counter - zb_bitfield_t nwk_counter_custom_setup:1; //replace NWK counter - zb_uint8_t nwk_counter_custom_value; //custom value of NWK counter - zb_uint16_t address_to_rejoin; /* address of device to rejoin at for TP/R21/BV-02 */ - zb_bitfield_t enable_rejoin_to_specified_device:1; /* enable rejoin at specified device */ - zb_bitfield_t set_empty_beacon_payload:1; /* set empty beacon payload (check pan id conflict) */ - zb_bitfield_t zdo_mgmt_nwk_update_force_scan_count:1; /*!< If set to 1, scan_count field will always - * be appended to Mgmt_NWK_Update_req packet */ - zb_bitfield_t disable_addr_conflict_check_on_update_device:1; /* Disable check for address conflict - * upon reception of Update device - refer to - * TP/PRO/BV-17 SECURED network */ - zb_bitfield_t delayed_rejoin_resp:1; /* Send rejoin resp after nwk status pkt - during address conflict resolution */ - zb_bitfield_t disable_beacon_send:1; /* Disabled responding with a beacon TP/PRO/BV-17 */ - zb_bitfield_t disable_discovery_route:1; /*!< Disable Discovery route bitfield in NWK FC */ - zb_uint8_t disable_frame_retransmission_countdown; /*!< Number of retransmitted packets to another - * devices, before retransmission will - * be disabled. - * @see FB-PRE-TC-03B */ - zb_bitfield_t disable_power_negotiation_support:1; /*!< Clear Power Negotiation Support bit - * in the End Device Timeout Response. - * @see TP/R22/SGMB-9*/ - zb_bitfield_t extended_beacon_send_jitter:1; /*!< If set to 1, a larger jitter will be - * used when handling a beacon request. */ - zb_bitfield_t aps_mcast_addr_overridden:1; /*!< If set to 1, the value for NWK destination - * address will be overridden with the value - * of aps_mcast_nwk_dst_addr field */ - zb_bitfield_t aps_disable_addr_update_on_update_device:1; /*!< Disable updating nwkAddressMap with - 64bit address received via UPDATE-DEVICE. */ - zb_bitfield_t nwk_disable_passive_acks:1; /*!< If set to 1, the device will not keep track of - received passive acks */ - zb_uint16_t aps_mcast_nwk_dst_addr; /* CCB2469: Broadcast NWK address for - * APS groupcast (multicast) */ - zb_uint8_t frag_block_size; /*!< If set to a nonzero value, APS will use it as a size of block - payload. */ - zb_bitfield_t allow_cbke_from_zc_ncp_dev:1; /*Allow ZC/TC NCP to perform CBKE */ - zb_bitfield_t break_nwk_fcf_counter:1; /*!< Flag to break the NWK FC failure counter once */ - zb_bitfield_t break_aps_fcf_counter:1; /*!< Flag to break the APS FC failure counter once */ - zb_bitfield_t break_nwk_key:1; /*!< NWK key distortion flag for one encryption operation */ - zb_bitfield_t break_aps_key:1; /*!< APS key distortion flag for one encryption operation */ - zb_bitfield_t make_frame_not_valid:1; /*!< Make a combination of MAC frame control fields not valid. Once. */ - zb_bitfield_t zc_flood_mode:1; /*!< Forces the MAC to send packets without CSMA-CA */ - zb_bitfield_t use_transport_key_for_aps_frames:1; /*!< Use transport key to secure APS frame. Once. */ - zb_bitfield_t certificate_priority_from_certdb:1; /*!< Change certificate source priority for CBKE: - 1. from cert db (NVRAM); - 2. from production configuration. - In a normal situation, vice versa. */ - zb_bitfield_t use_preconfigured_aps_link_key:1; /*!< Use preconfigured in application APS Link Key - * Used into TP_R20_BV-01 */ - zb_bitfield_t nwk_leave_from_unknown_addr:1; /*!< Send all nwk leave_req with src ieee addr= - and short= */ - zb_bitfield_t low_ram_concentrator:1; /*!< Forces coordinator to send no route cache in mtorr */ - - zb_bitfield_t tc_rejoin_mac_cap_wrong_dev_type:1; /* Toggle FFD bit in MAC capabilities for rejoin req */ - zb_bitfield_t tc_rejoin_mac_cap_wrong_rx_on_when_idle:1; /* Toggle FFD bit in MAC capabilities for rejoin req */ - zb_bitfield_t aps_drop_next_ack:1; /* Drop next APS ack */ - zb_bitfield_t aps_send_dup_tunneled_frame:1; - - zb_bitfield_t tc_rejoin_aps_decrypt_error:1; /* Simulate TC rejoin without known aps key */ - zb_ieee_addr_t nwk_leave_from_unknown_ieee_addr; /*!< IEEE source address used in nwk_leave if `nwk_leave_from_unknown_addr` is set */ - zb_uint16_t nwk_leave_from_unknown_short_addr; /*!< Short source address used in nwk_leave if `nwk_leave_from_unknown_addr` is set */ -#ifdef ZB_R22_CERT_MULTITEST_MANUAL_RUN - zb_bitfield_t nwk_parent_information_bit_reset_on_rejoin_rsp:1; /*!< Reset nwkParentInformation on rejoin response so the next packets until End Device Timeout response have End Device Initiator to 0 */ -#endif /* ZB_R22_CERT_MULTITEST_MANUAL_RUN */ - zb_uint8_t joins_ctr; /*!< count of joins to our device */ - zb_uint8_t max_joins; /*!< max number of successful joins */ -} zb_cert_hacks_t; - -#define ZB_CERT_HACKS() ZG->cert_hacks - -/* Value that means that ZB_CERT_HACKS().max_joins is uninitialized */ -#define ZB_MAX_JOINS_UNINITIALIZED ZB_UINT8_MAX -#endif /* ZB_CERTIFICATION_HACKS */ - -#ifdef ZB_STACK_REGRESSION_TESTING_API - -/* Used in custom regression ZBOSS tests - * see: ZBOSS/tests/regression_tests/ - */ - -/* Flags and attributes for tests, allows to switch stack behavior in run-time. - * Used to simulate legacy device behavior, error behavior e.t.c. - * By default set to zero and does not affect stack behavior. - */ - -typedef struct zb_reg_api_s -{ - zb_uint8_t zcl_ota_custom_query_jitter; /*!< Custom value of ota query jitter instead of - * randomly chosen - */ - zb_int8_t osif_interrupts_balance; /*!< The difference between - * zb_nrf52840_enable_all_inter and - * zb_nrf52840_disable_all_inter calls count - */ - zb_bool_t bdb_allow_multiple_fb_targets; /*!< The flag to allow use - * zb_bdb_finding_binding_target for - * multiple endpoints in the same time - */ - zb_callback_t sched_int_cb; /*!< Callback called in zb_schedule_callback() */ - zb_bool_t sched_cb_int_called; /*!< Flag for control that interrupt was not - * called from ZB_INT_DISABLE() section - * in ZB_SCHEDULE_CALLBACK code */ - zb_bool_t get_buf_delayed_int_called; /*!< Flag for control that interrupt was not - * called from ZB_INT_DISABLE() section - * in zb_get_buf_delayed_2param code */ - zb_bool_t perform_crash_on_nvram_write; /*!< The flag to perform crash - * on NVRAM write */ - zb_bool_t disable_sending_nwk_key; /*!< Do not send nwk key during association to - * the next device which attempts to associate. - * After one first usage flag will be reset. */ - zb_bool_t extended_beacon_send_delay; /*!< If set to 1, a larger delay will be - * used when handling a beacon request. */ - zb_bool_t enable_custom_best_parent; /*!< Enable custom short address for the first - * association attempt. Will be disabled - * after used. */ - zb_bool_t set_short_custom_best_parent; /*!< Set custom short address for the first - * association attempt. */ - zb_bool_t disable_extended_nwk_src; /*!< Disable including extended src address into - * nwk payload of packet */ - zb_bool_t allow_zero_ieee_addr; /*!< Allow to initialize a device with zero - * IEEE address */ - zb_bool_t ignore_nwk_key; /*!< The flag to enable ignoring network key - * from Trust Center */ - zb_bool_t disable_aps_acknowledgements; /*!< Disable APS ACKs for incoming - * APS packets. */ -} zb_reg_api_t; - -#define ZB_REGRESSION_TESTS_API() ZG->reg_api - -/* This define needs as nwk key disabling is used not only for regression tests but - * it also used in the CTH functionality. - */ - -#define ZB_NWK_KEY_DISABLE() (ZB_REGRESSION_TESTS_API().disable_sending_nwk_key) -#define ZB_NWK_KEY_DISABLE_RESET() ZB_REGRESSION_TESTS_API().disable_sending_nwk_key = ZB_FALSE - -#else - -#define ZB_NWK_KEY_DISABLE() 0 -#define ZB_NWK_KEY_DISABLE_RESET() - - -#endif /* ZB_STACK_REGRESSION_TESTING_API */ - -#if defined NCP_MODE && !defined NCP_MODE_HOST -/* - * Part of NCP device context, that can be configured through dynamic memory - * configuration feature. - */ -typedef struct zb_ncp_globals_s -{ -#ifndef ZB_CONFIGURABLE_MEM - zb_ncp_pending_calls_t calls[ZB_N_BUF_IDS]; -#else - zb_ncp_pending_calls_t *calls; -#endif -} -zb_ncp_globals_t; - -#define ZB_NCP_CTX_CALLS() ZG->ncp.calls - -#endif /* NCP_MODE && !NCP_MODE_HOST */ - -/** - Global data area for data not to be accessed from interrupt handlers -*/ -struct zb_globals_s -{ - zb_sched_globals_t sched; /*!< Global schedule context */ - zb_buf_pool_t bpool; /*!< Global buffer pool context */ - zb_addr_globals_t addr; /*!< Global address context */ - -#ifndef NCP_MODE_HOST - zb_nwk_globals_t nwk; /*!< Global NWK context - NIB */ - zb_aps_globals_t aps; /*!< Global APS context - AIB */ - zb_zdo_globals_t zdo; /*!< Global ZDO context - ZDO_CTX */ - zb_sec_globals_t sec; /*!< Global security context - SEC_CTX */ -#endif /* !defined NCP_MODE_HOST */ - - zb_commissioning_ctx_t commissioning_ctx; - -#if defined ZB_ENABLE_ZCL || defined ZB_ENABLE_ZGPD_ATTR_REPORTING - zb_zcl_globals_t zcl; /*!< Global ZCL context - ZCL_CTX */ -#endif /* defined ZB_ENABLE_ZCL || defined ZB_ENABLE_ZGPD_ATTR_REPORTING */ -#if defined ZB_ENABLE_ZGP_INFRA - zb_zgp_ctx_t zgp; -#endif /* defined ZB_ENABLE_ZGP_EP */ -#if defined ZB_USE_NVRAM - zb_nvram_globals_t nvram; /*!< Global NVRAM context - ZB_NVRAM */ -#endif // defined ZB_USE_NVRAM -#ifdef ZB_USE_BUTTONS - zb_buttons_global_t button; -#endif - zb_error_indication_ctx_t err_ind; -#ifdef USE_ZB_WATCHDOG - zb_watchdog_t watchdog[ZB_N_WATCHDOG]; -#endif -#ifdef ZB_CHECK_OOM_STATUS - zb_uint8_t oom_check_enabled; -#endif -#ifdef ZB_CERTIFICATION_HACKS - zb_cert_hacks_t cert_hacks; -#endif -#ifdef ZB_STACK_REGRESSION_TESTING_API - zb_reg_api_t reg_api; -#endif -#ifdef ZB_USE_SLEEP - zb_sleep_ctx_t sleep; -#endif -#ifdef ZB_TH_ENABLED - zb_th_context_t th_ctx; /* Global test harness context. */ -#endif -#if defined NCP_MODE && !defined NCP_MODE_HOST - zb_ncp_globals_t ncp; /* Part of NCP device context. */ -#endif -}; - -#if defined ENABLE_USB_SERIAL_IMITATOR || defined DOXYGEN - -typedef struct zb_usbc_ctx_s -{ - int rpipe; - int wpipe; -} zb_usbc_ctx_t; - -#endif /* defined ENABLE_USB_SERIAL_IMITATOR || defined DOXYGEN */ - - -/** - Global data area for data to be accessed from interrupt handlers - */ -struct zb_intr_globals_s -{ -#ifdef ZB_HAVE_IOCTX - zb_io_ctx_t ioctx; -#endif -/* Note: MAC split I/O context is not used on hardware, but it's used on Linux platform */ -#if defined( ENABLE_USB_SERIAL_IMITATOR ) - zb_usbc_ctx_t usbctx; /*!< USB imitator IO context. */ -#endif /* defined( ENABLE_USB_SERIAL_IMITATOR ) */ - zb_timer_t time; -}; - - -#define ZB_IOCTX() g_izb.ioctx -#define ZB_MACSPLIT_IOCTX() g_izb.macsplit_ioctx -#define ZB_TIMER_CTX() g_izb.time -#define SER_CTX() ZB_IOCTX().serial_ctx -#define USB_CTX() ZB_IOCTX().userial_ctx -#define SPI_CTX() ZB_IOCTX().spi_ctx - - -/*! @} */ -/*! @endcond */ - -#endif /* ZB_G_CONTEXT_H */ diff --git a/zboss/development/src/include/zb_hash.h b/zboss/development/src/include/zb_hash.h deleted file mode 100644 index e6753221dc..0000000000 --- a/zboss/development/src/include/zb_hash.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Macros for hash calculation -*/ - -#ifndef ZB_HASH_H -#define ZB_HASH_H 1 - -/*! @cond internals_doc */ -/*! \addtogroup ZB_BASE */ -/*! @{ */ - -/* DJB2 algorithm magic number */ -#define ZB_HASH_MAGIC_VAL 5381UL - -/** - * DJB2 hash function step - * - * See: [Hash Functions](www.cse.yorku.ca/~oz/hash.html) - */ -#define ZB_HASH_FUNC_STEP(hash_var, v) ((((hash_var) << 5) + (hash_var)) + (v)) -#define ZB_4INT_HASH_FUNC(v1, v2, v3, v4) (ZB_HASH_FUNC_STEP(ZB_HASH_FUNC_STEP( ZB_HASH_FUNC_STEP( ZB_HASH_FUNC_STEP(ZB_HASH_MAGIC_VAL, (v1)), (v2)), (v3)), (v4)) & ZB_INT_MASK) -#define ZB_2INT_HASH_FUNC(v1, v2) (ZB_HASH_FUNC_STEP(ZB_HASH_FUNC_STEP(ZB_HASH_MAGIC_VAL, (v1)), (v2)) & ZB_INT_MASK) - -#define ZB_1INT_HASH_FUNC(v1) (ZB_HASH_FUNC_STEP(ZB_HASH_MAGIC_VAL, (v1)) & ZB_INT_MASK) - -/* Calculate a hash using DJB2 hash function */ -zb_uint32_t zb_64bit_hash(zb_uint8_t *data); - -/** - * Calculate Fowler-Noll-Vo hash. - * - * See: [FNV Hash](www.isthe.com/chongo/tech/comp/fnv/) - */ -zb_uint32_t zb_fnv_32a_uint16(zb_uint16_t v); - -/*! @} */ -/*! @endcond */ - -#endif /* ZB_HASH_H */ diff --git a/zboss/development/src/include/zb_mac.h b/zboss/development/src/include/zb_mac.h deleted file mode 100644 index fbbe9fe3a3..0000000000 --- a/zboss/development/src/include/zb_mac.h +++ /dev/null @@ -1,3101 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Mac layer API. Platform-independent or default. -*/ - -#ifndef ZB_MAC_API_INCLUDED -#define ZB_MAC_API_INCLUDED - -#include "zb_types.h" -#include "zb_debug.h" -#include "zb_bufpool.h" -#include "zb_config_common.h" - -/* Include platform-specific MAC stuff from the separate repo */ -#ifndef ZB_EXTMAC -#include "mac_platform.h" -#else -#include "zb_extmac_hdr.h" -#endif - -#ifndef ZB_TRANSCEIVER_START_CHANNEL_NUMBER - #define ZB_TRANSCEIVER_START_CHANNEL_NUMBER 11U -#endif - -#ifndef ZB_TRANSCEIVER_MAX_CHANNEL_NUMBER - #define ZB_TRANSCEIVER_MAX_CHANNEL_NUMBER 26U -#endif - -#define ZB_MAC_IS_ADDRESS_BROADCAST(addr) ( ((addr) & 0xFFF0U) == 0xFFF0U ) - - -/** @cond internals_doc */ -/** - @addtogroup ZB_MAC - @{ -*/ - -#define ZB_MAC_MIN_HEADER_SIZE (2U /* fcf */ + 1U /* seq num */ + 2U /* dst short addr */ + \ - 2U /* pan */ + 2U /*src_short_addr*/) -/** - Return maximal mac header size -*/ -#define ZB_MAC_MAX_HEADER_SIZE(dst_short_addr, src_short_addr) \ - 2U /* fcf */ + 1U /* seq num */ + ((dst_short_addr) ? 2U : 8U) /* dst addr */ + \ - 2U /* pan */ + ((src_short_addr) ? 2U : 8U) /* src addr */ - -/** - offset in bytes from the start of the mac frame to sequence number - field -*/ -#define SEQ_NUMBER_OFFSET 2U -/* check specification IEEE 802.15 item 7.2.1 */ - -/** - offset in bytes from the start of the mac frame to destination PAN - identifier field -*/ -#define ZB_MAC_DST_PANID_OFFSET 3U -/* check specification IEEE 802.15 item 7.2.1 */ - - -#define ZB_MAC_ACK_FRAME_LEN ZB_MAC_DST_PANID_OFFSET -/** - Length of ACK frame to transmit - */ -#define ZB_MAC_TX_ACK_FRAME_LEN ZB_MAC_ACK_FRAME_LEN - -/** - Offset in bytes from the start of the mac frame to destination address - field if field destination Pan ID is presented in given mac - frame -*/ -#define DST_ADDR_OFFSET 5U -/* check specification IEEE 802.15 item 7.2.1 */ - -/** - length in bytes Sequence Number -*/ -#define SEQUENCE_NUMBER_LENGTH 2U -/* check specification IEEE 802.15 item 7.2.2.1 */ - -/** - length in bytes SuperFrame Specification -*/ -#define SUREPFRAME_SPEC_LENGTH 2U -/* check specification IEEE 802.15 item 7.2.2.1 */ - -/** - length in bytes GTS Specification -*/ -#define GTS_SPEC_LENGTH 1U -/* check specification IEEE 802.15 item 7.3.1.4 */ - -/** - length in bytes GTS Directions -*/ -#define GTS_DIRECTIONS_LENGTH 1U -/* check specification IEEE 802.15 item 7.3.1.4 */ - -/** - length in bytes GTS Descriptor -*/ -#define GTS_DESCRIPTOR_LENGTH 3U -/* check specification IEEE 802.15 item 7.3.1.4 */ - -/** - length in bytes Pending Address Specification -*/ -#define PENDING_ADDRESS_SPEC_LENGTH 1U -/* check specification IEEE 802.15 item 7.3.1.5 */ - -/** - length in bytes of and field containing Pan ID -*/ -#define PAN_ID_LENGTH 2U -/* check specification IEEE 802.15 item 7.2.1 */ - -/** - All supported channels mask -*/ -#define ZB_MAC_ALL_CHANNELS_MASK ZB_TRANSCEIVER_ALL_CHANNELS_MASK - -/** - Maximal pending addresses number -*/ -#define MAX_PENDING_ADDRESSES 7U - -/** - Maximal beacon overhead -*/ -#define MAX_BCN_OVERHEAD 75U -/** - Maximal beacon payload size -*/ -#define MAX_BCN_PAYLOAD (MAX_PHY_FRM_SIZE-MAX_BCN_OVERHEAD) -/** - Minimal CAP length -*/ -#define MAC_MIN_CAP_LENGTH 440U /* mac spec 7.4.1 MAC constants */ - -/* By default packet 1b length is before data, 2b packet trailer with rssi, lqi. Platform can redefine it. */ -#ifndef ZB_MAC_PACKET_LENGTH_SIZE -#define ZB_MAC_PACKET_LENGTH_SIZE 1U -#endif -#ifndef ZB_MAC_EXTRA_DATA_SIZE -#define ZB_MAC_EXTRA_DATA_SIZE 2U /* rssi & lqi - see ns_pkt_trailer_t */ -#endif - -/** - Maximal size of MAC header -*/ -#define ZB_MAC_MAX_MHR_SIZE 25U - -/** - MAC footer size -*/ -#define ZB_MAC_MFR_SIZE 2U - -/** - Maximal size available for NWK layer -*/ -#define ZB_MAC_MAX_PAYLOAD_SIZE (MAX_PHY_FRM_SIZE - (ZB_MAC_MAX_MHR_SIZE + ZB_MAC_MFR_SIZE)) - -/** - Is used for macBeaconOrder and macSuperframeOrder -*/ -#define ZB_TURN_OFF_ORDER 15U -/** - Short address value -*/ -#define ZB_MAC_SHORT_ADDR_NO_VALUE 0xFFFFU -/** - Not allocated short address value -*/ -#define ZB_MAC_SHORT_ADDR_NOT_ALLOCATED 0xFFFEU -/** - Broadcast Pan ID value -*/ -#define ZB_BROADCAST_PAN_ID 0xFFFFU - -/* 7.4 MAC constants and PIB attributes */ -/** - MAC base slot duration value -*/ -#define ZB_MAC_BASE_SLOT_DURATION 60U -/** - Superframe slots number -*/ -#define ZB_MAC_NUM_SUPERFRAME_SLOTS 16U -/** - MAC base superframe duration value -*/ -#define ZB_MAC_BASE_SUPERFRAME_DURATION ZB_MAC_BASE_SLOT_DURATION * ZB_MAC_NUM_SUPERFRAME_SLOTS /* = 960 */ - -/* - NOTE: 1 beacon interval = ZB_MAC_BASE_SUPERFRAME_DURATION * 1 symbol (16e-6 sec) = 15.36 milliseconds - Beacon interval is used to measure MAC timeouts -*/ - -/** - * @name IEEE 802.15.4 frame version - * @anchor mac_frame_version - * - * Note: These values were members of `enum mac_frame_version_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define MAC_FRAME_IEEE_802_15_4_2003 0U -#define MAC_FRAME_IEEE_802_15_4 1U -#define MAC_FRAME_IEEE_802_15_4_2015 2U -/** @} */ - -/** - * @name MAC transmission flags - * @anchor mac_tx_options_bits - * @see IEEE standard 802.15 - * - * Note: These values were members of `enum mac_tx_options_bits_e` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -/** 1 - acknowledged transmission, 0 - unacknowledged transmission */ -#define MAC_TX_OPTION_ACKNOWLEDGED_BIT 0x01U -/** 1 - GTS transmission, 0 - CAP transmission */ -#define MAC_TX_OPTION_GTS_CAP_BIT 0x02U -/** 1 - indirect transmission, 0 - direct transmission */ -#define MAC_TX_OPTION_INDIRECT_TRANSMISSION_BIT 0x04U -#define MAC_TX_OPTION_NO_CSMA_CA 0x08U /*!< non standard option, need it for GreenPower */ -/** temporary flag means ok to transmit indirect. Used with some non-DSR MAC only */ -#define MAC_TX_OPTION_OK_TO_INDIRECT_TRANSMISSION_NOW 0x10U -/** @} */ - -/** - * @name MAC frame types - * @anchor mac_frame_type - * - * Note: These values were members of `enum mac_frame_type_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define MAC_FRAME_BEACON 0U -#define MAC_FRAME_DATA 1U -#define MAC_FRAME_ACKNOWLEDGMENT 2U -#define MAC_FRAME_COMMAND 3U -#define MAC_FRAME_RESERVED1 4U -#define MAC_FRAME_RESERVED2 5U -#define MAC_FRAME_RESERVED3 6U -#define MAC_FRAME_RESERVED4 7U -/** @} */ - -/** - * @name MAC command frame id - * @anchor mac_command_frame_id - * - * Note: These values were members of `enum mac_command_frame_id_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define MAC_CMD_ASSOCIATION_REQUEST 1U -#define MAC_CMD_ASSOCIATION_RESPONSE 2U -#define MAC_CMD_DISASSOCIATION_NOTIFICATION 3U -#define MAC_CMD_DATA_REQUEST 4U -#define MAC_CMD_PAN_ID_CONFLICT_NOTIFICATION 5U -#define MAC_CMD_ORPHAN_NOTIFICATION 6U -#define MAC_CMD_BEACON_REQUEST 7U -#define MAC_CMD_COORDINATOR_REALIGNMENT 8U -#define MAC_CMD_GTS_REQUEST 9U -/** @} */ - - -/* Frame control field macroses */ - -/** - Sets frame type subfield in frame control field ( FCF ) - Valid values are defined in @ref mac_frame_type. - - - @param p_fcf - pointer to 16bit FCF field. - @param frame_type - @ref mac_frame_type. -*/ - - -#define ZB_FCF_SET_FRAME_TYPE( p_fcf, frame_type ) \ - do \ - { \ - ZB_ASSERT( (zb_uint8_t) ( frame_type ) < MAC_FRAME_RESERVED1 ); \ - ( ( ( zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) &= 0xf8U; \ - ( ( ( zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) |= (zb_uint8_t) ( frame_type ); \ - } while( 0 ) - - -/** - Gets frame type subfield in frame control field ( FCF ) - Return values are in range of @see @ref mac_frame_type. - - @param p_fcf - pointer to 16bit FCF field. -*/ - -#define ZB_FCF_GET_FRAME_TYPE( p_fcf ) ( ( ( ( const zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) & 0x07U ) - - -/** - Gets security bit subfield in frame control field ( FCF ) - Return values can be 0 or 1. - - @param p_fcf - pointer to 16bit FCF field. -*/ - -#define ZB_FCF_GET_SECURITY_BIT( p_fcf ) ( ( ( ( const zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) & 0x08U ) - - -/** - Sets security bit subfield in frame control field ( FCF ) - Input values can be 0 or 1. - - @param p_fcf - pointer to 16bit FCF field. - @param bit_value - 0 or 1. -*/ - -#define ZB_FCF_SET_SECURITY_BIT( p_fcf, bit_value ) \ - do \ - { \ - ZB_ASSERT( ( bit_value ) == 0U || ( bit_value ) == 1U ); \ - ( ( ( zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) &= 0xF7U; \ - ( ( ( zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) |= (bit_value) << 3U; \ - } while( 0 ) - -/** - Gets frame pending bit subfield in frame control field ( FCF ) - Return values can be 0 or 1. - - @param p_fcf - pointer to 16bit FCF field. -*/ - -#define ZB_FCF_GET_FRAME_PENDING_BIT( p_fcf ) (( ( ( const zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) & 0x10U ) - - -/** - Sets security bit subfield in frame control field ( FCF ) - - @param p_fcf - pointer to 16bit FCF field. - @param bit_value - 0 or 1. -*/ - -#define ZB_FCF_SET_FRAME_PENDING_BIT( p_fcf, bit_value ) \ - do \ - { \ - ZB_ASSERT( ( bit_value ) == 0U || ( bit_value ) == 1U ); \ - ( ( ( zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) &= 0xEFU; \ - ( ( ( zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) |= (bit_value) << 4U; \ - } while( 0 ) - -/** - Gets ack request bit subfield in frame control field ( FCF ) - Return values can be 0 or 1. - - @param p_fcf - pointer to 16bit FCF field. -*/ - -#define ZB_FCF_GET_ACK_REQUEST_BIT( p_fcf ) ( ( ( ( const zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) & 0x20U ) - - -/** - Sets ack request bit subfield in frame control field ( FCF ) - - @param p_fcf - pointer to 16bit FCF field. - @param bit_value - 0 or 1. -*/ - -#define ZB_FCF_SET_ACK_REQUEST_BIT(p_fcf, bit_value) \ - do \ - { \ - ZB_ASSERT((bit_value) == 0U || (bit_value) == 1U); \ - (((zb_uint8_t *)(p_fcf))[ZB_PKT_16B_ZERO_BYTE]) &= 0xDFU; \ - (((zb_uint8_t *)(p_fcf))[ZB_PKT_16B_ZERO_BYTE]) |= ((bit_value) << 5U); \ - } while (ZB_FALSE) - - -/** - Get sequence number from MAC FCF -*/ -#define ZB_FCF_GET_SEQ_NUMBER(p_fcf) ((const zb_uint8_t*)(p_fcf))[2] - - -/** - Gets Pan ID compression bit subfield in frame control field ( FCF ) - Return values can be 0 or 1. - - @param p_fcf - pointer to 16bit FCF field. -*/ - -#define ZB_FCF_GET_PANID_COMPRESSION_BIT( p_fcf ) (( ( ( ( const zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_ZERO_BYTE] ) & 0x40U )) - - -/** - Sets ack request bit subfield in frame control field ( FCF ) - - @param p_fcf - pointer to 16bit FCF field. - @param bit_value - 0 or 1. -*/ - -#define ZB_FCF_SET_PANID_COMPRESSION_BIT(p_fcf, bit_value) \ - do \ - { \ - ZB_ASSERT((bit_value) == 0U || (bit_value) == 1U); \ - (((zb_uint8_t *)(p_fcf))[ZB_PKT_16B_ZERO_BYTE]) &= 0xBFU; \ - (((zb_uint8_t *)(p_fcf))[ZB_PKT_16B_ZERO_BYTE]) |= ((bit_value) << 6U); \ - } while (ZB_FALSE) - - -/** - Gets destination addressing mode subfield in frame control field ( FCF ) - Return values is one value from @ref address_modes. - - @param p_fcf - pointer to 16bit FCF field. -*/ - -#define ZB_FCF_GET_FRAME_VERSION( p_fcf ) ( (( ( ( ( const zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_FIRST_BYTE] ) & 0x30U )) >> 4U ) - - -/** - Sets frame version subfield in frame control field ( FCF ) - Return values is one value defined in @ref mac_frame_version. - - @param p_fcf - pointer to 16bit FCF field. - @param frame_version - -*/ -#define ZB_FCF_SET_FRAME_VERSION( p_fcf, frame_version ) \ - do \ - { \ - ZB_ASSERT( (frame_version) == MAC_FRAME_IEEE_802_15_4_2003 \ - || (frame_version) == MAC_FRAME_IEEE_802_15_4 \ - || (frame_version) == MAC_FRAME_IEEE_802_15_4_2015 ); \ - \ - ( ( ( zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_FIRST_BYTE] ) &= 0xCFU; \ - ( ( ( zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_FIRST_BYTE] ) |= ( frame_version ) << 4U; \ - } while( 0 ) - - -/** - Gets IE list present bit subfield in frame control field ( FCF ) - Return values can be 0 or 1. - - @param p_fcf - pointer to 16bit FCF field. -*/ -#define ZB_FCF_GET_IE_LIST_PRESENT_BIT( p_fcf ) ((( ( ( ( const zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_FIRST_BYTE] ) & 0x2U )) >> 1U) - - -/** - Sets IE list present bit subfield in frame control field ( FCF ) - - @param p_fcf - pointer to 16bit FCF field. - @param bit_value - 0 or 1. -*/ -#define ZB_FCF_SET_IE_LIST_PRESENT_BIT(p_fcf, bit_value) \ - do \ - { \ - ZB_ASSERT((bit_value) == 0U || (bit_value) == 1U); \ - (((zb_uint8_t *)(p_fcf))[ZB_PKT_16B_FIRST_BYTE]) &= 0xFDU; \ - (((zb_uint8_t *)(p_fcf))[ZB_PKT_16B_FIRST_BYTE]) |= ((bit_value) << 1U); \ - } while (ZB_FALSE) - - -/** - Gets source addressing mode subfield in frame control field ( FCF ) - Return values is one value from @ref address_modes. - - @param p_fcf - pointer to 16bit FCF field. -*/ - -#define ZB_FCF_GET_SRC_ADDRESSING_MODE( p_fcf ) ( (( ( ( ( const zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_FIRST_BYTE] ) & 0xC0U )) >> 6U ) - -/** - Sets src addressing subfield in frame control field ( FCF ) - - @param p_fcf - pointer to 16bit FCF field. - @param addr_mode - 0 or 1. -*/ -/* implemented as function zb_fcf_set_src_addressing_mode() - #define ZB_FCF_SET_SRC_ADDRESSING_MODE( p_fcf, addr_mode ) \ - do \ - { \ - ZB_ASSERT( ( addr_mode ) == 0 || \ - ( addr_mode ) == 1 || \ - ( addr_mode ) == 2 || \ - ( addr_mode ) == 3 ); \ - \ - ( ( ( zb_uint8_t* ) ( p_fcf ))[ZB_PKT_16B_FIRST_BYTE] ) &= 0x3F; \ - ( ( ( zb_uint8_t* ) ( p_fcf ))[ZB_PKT_16B_FIRST_BYTE] ) |= ( addr_mode ) << 6; \ - } while( 0 ) -*/ -void zb_fcf_set_src_addressing_mode(zb_uint8_t *p_fcf, zb_uint8_t addr_mode); -#define ZB_FCF_SET_SRC_ADDRESSING_MODE zb_fcf_set_src_addressing_mode - -/** - Gets source addressing mode subfield in frame control field ( FCF ) - Return values is one value from @ref address_modes. - - @param p_fcf - pointer to 16bit FCF field. -*/ - -#define ZB_FCF_GET_DST_ADDRESSING_MODE( p_fcf ) (((( ( ( const zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_FIRST_BYTE] ) & 0x0CU) ) >> 2U ) - - -/** - Sets dst addressing subfield in frame control field ( FCF ) - - @param p_fcf - pointer to 16bit FCF field. - @param addr_mode - 0 or 1. -*/ -/* implemented as function zb_fcf_set_dst_addressing_mode() - #define ZB_FCF_SET_DST_ADDRESSING_MODE( p_fcf, addr_mode ) \ - do \ - { \ - ZB_ASSERT( ( addr_mode ) == 0 || \ - ( addr_mode ) == 1 || \ - ( addr_mode ) == 2 || \ - ( addr_mode ) == 3 ); \ - \ - ( ( ( ( zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_FIRST_BYTE]) ) &= 0xF3; \ - ( ( ( ( zb_uint8_t* ) ( p_fcf ) )[ZB_PKT_16B_FIRST_BYTE]) ) |= ( addr_mode ) << 2; \ - } while( 0 ) -*/ -void zb_fcf_set_dst_addressing_mode(zb_uint8_t *p_fcf, zb_uint8_t addr_mode); -#define ZB_FCF_SET_DST_ADDRESSING_MODE zb_fcf_set_dst_addressing_mode - -/** - Gets memory address of FCF field inside MAC frame - - @param p_buf - pointer to beginning of the MAC header r - @return - pointer to 16-bit FCF field -*/ - -#define ZB_MAC_GET_FCF_PTR( p_buf ) ( ( zb_uint8_t* ) ( p_buf ) ) - - -/** - Gets length in bytes of source address field inside MAC frame - - @param p_buf - pointer to beginning of the MAC header - @param out_len - name of variable of any int type which has been declared before. - stored value is in bytes, so following values are possible [ 0, 2, 8 ] - - @b Example - @code - int z; - ZB_FCF_GET_DST_ADDR_LENGTH( p_buf, z ); - @endcode -*/ - -/** - Tail size for mac packet. - - This is default value. Platform can redefine it. -*/ -#ifndef ZB_TAIL_SIZE_FOR_RECEIVED_MAC_FRAME -#define ZB_TAIL_SIZE_FOR_RECEIVED_MAC_FRAME (ZB_MAC_EXTRA_DATA_SIZE) -#endif - -#ifndef ZB_MAC_GET_LQI - -/** - Get LQI value - @param packet - pointer to buffer -*/ -#define ZB_MAC_GET_LQI(packet) *((zb_uint8_t*)zb_buf_end(packet) - ZB_MAC_EXTRA_DATA_SIZE) -#endif - -#ifndef ZB_MAC_SET_LQI -/** - Set LQI value - @param packet - pointer to buffer - @param v - LQI value -*/ - -#define ZB_MAC_SET_LQI(packet, v) *((zb_uint8_t*)zb_buf_end(packet) - ZB_MAC_EXTRA_DATA_SIZE) = (v) -#endif - - -#define ZB_MAC_ACK_LEN_BYTES 5U - -#ifndef ZB_MAC_GET_RSSI -/** - Get RSSI value - @param packet - pointer to buffer -*/ -#define ZB_MAC_GET_RSSI(packet) *((zb_int8_t*)zb_buf_end(packet) - ZB_MAC_EXTRA_DATA_SIZE + 1U) -#endif - -#ifndef ZB_MAC_SET_RSSI -/** - Set RSSI value - @param packet - pointer to buffer - @param v - RSSI value -*/ -#define ZB_MAC_SET_RSSI(packet, v) (*((zb_int8_t*)zb_buf_end(packet) - ZB_MAC_EXTRA_DATA_SIZE + 1U) = (v)) -#endif - -/** - Remove MAC header and trailer from the packet. - - To be used when passing packet up in NWK. - Save hdr offset in internal buf structure to be able to get mac hdr data from - upper layers, i.e. from nwk route discovery - - @param packet - packet to proceed - @param hlen - length MAC header - @param ptr - pointer to the NWK begin -*/ -#define ZB_MAC_CUT_HDR(packet, hlen, ptr) \ - do \ - { \ - /* Remove RSSI etc. */ \ - zb_buf_cut_right(packet, ZB_TAIL_SIZE_FOR_RECEIVED_MAC_FRAME); \ - ptr = zb_buf_cut_left(packet, hlen); \ - } while (0) - - -/* - NS build adds FCS to the outgoing packet end while HW build does not -*/ -#define ZB_TAIL_SIZE_FOR_SENDER_MAC_FRAME 2U - -/** - Gets Beacon Payload offset from the beginning of the Beacon frame - - @param beacon - pointer to beginning of the Beacon frame - @return beacon payload offset value -*/ -zb_ushort_t zb_mac_get_beacon_payload_offset(zb_uint8_t *beacon); - -#define ZB_BEACON_PAYLOAD_TAIL (ZB_TAIL_SIZE_FOR_RECEIVED_MAC_FRAME) -#define ZB_BEACON_PAYLOAD_LENGTH_MIN 2U - -/* MAC security */ -#ifdef ZB_MAC_SECURITY -#define MAC_SECUR_LEV5_KEYID1_AUX_HDR_SIZE 6U -#else -#define MAC_SECUR_LEV5_KEYID1_AUX_HDR_SIZE 0U -#endif - - -/** - Remove MAC header from the packet. - - To be used when passing packet up in NWK. - Save hdr offset in internal buf structure to be able to get mac hdr data from - upper layers, i.e. from nwk route discovery - - @param _packet - packet to proceed - @param _ptr - pointer to the NWK begin -*/ -#define ZB_MAC_CUT_HDR_WITHOUT_TRAILER(_packet, _ptr) \ - do \ - { \ - zb_ushort_t hlen; \ - void *mac_hdr = zb_buf_begin(_packet); \ - \ - /* Save hdr offset */ \ - hlen = zb_mac_calculate_mhr_length(ZB_FCF_GET_SRC_ADDRESSING_MODE(mac_hdr), \ - ZB_FCF_GET_DST_ADDRESSING_MODE(mac_hdr), \ - ZB_U2B(ZB_FCF_GET_PANID_COMPRESSION_BIT(mac_hdr))); \ - _ptr = zb_buf_cut_left( \ - _packet, hlen + MAC_SECUR_LEV5_KEYID1_AUX_HDR_SIZE * ZB_FCF_GET_SECURITY_BIT(mac_hdr)); \ - \ - \ - } while (ZB_FALSE) - - -/** - Get full MAC header size -*/ -#define ZB_MAC_HDR_FULL_SIZE(_mac_hdr) \ - (zb_mac_calculate_mhr_length(ZB_FCF_GET_SRC_ADDRESSING_MODE(_mac_hdr), \ - ZB_FCF_GET_DST_ADDRESSING_MODE(_mac_hdr), \ - ZB_U2B(ZB_FCF_GET_PANID_COMPRESSION_BIT(_mac_hdr))) \ - + MAC_SECUR_LEV5_KEYID1_AUX_HDR_SIZE * ZB_FCF_GET_SECURITY_BIT(_mac_hdr)) - -/** - Holds status of purge operation. - @note This struct does not contain msduHandle, because it must be in NWK - header - @param status - The status of the request to be purged an MSDU - from the transaction queue ( one of values of mac_status_e ) -*/ - -typedef ZB_PACKED_PRE struct zb_mac_purge_confirm_s -{ - zb_uint8_t status; -} ZB_PACKED_STRUCT -zb_mac_purge_confirm_t; - - -#define ZB_MAC_CAP_GET_ALTERNATE_PAN_COORDINATOR(cap) ((cap) & 1U) -#define ZB_MAC_CAP_SET_ALTERNATE_PAN_COORDINATOR(cap, v) (cap) |= (v) - -#define ZB_MAC_CAP_GET_DEVICE_TYPE(cap) (((cap) >> 1U) & 1U) -#define ZB_MAC_CAP_SET_DEVICE_TYPE(cap, v) \ - ( \ - (cap) &= 0xFDU, /* clear bit 1 */ \ - (cap) |= ((v) << 1U) /* set bit if it is == 1 */ \ - ) - -#define ZB_MAC_CAP_GET_POWER_SOURCE(cap) (((cap) >> 2U) & 1U) -#define ZB_MAC_CAP_SET_POWER_SOURCE(cap, v) ((cap) |= ((v) << 2U)) - -#define ZB_MAC_CAP_GET_RX_ON_WHEN_IDLE(cap) (((cap) >> 3U) & 1U) -#define ZB_MAC_CAP_SET_RX_ON_WHEN_IDLE(cap, v) ((cap) |= ((v) << 3U)) - -/** - Set capabilities typical for router: device type - R, power source - main, rx - on when idle. -*/ -#define ZB_MAC_CAP_SET_ROUTER_CAPS(cap) ((cap) |= (1U << 1U) | (1U << 2U) | (1U << 3U)) - -#define ZB_MAC_CAP_GET_SECURITY(cap) (((cap) >> 6U) & 1U) -#define ZB_MAC_CAP_SET_SECURITY(cap, v) ((cap) |= ((v) << 6U)) - -#define ZB_MAC_CAP_GET_ALLOCATE_ADDRESS(cap) (((cap) >> 7U) & 1U) -#define ZB_MAC_CAP_SET_ALLOCATE_ADDRESS(cap, v) ((cap) |= ((v) << 7U)) - - - - - - - -/** - Builds MLME disassociate request. The MLME-DISASSOCIATE.request primitive is - used by an associated device to notify the coordinator of its intent to leave - PAN. It is also used by the coordinator to instruct an associated device to leave the - PAN. - - @param buf - pointer to zb_buf_t container - - @param device_addr_mode - ( valid values ZB_ADDR_16BIT_DEV_OR_BROADCAST or - - @param device_pan_id - Pan ID of the device to which the - disassociation notification command is sent. - - @param device_addr - pointer to the address of the device to which the - disassociation notification command is sent. - - @param disassociate_reason - one of values of mac_status_e enum - - @param tx_indirect - 1 if the disassociation notification command is to be - sent indirectly, otherwise must be 0. - - @param out_len - out integer variable to receive length - -*/ -#define ZB_MLME_BUILD_DISASSOCIATE_REQUEST( buf, \ - device_addr_mode, \ - device_pan_id, \ - device_addr, \ - disassociate_reason, \ - tx_indirect, \ - out_len ) \ - do \ - { \ - } while( 0 ); - - -/** - Defines struct for MLME disassociate indication primitive. - - @param device_address - the address of the device requesting disassociation. - - @param disassociate_reason - the status of the association attempt. ( value from mac_status_e enum ) - -*/ -typedef ZB_PACKED_PRE struct zb_mac_disassociate_indication_s -{ - zb_ieee_addr_t device_address; - zb_uint8_t disassociate_reason; -} ZB_PACKED_STRUCT -zb_mac_disassociate_indication_t; - -/** - Returns pointer to zb_mac_disassociate_indication_t structure - located somewhere in buf. - - @param buf - pointer to zb_buf_t container - @param outptr - out pointer to zb_mac_associate_confirm_t struct located - somewhere inside buf -*/ - -#define ZB_MLME_GET_DISASSOCIATE_INDICATION_PTR( buf, outptr ) \ - do \ - { \ - } while( 0 ); - -/** - Defines struct which describes MLME-DISASSOCIATE.confirm primitive. - - @param status - the status of the disassociation attempt. ( one of the - values list from the mac_status_e enum ) - - @param device_addr_mode - ( valid values ZB_ADDR_16BIT_DEV_OR_BROADCAST or - ZB_ADDR_64BIT_DEV ). The addressing mode of the device that has either requested - disassociation or been instructed to disassociate by its coordinator. - - @param device_pan_id - Pan ID of the device that has either requested disassociation or - been instructed to disassociate by its coordinator. - - @param device_addr - the address of the device that has either requested disassociation or - been instructed to disassociate by its coordinator. - -*/ - -typedef ZB_PACKED_PRE struct zb_mac_disassociate_confirm_s -{ - zb_uint8_t status; - zb_uint8_t device_addr_mode; - zb_uint16_t device_pan_id; - zb_addr_u device_addr; -} ZB_PACKED_STRUCT -zb_mac_disassociate_confirm_t; - - -/** - Returns pointer to zb_mac_disassociate_confirm_t structure - located somewhere in buf. - - @param buf - pointer to zb_buf_t container - @param outptr - out pointer to zb_mac_associate_confirm_t struct located - somewhere inside buf -*/ - -#define ZB_MAC_GET_DISASSOCIATE_CONFIRM_PTR( buf, outptr ) \ - do \ - { \ - } while( 0 ) - -/** - Define the Superframe Specification field - - @param beacon_order - shall specify the transmission interval of the beacon. - ( see 7.5.1.1 ) - - @param superframe_order - shall specify the length of time during which the - superframe is active (i.e., receiver enabled), - including the beacon frame transmission time. See - 7.5.1.1 for explanation of the relationship between - the superframe order and the superframe duration. - - @param final_cap_slot - specifies the final superframe slot utilized by the CAP. - The duration of the CAP, as implied by this subfield, - shall be greater than or equal to the value specified by - aMinCAPLength. However, an exception is allowed for - the accommodation of the temporary increase in the - beacon frame length needed to perform GTS maintenance - (see 7.2.2.1.3). - - @param battery_life_extension - shall be set to one if frames transmitted to - the beaconing device during its CAP are - required to start in or before - macBattLifeExtPeriods full backoff periods - after the IFS period following the beacon. - Otherwise, the BLE subfield shall be set to zero. - - @param reserved - reserved for future needs. - - @param pan_coordinator - shall be set to one if the beacon frame is being - transmitted by the PAN coordinator. Otherwise, the - PAN Coordinator subfield shall be set to zero. - - @param associate_permit - shall be set to one if macAssociationPermit is set - to TRUE ( i.e., the coordinator is accepting - association to the PAN ). The association permit bit - shall be set to zero if the coordinator is currently - not accepting association requests on its network. - -*/ - -typedef ZB_PACKED_PRE struct zb_super_frame_spec_s -{ -#ifdef ZB_LITTLE_ENDIAN - zb_bitfield_t beacon_order:4; - zb_bitfield_t superframe_order:4; - - zb_bitfield_t final_cap_slot:4; - zb_bitfield_t battery_life_extension:1; - zb_bitfield_t reserved:1; - zb_bitfield_t pan_coordinator:1; - zb_bitfield_t associate_permit:1; -#else - zb_bitfield_t final_cap_slot:4; - zb_bitfield_t battery_life_extension:1; - zb_bitfield_t reserved:1; - zb_bitfield_t pan_coordinator:1; - zb_bitfield_t associate_permit:1; - - zb_bitfield_t beacon_order:4; - zb_bitfield_t superframe_order:4; -#endif -} ZB_PACKED_STRUCT -zb_super_frame_spec_t; - -/* zb_super_frame_spec_t structure is MSBF/LSBF specific, use the - * following macro to make code MSBF/LSBF portable */ - -/** - Sets superframe beacon order - @param superframe - pointer to superframe - @param beacon_order - beacon order value -*/ -#define ZB_SUPERFRAME_SET_BEACON_ORDER(superframe, beacon_order) \ - do \ - { \ - ((zb_uint8_t*)(superframe))[ZB_PKT_16B_ZERO_BYTE] &= 0xF0U; \ - ((zb_uint8_t*)(superframe))[ZB_PKT_16B_ZERO_BYTE] |= (beacon_order); \ - } while(0) - -/** - Sets superframe order - @param superframe - pointer to superframe - @param superframe_order - superframe order value -*/ -#define ZB_SUPERFRAME_SET_SUPERFRAME_ORDER(superframe, superframe_order) \ - do \ - { \ - ((zb_uint8_t *)(superframe))[ZB_PKT_16B_ZERO_BYTE] &= 0x0FU; \ - ((zb_uint8_t *)(superframe))[ZB_PKT_16B_ZERO_BYTE] |= (zb_uint8_t)((superframe_order) << 4U); \ - } while (0) - -/** - Sets superframe fcs - @param superframe - pointer to superframe - @param fcs - fcs value -*/ -#define ZB_SUPERFRAME_SET_FINAL_CAP_SLOT(superframe, fcs) \ - do \ - { \ - ((zb_uint8_t*)(superframe))[ZB_PKT_16B_FIRST_BYTE] &= 0xF0U; /*1111.0000*/ \ - ((zb_uint8_t*)(superframe))[ZB_PKT_16B_FIRST_BYTE] |= (fcs); \ - } while(0) - -/** - Sets superframe ble - @param superframe - pointer to superframe - @param ble - superframe ble value -*/ -#define ZB_SUPERFRAME_SET_BLE(superframe, ble) \ - do \ - { \ - ((zb_uint8_t*)(superframe))[ZB_PKT_16B_FIRST_BYTE] &= 0xEFU; /*1110.1111*/ \ - ((zb_uint8_t*)(superframe))[ZB_PKT_16B_FIRST_BYTE] |= (ble) << 4U; \ - } while(0) - -/** - Sets superframe Pan coordinator flag - @param superframe - pointer to superframe - @param pan_coord - Pan coordinator flag value -*/ -#define ZB_SUPERFRAME_SET_PAN_COORD(superframe, pan_coord) \ - do \ - { \ - ((zb_uint8_t*)(superframe))[ZB_PKT_16B_FIRST_BYTE] &= 0xBFU; /*1011.1111*/ \ - ((zb_uint8_t*)(superframe))[ZB_PKT_16B_FIRST_BYTE] |= (pan_coord) << 6U; \ - } while(0) - -/** - Sets superframe association permit flag - @param superframe - pointer to superframe - @param ass_permit - association permit flag value -*/ -#define ZB_SUPERFRAME_SET_ASS_PERMIT(superframe, ass_permit) \ - do \ - { \ - ((zb_uint8_t*)(superframe))[ZB_PKT_16B_FIRST_BYTE] &= 0x7FU; /*0111.1111*/ \ - ((zb_uint8_t*)(superframe))[ZB_PKT_16B_FIRST_BYTE] |= (ass_permit) << 7U; \ - } while(0) - - -/** - Define the Beacon Payload field - - see figure 3.49 - - @param protocol_id - This field identifies the network layer protocols in use and, - for purposes of this specification, shall always be set to 0, - indicating the Zigbee protocols. - The value 0xff shall also be reserved for future use by - the Zigbee Alliance. - ( see Zigbee 3.6.7 ) - - @param stack_profile - ZBOSS profile identifier. ( see Zigbee 3.6.7 ) - - @param protocol_version - The version of the Zigbee protocol. ( see Zigbee 3.6.7 ) - - @param reserved - reserved for future needs. - - @param router_capacity - This value is set to TRUE if this device is capable - of accepting join requests from router-capable devices - and is set to FALSE otherwise. ( see Zigbee 3.6.7 ) - - @param device_depth - The network depth of this device. A value of 0x00 indicates - that this device is the Zigbee coordinator for the network. - ( see Zigbee 3.6.7 ) - - @param end_device_capacity - This value is set to TRUE if the device is capable - of accepting join requests from end devices seeking - to join the network and is set to FALSE otherwise. - ( see Zigbee 3.6.7 ) - - @param nwkExtendedPANId - The globally unique ID for the PAN for which the beaconing - device is a member. By default, this is the 64-bit IEEE address - of the ZigBee coordinator that formed the network, - but other values are possible and - there is no required structure to the address. - ( see zigbee 3.6.7 ) - - @param txoffset - This value indicates the difference in time, measured in symbols, - between the beacon transmission time of the device and - the beacon transmission time of its parent; - This offset may be subtracted from the beacon transmission time - of the device to calculate the beacon transmission time of the parent. - This parameter is set to the default value of 0xFFFFFF - in beaconless networks. - ( see Zigbee 3.6.7 ) - - @param nwkUpdateId - This field reflects the value of nwkUpdateId from the NIB. - ( see Zigbee 3.6.7 ) - -*/ -typedef ZB_PACKED_PRE struct zb_mac_beacon_payload_s -{ - zb_uint8_t protocol_id; /**< for purposes of this specification, - shall always be set to 0, - indicating the Zigbee protocols. - */ -#ifdef ZB_LITTLE_ENDIAN - zb_bitfield_t stack_profile:4; - zb_bitfield_t protocol_version:4; - - /* Used by Amazon WWAH, reserved otherwise */ - zb_bitfield_t long_uptime:1; - zb_bitfield_t tc_connectivity:1; - - zb_bitfield_t router_capacity:1; - zb_bitfield_t device_depth:4; - zb_bitfield_t end_device_capacity:1; - -#else /* #ifdef ZB_LITTLE_ENDIAN */ - - zb_bitfield_t long_uptime:1; - zb_bitfield_t tc_connectivity:1; - - zb_bitfield_t router_capacity:1; - zb_bitfield_t device_depth:4; - zb_bitfield_t end_device_capacity:1; - - zb_bitfield_t stack_profile:4; - zb_bitfield_t protocol_version:4; -#endif /* #else ZB_LITTLE_ENDIAN */ - - zb_ext_pan_id_t extended_panid; - zb_uint8_t txoffset[3]; /**< This parameter is set to the - default value of 0xFFFFFF in - a beaconless networks. */ - zb_uint8_t nwk_update_id; /*!< This field reflects the value of - nwkUpdateId from the NIB. */ -} ZB_PACKED_STRUCT -zb_mac_beacon_payload_t; - - -/** - Gets Superframe specification from beacon frame - - @param mhr - pointer to beginning of the MAC header - @param mhr_len - MAC header length (must be already known - use \see zb_parse_mhr - @param superframe - out pointer to superframe specification - - @b Example - @code - zb_uint8_t *mac_hdr; - ZB_GET_SUPERFRAME( mhr, mhr_len, superframe ); - @endcode -*/ -#define ZB_GET_SUPERFRAME(mhr, mhr_len, superframe) \ - ZB_LETOH16(superframe, ((const zb_uint8_t*)(mhr) + (mhr_len))) - - -/** - Gets GTS fields from beacon frame - - @param mhr - pointer to beginning of the MAC header - @param mhr_len - MAC header length (must be already known - use \see zb_parse_mhr - @param gts_fields_p - out pointer to GTS fields - - @b Example - @code - zb_mac_gts_fields_t *beacon_payload; - ZB_MAC_GET_GTS_FIELDS( p_buf, mhr_len, gts_fields ); - @endcode -*/ -#define ZB_MAC_GET_GTS_FIELDS(mhr, mhr_len, gts_fields_p ) \ - (gts_fields_p) = (void *)(((zb_uint8_t *)mhr) + mhr_len + SUREPFRAME_SPEC_LENGTH) - - -/** - Get superframe spec from the Beacon packet. - - @param mhr - pointer to beginning of the MAC header - @param mhr_len - MAC header length (must be already known - use \see zb_parse_mhr - @param superframe_p - out pointer to Superframe - -*/ -#define ZB_MAC_GET_SUPERFRAME_SPEC(mhr, mhr_len, superframe_p) \ - superframe_p = (void *)(((zb_uint8_t *)mhr) + mhr_len); - - - -/** - Gets Beacon Order subfield in Superframe Specification field ( SFS ) - - @param p_sfs - pointer to 16bit SFS field. -*/ - -#define ZB_MAC_GET_BEACON_ORDER( p_sfs ) ((zb_uint_t)((((zb_uint8_t*)(p_sfs))[ZB_PKT_16B_ZERO_BYTE]) & 0x07U)) - -/** - Gets Association Permit subfield in Superframe Specification field ( SFS ) - - @param p_sfs - pointer to 16bit SFS field. -*/ - -#define ZB_MAC_GET_ASSOCIATION_PERMIT( p_sfs ) ((zb_uint_t)((((zb_uint8_t*)(p_sfs))[ZB_PKT_16B_FIRST_BYTE] >> 7U) & 1U)) - -/** - Gets Superframe Order subfield in Superframe Specification field ( SFS ) - - @param p_sfs - pointer to 16bit SFS field. -*/ - -#define ZB_MAC_GET_SUPERFRAME_ORDER( p_sfs ) ((zb_uint_t)((((zb_uint8_t*)(p_sfs))[ZB_PKT_16B_ZERO_BYTE] >> 4U) & 0xFU)) - -/** - Gets Pan Coordinator subfield in Superframe Specification field ( SFS ) - - @param p_sfs - pointer to 16bit SFS field. -*/ - -#define ZB_MAC_GET_SUPERFRAME_PAN_COORDINATOR( p_sfs ) ((zb_uint_t)((((zb_uint8_t*) (p_sfs))[ZB_PKT_16B_FIRST_BYTE] >> 6U) & 1U)) - -#define ZB_MAC_INVALID_LOGICAL_PAGE 0xFFU -#define ZB_MAC_INVALID_LOGICAL_CHANNEL 0xFFU - - -/** - Defines Pan descriptor structure - - @param coord_addr_mode - the coordinator addressing mode corresponding - to the received beacon frame. - ( valid values ZB_ADDR_16BIT_DEV_OR_BROADCAST or - ZB_ADDR_64BIT_DEV ). - - @param coord_pan_id - Pan ID of the coordinator as specified - in the received beacon frame. - - @param coord_address - pointer to 16-bit or 64-bit IEEE address. This value - depends on coord_addr_mode. - - @param channel_page - the current channel page occupied by the network - - @param logical_channel - the current logical channel occupied by the - network. - - @param super_frame_spec - the superframe specification as specified in the - received beacon frame. - - @param gts_permit - TRUE if the beacon is from the Pan coordinator that - is accepting GTS requests. - - @param LinkQuality - the LQI at which the network beacon was received. -*/ - - -typedef ZB_PACKED_PRE struct zb_mac_pan_descriptor_s // 7.1.5.1.1 table-41 -{ - zb_uint8_t coord_addr_mode; - zb_uint16_t coord_pan_id; - zb_addr_u coord_address; /* pointer to 16-bit or 64-bit address, this - * depends on value of coord_addr_mode */ - zb_uint8_t channel_page; - zb_uint8_t logical_channel; - zb_super_frame_spec_t super_frame_spec; - zb_uint8_t gts_permit; - zb_uint8_t link_quality; - /* Zigbee does not use security and uses beaconless mode, so skip other Pan descriptor - fields - for timestamp and security */ -#if defined ZB_ENHANCED_BEACON_SUPPORT - zb_uint16_t enh_beacon_nwk_addr; /* the field is required for enhanced beacons handling */ -#endif /* ZB_ENHANCED_BEACON_SUPPORT */ -} ZB_PACKED_STRUCT -zb_pan_descriptor_t; - -/** - Defines pending address specification field. - - @param num_of_short_addr - indicates the number of 16-bit short addresses - contained in the Address List field of the beacon frame. - @param rvd0 - reserved bit. - @param num_of_long_addr -indicates the number of IEEE-addresses - contained in the Address List field of the beacon frame. - @param rvd1 - reserved bit. -*/ -typedef ZB_PACKED_PRE struct zb_pending_address_spec_s -{ - zb_bitfield_t num_of_short_addr:3; - zb_bitfield_t rvd0:1; - zb_bitfield_t num_of_long_addr:3; - zb_bitfield_t rvd1:1; -} ZB_PACKED_STRUCT -zb_pending_address_spec_t; - -/** - - Parameters for MLME-SCAN.request primitive - - @param buf - pointer to zb_buf_t container - @param type - one value of @ref mac_scan_type - - @param _channel_page - the channel page on which to perform the scan - - @param _channels - bitmap. Only first 27 bits are used. - Bits (b0, b1,... b26) indicate which channels are to be scanned - ( 1 = scan, 0 = do not scan) for each of the 27 channels supported by hardware. - UBEK transceiver maps 16 IEEE 802.15.4 2.4GHz band channels to following interval [ 11, 26 ]. - So values of all others bits except bits from 11 to 26 are ignored - - @param duration - a value used to calculate the length of time to spend scanning each channel for ED, - active, and passive scans. This parameter is ignored for orphan scans. The time spent scanning - each channel is [ aBaseSuperframeDuration * ( 2**n + 1 ) ] symbols, where n is the value of the - ScanDuration parameter. - - @param mac_iface_id - index of interface that will be used for scanning - TODO [Multi-MAC] will it be better to just extract iface_id from _channel_page and _channels? -*/ -#define ZB_MLME_BUILD_SCAN_REQUEST( buf, _channel_page, _channels, type, duration, mac_iface_id) \ -do \ -{ \ - zb_mlme_scan_params_t *_p = zb_buf_alloc_tail((buf), sizeof(zb_mlme_scan_params_t)); \ - _p->channel_page = _channel_page; \ - _p->channels = _channels; \ - _p->scan_type = type; \ - _p->scan_duration = duration; \ - _p->iface_id = mac_iface_id; \ -} while( 0 ) - -#define ZB_MLME_SCAN_REQUEST_IE_SIZES_HDR_LEN 2U - -/** - * Write total header IE and payload IE sizes into buffer for mlme-scan.req - * After these two bytes HIE and PIE themselves follow - */ -#define ZB_MLME_SCAN_REQUEST_SET_IE_SIZES_HDR(ptr, hie_len, pie_len) \ - do \ - { \ - (ptr)[ZB_PKT_16B_ZERO_BYTE] = (hie_len) & 0xFFU; \ - (ptr)[ZB_PKT_16B_FIRST_BYTE] = (pie_len) & 0xFFU; \ - } while( 0 ) - - - -/** - Defines structure for MAC-MLME.confirm primitive - - @param status - one of values of \ref mac_status - - @param scan_type - one of values of @ref mac_scan_type - - @param channel_page - the channel page on which the scan was performed - - @param result_list_size - the number of elements returned in the appropriate - result lists. This value is zero for the result of - an orphan scan. - - @param unscanned_channels - indicates which channels given in the - request were not scanned - ( 1 = not scanned, 0 = scanned or not requested). - This parameter is not valid for ED scans. - - @param energy_detect - the array of energy measurements, one for each channel - searched during an ED scan. This parameter is null for - active, passive, and orphan scans. - - @param pan_descriptor - The list of Pan descriptors, one for each beacon - found during an active or passive scan if - macAutoRequest is set to TRUE. This parameter is null - for ED and orphan scans or when macAutoRequest is set - to FALSE during an active or passive scan. -*/ - - -typedef ZB_PACKED_PRE struct zb_mac_scan_confirm_s -{ - zb_uint8_t iface_id; - zb_uint8_t status; - zb_uint8_t scan_type; - zb_uint8_t channel_page; - zb_uint8_t result_list_size; - zb_uint32_t unscanned_channels; - - ZB_PACKED_PRE union - { - zb_uint8_t energy_detect[ ZB_MAC_SUPPORTED_CHANNELS ]; - } ZB_PACKED_STRUCT list; -} ZB_PACKED_STRUCT -zb_mac_scan_confirm_t; - - -/** @} */ -/** @endcond */ - -/** - * @addtogroup mac_pib - * @{ - */ - -/** - * @name MAC PIB attributes - * @anchor mac_pib_attr - */ -/** @{ */ -/* PHY PIB */ -#define ZB_PHY_PIB_CURRENT_CHANNEL 0x00U -#define ZB_PHY_PIB_CURRENT_PAGE 0x04U - -/* MAC PIB */ -#define ZB_PIB_ATTRIBUTE_ACK_WAIT_DURATION 0x40U -#define ZB_PIB_ATTRIBUTE_ASSOCIATION_PERMIT 0x41U -#define ZB_PIB_ATTRIBUTE_AUTO_REQUEST 0x42U -#define ZB_PIB_ATTRIBUTE_BATT_LIFE_EXT 0x43U -#define ZB_PIB_ATTRIBUTE_BATT_LIFE_EXT_PERIODS 0x44U -#define ZB_PIB_ATTRIBUTE_BEACON_PAYLOAD 0x45U -#define ZB_PIB_ATTRIBUTE_BEACON_PAYLOAD_LENGTH 0x46U -#define ZB_PIB_ATTRIBUTE_BEACON_ORDER 0x47U -#define ZB_PIB_ATTRIBUTE_BEACON_TX_TIME 0x48U -#define ZB_PIB_ATTRIBUTE_BSN 0x49U -#define ZB_PIB_ATTRIBUTE_COORD_EXTEND_ADDRESS 0x4aU -#define ZB_PIB_ATTRIBUTE_COORD_SHORT_ADDRESS 0x4bU -#define ZB_PIB_ATTRIBUTE_DSN 0x4cU -#define ZB_PIB_ATTRIBUTE_GTS_PERMIT 0x4dU -#define ZB_PIB_ATTRIBUTE_MAX_CSMA_BACKOFFS 0x4eU -#define ZB_PIB_ATTRIBUTE_MIN_BE 0x4fU -#define ZB_PIB_ATTRIBUTE_PANID 0x50U -#define ZB_PIB_ATTRIBUTE_PROMISCUOUS_MODE 0x51U -#define ZB_PIB_ATTRIBUTE_RX_ON_WHEN_IDLE 0x52U -#define ZB_PIB_ATTRIBUTE_SHORT_ADDRESS 0x53U -#define ZB_PIB_ATTRIBUTE_SUPER_FRAME_ORDER 0x54U -#define ZB_PIB_ATTRIBUTE_TRANSACTION_PERSISTENCE_TIME 0x55U -#define ZB_PIB_ATTRIBUTE_ASSOCIATED_PAN_COORD 0x56U -#define ZB_PIB_ATTRIBUTE_MAX_BE 0x57U -#define ZB_PIB_ATTRIBUTE_MAX_FRAME_TOTAL_WAIT_TIME 0x58U -#define ZB_PIB_ATTRIBUTE_MAX_FRAME_RETRIES 0x59U -#define ZB_PIB_ATTRIBUTE_RESPONSE_WAIT_TIME 0x5aU -#define ZB_PIB_ATTRIBUTE_SYNC_SYMBOL_OFFSET 0x5bU -#define ZB_PIB_ATTRIBUTE_TIMESTAMP_SUPPORTED 0x5cU -#define ZB_PIB_ATTRIBUTE_SECURITY_ENABLED 0x5dU - -/* Non-standard values */ -#define ZB_PIB_ATTRIBUTE_EXTEND_ADDRESS 0x81U /*!< long MAC address */ -#define ZB_PIB_ATTRIBUTE_NO_AUTO_ACK 0x82U /*!< for toggling auto ack on platform */ -/** data indication callback when in promisc mode */ -#define ZB_PIB_ATTRIBUTE_PROMISCUOUS_MODE_CB 0x83U -#define ZB_PIB_ATTRIBUTE_PROMISCUOUS_RX_ON 0x84U /*!< switch rx on/off when in sniffer mode */ -#define ZB_PIB_ATTRIBUTE_SRC_MATCH 0x85U /*!< Source match for MAC ACK pending bit */ -#define ZB_PIB_ATTRIBUTE_JOINING_IEEE_LIST 0x86U /*!< mibJoiningIeeeList, r22 */ -#define ZB_PIB_ATTRIBUTE_JOINING_IEEE_LIST_LENGTH 0x8AU /*!< mibJoiningIeeeList length, r22 */ -#define ZB_PIB_ATTRIBUTE_JOINING_POLICY 0x87U /*!< mibJoiningPolicy, r22 */ -#define ZB_PIB_ATTRIBUTE_IEEE_EXPIRY_INTERVAL 0x88U /*!< mibIeeeExpiryInterval, r22 */ -#define ZB_PIB_ATTRIBUTE_IEEE_EXPIRY_INTERVAL_COUNTDOWN 0x89U /*!< mibIeeeExpiryIntervalCountdown */ -#define ZB_PIB_ATTRIBUTE_SKIP_ALL_GPF 0x8AU /*!< zgp_skip_all_packets */ -#define ZB_PIB_ATTRIBUTE_BEACON_JITTER 0x8BU /*!< Beacon jitter (custom option) */ - -/* ZBOSS MAC custom attributes */ -#define ZB_PIB_ATTRIBUTE_IEEE_DIAGNOSTIC_INFO 0x8FU /*!< Get diagnostics counters. */ -/** Get and clear diagnostics counters. Only ZCL counters will be cleared. */ -#define ZB_PIB_ATTRIBUTE_GET_AND_CLEANUP_DIAG_INFO 0x90U - -#define ZB_PIB_ATTRIBUTE_PTA_OPTIONS 0x91U -#define ZB_PIB_ATTRIBUTE_PTA_STATE 0x92U -#define ZB_PIB_ATTRIBUTE_PTA_PRIORITY 0x93U -/** @} */ - -/** - * @brief Type for MAC PIB attributes. - * - * @deprecated holds one of @ref mac_pib_attr. Kept only for backward compatibility as - * @ref mac_pib_attr were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_mac_pib_attr_t; - -/** @} */ /* mac_pib */ - -/** \addtogroup mac_api */ -/** @{ */ - -/** - * @typedef zb_mac_capability_info_t - * @brief Defines capability information field as a set of bitfields. - * @li bit 0 alternate_PAN_coordinator - the bit is set if the device is capable - * of becoming the Pan coordinator. Otherwise the subfield is set to zero. - * @li bit 1 device_type - the bit is set if the device is FFD. The zero value indicates that - * device is RFD. - * @li bit 2 power_source - the bit is set if the device is receiving power from the alternating - * current mains. Otherwise, the subfield is set to zero. - * @li bit 3 receive_on_when_idle - the bit is set if the device does not disable its receiver to - * conserve power during idle periods. Otherwise the bit shall be set to zero. - * @li bit 6 security_capability - the bit is set if the device is capable of sending and - * receiving cryptographically protected MAC frames, Otherwise shall be set to zero . - * @li bit 7 allocate_address - the bit is set if the device wishes the coordinator to allocate - * 16bit short address as a result of the association procedure. Otherwise it shall be set to - * zero. - */ -typedef zb_uint8_t zb_mac_capability_info_t; - -/** - * @name MAC common constants and types. - * @{ - */ - -/** - * @name MAC status - * @anchor mac_status - * @brief MAC status (see table 78 in MAC 2006 specification). - */ -/** @{ */ -#define MAC_SUCCESS 0x00U /*!< Transaction was successful */ -#define MAC_PAN_AT_CAPACITY 0x01U -#define MAC_PAN_ACCESS_DENIED 0x02U -#define MAC_BEACON_LOSS 0xe0U /*!< Beacon was lost (used in beacon'd networks) */ -#define MAC_CHANNEL_ACCESS_FAILURE 0xe1U /*!< Unable to transmit due to channel being busy */ -#define MAC_COUNTER_ERROR 0xdBU /*!< Frame counter of received frame is invalid */ -#define MAC_DENIED 0xe2U /*!< GTS request denied */ -#define MAC_DISABLE_TRX_FAILURE 0xe3U /*!< Failed to disable the transceiver */ -#define MAC_SECURITY_ERROR 0xe4U /*!< Frame failed decryption */ -#define MAC_FRAME_TOO_LONG 0xe5U /*!< Frame exceeded maximum size */ -#define MAC_IMPROPER_KEY_TYPE 0xdcU /*!< Key not allowed to be used with this frame type */ -#define MAC_IMPROPER_SECURITY_LEVEL 0xddU /*!< Frame does not meet min security level expected */ -#define MAC_INVALID_ADDRESS 0xf5U /*!< Data request failed because no src or dest address */ -#define MAC_INVALID_GTS 0xe6U /*!< Invalid timeslot requested (beacon'd networks) */ -#define MAC_INVALID_HANDLE 0xe7U /*!< Invalid frame data handle */ -#define MAC_INVALID_INDEX 0xf9U /*!< Invalid index when trying to write MAC PIB */ -#define MAC_INVALID_PARAMETER 0xe8U /*!< Invalid parameter passed to service */ -#define MAC_LIMIT_REACHED 0xfaU /*!< Scan terminated because max Pan descriptors reached */ -#define MAC_NO_ACK 0xe9U /*!< ACK not received after tx with ack_req flag set */ -#define MAC_NO_BEACON 0xeaU /*!< Beacon not returned after beacon request */ -#define MAC_NO_DATA 0xebU /*!< Data frame not returned after data request (indirect poll) */ -/** No short address allocated to this device (due to lack of address space) */ -#define MAC_NO_SHORT_ADDRESS 0xecU -/** Rx enable request failed. Spec'd number of symbols longer than beacon interval */ -#define MAC_ON_TIME_TOO_LONG 0xf6U -/** Association failed due to lack of capacity (no nbor tbl entry or no address) */ -#define MAC_OUT_OF_CAP 0xedU -/** Different networks within listening range have identical Pan IDs */ -#define MAC_PAN_ID_CONFLICT 0xeeU -/** Rx enable failed. Too late for current superframe and unable to be deferred */ -#define MAC_PAST_TIME 0xf7U -#define MAC_READ_ONLY 0xfbU /*!< PIB attribute is read only */ -#define MAC_REALIGNMENT 0xefU /*!< Coordinator realignment received */ -/** Request to perform scan failed because scan already in progress */ -#define MAC_SCAN_IN_PROGRESS 0xfcU -/** Start time of beacon overlapped transmission time of coordinator beacon */ -#define MAC_SUPERFRAME_OVERLAP 0xfdU -/** Device not tracking beacons but instructed to send beacons based on tracked beacons */ -#define MAC_TRACKING_OFF 0xf8U -#define MAC_TRANSACTION_EXPIRED 0xf0U /*!< Frame buffered in indirect queue expired */ -#define MAC_TRANSACTION_OVERFLOW 0xf1U /*!< Exceeded maximum amount of entries in indirect queue */ -#define MAC_TX_ACTIVE 0xf2U /*!< Transmission in progress */ -#define MAC_UNAVAILABLE_KEY 0xf3U /*!< Security key unavailable */ -#define MAC_UNSUPPORTED_ATTRIBUTE 0xf4U /*!< Requested PIB attribute is not supported */ -/** 802.15.4 2003 security on frame, but not supported by device */ -#define MAC_UNSUPPORTED_LEGACY 0xdeU -#define MAC_UNSUPPORTED_SECURITY 0xdfU /*!< Security on received frame is not supported */ -#define MAC_PURGED 0xdaU /*!< Custom status: the packet has been purged */ -#define MAC_INTERRUPTED 0xd0U /*!< Custom status: the operation has been interrupted */ -/** @} */ - -/** - * @brief Type for MAC status. - * - * Holds one of @ref mac_status. - */ -typedef zb_uint8_t zb_mac_status_t; - - -/** - * @brief PHY enumerations descriptions - */ -typedef enum zb_phy_status_e -{ - PHY_BUSY = 0x00, - PHY_BUSY_RX = 0x01, - PHY_BUSY_TX = 0x02, - PHY_FORCE_TRX_OFF = 0x03, - PHY_IDLE = 0x04, - PHY_INVALID_PARAMETER = 0x05, - PHY_RX_ON = 0x06, - PHY_SUCCESS = 0x07, - PHY_TRX_OFF = 0x08, - PHY_TX_ON = 0x09, - PHY_UNSUPPORTED_ATTRIBUTE = 0x0a, - PHY_READ_ONLY = 0x0b -} zb_phy_status_t; - -/** - * @name Address Modes - * @anchor address_modes - * Address modes for different protocol layers. - * Hope can use same constants without re-assign. - */ -/** @{ */ -/** 802.15: 0x00 = no address (addressing fields omitted, see 7.2.1.1.8). */ -#define ZB_ADDR_NO_ADDR 0x00U -/** 802.15: 0x01 = reserved. - * NWK: 0x01 = 16-bit multicast group address. */ -#define ZB_ADDR_16BIT_MULTICAST 0x01U -/** APS: 0x01 = 16-bit group address for DstAddress. */ -#define ZB_ADDR_16BIT_GROUP ZB_ADDR_16BIT_MULTICAST -/** 802.15: 0x02 = 16-bit short address. - * NWK: 0x02 = 16-bit network address of a device or a 16-bit broadcast address. */ -#define ZB_ADDR_16BIT_DEV_OR_BROADCAST 0x02U -/** 802.15: 0x03 = 64-bit extended address. */ -#define ZB_ADDR_64BIT_DEV 0x03U -/** @} */ - -/** - * @brief Type for address modes (different protocol layers). - * - * Designed to hold one of @ref address_modes. - */ -typedef zb_uint8_t zb_addr_mode_t; - -/** @} */ /* MAC common constants and types. */ - -/** - * @name MAC data service constants and API. - * @{ - */ - -/* Structure is used for both NWK and ZGP data requests. For ZGP data request, - * source address is not used, but tx_at field matters. - * The structure is used for memory consumption optimization. - */ -#if defined (__ICCARM__) -/* Probably IAR version needs to refine */ -#if (__VER__ > 6040002) /* If iccarm version is fresh than 6.40.2 ---------- */ -ZB_PACKED_PRE -#endif -#elif __CC_ARM -ZB_PACKED_PRE -#endif -union zb_addr_time_u -{ - zb_uint16_t addr_short; - zb_ieee_addr_t addr_long; - zb_time_t tx_at; /**< No src addr. Transmit ZGPDF at given time */ -}; - -/** @brief Parameters for data request. */ -typedef ZB_PACKED_PRE struct zb_mcps_data_req_params_s -{ -#ifndef ZB_MAC_EXT_DATA_REQ - /* Quite old, from 2007: short addresses only */ - zb_uint16_t src_addr; /**< Source address */ - zb_uint16_t dst_addr; /**< Destination address */ -#else - /* In Zigbee 2007 never need to send data to/from long address, but need it for - * MAC certification testing and for interpan (ZLL). So actually we are here always. */ - union zb_addr_time_u src_addr; /**< Source address */ - zb_addr_u dst_addr; /**< Destination address */ - zb_uint16_t dst_pan_id; /**< Destination Pan ID */ -#endif /* ZB_MAC_EXT_DATA_REQ */ - zb_bitfield_t tx_options:5; /**< Options. @see mac_tx_options_bits */ - zb_bitfield_t src_addr_mode:2; /**< Source address mode, one of @ref address_modes */ - zb_bitfield_t reserved1:1; - zb_bitfield_t mhr_len:5; /* mhr length, filled by MAC and used internally. - * Can't be >= 32 */ - zb_bitfield_t dst_addr_mode:2; /**< Destination address mode, one of @ref address_modes */ - zb_bitfield_t reserved2:1; -#ifdef ZB_ENABLE_NWK_RETRANSMIT - zb_uint8_t nwk_retry_cnt; -#endif - zb_uint8_t msdu_handle; /**< */ -#ifdef ZB_MAC_SECURITY - zb_uint8_t security_level; /**< */ - zb_uint8_t key_id_mode; /**< */ - zb_uint8_t key_source[8]; /**< */ - zb_uint8_t key_index; /**< */ -#endif - zb_uint8_t iface_id; -} ZB_PACKED_STRUCT -zb_mcps_data_req_params_t; - -/* Assert that MCPS Data Request parameters will fit inside the buffer with the full length MAC frame (TP/154/MAC/DATA-01.h) - * - * IEEE 802.15.4 frame header (9 bytes): - * - FCS: 2 bytes - * - Seq: 1 byte - * - DST PAN: 2 bytes - * - DST short: 2 bytes - * - SRC short: 2 bytes - * - * IEEE 802.15.4 frame payload (116 bytes) - */ -ZB_ASSERT_COMPILE_DECL(ZB_IO_BUF_SIZE > (9 + 0x74 + (sizeof(zb_mcps_data_req_params_t) + ZB_BUF_ALLOC_ALIGN - 1) / ZB_BUF_ALLOC_ALIGN * ZB_BUF_ALLOC_ALIGN)); - - -/*!< MSDU handle for GPDFs sent from ZGP EP in Direct mode */ -#define ZB_MAC_DIRECT_GPDF_MSDU_HANDLE 0xE1U - - -/** @brief Parameters for data confirm call. */ -typedef ZB_PACKED_PRE struct zb_mcps_data_confirm_params_s -{ - /* Put some data_req parameters into confirm. Confirm call always removes MAC hdr now. */ - zb_addr_u src_addr; /**< Source address */ - zb_addr_u dst_addr; /**< Destination address */ - zb_uint16_t dst_pan_id; /**< Destination Pan ID */ - zb_mac_status_t status; - zb_bitfield_t tx_options:4; /**< Options. @see mac_tx_options_bits. Note: no space for MAC_TX_OPTION_OK_TO_INDIRECT_TRANSMISSION_NOW used internally in non-DSR MAC adopter only */ - zb_bitfield_t src_addr_mode:2; /**< Source address mode, one of @ref address_modes */ - zb_bitfield_t dst_addr_mode:2; /**< Destination address mode, one of @ref address_modes */ - -#ifdef ZB_ENABLE_NWK_RETRANSMIT - zb_uint8_t nwk_retry_cnt; -#endif - zb_uint8_t msdu_handle; /**< MSDU handle value. */ - zb_uint8_t iface_id; -} ZB_PACKED_STRUCT zb_mcps_data_confirm_params_t; - -/** - * @brief MCPS-DATA.request. - * Accepts data request. - * @param param - reference to buffer, contains upper layer data to send. - */ -void zb_mcps_data_request(zb_uint8_t param); - -/** - * @brief MCPS-DATA.indication primitive. - * This function called via scheduler by the MAC layer to pass incoming data packet to the NWK - * layer. - * @note This function must be defined in the NWK layer! MAC layer just calls this - * function. - * @param param - reference to buffer, contains nsdu, the set of octets comprising the NSDU to be - * transferred (with length). - * - * Other fields got from MAC nsdu by macros - */ -void zb_mcps_data_indication(zb_uint8_t param); - -/** - * @brief MCPS-DATA.confirm primitive. - * This function called via scheduler by the MAC layer to pass incoming data packet to the NWK - * layer. - * @note zb_mcps_data_indication() must be defined in the NWK layer! MAC layer just - * calls this function. - * @param param - reference to buffer, contains nsdu - the set of octets comprising the NSDU to be - * transferred (with length). - * - * Other fields got from MAC nsdu by macros. - */ -void zb_mcps_data_confirm(zb_uint8_t param); - -/** @} */ /* MAC data service constants ans API */ - -/** - * @name MAC management service. - * @{ - */ - -/** - * @brief MCPS-POLL.indication primitive. - * This function called via scheduler by the MAC layer to pass information from - * incoming data poll to the NWK layer. - * @note This function must be defined in the NWK layer! MAC layer just calls this function. - * @param param - reference to buffer, contains nsdu, the set of octets comprising the NSDU to be - * transferred (with length). - * - * Other fields got from MAC nsdu by macros - */ -void zb_mcps_poll_indication(zb_uint8_t param); - - -/** @brief Defines MLME-POLL.indication primitive. */ -typedef ZB_PACKED_PRE struct zb_mlme_poll_indication_s -{ - zb_uint16_t addr_mode; - zb_uint16_t dev_addr; -} ZB_PACKED_STRUCT -zb_mlme_poll_indication_t; - - -/** - * Union for constant sized callback type. - * We need such a type in case of architecture split. - */ -#if defined (__ICCARM__) -/* Probably IAR version needs to refine */ -#if (__VER__ > 6040002) /* If iccarm version is fresh than 6.40.2 ---------- */ -ZB_PACKED_PRE -#endif -#elif __CC_ARM -ZB_PACKED_PRE -#endif -union zb_cb_align64_u -{ - zb_uint64_t u64; - zb_callback_t cb; -}; - -/** @brief Defines MLME-GET.request primitive. */ -typedef ZB_PACKED_PRE struct zb_mlme_get_request_s -{ - zb_uint8_t pib_attr; - zb_uint8_t iface_id; - union zb_cb_align64_u confirm_cb_u; -} ZB_PACKED_STRUCT zb_mlme_get_request_t; - -/** @brief Defines MLME-GET.confirm primitive. */ -typedef ZB_PACKED_PRE struct zb_mlme_get_confirm_s -{ - zb_mac_status_t status; - zb_uint8_t pib_attr; - zb_uint8_t iface_id; - zb_uint8_t pib_length; -} ZB_PACKED_STRUCT -zb_mlme_get_confirm_t; - -/** @brief Defines MLME-SET.request primitive. */ -typedef ZB_PACKED_PRE struct zb_mlme_set_request_s -{ - zb_uint8_t pib_attr; - zb_uint8_t iface_id; - zb_uint8_t pib_length; - union zb_cb_align64_u confirm_cb_u; -} ZB_PACKED_STRUCT -zb_mlme_set_request_t; - -/** @brief Defines MLME-SET.confirm primitive. */ -typedef ZB_PACKED_PRE struct zb_mlme_set_confirm_s -{ - zb_mac_status_t status; - zb_uint8_t pib_attr; - zb_uint8_t iface_id; /*!< MAC Interface # */ - ZB_PACKED_PRE union zb_cb_align64_u confirm_cb_u; -} ZB_PACKED_STRUCT zb_mlme_set_confirm_t; - -#if defined ZB_JOINING_LIST_SUPPORT -/* @brief Custom structure for MLME-GET.req when fetching ZB_PIB_ATTRIBUTE_JOINING_IEEE_LIST - * Must be located after zb_mlme_get_request_t. - * At 08/16/17 passing buffer params to MLME-GET.req will cause problems with mac split - */ -typedef ZB_PACKED_PRE struct zb_mlme_get_ieee_joining_list_req_s -{ - zb_uint8_t start_index; - zb_uint8_t count; -} ZB_PACKED_STRUCT -zb_mlme_get_ieee_joining_list_req_t; - -/* @brief to be used as payload for zb_mlme_get_confirm_t */ -typedef ZB_PACKED_PRE struct zb_mlme_get_ieee_joining_list_res_s -{ - zb_uint8_t start_index; - zb_uint8_t total_length; - zb_uint8_t joining_policy; - zb_uint8_t addr_count; -} ZB_PACKED_STRUCT -zb_mlme_get_ieee_joining_list_res_t; - -/* @brief */ -typedef enum zb_mlme_set_ieee_joining_list_req_type_e -{ - ZB_MLME_SET_IEEE_JL_REQ_RANGE = 0, - ZB_MLME_SET_IEEE_JL_REQ_INSERT, - ZB_MLME_SET_IEEE_JL_REQ_ERASE, - ZB_MLME_SET_IEEE_JL_REQ_CLEAR, -} zb_mlme_set_ieee_joining_list_req_type_t; - -typedef ZB_PACKED_PRE struct zb_mlme_set_ieee_joining_list_range_s -{ - zb_uint8_t start_index; /* the first element to be replaced */ - zb_uint8_t items_count; - zb_uint8_t joining_policy; - zb_uint8_t list_size; /* list size to set */ -} ZB_PACKED_STRUCT -zb_mlme_set_ieee_joining_list_range_t; - -typedef ZB_PACKED_PRE struct zb_mlme_set_ieee_joining_list_clear_s -{ - zb_uint8_t joining_policy; /* policy to set on clearing */ -} ZB_PACKED_STRUCT -zb_mlme_set_ieee_joining_list_clear_t; - -/* @brief to be used as payload for zb_mlme_set_request_t */ -typedef ZB_PACKED_PRE struct zb_mlme_set_ieee_joining_list_req_s -{ - zb_uint8_t op_type; /* operation type */ - ZB_PACKED_PRE union - { - zb_mlme_set_ieee_joining_list_range_t range_params; - zb_mlme_set_ieee_joining_list_clear_t clear_params; - zb_ieee_addr_t ieee_value; - } ZB_PACKED_STRUCT param; -} ZB_PACKED_STRUCT -zb_mlme_set_ieee_joining_list_req_t; - -#endif /* ZB_JOINING_LIST_SUPPORT */ - -/** - * @brief MLME-GET.request primitive. - * @param param - reference to the buffer containing request data. - * - * @snippet aib_nib_pib_test/start_ze.c zb_mlme_get_request - * - */ -void zb_mlme_get_request(zb_uint8_t param); - -#ifdef MAC_DIRECT_PIB_ACCESS -/** - * @brief MLME-GET.confirm primitive. - * @param param - reference to the buffer containing operation status information. - */ -void zb_mlme_get_confirm(zb_uint8_t param); -#endif /* MAC_DIRECT_PIB_ACCESS */ - -/** - * @brief MLME-SET.request primitive. - * @param param - reference to the buffer containing request data. - * - * @snippet aib_nib_pib_test/start_ze.c zb_mlme_set_request - * - */ -void zb_mlme_set_request(zb_uint8_t param); - -#if (defined ZB_ZGPD_ROLE && defined ZB_ENABLE_ZGP) || defined MAC_DIRECT_PIB_ACCESS -/** - * @brief MLME-SET.confirm primitive. - * @param param - reference to the buffer containing operation status information. - */ -void zb_mlme_set_confirm(zb_uint8_t param); -#endif /* (ZB_ZGPD_ROLE && ZB_ENABLE_ZGP) || MAC_DIRECT_PIB_ACCESS */ - -/** @brief Parameters for start request. */ -typedef ZB_PACKED_PRE struct zb_mlme_start_req_s -{ - zb_uint8_t iface_id; - zb_uint16_t pan_id; /**< Pan ID */ - zb_uint8_t logical_channel; /**< Logical channel */ - zb_uint8_t channel_page; /**< The channel page to use */ - zb_uint8_t beacon_order; /**< Beacon order */ - zb_uint8_t superframe_order; /**< Superframe order */ - zb_bitfield_t pan_coordinator:1; /**< Is Coordinator */ - zb_bitfield_t battery_life_extension:1; /**< IS Battery life extension */ - zb_bitfield_t coord_realignment:1; /**< */ - zb_bitfield_t reserved:5; /**< Reserved */ -} ZB_PACKED_STRUCT -zb_mlme_start_req_t; - -/** - * @brief Handles start request. - * @param param - reference to buffer, contains zb_mlme_start_req_t parameters for start. - * - */ -void zb_mlme_start_request(zb_uint8_t param); - - -/** - * @brief Confirms start procedure. - * @param param - reference to buffer. - */ -void zb_mlme_start_confirm(zb_uint8_t param); - -/** @brief Parameter for the zb_mlme_reset_request(). */ -typedef ZB_PACKED_PRE struct zb_mlme_reset_request_s -{ - zb_uint8_t set_default_pib; /**< If TRUE, the MAC sublayer is reset, and all MAC PIB - attributes are set to their default values. If FALSE, the - MAC sublayer is reset, but all MAC PIB attributes retain - their values prior to the generation of the - MLME-RESET.request primitive. */ - zb_uint8_t iface_id; -} ZB_PACKED_STRUCT -zb_mlme_reset_request_t; - -/** - * @brief Handles MLME-RESET.request. - * @param param - parameter (packet buffer), see @ref zb_mlme_reset_request_s is on its tail. - */ -void zb_mlme_reset_request(zb_uint8_t param); - -/** @brief Parameter for the zb_mlme_reset_confirm(). */ -typedef ZB_PACKED_PRE struct zb_mlme_reset_confirm_s -{ - zb_uint8_t status; /**< Status */ - zb_uint8_t iface_id; -} ZB_PACKED_STRUCT -zb_mlme_reset_confirm_t; - -/** - * @brief MLME-RESET.confirm. - * This function called by MAC layer via callback. - * @param param - packet buffer. Only its header.status is used. - */ -void zb_mlme_reset_confirm (zb_uint8_t param); - -/** - * @name Possible scan operations - * @anchor mac_scan_type - * - * Note: These values were members of `enum zb_mac_scan_type_e` type but were converted - * to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ED_SCAN 0U /**< ED scan (optional for RFD). */ -#define ACTIVE_SCAN 1U /**< active scan (optional for RFD). */ -#define PASSIVE_SCAN 2U /**< passive scan. */ -#define ORPHAN_SCAN 3U /**< orphan scan. */ -#define ENHANCED_ACTIVE_SCAN 4U /**< enhanced active scan. */ -/** @} */ - -/** - Table 67 MLME-SCAN.request parameters - - Table 67defines more parameters but NWK sends only 3 parameters. - Others should be set by MAC to some constants. - -*/ - -typedef ZB_PACKED_PRE struct -{ - zb_uint8_t scan_type; /**< Indicates the type of scan performed. See @ref mac_scan_type - 0x00 = ED scan (optional for RFD). - 0x01 = active scan (optional for RFD). - 0x02 = passive scan. - 0x03 = orphan scan. - 0x04 = enhanced active scan. - */ - zb_uint8_t scan_duration; /**< A value used to calculate the length of time to - spend scanning each channel for ED, active, - and passive scans. This parameter is ignored for - orphan scans. - The time spent scanning each channel is - [aBaseSuperframeDuration * (2**n + 1)] - symbols, where n is the value of the - ScanDuration parameter. */ - zb_uint8_t channel_page; /**< The channel page on which to perform the scan. */ - zb_uint32_t channels; /**< The 27bits (b , b ,... b ) indicate which - channels are to be scanned (1=scan, 0=do not - scan) for each of the 27 channels supported by - the ChannelPage parameter. */ - zb_uint8_t iface_id; /**< MAC interface index */ -} ZB_PACKED_STRUCT zb_mlme_scan_params_t; - -/** - * @brief Handles scan request. - * @param param - reference to buffer, contains @ref zb_mlme_scan_params_t parameters for scan. - * - * @snippet start_ze_s05.c zb_mlme_scan_request - */ -void zb_mlme_scan_request(zb_uint8_t param); - - -/** - * @brief Confirms scan procedure. - * @param param - reference to buffer. - */ -void zb_mlme_scan_confirm(zb_uint8_t param); - - -void zb_mac_cancel_scan(zb_bufid_t buf); - -void zb_mac_cancel_scan_response(zb_bufid_t buf); - -/** - * @brief Beacon type - */ -typedef enum zb_mac_beacon_type_e -{ - ZB_MAC_BEACON_TYPE_BEACON, - ZB_MAC_BEACON_TYPE_ENHANCED_BEACON -} zb_mac_beacon_type_t; - -/** - * @brief Defines MLME-BEACON-NOTIFY.indication. - * @param bsn - the beacon sequence number (or enhanced beacon sequence number). - * @param pan_descriptor - the Pan Descriptor for the received. - * @param pend_addr_spec - the beacon pending address specification. - * @param addr_list - the list of addresses of the devices for which the beacon source has data. - * @param beacon_type - indicates whether a beacon or an enhanced beacon was received. - * @param sdu_length - the number of octets contained in the beacon payload of the beacon frame - * received by the MAC sublayer. - * @param total_hie_size - the total size of header IEs stored in sdu, in bytes. - * @param total_pie_size - the total size of payload IEs stored in sdu, in bytes. - * - * @param rssi - custom field; used to execute Beacons Survey procedure in WWAH and r23 - * @param sdu - depending on beacon_type: - * - * 1. For beacons: the set of octets comprising the beacon payload to be transferred - * from the MAC sublayer entity to the next higher layer. - * - * 2. For enhanced beacons: the set of octets containing all received IEs: - * first come header IEs - with the total size of total_hie_size - * then come payload IEs - with the total size of total_pie_size - */ -typedef ZB_PACKED_PRE struct zb_mac_beacon_notify_indication_s -{ - zb_uint8_t iface_id; - zb_uint8_t bsn; - zb_pan_descriptor_t pan_descriptor; - zb_pending_address_spec_t pend_addr_spec; - zb_addr_u addr_list[ MAX_PENDING_ADDRESSES ]; - zb_uint8_t ebsn; - zb_mac_beacon_type_t beacon_type; - zb_uint8_t sdu_length; - zb_uint8_t total_hie_size; - zb_uint8_t total_pie_size; - zb_int8_t rssi; - zb_uint8_t sdu[1]; -} ZB_PACKED_STRUCT -zb_mac_beacon_notify_indication_t; - -/** - * @brief MLME-BEACON-NOTIFY.indication primitive. - * This function called via scheduler by the MAC layer to pass incoming beacon indication to the - * NWK layer. - * @note zb_mlme_beacon_notify_indication() must be defined in the NWK layer! MAC - * layer just calls this function. - * @param param - reference to buffer containing @ref zb_mac_beacon_notify_indication_s. - */ -void zb_mlme_beacon_notify_indication(zb_uint8_t param); - -/** - * @brief Data structure for mlme_associate_request. - * Some fields are not set - (set explicitly by MAC): - * @li CoordAddrMode - 3 (64-bit address) - * @li SecurityLevel - ? - * @li KeyIdMode - ? - * @li KeySource - ? - * @li KeyIndex - ? - */ -typedef ZB_PACKED_PRE struct zb_mlme_associate_params_s -{ - zb_uint16_t pan_id; - zb_addr_u coord_addr; - zb_uint8_t coord_addr_mode; - zb_uint8_t channel_page; - zb_uint8_t logical_channel; - zb_mac_capability_info_t capability; -} ZB_PACKED_STRUCT - zb_mlme_associate_params_t; - -/** - * @brief Builds MLME-ASSOCIATE request. This request allows a device to request an association - * with a coordinator. - * @param buf - pointer to @ref zb_buf_t. - * @param _channel_page - the channel page on which to attempt association. - * @param _logical_channel - selected from the available logical channels supported by the PHY. - * @param coord_PAN_id - the identifier of the PAN with which to associate. - * @param addr_mode - ZB_ADDR_16BIT_DEV_OR_BROADCAST or ZB_ADDR_64BIT_DEV. See @ref address_modes. - * @param p_address - pointer of the address of the coordinator with which to associate, Suppose - * 64-bit address mode. - * @param _capability - zb_mac_capability_info_t struct. Specifies the operational capabilities of - * the associating device. - * - * snippet association_04_rfd.c ZB_MLME_BUILD_ASSOCIATE_REQUEST - */ -#define ZB_MLME_BUILD_ASSOCIATE_REQUEST( buf, \ - _channel_page, \ - _logical_channel, \ - coord_PAN_id, \ - addr_mode, \ - p_address, \ - _capability) \ -do \ -{ \ - zb_mlme_associate_params_t *_p = (zb_mlme_associate_params_t *)ZB_BUF_GET_PARAM((buf), zb_mlme_associate_params_t); \ - _p->channel_page = (_channel_page); \ - _p->logical_channel = (_logical_channel); \ - _p->pan_id = (coord_PAN_id); \ - _p->coord_addr_mode = (addr_mode); \ - if ((addr_mode) == ZB_ADDR_64BIT_DEV) \ - { \ - ZB_IEEE_ADDR_COPY(_p->coord_addr.addr_long, (p_address)); \ - } \ - else \ - { \ - ZB_MEMCPY(&_p->coord_addr.addr_short, (p_address), sizeof(zb_uint16_t)); \ - } \ - _p->capability = ( _capability ); \ -} while( 0 ) - -/** - * @brief Defines struct for indication of associate request. - * @param device_address - IEEE 64bit address. - * @param capability - @ref zb_mac_capability_info_t struct. Specifies the operational - * capabilities of the associating device. - */ -typedef ZB_PACKED_PRE struct zb_mlme_associate_indication_s -{ - zb_uint8_t iface_id; - zb_ieee_addr_t device_address; - zb_mac_capability_info_t capability; - zb_uint8_t lqi; /* non-standard, but MAC has it and we really - * need it */ -} ZB_PACKED_STRUCT zb_mlme_associate_indication_t; - -/** - * @brief MLME-COMM-STATUS.indication data structure. - * Not all fields included. - * - * Currently used after MLME-ASSOCIATE.response only. - * When will be used for MLME-ORPHAN.response, maybe, will add some fields. - */ -typedef ZB_PACKED_PRE struct zb_mlme_associate_response_s -{ - zb_ieee_addr_t device_address; - zb_uint16_t short_address; - zb_uint8_t status; -} ZB_PACKED_STRUCT -zb_mlme_associate_response_t; - -/** - * @brief Builds MLME-ASSOCIATE response. - * @param buf - pointer to @ref zb_buf_t. - * @param p_address - pointer to the extended 64-bit IEEE address of the coordinator with which - * to associate, size of address depends on coord_addr_mode parameter. - * @param short_addr - 16-bit short device address allocated by the coordinator on successful - * association. This parameter is set to 0xffff if the association was unsuccessful. - * @param st - one of values of @ref mac_status. - * - * @snippet data_01_ffd.c ZB_MLME_BUILD_ASSOCIATE_RESPONSE - */ -#define ZB_MLME_BUILD_ASSOCIATE_RESPONSE( buf, \ - p_address, \ - short_addr, \ - st) \ - do \ - { \ - zb_mlme_associate_response_t *p = (zb_mlme_associate_response_t *)ZB_BUF_GET_PARAM((buf), zb_mlme_associate_response_t); \ - ZB_IEEE_ADDR_COPY(p->device_address, (p_address)); \ - p->short_address = (short_addr); \ - p->status = (st); \ - } \ - while( 0 ) - -/** - * @brief Defines structure for MLME-ASSOCIATE confirm primitive. - * @param assoc_short_address - the short device address allocated by the coordinator on successful - * association. This parameter will be equal to 0xffff if the association attempt was - * unsuccessful. - * @param status - the status of the association attempt (value from @ref mac_status). - */ -typedef ZB_PACKED_PRE struct zb_mlme_associate_confirm_s -{ - zb_uint16_t assoc_short_address; - zb_mac_status_t status; - /* more fields (will it be used?): - SecurityLevel - KeyIdMode - KeySource - KeyIndex - */ - zb_ieee_addr_t parent_address; /* non-standard field, but we really need it */ -} ZB_PACKED_STRUCT zb_mlme_associate_confirm_t; - -/** - * @brief Returns pointer to @ref zb_mlme_associate_confirm_s structure located somewhere in buf. - * @param buf - pointer to @ref zb_buf_t container. - * @param outptr - out pointer to @ref zb_mlme_associate_confirm_s struct located somewhere inside - * buf. - */ -#define ZB_MLME_GET_ASSOCIATE_CONFIRM_PTR( buf, outptr ) \ - do \ - { \ - } while( 0 ) - -/** - * @brief Handle MLME-ASSOCIATION.request. - * @param param - reference to buffer, contains @ref zb_mlme_associate_params_t parameters. - * - * @snippet association_04_rfd.c ZB_MLME_BUILD_ASSOCIATE_REQUEST - */ -void zb_mlme_associate_request(zb_uint8_t param); - -/** - * @brief Associate response - coordinator side. - * Send response to device. - * @param param - reference to buffer. - * - * @snippet data_01_ffd.c ZB_MLME_BUILD_ASSOCIATE_RESPONSE - */ -void zb_mlme_associate_response(zb_uint8_t param); - -void zb_mlme_associate_indication(zb_uint8_t param); - -void zb_mlme_associate_confirm(zb_uint8_t param); - -/** @brief Parameters for poll indication. */ -typedef ZB_PACKED_PRE struct zb_mcps_poll_indication_param_s -{ - zb_uint8_t iface_id; -} ZB_PACKED_STRUCT zb_mcps_poll_indication_param_t; - -/** @brief Parameters for poll request. */ -typedef ZB_PACKED_PRE struct zb_mlme_poll_request_s -{ - zb_uint8_t coord_addr_mode; /**< */ - zb_addr_u coord_addr; /**< */ - zb_uint16_t coord_pan_id; /**< */ - zb_time_t poll_rate; -} ZB_PACKED_STRUCT - zb_mlme_poll_request_t; - -/** - * @brief Handles MLME-poll.confirm. - * @param param - parameter (packet buffer), with poll status. - */ -void zb_mlme_poll_confirm(zb_uint8_t param); - -void zb_mlme_poll_request(zb_uint8_t param); - -/** - * @brief Sync loss reasons. - * The reason that synchronization was lost. - */ - -#define ZB_SYNC_LOSS_REASON_PAN_ID_CONFLICT 0U -#define ZB_SYNC_LOSS_REASON_REALIGNMENT 1U -#define ZB_SYNC_LOSS_REASON_BEACON_LOST 2U - -/** @brief Parameters for sync loss indication. */ -typedef ZB_PACKED_PRE struct zb_mlme_sync_loss_ind_s -{ - zb_uint16_t pan_id; /* Pan ID with which the device lost - * synchronization or to which it was realigned */ - zb_uint8_t loss_reason; /* Lost synchronization reason */ - zb_uint8_t logical_channel; /* Logical channel */ - zb_uint8_t channel_page; /* Channel page */ -} ZB_PACKED_STRUCT - zb_mlme_sync_loss_ind_t; - -/** - * @brief MLME-COMM-STATUS.indication data structure. - * Not all fields included. - * - * Currently used after MLME-ASSOCIATE.response only. - * When will be used for MLME-ORPHAN.response, maybe, will add some fields. - */ -typedef ZB_PACKED_PRE struct zb_mlme_comm_status_indication_s -{ - zb_addr_u src_addr; /**< The individual device address of the entity from which the frame - causing the error originated. */ - zb_uint8_t src_addr_mode; - zb_addr_u dst_addr; /**< The individual device address of the device for which the frame - was intended */ - zb_uint8_t dst_addr_mode; - zb_mac_status_t status; /**< The communications status. - SUCCESS, - TRANSACTION_OVERFLOW, - TRANSACTION_EXPIRED, - CHANNEL_ACCESS_FAILURE, - NO_ACK, COUNTER_ERROR, - FRAME_TOO_LONG, - IMPROPER_KEY_TYPE, - IMPROPER_SECURITY_LEVEL, - SECURITY_ERROR, - UNAVAILABLE_KEY, - UNSUPPORTED_LEGACY, - UNSUPPORTED_SECURITY or - INVALID_PARAMETER - */ - zb_uint16_t pan_id; /* 16-bit Pan ID of the device from which the frame was - received or to which the frame was being sent. */ - zb_bool_t is_orphaning; -} ZB_PACKED_STRUCT -zb_mlme_comm_status_indication_t; - -void zb_mlme_comm_status_indication(zb_uint8_t param); - -#ifdef ZB_MAC_DUTY_CYCLE_MONITORING - -typedef zb_uint8_t zb_mac_duty_cycle_status_t; -#define ZB_MAC_DUTY_CYCLE_STATUS_NORMAL 0U -#define ZB_MAC_DUTY_CYCLE_STATUS_LIMITED 1U -#define ZB_MAC_DUTY_CYCLE_STATUS_CRITICAL 2U -#define ZB_MAC_DUTY_CYCLE_STATUS_SUSPENDED 3U - -/** @brief Defines MLME-DUTY_CYCLE-MODE.indication primitive. */ -typedef ZB_PACKED_PRE struct zb_mlme_duty_cycle_mode_indication_s -{ - zb_uint8_t status; /**< Current MAC Duty Cycle mode: @ref - * zb_mac_duty_cycle_status_t value */ -} ZB_PACKED_STRUCT zb_mlme_duty_cycle_mode_indication_t; - - -/** @brief MLME-DUTY-CYCLE-MODE.indication primitive. - * @details This function is called via scheduler by the MAC layer to pass Duty Cycle mode change - * to the NWK layer. Note that zb_mlme_duty_cycle_mode_indication() must be defined at the NWK layer! - * MAC layer just calls this function. - * @param param - reference to the buffer containing Duty Cycle mode value. - */ -void zb_mlme_duty_cycle_mode_indication(zb_uint8_t param); - -zb_uint_t zb_mac_duty_cycle_get_time_period_sec(void); - -#endif /* ZB_MAC_DUTY_CYCLE_MONITORING */ - -#if defined ZB_MAC_POWER_CONTROL -typedef ZB_PACKED_PRE struct zb_mac_power_ctrl_info_tbl_ent_s -{ - zb_uint16_t short_addr; - zb_ieee_addr_t ieee_addr; - zb_int8_t tx_power; /* TX power level */ - zb_int8_t last_rssi; /* Last RSSI level */ - zb_bool_t nwk_negotiated; /* NWK negotiated */ -} ZB_PACKED_STRUCT zb_mac_power_ctrl_info_tbl_ent_t; - -typedef ZB_PACKED_PRE struct zb_mlme_get_power_info_tbl_req_s -{ - zb_uint16_t short_addr; - zb_ieee_addr_t ieee_addr; -} ZB_PACKED_STRUCT zb_mlme_get_power_info_tbl_req_t; - -/*! -* Optimal signal level should be +20dB above the reference sensitivity -* @ref ZB_EU_FSK_REFERENCE_SENSITIVITY -* @ref ZB_NA_FSK_REFERENCE_SENSITIVITY -* -* See reference document 20-66955-016 section D.9.2.4.2. Zigbee Specification -*/ -#define ZB_MAC_POWER_CONTROL_OPT_SIGNAL_LEVEL(page) \ - ((ZB_LOGICAL_PAGE_IS_SUB_GHZ_NA_FSK(page) ? (ZB_NA_FSK_REFERENCE_SENSITIVITY) : (ZB_EU_FSK_REFERENCE_SENSITIVITY)) + 20) - -/* [VK]: Get/set power information table req/conf functions - * were renamed not to trigger MISRAC2012-Rule-5.1: - * The external identifier 'func_name' clashes with other - * identifier(s) in the first 31 characters 1 time(s). - */ -void zb_mlme_get_power_info_table_request(zb_uint8_t param); - -typedef ZB_PACKED_PRE struct zb_mlme_get_power_info_tbl_conf_s -{ - zb_uint8_t status; - zb_mac_power_ctrl_info_tbl_ent_t ent; -} ZB_PACKED_STRUCT zb_mlme_get_power_info_tbl_conf_t; - -void zb_mlme_get_power_info_table_confirm(zb_uint8_t param); - -typedef ZB_PACKED_PRE struct zb_mlme_set_power_info_tbl_req_s -{ - zb_mac_power_ctrl_info_tbl_ent_t ent; -} ZB_PACKED_STRUCT zb_mlme_set_power_info_tbl_req_t; - -void zb_mlme_set_power_info_table_request(zb_uint8_t param); - -typedef ZB_PACKED_PRE struct zb_mlme_set_power_info_tbl_conf_s -{ - zb_uint8_t status; -} ZB_PACKED_STRUCT zb_mlme_set_power_info_tbl_conf_t; - -void zb_mlme_set_power_info_table_confirm(zb_uint8_t param); - -#endif /* ZB_MAC_POWER_CONTROL */ - -/** @} */ /* MAC management service. */ - -/** @} */ - - -/** @cond internals_doc */ -/** \addtogroup ZB_MAC */ -/** @{ */ - -/** - Parameters for realignment command, mac spec 7.3.8 Coordinator -*/ -typedef ZB_PACKED_PRE struct zb_coord_realignment_cmd_s -{ - /* MHR fields - are not described here */ - zb_uint8_t cmd_frame_id; /**< Command Frame Identifier == 0x08*/ - zb_uint16_t pan_id; /**< Pan ID */ - zb_uint16_t coord_short_addr; /**< Coordinator Short Address */ - zb_uint8_t logical_channel; /**< Logical Channel */ - zb_uint16_t short_addr; /**< Short Address */ -#if (MAC_FRAME_VERSION > MAC_FRAME_IEEE_802_15_4_2003) - zb_uint8_t channel_page; /**< Channel page, may be omitted */ -#endif -} ZB_PACKED_STRUCT -zb_coord_realignment_cmd_t; - - -/** - Parser MAC header. - - mac spec 7.2.1 General MAC frame format - @note Actually MHR is of variable length and this structure can't - be used for physical data i/o, it is used only for function calls. -*/ -typedef struct zb_mac_mhr_s -{ - zb_addr_u dst_addr; /**< */ - zb_addr_u src_addr; /**< */ - zb_uint16_t src_pan_id; /**< */ - zb_uint16_t dst_pan_id; /**< */ - zb_uint8_t frame_control[2]; /**< */ - zb_uint8_t seq_number; /**< */ - zb_uint8_t mhr_len; /**< */ - -#ifdef ZB_MAC_SECURITY - zb_uint8_t security_level; - zb_uint8_t key_id_mode; - zb_uint8_t key_source[8]; - zb_uint8_t key_index; - zb_uint32_t frame_counter; -#endif - -} - zb_mac_mhr_t; - -/** - Parameters for sending beacon frame -*/ -typedef struct zb_beacon_frame_params_s -{ - zb_uint8_t src_addr_mode; /**< */ - zb_uint8_t security_enabled; /**< */ - zb_uint8_t frame_pending; /**< */ - zb_uint8_t ble; /**< */ - zb_uint8_t beacon_order; /**< */ - zb_uint8_t superframe_order; /**< */ -} - zb_beacon_frame_params_t; - -/** - Parameters for sending data request -*/ -typedef enum zb_callback_type_e -{ - MAC_ASS_CONFIRM_CALLBACK = 0, /**< */ - MAC_POLL_REQUEST_CALLBACK = 1 /**< */ -} - zb_callback_type_t; - -typedef struct zb_mlme_data_req_params_s -{ - zb_uint8_t src_addr_mode; /**< Source address mode */ - zb_uint8_t dst_addr_mode; /**< Destination address mode */ - zb_addr_u src_addr; /**< Source address */ - zb_addr_u dst_addr; /**< Destination address */ - zb_callback_type_t cb_type; /**< Callback for mlme-data-request function */ -} - zb_mlme_data_req_params_t; - -/* Moved zb_mac_pending_data_t to zboss_api_internal.h */ - -/** - Parameters for orphan indication -*/ -typedef struct zb_mac_orphan_ind_s -{ - zb_ieee_addr_t orphan_addr; /*= 2 - zb_uint8_t logical_channel[ZB_NWK_MAC_IFACE_TBL_SIZE - 1]; /**< Logical channel */ - zb_uint8_t channel_page[ZB_NWK_MAC_IFACE_TBL_SIZE - 1]; /**< The channel page to use */ -#endif -} ZB_PACKED_STRUCT -zb_mlme_multimac_start_req_t; - -#if defined ZB_ALIEN_MAC || defined ZB_NSNG - -#define ZB_TRANSCEIVER_TIME_SUBTRACT ZB_TIME_SUBTRACT - -#else - -zb_time_t osif_sub_trans_timer(zb_time_t t2, zb_time_t t1); -#define ZB_TRANSCEIVER_TIME_SUBTRACT osif_sub_trans_timer - -#endif - -#ifdef ZB_ENABLE_ZGP -void zb_gp_mcps_data_indication(zb_uint8_t param); -#endif /* ZB_ENABLE_ZGP */ - -#ifdef ZB_MAC_CONFIGURABLE_TX_POWER - -typedef zb_ret_t (*zb_tx_power_provider_t)(zb_uint8_t page, zb_uint8_t channel, zb_int8_t *power_dbm); - -void zb_mac_set_tx_power_provider_function(zb_tx_power_provider_t new_provider); -void zb_mac_set_tx_power_async_confirm(zb_bufid_t param); -void zb_mac_get_tx_power_async_confirm(zb_bufid_t param); - -/** - * @brief Update transceiver power for each page and channel synchronously according to power provider. -*/ -void zb_mac_update_channel_pages(void); - -#endif /* #ifdef ZB_MAC_CONFIGURABLE_TX_POWER */ - -/** - * @name Type of indirect queue purge request - * @anchor mcps_purge_indir_q_type - * - * Note: These values were members of `enum zb_mcps_purge_indir_q_type_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_MCPS_INDIR_Q_PURGE_TYPE_NONE 0U -#define ZB_MCPS_INDIR_Q_PURGE_TYPE_ASSOCIATION 1U -#define ZB_MCPS_INDIR_Q_PURGE_TYPE_REJOIN 2U -/** @} */ - -#if !defined ZB_LITE_NO_INDIRECT_QUEUE_PURGE - -typedef ZB_PACKED_PRE struct zb_mcps_purge_indir_q_req_s -{ - zb_uint8_t type; - zb_uint16_t short_addr; - zb_ieee_addr_t ieee_addr; -} ZB_PACKED_STRUCT zb_mcps_purge_indir_q_req_t; - -typedef ZB_PACKED_PRE struct zb_mcps_purge_indir_q_conf_s -{ - zb_mac_status_t status; - zb_uint8_t type; -} ZB_PACKED_STRUCT zb_mcps_purge_indir_q_conf_t; - -void zb_mcps_purge_indirect_queue_request(zb_uint8_t param); - -void zb_mcps_purge_indirect_queue_confirm(zb_uint8_t param); - -#endif - - -#if defined ZB_TRAFFIC_DUMP_ON && !defined ZB_TRANSPORT_OWN_TRAFFIC_DUMP_ON -#include "zb_mac_transport.h" -#define ZB_DUMP_IFACE_DEFAULT ZB_DUMP_IFACE_ZIGBEE -void zb_mac_traffic_dump_no_buf(zb_uint8_t* data, zb_uint8_t len, zb_bool_t is_w, zb_uint8_t interface_type, zb_uint8_t interface_id); -void zb_mac_traffic_dump(zb_bufid_t buf, zb_bool_t is_w, zb_uint8_t interface_type, zb_uint8_t interface_id); -#if defined ZB_MULTIMAC -#define ZB_DUMP_INCOMING_DATA(buf, iface_type, iface_id) zb_mac_traffic_dump((buf), ZB_FALSE, iface_type, iface_id) -#define ZB_DUMP_OUTGOING_DATA(buf, iface_type, iface_id) zb_mac_traffic_dump((buf), ZB_TRUE, iface_type, iface_id) -#else -#define zb_mac_dump_mac_ack(is_out, data_pending, dsn) zb_mac_dump_mac_ack_iface(is_out, data_pending, dsn, ZB_DUMP_IFACE_DEFAULT, 0) -#define ZB_DUMP_INCOMING_DATA(buf) zb_mac_traffic_dump((buf), ZB_FALSE, ZB_DUMP_IFACE_DEFAULT, 0) -#define ZB_DUMP_OUTGOING_DATA(buf) zb_mac_traffic_dump((buf), ZB_TRUE, ZB_DUMP_IFACE_DEFAULT, 0) -#endif -#else -#define ZB_DUMP_INCOMING_DATA(buf) ZVUNUSED(buf) -#define ZB_DUMP_OUTGOING_DATA(buf) ZVUNUSED(buf) -#endif - -void mac_clear_filters(void); - -/** - Check whether a frame is a broadcast frame -*/ -zb_bool_t zb_mac_check_frame_is_broadcast(const zb_mac_mhr_t *mhr); - -/** - Check destination address of a frame -*/ -zb_bool_t zb_mac_check_frame_dst_addr(const zb_mac_mhr_t *mhr); - -/** - Check destination PAN ID of a frame -*/ -zb_bool_t zb_mac_check_frame_pan_id(const zb_mac_mhr_t *mhr); - -#ifdef ZB_PHY_TESTING_MODE - -/** - * Validate received packet buffer in PHY Testing mode - */ -void zb_mac_phy_testing_rx_data_indication_cb(zb_uint8_t param); - -/** - * Handle PHY Testing mode request - */ -void zb_mac_phy_testing_mode_request(zb_bufid_t param); - -/** - * Handle PHY Testing mode statistics request - */ -void zb_mac_phy_testing_mode_statistics_request(zb_bufid_t param); - -/** - * Handle tx_done event in PHY Testing mode - */ -void zb_mac_phy_testing_tx_done(void); - -/* - * Notify upper layer that the transceiver entered the PHY testing mode - * or that the test has finished. -*/ -void zb_mac_phy_testing_mode_notification(zb_bufid_t param); - -#endif - - -#if defined ZB_MAC_API_TRACE_PRIMITIVES - -/* MAC API trace functions */ -void zb_mac_api_trace_association_request(zb_uint8_t param); -void zb_mac_api_trace_association_response(zb_uint8_t param); -void zb_mac_api_trace_association_confirm(zb_uint8_t param); -void zb_mac_api_trace_association_indication(zb_uint8_t param); -void zb_mac_api_trace_reset_request(zb_uint8_t param); -void zb_mac_api_trace_reset_confirm(zb_uint8_t param); -void zb_mac_api_trace_beacon_notify_indication(zb_uint8_t param); -void zb_mac_api_trace_comm_status_indication(zb_uint8_t param); -void zb_mac_api_trace_orphan_indication(zb_uint8_t param); -void zb_mac_api_trace_orphan_response(zb_uint8_t param); -void zb_mac_api_trace_scan_request(zb_uint8_t param); -void zb_mac_api_trace_scan_confirm(zb_uint8_t param); -void zb_mac_api_trace_poll_request(zb_uint8_t param); -void zb_mac_api_trace_poll_confirm(zb_uint8_t param); -void zb_mac_api_trace_start_request(zb_uint8_t param); -void zb_mac_api_trace_start_confirm(zb_uint8_t param); -void zb_mac_api_trace_set_request(zb_uint8_t param); -void zb_mac_api_trace_set_confirm(zb_uint8_t param); -void zb_mac_api_trace_purge_request(zb_uint8_t param); -void zb_mac_api_trace_purge_confirm(zb_uint8_t param); -void zb_mac_api_trace_data_request(zb_uint8_t param); -void zb_mac_api_trace_data_confirm(zb_uint8_t param); -void zb_mac_api_trace_data_indication(zb_uint8_t param); -void zb_mac_api_trace_get_request(zb_uint8_t param); -void zb_mac_api_trace_get_confirm(zb_uint8_t param); -void zb_mac_api_trace_cca_confirm(zb_uint8_t param); - -#endif /* ZB_MAC_API_TRACE_PRIMITIVES */ - -#ifdef ZB_MAC_API_TRACE_PRIMITIVES - -#define ZB_MAC_API_TRACE_ASSOCIATION_REQUEST(param) zb_mac_api_trace_association_request(param) -#define ZB_MAC_API_TRACE_ASSOCIATION_CONFIRM(param) zb_mac_api_trace_association_confirm(param) -#define ZB_MAC_API_TRACE_ASSOCIATION_INDICATION(param) zb_mac_api_trace_association_indication(param) -#define ZB_MAC_API_TRACE_ASSOCIATION_RESPONSE(param) zb_mac_api_trace_association_response(param) -#define ZB_MAC_API_TRACE_START_REQUEST(param) zb_mac_api_trace_start_request(param) -#define ZB_MAC_API_TRACE_START_CONFIRM(param) zb_mac_api_trace_start_confirm(param) -#define ZB_MAC_API_TRACE_ORPHAN_RESPONSE(param) zb_mac_api_trace_orphan_response(param) -#define ZB_MAC_API_TRACE_ORPHAN_INDICATION(param) zb_mac_api_trace_orphan_indication(param) -#define ZB_MAC_API_TRACE_COMM_STATUS_INDICATION(param) zb_mac_api_trace_comm_status_indication(param) -#define ZB_MAC_API_TRACE_BEACON_NOTIFY_INDICATION(param) zb_mac_api_trace_beacon_notify_indication(param) -#define ZB_MAC_API_TRACE_PURGE_REQUEST(param) zb_mac_api_trace_purge_request(param) -#define ZB_MAC_API_TRACE_PURGE_CONFIRM(param) zb_mac_api_trace_purge_confirm(param) -#define ZB_MAC_API_TRACE_DATA_REQUEST(param) zb_mac_api_trace_data_request(param) -#define ZB_MAC_API_TRACE_DATA_CONFIRM(param) zb_mac_api_trace_data_confirm(param) -#define ZB_MAC_API_TRACE_DATA_INDICATION(param) zb_mac_api_trace_data_indication(param) -#define ZB_MAC_API_TRACE_POLL_REQUEST(param) zb_mac_api_trace_poll_request(param) -#define ZB_MAC_API_TRACE_POLL_CONFIRM(param) zb_mac_api_trace_poll_confirm(param) -#define ZB_MAC_API_TRACE_GET_REQUEST(param) zb_mac_api_trace_get_request(param) -#define ZB_MAC_API_TRACE_GET_CONFIRM(param) zb_mac_api_trace_get_confirm(param) -#define ZB_MAC_API_TRACE_SET_REQUEST(param) zb_mac_api_trace_set_request(param) -#define ZB_MAC_API_TRACE_SET_CONFIRM(param) zb_mac_api_trace_set_confirm(param) -#define ZB_MAC_API_TRACE_SCAN_REQUEST(param) zb_mac_api_trace_scan_request(param) -#define ZB_MAC_API_TRACE_SCAN_CONFIRM(param) zb_mac_api_trace_scan_confirm(param) -#define ZB_MAC_API_TRACE_RESET_REQUEST(param) zb_mac_api_trace_reset_request(param) -#define ZB_MAC_API_TRACE_RESET_CONFIRM(param) zb_mac_api_trace_reset_confirm(param) -#define ZB_MAC_API_TRACE_CCA_CONFIRM(param) zb_mac_api_trace_cca_confirm(param) - -#else - -#define ZB_MAC_API_TRACE_ASSOCIATION_REQUEST(param) -#define ZB_MAC_API_TRACE_ASSOCIATION_CONFIRM(param) -#define ZB_MAC_API_TRACE_ASSOCIATION_INDICATION(param) -#define ZB_MAC_API_TRACE_ASSOCIATION_RESPONSE(param) -#define ZB_MAC_API_TRACE_START_REQUEST(param) -#define ZB_MAC_API_TRACE_START_CONFIRM(param) -#define ZB_MAC_API_TRACE_ORPHAN_RESPONSE(param) -#define ZB_MAC_API_TRACE_ORPHAN_INDICATION(param) -#define ZB_MAC_API_TRACE_COMM_STATUS_INDICATION(param) -#define ZB_MAC_API_TRACE_BEACON_NOTIFY_INDICATION(param) -#define ZB_MAC_API_TRACE_PURGE_REQUEST(param) -#define ZB_MAC_API_TRACE_PURGE_CONFIRM(param) -#define ZB_MAC_API_TRACE_DATA_REQUEST(param) -#define ZB_MAC_API_TRACE_DATA_CONFIRM(param) -#define ZB_MAC_API_TRACE_DATA_INDICATION(param) -#define ZB_MAC_API_TRACE_POLL_REQUEST(param) -#define ZB_MAC_API_TRACE_POLL_CONFIRM(param) -#define ZB_MAC_API_TRACE_GET_REQUEST(param) -#define ZB_MAC_API_TRACE_GET_CONFIRM(param) -#define ZB_MAC_API_TRACE_SET_REQUEST(param) -#define ZB_MAC_API_TRACE_SET_CONFIRM(param) -#define ZB_MAC_API_TRACE_SCAN_REQUEST(param) -#define ZB_MAC_API_TRACE_SCAN_CONFIRM(param) -#define ZB_MAC_API_TRACE_RESET_REQUEST(param) -#define ZB_MAC_API_TRACE_RESET_CONFIRM(param) -#define ZB_MAC_API_TRACE_CCA_CONFIRM(param) - -#endif /* ZB_MAC_API_TRACE_PRIMITIVES */ - -#if defined ZB_MAC_DIAGNOSTICS - -typedef ZB_PACKED_PRE struct zb_mac_diagnostic_ent_s -{ - zb_uint16_t mac_tx_ucast_total; /* Total number of Mac Tx Transactions to - * attempt to send a message (but not - * counting retries) */ - zb_uint16_t mac_tx_ucast_failures; /* Total number of failed Tx - * Transactions. So if the Mac send a - * single packet, it will be retried 4 - * times without ack, that counts as 1 failure */ - zb_uint16_t mac_tx_ucast_retries; /* Total number of Mac Retries regardless of - * whether the transaction resulted in - * success or failure. */ -} ZB_PACKED_STRUCT -zb_mac_diagnostic_ent_t; - -typedef ZB_PACKED_PRE struct zb_mac_diagnostic_ctx_s -{ - zb_mac_diagnostic_ent_t filter[ZB_MAC_DIAGNOSTICS_FILTER_SIZE]; - zb_uint32_t mac_rx_bcast; /* A counter that is incremented each time - * the MAC layer receives a broadcast. */ - zb_uint32_t mac_tx_bcast; /* A counter that is incremented each time - * the MAC layer transmits a broadcast. */ - zb_uint32_t mac_rx_ucast; /* A counter that is incremented each time the - * MAC layer receives a unicast. */ - - zb_uint32_t mac_tx_for_aps_messages; /* Counter used to calculate average_mac_retry_per_aps_message_sent */ - - /* These 3 counters are required not to break - * ZDO channel management logic that - * uses normalized counters values. - */ - zb_uint32_t mac_tx_ucast_total_zcl; /* The same as mac_tx_ucast_total, but non-normalized */ - zb_uint16_t mac_tx_ucast_failures_zcl; /* The same as mac_tx_ucast_failures, but non-normalized */ - zb_uint16_t mac_tx_ucast_retries_zcl; /* The same as mac_tx_ucast_retries, but non-normalized*/ - - zb_uint16_t phy_to_mac_que_lim_reached; /* A counter that is incremented each time - * when MAC RX queue if full. */ - - zb_uint16_t mac_validate_drop_cnt; /* How many times the packet was dropped at the packet - * validation stage for length or bad formatting. */ - - zb_uint16_t phy_cca_fail_count; /* Number of the PHY layer was unable - * to transmit due to a failed CCA */ - - zb_uint8_t last_msg_lqi; /* LQI value of the last received packet */ - zb_int8_t last_msg_rssi; /* RSSI value of the last received packet */ - zb_bitfield_t write_idx:4; /* Index of the current bucket */ - zb_bitfield_t written:4; /* Number of used buckets of the filter */ -} ZB_PACKED_STRUCT -zb_mac_diagnostic_ctx_t; - - -void zb_mac_diagnostics_init(zb_mac_diagnostic_ctx_t *ctx); -void zb_mac_diagnostics_periodic_handler(zb_uint8_t unused); -void zb_mac_diagnostics_get_info(zb_mac_diagnostic_ex_info_t *diag_info); -void zb_mac_diagnostics_cleanup_info(void); -void zb_mac_diagnostics_inc_tx_total(void); -void zb_mac_diagnostics_inc_tx_failed(void); -void zb_mac_diagnostics_inc_tx_retry(void); -void zb_mac_diagnostics_inc_tx_bcast(void); -void zb_mac_diagnostics_inc_rx_que_full(zb_uint8_t counts); -void zb_mac_diagnostics_inc_validate_drop_cnt(void); -void zb_mac_diagnostics_inc_phy_cca_fail(void); -void zb_mac_diagnostics_inc_tx_for_aps_messages(void); -void zb_mac_update_rx_zcl_diagnostic(zb_mac_mhr_t *mhr, zb_bufid_t buf); - -#define ZB_MAC_DIAGNOSTIC_UNICAST_TX_TOTAL_INC() zb_mac_diagnostics_inc_tx_total() -#define ZB_MAC_DIAGNOSTIC_UNICAST_TX_FAILED_INC() zb_mac_diagnostics_inc_tx_failed() -#define ZB_MAC_DIAGNOSTIC_UNICAST_TX_RETRY_INC() zb_mac_diagnostics_inc_tx_retry() -#define ZB_MAC_DIAGNOSTIC_BCAST_TX_TOTAL_INC() zb_mac_diagnostics_inc_tx_bcast() -#define ZB_MAC_UPDATE_RX_ZCL_DIAGNOSTIC(mhr, buf) zb_mac_update_rx_zcl_diagnostic((mhr), (buf)) -#define ZB_MAC_DIAGNOSTICS_RX_QUE_FULL_INC(counts) zb_mac_diagnostics_inc_rx_que_full((counts)) -#define ZB_MAC_DIAGNOSTICS_VALIDATE_DROP_CNT_INC() zb_mac_diagnostics_inc_validate_drop_cnt() -#define ZB_MAC_DIAGNOSTICS_PHY_CCA_FAIL_INC() zb_mac_diagnostics_inc_phy_cca_fail() -#define ZB_MAC_DIAGNOSTICS_INC_TX_FOR_APS_MESSAGES() zb_mac_diagnostics_inc_tx_for_aps_messages() - -#else - -#define ZB_MAC_DIAGNOSTIC_UNICAST_TX_TOTAL_INC() -#define ZB_MAC_DIAGNOSTIC_UNICAST_TX_FAILED_INC() -#define ZB_MAC_DIAGNOSTIC_UNICAST_TX_RETRY_INC() -#define ZB_MAC_DIAGNOSTIC_BCAST_TX_TOTAL_INC() -#define ZB_MAC_UPDATE_RX_ZCL_DIAGNOSTIC(mhr, buf) -#define ZB_MAC_DIAGNOSTICS_RX_QUE_FULL_INC(counts) -#define ZB_MAC_DIAGNOSTICS_VALIDATE_DROP_CNT_INC() -#define ZB_MAC_DIAGNOSTICS_PHY_CCA_FAIL_INC() -#define ZB_MAC_DIAGNOSTICS_INC_TX_FOR_APS_MESSAGES() - -#endif /* ZB_MAC_DIAGNOSTICS */ - -#ifndef ZB_MAC_MAX_PTA_OPTIONS_LEN -#define ZB_MAC_MAX_PTA_OPTIONS_LEN 127u -#endif - -#endif /* ZB_MAC_API_INCLUDED */ diff --git a/zboss/development/src/include/zb_mac_transport.h b/zboss/development/src/include/zb_mac_transport.h deleted file mode 100644 index be62447e2a..0000000000 --- a/zboss/development/src/include/zb_mac_transport.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: MAC and trace transport API - -*/ - -#ifndef MAC_TRANSPORT_H -#define MAC_TRANSPORT_H 1 - -/*! @cond internals_doc */ -/*! \addtogroup ZB_MAC_TRANSPORT */ -/*! @{ */ - - -/* - That file is mostly historical. - Initially it described some serial protocol. - Now it describes traffic dump format. -*/ - -/** - Packet types. - - This enum describes possible packet types to be transferred through pipes. - */ -typedef enum zb_mac_transport_type_e -{ - ZB_MAC_TRANSPORT_TYPE_CONSOLE = 0x00, /*!< Data packet type */ - ZB_MAC_TRANSPORT_TYPE_DUMP = 0x01, /*!< Dump packet type */ - ZB_MAC_TRANSPORT_TYPE_TRACE = 0x02, /*!< Trace packet type */ - ZB_MAC_TRANSPORT_TYPE_CRASH_DATA = 0x03, /*!< Crash dump */ - ZB_MAC_TRANSPORT_TYPE_MAC_SPLIT_DATA = 0x04, /*!< MAC split data */ - ZB_MAC_TRANSPORT_TYPE_OTA_PROTOCOL = 0x05, /*!< OTA protocol used over MACSPLIT */ - ZBNCP_TRANSPORT_TYPE_DUMP = 0x06, /* NCP dump packet type */ - ZB_MAC_TRANSPORT_TYPE_NUM -} -zb_mac_transport_type_t; - -/* Available interface types */ -typedef enum zb_dump_iface_type_e -{ - ZB_DUMP_IFACE_ZIGBEE = 0, - ZB_DUMP_IFACE_SUBGHZ = 1, - ZB_DUMP_IFACE_BLE_DIRECT = 2, - ZB_DUMP_IFACE_NCP = 3, - ZB_DUMP_IFACE_MAX -} zb_dump_iface_type_t; - -/** - Legacy packet header. Now used in ZBOSS internal traffic dump. - - */ -typedef ZB_PACKED_PRE struct zb_mac_transport_hdr_s -{ - zb_uint8_t len; /*!< Packet length, including hdr */ - zb_uint8_t type; /*!< Packet type, @see zb_mac_transport_type_t */ - zb_uint16_t time; /*!< time label */ -} ZB_PACKED_STRUCT -zb_mac_transport_hdr_t; - - -typedef ZB_PACKED_PRE struct zb_dump_hdr_v3_s -{ - zb_uint8_t version; - zb_uint8_t len; - zb_uint8_t page; - zb_uint8_t channel; - zb_uint32_t trace_cnt; -} ZB_PACKED_STRUCT -zb_dump_hdr_v3_t; - -typedef ZB_PACKED_PRE struct zb_dump_hdr_v4_s -{ - zb_uint8_t version; - zb_uint8_t len; - zb_uint8_t page; - zb_uint8_t channel; - zb_uint32_t trace_cnt; - zb_uint8_t interface_type : 4; - zb_uint8_t interface_id : 4; - zb_int8_t rssi; - zb_uint8_t lqi; -} ZB_PACKED_STRUCT -zb_dump_hdr_v4_t; - -typedef ZB_PACKED_PRE struct zb_dump_hdr_s -{ - zb_uint32_t trace_cnt; - zb_uint8_t channel; - zb_uint8_t len; -} ZB_PACKED_STRUCT -zb_dump_hdr_t; - -#if defined ZB_TRAFFIC_DUMP_ON -void zb_dump_put_2buf(zb_uint8_t *buf1, zb_uint_t len1, const zb_uint8_t *buf2, zb_uint_t len2, zb_mac_transport_type_t dump_type, zb_bool_t is_w); -#endif /* ZB_TRAFFIC_DUMP_ON */ - - -/*! @} */ -/*! @endcond */ - -#endif /* MAC_TRANSPORT_H */ diff --git a/zboss/development/src/include/zb_nvram.h b/zboss/development/src/include/zb_nvram.h deleted file mode 100644 index 2a0dc54682..0000000000 --- a/zboss/development/src/include/zb_nvram.h +++ /dev/null @@ -1,1377 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Zigbee nvram internal management -*/ - -#ifndef ZB_NVRAM_H -#define ZB_NVRAM_H 1 - -#if defined ZB_USE_NVRAM || defined doxygen - -/* Always use 32-bit time label. It implies 16-bit variable - * for data length in header, which allows to store big datasets - * like ZGP dataset */ -#define ZB_NVRAM_32BIT_TL - -/** - NVRAM time label (initially): 16 bits, 0xffff is reserved (negative) - Cortex M3 can write by 32-bit words only. Use 32-bit time. - */ -#ifdef ZB_PLATFORM_CORTEX_M3 -#ifndef ZB_NVRAM_32BIT_TL -#define ZB_NVRAM_32BIT_TL -#endif -/** if defined, after erase memory contents is zero, else -1 */ -#endif - -#if (defined ZB_PLATFORM_XAP5 || defined ZB_PLATFORM_CORTEX_M3) -#define ZB_NVRAM_ERASE_TO_ZERO -#endif - -#ifndef ZB_NVRAM_32BIT_TL -typedef zb_uint16_t zb_nvram_tl_t; -#else -typedef zb_uint32_t zb_nvram_tl_t; -#endif - -#ifdef ZB_NVRAM_ERASE_TO_ZERO -#define ZB_NVRAM_TL_RESERVED 0U -#endif - -#ifndef ZB_NVRAM_32BIT_TL - -#ifndef ZB_NVRAM_ERASE_TO_ZERO -#define ZB_NVRAM_TL_RESERVED 0xffffU -#endif - -#define ZB_NVRAM_TL_MASK 0x7fff - -#else - -#ifndef ZB_NVRAM_ERASE_TO_ZERO -#define ZB_NVRAM_TL_RESERVED (zb_uint32_t)(~0u) -#endif - -#define ZB_NVRAM_TL_MASK 0x7fffffffU -#endif - -#define ZB_NVRAM_HALF_MAX_TL_VAL (ZB_NVRAM_TL_MASK / 2U) - -#ifndef ZB_NVRAM_ERASE_TO_ZERO -#define ZB_NVRAM_TL_INC(a) (zb_nvram_tl_t)(((a) + 1U) & ZB_NVRAM_TL_MASK) -#else -/* Increment time label, with overflow. If 0 is reserved (produced by erase), jump over it. */ -#define ZB_NVRAM_TL_INC(a) (zb_nvram_tl_t)((a) == ZB_NVRAM_TL_MASK ? 1U : (a) + 1U) -#endif - -#define ZB_NVRAM_TL_GE(a, b) ((((a) - (b)) & ZB_NVRAM_TL_MASK) < ZB_NVRAM_HALF_MAX_TL_VAL) -#define ZB_NVRAM_TL_GT(a, b) ((a) != (b) && ZB_NVRAM_TL_GE(a, b)) - -#define ZB_NVRAM_TL_INITIAL 1U - - -/** - Data set header in nvram segment - */ -typedef ZB_PACKED_PRE struct zb_nvram_dataset_hdr_1_0_s -{ - /* We must write time label separately from other fields. - If it is ok to write 2 bytes into flash, can use 4 bytes header, else use - 4 bytes time label and 4 bytes for other fields. */ - zb_nvram_tl_t time_label; /*!< Time index - not real or Zigbee time */ -#ifndef ZB_NVRAM_32BIT_TL -#warning ("check maximum dataset length") - zb_lbitfield_t data_len:11; /*!< Record length. It equals to header length + dataset length <= 2k - is it enough? */ - zb_bitfield_t data_set_type:5; /*!< Dataset type. See @par zb_nvram_dataset_types_t */ -#else - /* If must align anyway, need not use bitfields */ - zb_uint16_t data_len; /*!< Record length. It equals to header length + dataset length */ - zb_uint16_t data_set_type; /*!< Dataset type. See @par zb_nvram_dataset_types_t */ -#endif /* 32 bit */ - - /* FIXME: it looks like migration from old datasets-vistout-version is broken: there must be no data_set_version. - Anyway, it is useful for one-time nvram migration of very old devices, so just ignore it now. - */ - zb_uint16_t data_set_version; /*!< Dataset version. - * Unique per dataset: each dataset fills it with its own version. */ - zb_uint8_t reserved[2]; /*!< Alignment, reserved for future use. */ -} ZB_PACKED_STRUCT -zb_nvram_dataset_hdr_1_0_t; - -/** - * @name NVRAM transaction state - * @anchor nvram_transaction_state - * - * Note: These values were members of `enum zb_nvram_transaction_state_e` type but were converted to - * a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_NVRAM_TRANSACTION_AUTOCOMMIT 0U -#define ZB_NVRAM_TRANSACTION_ONGOING 1U -/** @} */ - -/** - Data set header in nvram segment - */ -typedef ZB_PACKED_PRE struct zb_nvram_dataset_hdr_7_0_s -{ - /* We must write time label separately from other fields. - If it is ok to write 2 bytes into flash, can use 4 bytes header, else use - 4 bytes time label and 4 bytes for other fields. */ - /* Note: to simplify migration keep that field in nvram v8 (with data set trailers). */ - zb_nvram_tl_t time_label; /*!< Time index - not real or ZigBee time */ -#ifndef ZB_NVRAM_32BIT_TL -#warning ("check maximum dataset length") - zb_lbitfield_t data_len:11; /*!< Record length. It equal header length + dataset length <= 2k - is it enough? */ - zb_bitfield_t data_set_type:5; /*!< Dataset type. See @par zb_nvram_dataset_types_t */ -#else - /* If must align anyway, need not use bitfields */ - zb_uint16_t data_len; /*!< Record length. It equal header length + dataset length */ - zb_uint16_t data_set_type; /*!< Dataset type. See @par zb_nvram_dataset_types_t */ -#endif /* 32 bit */ - zb_uint16_t data_set_version; /*!< Dataset version. Unique per each - * dataset */ - zb_uint8_t transaction_status; /*!< Current transaction status. @see @ref nvram_transaction_state */ - zb_uint8_t reserved; /*!< Alignment. Reserved for future - use */ -} ZB_PACKED_STRUCT -zb_nvram_dataset_hdr_7_0_t; - - -/** - Data set trailer - */ -typedef ZB_PACKED_PRE struct zb_nvram_dataset_tail_8_0_s -{ - zb_nvram_tl_t time_label; /*!< Time index - not real or ZigBee time - kind of TSN */ -} ZB_PACKED_STRUCT -zb_nvram_dataset_tail_8_0_t; - -/* TODO: implement migration tail_8_0 -> tail_9_0 */ -/** - Data set trailer - */ -typedef ZB_PACKED_PRE struct zb_nvram_dataset_tail_9_0_s -{ - zb_nvram_tl_t time_label; /*!< Time index - not real or ZigBee time - kind of TSN */ - zb_uint16_t crc; /*!< CRC16 field for validate dataset integrity */ - zb_uint16_t reserved; /*!< Reserved field for future needs */ -} ZB_PACKED_STRUCT -zb_nvram_dataset_tail_9_0_t; - -typedef zb_nvram_dataset_tail_9_0_t zb_nvram_dataset_tail_t; - -/* Current dataset */ -#define SIZE_DS_HEADER_1_0 sizeof(zb_nvram_dataset_hdr_1_0_t) -#define PAGE_HEADER_SIZE_1_0 (SIZE_DS_HEADER_1_0 + sizeof(zb_nvram_page_hdr_dataset_t)) - -typedef zb_nvram_dataset_hdr_7_0_t zb_nvram_dataset_hdr_t; - -#define SIZE_DS_HEADER sizeof(zb_nvram_dataset_hdr_t) -#define PAGE_HEADER_SIZE (SIZE_DS_HEADER + sizeof(zb_nvram_page_hdr_dataset_t) + sizeof(zb_nvram_dataset_tail_t)) - -#ifndef ZB_NVRAM_ERASE_TO_ZERO - -#ifndef ZB_NVRAM_32BIT_TL -#define ZB_NVRAM_DATA_LEN_RESERVED 0x7ffU -#define ZB_NVRAM_DATA_SET_TYPE_RESERVED 0x1fU -#else -#define ZB_NVRAM_DATA_LEN_RESERVED 0xffffU -#define ZB_NVRAM_DATA_SET_TYPE_RESERVED 0xffffU -#endif - -#define ZB_NVRAM_DATA_SET_VERSION_RESERVED 0xffffU - -#else - -#define ZB_NVRAM_DATA_LEN_RESERVED 0U -#define ZB_NVRAM_DATA_SET_TYPE_RESERVED 0U - -#define ZB_NVRAM_DATA_SET_VERSION_RESERVED 0U - -#endif /* erase to zero */ - -#define ZB_NVRAM_DATA_SET_VERSION_NOT_AVAILABLE 0xffffU - -/** - Return 1 if data set header is empty. - - No more data in the nvram segment after empty header. If empty header is at - nvram segment begin, entire segment is empty. It usually means segment is - just erased. - */ - -#define ZB_NVRAM_DATA_SET_HDR_IS_EMPTY(hdrp) ( \ - (hdrp)->time_label == ZB_NVRAM_TL_RESERVED \ - && (hdrp)->data_len == ZB_NVRAM_DATA_LEN_RESERVED \ - && (hdrp)->data_set_type == ZB_NVRAM_DATA_SET_TYPE_RESERVED \ - && (hdrp)->data_set_version == ZB_NVRAM_DATA_SET_VERSION_RESERVED \ - ) - -#define ZB_NVRAM_DATA_SET_HDR_1_0_IS_EMPTY(hdrp) ( \ - (hdrp)->time_label == ZB_NVRAM_TL_RESERVED \ - && (hdrp)->data_len == ZB_NVRAM_DATA_LEN_RESERVED \ - && (hdrp)->data_set_type == ZB_NVRAM_DATA_SET_TYPE_RESERVED \ - ) - -typedef struct zb_nvram_position_s -{ - zb_nvram_tl_t time_label; - zb_lbitfield_t pos:30; - zb_lbitfield_t page:2; - zb_uint16_t payload_length; - zb_uint16_t version; -} zb_nvram_position_t; - - -/** - * @name NVRAM versioning - * @anchor nvram_versions - * - * Format of stored datasets in NVRAM has a version. It is called NVRAM version. - * The version is common for all datasets. If structure of some dataset - * is changed, then the version should be updated (incremented). - * - * Current NVRAM version is determined at compile time and almost all functions - * should not bother about NVRAM version in use. The main problem is to convert - * datasets stored in older format to current datasets format. - * - * It is responsibility of specific datasets read functions like - * \ref zb_nvram_read_common_dataset, \ref zb_nvram_read_ha_dataset, etc. - * Version number and length of dataset to be read are passed to these - * functions. They should analyze them in order to convert old dataset - * representation to the new one. The only exception is user application - * dataset read function, where no version is provided. Application should - * use own dataset versioning scheme if necessary. - * - * The easiest change in format to handle is adding fields to the end. - * In that case dataset read function can analyze only dataset length parameter - * and read data of this length from nvram to dataset of current version. - * All new fields should be set to some default values in this case. - * - * NVRAM version is page-wide. Datasets with different versions can't be mixed - * on one page. Version is stored in separate dataset \ref zb_nvram_page_hdr_dataset_t. - * This dataset is always stored as first dataset on page and is written - * after page erase procedure. - * - * Since different dataset versions can't be mixed on one page, migration of - * datasets is needed if attempt to write to old version page was made. - * This is done in \ref migrate_curr_page_to_new_version. - * - * Note: These values were members of `enum zb_nvram_versions_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -/* First version should be 0. New versions should be added to the end, before ZB_NVRAM_VER_COUNT */ -#define ZB_NVRAM_VER_1_0 0U -#define ZB_NVRAM_VER_2_0 1U -#define ZB_NVRAM_VER_3_0 2U -#define ZB_NVRAM_VER_4_0 3U -#define ZB_NVRAM_VER_5_0 4U -#define ZB_NVRAM_VER_6_0 5U -#define ZB_NVRAM_VER_7_0 6U /* Used for ZBOSS SDK: stub for the next versions */ -#define ZB_NVRAM_VER_8_0 7U /* Used before introducing dataset tails */ -#define ZB_NVRAM_VER_9_0 8U /* Version of NVRAM having additional dataset trailers */ -#define ZB_NVRAM_VER_10_0 9U /* Version with unused CRC field in tail */ -#define ZB_NVRAM_VER_11_0 10U /* Version with used CRC field in tail */ -#define ZB_NVRAM_LAST_VER ZB_NVRAM_VER_11_0 /* Should always be equal to the highest version */ -/*------------------*/ -#define ZB_NVRAM_VER_COUNT (ZB_NVRAM_LAST_VER + 1U) -/** @} */ - - -#define ZB_MIN_NVRAM_VER_WITH_DS_TRAILERS ZB_NVRAM_VER_9_0 -#define ZB_MIN_NVRAM_VER_WITH_DS_CRC_IN_TAIL ZB_NVRAM_VER_11_0 - -/* Initnial value for crc calculation */ -#define ZB_NVRAM_CRC_DEFAULT_VALUE 0xFFFFU - -typedef zb_uint16_t zb_nvram_ver_t; - -#define ZB_NVRAM_MAX_VERSION (ZB_NVRAM_VER_COUNT - 1U) -/* Always assume that current NVRAM version in use is the last version. - * That means support of reading NVRAM datasets in older versions, - * but write datasets only in newest format */ -#define ZB_NVRAM_VERSION ZB_NVRAM_MAX_VERSION - -/** - Return 1 if data set type is valid. - */ -#define ZB_NVRAM_DATA_SET_HDR_IS_VALID(hdrp) ( \ - (hdrp)->data_set_type < (zb_uint16_t)ZB_NVRAM_DATASET_NUMBER \ - ) - -typedef struct zb_nvram_migration_info_s -{ - zb_uint32_t src_pos; - zb_uint32_t dst_pos; - zb_uint8_t src_page; - zb_uint8_t dst_page; - zb_uint8_t length; - zb_nvram_ver_t nvram_ver; -} -zb_nvram_migration_info_t; - - -/** - * Common NVRAM dataset. See spec 2.2.8, 3.6.8, 4.3.3, 4.4.10 - */ -typedef ZB_PACKED_PRE struct zb_nvram_dataset_common_ver_1_0_s -{ - zb_bitfield_t aps_designated_coordinator : 1; /*!< This boolean flag indicates whether the - device should assume on startup that it must - become a Zigbee coordinator. */ - zb_bitfield_t aps_insecure_join : 1; /*!< A boolean flag, which defaults to TRUE and - indicates whether it is OK to use insecure - join on startup. */ - zb_bitfield_t stack_profile:4; /*!< Stack profile identifier */ - zb_bitfield_t use_tc_alternative_key:1; /*!< if 1, use alternative TC key */ - zb_bitfield_t reserved:1; - zb_uint8_t depth; /*!< current node depth */ - zb_uint16_t nwk_manager_addr; /*!< NWK manager address */ - zb_uint16_t panId; /*!< Pan ID */ - zb_uint16_t network_address; /*!< Current network address */ - - zb_uint32_t aps_channel_mask; /*!< This is the mask containing allowable - channels on which the device may attempt - to form or join a network at startup time. */ - zb_ext_pan_id_t aps_use_extended_pan_id; - zb_ext_pan_id_t nwk_extended_pan_id; /*!< Extended Pan ID for the PAN of which the device is a member */ - zb_ieee_addr_t parent_address; /*!< Parent address */ - zb_ieee_addr_t trust_center_address; /*!< Trust Center IEEE address */ - zb_uint8_t nwk_key[ZB_CCM_KEY_SIZE]; /*!< Network Key */ - zb_uint8_t nwk_key_seq; - zb_uint8_t tc_standard_key[ZB_CCM_KEY_SIZE]; /*!< Trust Center Standard Key */ - zb_uint8_t tc_alternative_key[ZB_CCM_KEY_SIZE]; /*!< Trust Center Alternative Key */ - - /* Custom fields*/ - zb_uint8_t channel; /*!< Current channel. Custom field */ - zb_uint8_t aligned[2]; - -} ZB_PACKED_STRUCT -zb_nvram_dataset_common_ver_1_0_t; - -typedef ZB_PACKED_PRE struct zb_nvram_dataset_common_ver_2_0_s -{ - zb_bitfield_t aps_designated_coordinator : 1; /*!< This boolean flag indicates whether the - device should assume on startup that it must - become a Zigbee coordinator. */ - zb_bitfield_t aps_insecure_join : 1; /*!< A boolean flag, which defaults to TRUE and - indicates whether it is OK to use insecure - join on startup. */ - zb_bitfield_t stack_profile:4; /*!< Stack profile identifier */ - zb_bitfield_t reserved:2; - zb_uint8_t depth; /*!< current node depth */ - zb_uint16_t nwk_manager_addr; /*!< NWK manager address */ - zb_uint16_t panId; /*!< Pan ID */ - zb_uint16_t network_address; /*!< Current network address */ - - zb_uint32_t aps_channel_mask; /*!< This is the mask containing allowable - channels on which the device may attempt - to form or join a network at startup time. */ - zb_ext_pan_id_t aps_use_extended_pan_id; - zb_ext_pan_id_t nwk_extended_pan_id; /*!< Extended Pan ID for the PAN of which the device is a member */ - zb_ieee_addr_t parent_address; /*!< Parent address */ - zb_ieee_addr_t trust_center_address; /*!< Trust Center IEEE address */ - zb_uint8_t nwk_key[ZB_CCM_KEY_SIZE]; /*!< Network Key */ - zb_uint8_t nwk_key_seq; - zb_uint8_t tc_standard_key[ZB_CCM_KEY_SIZE]; /*!< Trust Center Standard Key */ - - /* Custom fields*/ - zb_uint8_t channel; /*!< Current channel. Custom field */ - zb_uint8_t aligned[2]; - -} ZB_PACKED_STRUCT -zb_nvram_dataset_common_ver_2_0_t; - - -typedef ZB_PACKED_PRE struct zb_nvram_dataset_common_ver_4_0_s -{ - zb_bitfield_t aps_designated_coordinator : 1; /*!< This boolean flag indicates whether the - device should assume on startup that it must - become a Zigbee coordinator. */ - zb_bitfield_t aps_insecure_join : 1; /*!< A boolean flag, which defaults to TRUE and - indicates whether it is OK to use insecure - join on startup. */ - zb_bitfield_t stack_profile:4; /*!< Stack profile identifier */ - /*zb_bitfield_t reserved:2;*/ - zb_bitfield_t device_type:2; /*!< NIB device type */ - zb_uint8_t depth; /*!< current node depth */ - zb_uint16_t nwk_manager_addr; /*!< NWK manager address */ - zb_uint16_t panId; /*!< Pan ID */ - zb_uint16_t network_address; /*!< Current network address */ - - zb_channel_list_t aps_channel_mask_list; /*!< This is the masks list containing allowable - * channels on which the device may attempt - * to form or join a network at startup time. */ - zb_ext_pan_id_t aps_use_extended_pan_id; - zb_ext_pan_id_t nwk_extended_pan_id; /*!< The extended PAN identifier for the PAN of which the device is a member */ - zb_ieee_addr_t parent_address; /*!< Parent address */ - zb_ieee_addr_t trust_center_address; /*!< Trust Center IEEE address */ - zb_uint8_t nwk_key[ZB_CCM_KEY_SIZE]; /*!< Network Key */ - zb_uint8_t nwk_key_seq; - zb_uint8_t tc_standard_key[ZB_CCM_KEY_SIZE]; /*!< Trust Center Standard Key */ - - /* Custom fields*/ - /* In default configuration ZB_NWK_MAC_IFACE_TBL_SIZE is 1, so the dataset is compatible with previous stack versions. - * When multiple interfaces are enabled, the dataset will become incompatible with default configuration and - * migrations between single-MAC and multi-MAC NVRAM are not supported now */ - zb_uint8_t channel[ZB_NWK_MAC_IFACE_TBL_SIZE]; /*!< Current channel. Custom field */ - zb_uint8_t page[ZB_NWK_MAC_IFACE_TBL_SIZE]; /*!< Current page. Custom field */ - zb_nwk_mac_iface_tbl_ent_t mac_iface_tbl[ZB_NWK_MAC_IFACE_TBL_SIZE]; /*!< nwkMacInterfaceTable from NWK NIB()*/ - /* There was 1 reserved byte */ - zb_bitfield_t hub_connectivity:1; /*!< hub connectivity for WWAH and r23 all hubs */ - zb_bitfield_t rx_on:1; /*!< rx-on-when-idle for ZED */ - zb_bitfield_t tc_swapped:1; /*!< TC swapout is in progress for ZC (not - * all known devices came back) / Joiner - * detected TC swapout, not all precessing - * completed. */ - zb_bitfield_t reserved:5; -#if ZB_NWK_MAC_IFACE_TBL_SIZE == 1 -#elif ZB_NWK_MAC_IFACE_TBL_SIZE == 2 - /* sizeof(zb_nvram_dataset_common_ver_3_0_t) == 106 (without additional reserved bytes) */ - zb_uint8_t mm_reserved[2]; -#else - #error Current Multi-MAC configuration is not supported -#endif - -} ZB_PACKED_STRUCT -zb_nvram_dataset_common_ver_4_0_t; - -/* The new dataset does not introduce new fields, but renames the previously reserved fields, - * so we can use the new dataset definition while loading legacy structure. - */ -typedef zb_nvram_dataset_common_ver_4_0_t zb_nvram_dataset_common_ver_3_0_t; - -typedef zb_nvram_dataset_common_ver_4_0_t zb_nvram_dataset_common_t; - -/** - * @name NVRAM dataset common versions - * @anchor nvram_dataset_common_versions - * - * Note: These values were members of `enum zb_nvram_dataset_common_versions_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_NVRAM_COMMON_DATA_DS_VER_1 0U -#define ZB_NVRAM_COMMON_DATA_DS_VER_2 1U -#define ZB_NVRAM_COMMON_DATA_DS_VER_3 2U -#define ZB_NVRAM_COMMON_DATA_DS_VER_4 3U -/** @} */ - -#define ZB_NVRAM_COMMON_DATA_DS_VER ZB_NVRAM_COMMON_DATA_DS_VER_4 - - -/* Check dataset alignment for IAR compiler and ARM Cortex target platform */ -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_dataset_common_t); - -typedef ZB_PACKED_PRE struct zb_nvram_dataset_counters_ver_1_0_s -{ - zb_uint32_t nib_counter; -} ZB_PACKED_STRUCT -zb_nvram_dataset_counters_ver_1_0_t; - -typedef ZB_PACKED_PRE struct zb_nvram_dataset_counters_ver_2_0_s -{ - zb_uint32_t nib_counter; - zb_uint32_t aib_counter; -} ZB_PACKED_STRUCT -zb_nvram_dataset_counters_ver_2_0_t; - -/** - * @name NVRAM dataset counters versions - * @anchor nvram_dataset_binding_versions - */ -/** @{ */ -#define ZB_IB_COUNTERS_DS_VER_1 0U -#define ZB_IB_COUNTERS_DS_VER_2 1U -/** @} */ - -typedef zb_nvram_dataset_counters_ver_2_0_t zb_nvram_dataset_counters_t; -#define ZB_IB_COUNTERS_DS_VER ZB_IB_COUNTERS_DS_VER_2 - -/* Check dataset alignment for IAR compiler and ARM Cortex target platform */ -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_dataset_counters_t); - -#if defined ZB_ENABLE_HA - -/** - * HA NVRAM dataset. See HA spec IAS Zone Cluster - */ -typedef ZB_PACKED_PRE struct zb_nvram_dataset_ha_s -{ - /* IAS Zone data */ - zb_ieee_addr_t cie_address; /*!< CIE address */ - - zb_uint8_t cie_ep; /*!< CIE EP used for notifications*/ - zb_uint8_t zone_state; /*!< Zone State */ - zb_uint16_t cie_short_addr; /*!< CIE short address used for notifications*/ - - zb_uint8_t zone_id; /*!< ZoneID value */ - /* Poll control data */ - zb_uint8_t poll_ctrl_ep; /*!< poll control client endpoint */ - zb_uint16_t poll_ctrl_short_addr; /*!< poll control client short addr*/ - - /* Reserved data */ - zb_uint8_t reserved; /* Reserved */ - - /*Diagnostic cluster data */ - zb_uint16_t number_of_resets; /*Number of resets*/ - zb_uint16_t join_indication; /*Number of join attempts*/ - zb_uint16_t packet_buffer_allocate_failures; /*Number of buffer allocation errors*/ - - zb_uint8_t cie_address_is_set; /*!< Is CIE address set */ -} ZB_PACKED_STRUCT -zb_nvram_dataset_ha_t; - -typedef enum zb_nvram_dataset_ha_versions_e -{ - ZB_NVRAM_HA_DATA_DS_VER_1 = 0, -} -zb_nvram_dataset_ha_versions_t; - -#define ZB_NVRAM_HA_DATA_DS_VER ZB_NVRAM_HA_DATA_DS_VER_1 - -/* Check dataset alignment for IAR compiler and ARM Cortex target platform */ -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_dataset_ha_t); - -#endif /*defined ZB_ENABLE_HA*/ - -#ifdef ZDO_DIAGNOSTICS - -/** - * Dataset of the ZDO Diagnostics. - */ -typedef ZB_PACKED_PRE struct zb_nvram_dataset_diagnostics_v1_s -{ - /*! @brief An attribute that is incremented - * each time the device resets. */ - zb_uint16_t number_of_resets; - - /*! @brief A counter that is incremented each time - * an entry is added to the neighbor table. */ - zb_uint16_t nwk_neighbor_added; - - /*! @brief A counter that is incremented each time - * an entry is removed from the neighbor table. */ - zb_uint16_t nwk_neighbor_removed; - - /*! @brief A counter that is incremented each time a neighbor table entry - * becomes stale because the neighbor has not been heard from. */ - zb_uint16_t nwk_neighbor_stale; - - /*! @brief A counter that is incremented each time - * a node joins or rejoins the network via this node. */ - zb_uint16_t join_indication; - - /*! @brief A counter that is incremented each time an entry - * is removed from the child table. */ - zb_uint16_t childs_removed; - - /*! @brief A counter that is incremented each time - * the stack failed to allocate a packet buffers. */ - zb_uint16_t packet_buffer_allocate_failures; - - zb_uint8_t alignment[2]; /* total size == 16 bytes */ -} ZB_PACKED_STRUCT -zb_nvram_dataset_diagnostics_v1_t; - -/** - * @name NVRAM dataset diagnostics versions - * @anchor nvram_dataset_diagnostics_versions - */ -/** @{ */ -#define ZB_NVRAM_DIAGNOSTICS_DATA_DS_VER_1 0U -/** @} */ - -#define ZB_NVRAM_DIAGNOSTICS_DATA_DS_VER ZB_NVRAM_DIAGNOSTICS_DATA_DS_VER_1 - -/* Check dataset alignment for IAR compiler and ARM Cortex target platform */ -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_dataset_diagnostics_v1_t); - -#endif /* ZDO_DIAGNOSTICS */ - -#ifdef ZB_CONFIGURABLE_MEM - -#define ZB_NVRAM_APS_BINDING_TABLE_SPECIFIC_MIGRATION - -#ifndef ZB_ED_ROLE -#define ZB_APS_SRC_BINDING_TABLE_SIZE_OLD 16U -#define ZB_APS_DST_BINDING_TABLE_SIZE_OLD 32U -#else -#define ZB_APS_SRC_BINDING_TABLE_SIZE_OLD 8U -#define ZB_APS_DST_BINDING_TABLE_SIZE_OLD 16U -#endif /* ZB_ED_ROLE */ - -#else /* defined ZB_CONFIGURABLE_MEM */ - -#define ZB_APS_SRC_BINDING_TABLE_SIZE_OLD ZB_APS_SRC_BINDING_TABLE_SIZE -#define ZB_APS_DST_BINDING_TABLE_SIZE_OLD ZB_APS_DST_BINDING_TABLE_SIZE - -#define ZB_SINGLE_TRANS_INDEX_SIZE_OLD ((ZB_APS_BIND_TRANS_TABLE_SIZE + 7U) / 8U) - -#endif /* defined ZB_CONFIGURABLE_MEM */ - -typedef ZB_PACKED_PRE struct zb_aps_bind_dst_table_old_s -{ - ZB_PACKED_PRE union - { - zb_uint16_t group_addr; /*!< group address */ - zb_aps_bind_long_dst_addr_t long_addr; /*!< @see zb_asp_long_dst_addr_t */ - } u; -#ifndef ZB_CONFIGURABLE_MEM - zb_uint8_t trans_index[ZB_SINGLE_TRANS_INDEX_SIZE_OLD]; -#else - zb_uint8_t *trans_index; -#endif - - zb_bitfield_t dst_addr_mode:3; /*!< destination address mode flag, 0 - * - group address, otherwise long - * address plus dest endpoint */ - zb_bitfield_t src_table_index:5; /*!< index from zb_asp_src_table_t */ -} ZB_PACKED_STRUCT zb_aps_bind_dst_table_old_t; - -typedef ZB_PACKED_PRE struct zb_aps_binding_table_old_s -{ - zb_aps_bind_src_table_t src_table[ZB_APS_SRC_BINDING_TABLE_SIZE_OLD]; /*!< Source table */ - zb_aps_bind_dst_table_old_t dst_table[ZB_APS_DST_BINDING_TABLE_SIZE_OLD]; /*!< Destination table */ - zb_uint8_t src_n_elements; /*!< Count elements in source table */ - zb_uint8_t dst_n_elements; /*!< Count elements in destination table */ -#ifdef SNCP_MODE - zb_uint8_t remote_bind_offset; /*!< Offset to attribute id's to remote binding requests */ - zb_uint8_t align; -#else - /* FIXME: why align here? */ - zb_uint8_t align[2]; -#endif -#ifndef ZB_CONFIGURABLE_MEM - zb_uint8_t trans_table[ZB_APS_BIND_TRANS_TABLE_SIZE]; /*!< Buffers for simultaneous sendings */ -#else - zb_uint8_t *trans_table; -#endif -} ZB_PACKED_STRUCT zb_aps_binding_table_old_t; - -typedef zb_aps_binding_table_old_t zb_nvram_dataset_binding_v1_t; - -typedef ZB_PACKED_PRE struct zb_aps_bind_dst_table_v2_s -{ -#ifdef ZB_CONFIGURABLE_MEM - /* WARNING: this field will be rewritten if APS binding dataset is present in NVRAM */ - zb_uint8_t *trans_index; -#endif /* defined ZB_CONFIGURABLE_MEM */ - - ZB_PACKED_PRE union - { - zb_uint16_t group_addr; /*!< group address */ - zb_aps_bind_long_dst_addr_t long_addr; /*!< @see zb_asp_long_dst_addr_t */ - } u; - -#ifndef ZB_CONFIGURABLE_MEM - zb_uint8_t trans_index[ZB_SINGLE_TRANS_INDEX_SIZE]; -#endif /* defined ZB_CONFIGURABLE_MEM */ - zb_uint8_t align; - - zb_bitfield_t dst_addr_mode:3; /*!< destination address mode flag, 0 - * - group address, otherwise long - * address plus dest endpoint */ - zb_bitfield_t src_table_index:5; /*!< index from zb_asp_src_table_t */ -} ZB_PACKED_STRUCT zb_aps_bind_dst_table_v2_t; - -/** - * @brief APS binding NVRAM dataset. - */ -typedef ZB_PACKED_PRE struct zb_nvram_dataset_binding_v3_s -{ - zb_uint8_t src_n_elements; /*!< Count elements in source table */ - zb_uint8_t dst_n_elements; /*!< Count elements in destination table */ -#ifdef SNCP_MODE - zb_uint8_t remote_bind_offset; /*!< Offset to attribute id's to remote binding requests */ - zb_uint8_t align; -#else - zb_uint8_t align[2]; -#endif -} ZB_PACKED_STRUCT -zb_nvram_dataset_binding_v3_t; - -/* The new dataset header does not introduce new fields, but renames the previously reserved fields, - * so we can use the new dataset header definition while loading legacy structure. - * The binding dataset contents have changed, because the zb_aps_bind_dst_table_t has a different size. - * The v2 loading function uses the zb_aps_bind_dst_table_v2_t type instead. - */ -typedef zb_nvram_dataset_binding_v3_t zb_nvram_dataset_binding_v2_t; - -typedef zb_nvram_dataset_binding_v3_t zb_nvram_dataset_binding_t; - -/** - * @name NVRAM dataset binding versions - * @anchor nvram_dataset_binding_versions - * - * Note: These values were members of `enum zb_nvram_dataset_binding_versions_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_NVRAM_APS_BINDING_DATA_DS_VER_1 0U -#define ZB_NVRAM_APS_BINDING_DATA_DS_VER_2 1U -#define ZB_NVRAM_APS_BINDING_DATA_DS_VER_3 2U -/** @} */ - -#define ZB_NVRAM_APS_BINDING_DATA_DS_VER ZB_NVRAM_APS_BINDING_DATA_DS_VER_3 - -/* Check dataset alignment for IAR compiler and ARM Cortex target platform */ -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_dataset_binding_v3_t); - -typedef ZB_PACKED_PRE struct zb_nvram_dataset_groups_hdr_s -{ - zb_uint8_t n_groups; /*!< # of entries in APS group table */ - zb_uint8_t aligned[3]; -} ZB_PACKED_STRUCT -zb_nvram_dataset_groups_hdr_t; - -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_dataset_groups_hdr_t); -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_aps_group_table_ent_t); - -/** - * @name NVRAM dataset groups versions - * @anchor nvram_dataset_groups_versions - * - * Note: These values were members of `enum zb_nvram_dataset_groups_versions_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_NVRAM_APS_GROUPS_DATA_DS_VER_1 0U -/** @} */ - -#define ZB_NVRAM_APS_GROUPS_DATA_DS_VER ZB_NVRAM_APS_GROUPS_DATA_DS_VER_1 - - -#if defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN -/** - * HA POLL CONTROL NVRAM dataset. - */ -typedef ZB_PACKED_PRE struct zb_nvram_dataset_poll_control_s -{ - zb_uint32_t checkin_interval; - zb_uint32_t long_poll_interval; - zb_uint16_t short_poll_interval; - zb_uint16_t fast_poll_timeout; - zb_uint32_t checkin_interval_min; - zb_uint32_t long_poll_interval_min; - zb_uint16_t fast_poll_timeout_max; - zb_uint8_t aligned[2]; -} ZB_PACKED_STRUCT -zb_nvram_dataset_poll_control_t; - -/* Check dataset alignment for IAR compiler and ARM Cortex target platform */ -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_dataset_poll_control_t); - -typedef enum zb_nvram_dataset_poll_control_versions_e -{ - ZB_NVRAM_HA_POLL_CONTROL_DATA_DS_VER_1 = 0, -} -zb_nvram_dataset_poll_control_versions_t; - -#define ZB_NVRAM_HA_POLL_CONTROL_DATA_DS_VER ZB_NVRAM_HA_POLL_CONTROL_DATA_DS_VER_1 - -#endif /* defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN */ - -#if defined ZB_ZCL_SUPPORT_CLUSTER_WWAH || defined DOXYGEN -/** - * WWAH NVRAM dataset. - */ -typedef ZB_PACKED_PRE struct zb_nvram_dataset_wwah_s -{ - /* >>> WWAH CTX TODO: clarify what is needed to store */ - zb_uint8_t wwah_behavior; - zb_uint16_t time_server_addr; - zb_uint8_t time_server_endpoint; - - zb_uint8_t aps_ack_exempt_table_cnt; - zb_uint8_t aps_link_key_enabled_by_default; - - zb_uint8_t aps_link_key_authorization_table_cnt; - zb_uint8_t use_trust_center_for_cluster_table_cnt; - zb_uint8_t reserved; /* there was classification mask - no longer needed, may be ignored while loading old datasets. */ - zb_zcl_wwah_periodic_checkins_data_t periodic_checkins; - /* <<< WWAH CTX */ - - /* >>> WWAH attributes */ - zb_uint16_t cluster_revision; - zb_uint8_t nwk_retry_count; - zb_uint8_t mac_retry_count; - zb_uint8_t wwah_app_event_retry_queue_size; - zb_uint8_t mac_poll_failure_wait_time; - zb_uint8_t current_debug_report_id; - zb_uint8_t pending_network_update_channel; - zb_uint16_t pending_network_update_panid; - zb_uint16_t ota_max_offline_duration; /* 79b */ - - zb_bitfield_t disable_ota_downgrades:1; - zb_bitfield_t mgmt_leave_without_rejoin_enabled:1; - zb_bitfield_t router_check_in_enabled:1; - zb_bitfield_t touchlink_interpan_enabled:1; - zb_bitfield_t wwah_parent_classification_enabled:1; - zb_bitfield_t wwah_app_event_retry_enabled:1; - zb_bitfield_t wwah_rejoin_enabled:1; - zb_bitfield_t configuration_mode_enabled:1; - zb_bitfield_t tc_security_on_nwk_key_rotation_enabled:1; - zb_bitfield_t wwah_bad_parent_recovery_enabled:1; - zb_bitfield_t align_bitfield:6; - /* <<< WWAH attributes */ - - zb_uint8_t align_struct[1]; -} ZB_PACKED_STRUCT -zb_nvram_dataset_wwah_t; - -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_dataset_wwah_t); - -typedef enum zb_nvram_dataset_wwah_versions_e -{ - ZB_NVRAM_ZCL_WWAH_DATA_DS_VER_1 = 0, -} -zb_nvram_dataset_wwah_versions_t; - -#define ZB_NVRAM_ZCL_WWAH_DATA_DS_VER ZB_NVRAM_ZCL_WWAH_DATA_DS_VER_1 - -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_WWAH || defined DOXYGEN */ - -/****** GrPw dataset *****/ - -#ifdef ZB_ENABLE_ZGP - -typedef ZB_PACKED_PRE struct zb_nvram_zgp_sink_tbl_entry_ver_6_0_s -{ - zb_uint32_t src_id; - zb_ieee_addr_t ieee_addr; - - zb_uint32_t zgpd_sec_frame_counter; - -/** - * Options field of sink table entry - * - * [0-2] app_id ZGPD Application ID - * [3] sn_cap Sequence number capability - * [4] sn_expired Sequence number expired - * [5] is_manuf_id Is manufactured device id - * [6] is_used_entry Is used entry - * [7-8] sec_lvl Security level - * [9-11] sec_key_type Security key type - * - */ - zb_uint16_t options; - - zb_uint8_t match_dev_tbl_idx; - zb_uint8_t zgpd_key[ZB_CCM_KEY_SIZE]; - zb_uint8_t aligned[1]; -} -ZB_PACKED_STRUCT -zb_nvram_zgp_sink_tbl_entry_ver_6_0_t; - -/* Check dataset alignment for IAR compiler and ARM Cortex target platform */ -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_zgp_sink_tbl_entry_ver_6_0_t); - -typedef zb_nvram_zgp_sink_tbl_entry_ver_6_0_t zb_nvram_zgp_sink_tbl_t; - -typedef ZB_PACKED_PRE struct zb_nvram_zgp_dataset_info_ver_6_0_s -{ - zb_uint16_t zgp_sink_tbl_size; - zb_uint32_t immed_tx_frame_counter; -} -ZB_PACKED_STRUCT -zb_nvram_zgp_dataset_info_ver_6_0_t; - -#ifdef ZB_ENABLE_ZGP_PROXY -typedef ZB_PACKED_PRE struct zb_nvram_zgp_dataset_ver_6_0_s -{ - zb_nvram_zgp_dataset_info_ver_6_0_t zgp_info; - zb_nvram_zgp_sink_tbl_t zgp_sink_tbl[ZB_ZGP_SINK_TBL_SIZE]; -} -ZB_PACKED_STRUCT -zb_nvram_zgp_dataset_ver_6_0_t; - -typedef zb_nvram_zgp_dataset_info_ver_6_0_t zb_nvram_zgp_dataset_info_t; -typedef zb_nvram_zgp_dataset_ver_6_0_t zb_nvram_zgp_dataset_t; -#endif /* ZB_ENABLE_ZGP_PROXY */ - -typedef enum zb_nvram_dataset_grpw_data_versions_e -{ - ZB_NVRAM_DATASET_GRPW_DATA_DS_VER_1 = 0, - ZB_NVRAM_DATASET_GRPW_DATA_DS_VER_2 = 1, - ZB_NVRAM_DATASET_GRPW_DATA_DS_VER_3 = 2, - ZB_NVRAM_DATASET_GRPW_DATA_DS_VER_4 = 3, - ZB_NVRAM_DATASET_GRPW_DATA_DS_VER_5 = 4, - ZB_NVRAM_DATASET_GRPW_DATA_DS_VER_6 = 5, -} -zb_nvram_dataset_grpw_data_versions_t; - -#define ZB_NVRAM_DATASET_GRPW_DATA_DS_VER ZB_NVRAM_DATASET_GRPW_DATA_DS_VER_6 - -typedef enum zb_nvram_dataset_gr_sinkt_versions_e -{ - ZB_NVRAM_DATASET_GP_SINKT_DS_VER_1 = 0, -} -zb_nvram_dataset_gr_sinkt_versions_t; - -#define ZB_NVRAM_DATASET_GP_SINKT_DS_VER ZB_NVRAM_DATASET_GP_SINKT_DS_VER_1 - -typedef enum zb_nvram_dataset_gr_proxyt_versions_e -{ - ZB_NVRAM_DATASET_GP_PRPOXYT_DS_VER_1 = 0, -} -zb_nvram_dataset_gr_proxyt_versions_t; - -#define ZB_NVRAM_DATASET_GP_PRPOXYT_DS_VER ZB_NVRAM_DATASET_GP_PRPOXYT_DS_VER_1 - -typedef enum zb_nvram_dataset_gp_cluster_versions_e -{ - ZB_NVRAM_DATASET_GP_CLUSTER_DS_VER_1 = 0, -} -zb_nvram_dataset_gp_cluster_versions_t; - -#define ZB_NVRAM_DATASET_GP_CLUSTER_DS_VER ZB_NVRAM_DATASET_GP_CLUSTER_DS_VER_1 - -typedef enum zb_nvram_dataset_gp_app_tbl_versions_e -{ - ZB_NVRAM_DATASET_GP_APP_TBL_DS_VER_1 = 0, -} -zb_nvram_dataset_gp_app_tbl_versions_t; - -#define ZB_NVRAM_DATASET_GP_APP_TBL_DS_VER ZB_NVRAM_DATASET_GP_APP_TBL_DS_VER_1 - -#endif /* #ifdef ZB_ENABLE_ZGP */ - -/* CR: Discussion: MM: I decided to use internal dataset versioning - * due to its dynamical size */ - -/** - ZB_NVRAM_ADDR_MAP - Address map dataset is stored in NVM using 2 structures: - zb_nvram_addr_map_hdr_t - Array of zb_nvram_addr_map_rec_t records - - If header store 0 as array size, no record follows -*/ - -/** - * @name NVRAM address map dataset version - * @anchor nvram_addr_map_ds_versions - * - * Note: These values were members of `enum zb_nvram_addr_map_ds_versions_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -/* First(0) version should be 0. - * New versions should be added to the end, before ZB_NVRAM_ADDR_MAP_DS_VER. - * After, ZB_NVRAM_ADDR_MAP_DS_VER should be updated. */ -#define ZB_NVRAM_ADDR_MAP_DS_VER_0 0U -#define ZB_NVRAM_ADDR_MAP_DS_VER_1 1U -#define ZB_NVRAM_ADDR_MAP_DS_VER_2 2U -#define ZB_NVRAM_ADDR_MAP_DS_VER ZB_NVRAM_ADDR_MAP_DS_VER_2 /* Should be equal to latest (highest) version */ -#define ZB_NVRAM_ADDR_MAP_DS_VER_COUNT (ZB_NVRAM_ADDR_MAP_DS_VER + 1U) -/** @} */ - -typedef ZB_PACKED_PRE struct zb_nvram_addr_map_hdr_v0_s -{ - zb_uint8_t addr_map_num; /*!< Stores number of addr maps - see zb_address_map_t */ - zb_uint8_t version; /*!< Stores version of the dataset */ -} -ZB_PACKED_STRUCT -zb_nvram_addr_map_hdr_v0_t; - -typedef ZB_PACKED_PRE struct zb_nvram_addr_map_hdr_s -{ - zb_uint8_t addr_map_num; /*!< Stores number of addr maps - see zb_address_map_t */ - zb_uint8_t version; /*!< Stores version of the dataset */ - zb_uint8_t aligned[2]; -} -ZB_PACKED_STRUCT -zb_nvram_addr_map_hdr_t; - -/** Store a NVM record describing address map, see zb_address_map_t */ -typedef ZB_PACKED_PRE struct zb_nvram_addr_map_rec_v0_s -{ - zb_ieee_addr_t ieee_addr; /*!< Uncompressed IEEE address */ - zb_uint16_t addr; /*!< 16-bit device address */ - zb_uint8_t index; /*!< Reference for neighbor table */ -} -ZB_PACKED_STRUCT -zb_nvram_addr_map_rec_v0_t; - -/** Store a NVM record describing address map, see zb_address_map_t */ -typedef ZB_PACKED_PRE struct zb_nvram_addr_map_rec_v1_s -{ - zb_ieee_addr_t ieee_addr; /*!< Uncompressed IEEE address */ - zb_uint16_t addr; /*!< 16-bit device address */ - zb_uint8_t index; /*!< Reference for neighbor table */ - zb_uint8_t redirect_type; /*!< Redirect type */ - zb_uint8_t redirect_ref; /*!< reference to regular/redirect - * entry */ -} -ZB_PACKED_STRUCT -zb_nvram_addr_map_rec_v1_t; - -/** Store a NVM record describing address map, see zb_address_map_t */ -typedef ZB_PACKED_PRE struct zb_nvram_addr_map_rec_v2_s -{ - zb_ieee_addr_t ieee_addr; /*!< Uncompressed IEEE address */ - zb_uint16_t addr; /*!< 16-bit device address */ - zb_uint8_t index; /*!< Reference for neighbor table */ - zb_uint8_t redirect_type; /*!< Redirect type */ - zb_uint8_t redirect_ref; /*!< reference to regular/redirect - * entry */ - zb_uint8_t aligned[3]; -} -ZB_PACKED_STRUCT -zb_nvram_addr_map_rec_v2_t; - -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_addr_map_rec_v2_t); - -/** - ZB_NVRAM_NEIGHBOUR_TBL - Neighbour table dataset is stored in NVM using 2 structures: - zb_nvram_neighbour_hdr_t - Array of zb_nvram_neighbour_rec_t records. - - If array size specified in header is 0, no record follows. -*/ - -/** - * @name NVRAM neighbor table dataset versions - * @anchor nvram_neighbor_tbl_ds_versions - * - * Note: These values were members of `enum zb_nvram_neighbor_tbl_ds_versions_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -/* First(0) version should be 0. - * New versions should be added to the end, before ZB_NVRAM_NEIGHBOUR_TBL_DS_VER. - * After, ZB_NVRAM_NEIGHBOUR_TBL_DS_VER should be updated. */ -#define ZB_NVRAM_NEIGHBOR_TBL_DS_VER_0 0U -#define ZB_NVRAM_NEIGHBOR_TBL_DS_VER_1 1U -#define ZB_NVRAM_NEIGHBOR_TBL_DS_VER_2 2U -#define ZB_NVRAM_NEIGHBOR_TBL_DS_VER_3 3U -#define ZB_NVRAM_NEIGHBOUR_TBL_DS_VER ZB_NVRAM_NEIGHBOR_TBL_DS_VER_3 /* Should be equal to latest (highest) version */ -#define ZB_NVRAM_NEIGHBOR_TBL_DS_VER_COUNT (ZB_NVRAM_NEIGHBOUR_TBL_DS_VER + 1U) -/** @} */ - -typedef ZB_PACKED_PRE struct zb_nvram_neighbour_hdr_v0_s -{ - zb_uint8_t nbr_rec_num; /*!< Stores number of stored neighbour devices */ - zb_uint8_t version; /*!< Stores version of the dataset */ -} -ZB_PACKED_STRUCT -zb_nvram_neighbour_hdr_v0_t; - -typedef ZB_PACKED_PRE struct zb_nvram_neighbour_hdr_v1_s -{ - zb_uint8_t nbr_rec_num; /*!< Stores number of stored neighbour devices */ - zb_uint8_t version; /*!< Stores version of the dataset */ - zb_uint8_t aligned[2]; -} -ZB_PACKED_STRUCT -zb_nvram_neighbour_hdr_v1_t; - -typedef zb_nvram_neighbour_hdr_v1_t zb_nvram_neighbour_hdr_t; - - -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_neighbour_hdr_t); - -typedef ZB_PACKED_PRE struct zb_nvram_neighbour_rec_v0_s -{ - zb_address_ieee_ref_t addr_ref; /*!< Neighbor address */ - zb_bitfield_t depth:4; /*!< Device depth */ - zb_bitfield_t rx_on_when_idle:1; /*!< Store device rx On when idle state */ - zb_bitfield_t relationship:3; /*!< The relationship with nbr device, see @ref nwk_relationship */ - zb_bitfield_t device_type:2; /*!< Neighbor device type - @see @ref nwk_device_type */ - zb_bitfield_t reserved:6; - zb_uint8_t key_seq_number; /*!< key number */ -} -ZB_PACKED_STRUCT -zb_nvram_neighbour_rec_v0_t; - - -typedef ZB_PACKED_PRE struct zb_nvram_neighbour_rec_v1_s -{ - zb_address_ieee_ref_t addr_ref; /*!< Neighbor address */ - zb_bitfield_t depth:4; /*!< Device depth */ - zb_bitfield_t rx_on_when_idle:1; /*!< Store device rx On when idle state */ - zb_bitfield_t relationship:3; /*!< The relationship with nbr device, see @ref nwk_relationship */ - zb_bitfield_t device_type:2; /*!< Neighbor device type - @see @ref nwk_device_type */ - zb_bitfield_t nwk_ed_timeout:4; /*!< ED timeout value (for Child Aging) */ - zb_bitfield_t reserved:2; - zb_uint8_t key_seq_number; /*!< key number */ -} -ZB_PACKED_STRUCT -zb_nvram_neighbour_rec_v1_t; - -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_neighbour_rec_v1_t); - -typedef ZB_PACKED_PRE struct zb_nvram_neighbour_rec_v2_s -{ - zb_address_ieee_ref_t addr_ref; /*!< Neighbor address */ - zb_bitfield_t depth:4; /*!< Device depth */ - zb_bitfield_t rx_on_when_idle:1; /*!< Store device rx On when idle state */ - zb_bitfield_t relationship:3; /*!< The relationship with nbr device, see @ref nwk_relationship */ - zb_bitfield_t device_type:2; /*!< Neighbor device type - @see @ref nwk_device_types */ - zb_bitfield_t nwk_ed_timeout:4; /*!< ED timeout value (for Child Aging) */ - zb_bitfield_t reserved:2; - zb_uint8_t key_seq_number; /*!< key number */ - zb_uint8_t mac_iface_idx; /*!< Mac Interface Table index */ - zb_uint8_t align[3]; /*!< Reserved for future use */ -} -ZB_PACKED_STRUCT -zb_nvram_neighbour_rec_v2_t; - -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_neighbour_rec_v2_t); - -typedef ZB_PACKED_PRE struct zb_nvram_page_hdr_dataset_s -{ - /*!< Version of dataset structures stored in NVRAM (simple counter) - * One version for all datasets. */ - zb_nvram_ver_t version; - zb_uint8_t aligned[4-sizeof(zb_nvram_ver_t)]; -} -zb_nvram_page_hdr_dataset_t; - -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_nvram_page_hdr_dataset_t); - -typedef enum zb_nvram_zcl_reporting_data_ds_versions_e -{ - ZB_NVRAM_ZCL_REPORTING_DATA_DS_VER_1 = 0, -} -zb_nvram_zcl_reporting_data_ds_versions_t; - -#define ZB_NVRAM_ZCL_REPORTING_DATA_DS_VER ZB_NVRAM_ZCL_REPORTING_DATA_DS_VER_1 - -/** - * @name NVRAM APS secure data dataset version - * @anchor nvram_aps_secure_data_ds_versions - * - * Note: These values were members of `enum zb_nvram_aps_secure_data_ds_versions_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_NVRAM_APS_SECURE_DATA_DS_VER_1 0U -/** @} */ - -#define ZB_NVRAM_APS_SECURE_DATA_DS_VER ZB_NVRAM_APS_SECURE_DATA_DS_VER_1 - -typedef enum zb_nvram_installcodes_ds_versions_e -{ - ZB_NVRAM_INSTALLCODES_DS_VER_1 = 0, -} -zb_nvram_installcodes_ds_versions_t; - -#define ZB_NVRAM_INSTALLCODES_DS_VER ZB_NVRAM_INSTALLCODES_DS_VER_1 - -#ifdef ZB_ENABLE_ZGP - -extern zb_ret_t zb_nvram_write_zgp_proxy_table_dataset(zb_uint8_t page, zb_uint32_t pos); -extern void zb_nvram_read_zgp_proxy_table_dataset(zb_uint8_t page, zb_uint32_t pos, zb_uint16_t length, - zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver); -extern zb_uint16_t zb_nvram_zgp_proxy_table_length(void); -extern void zb_nvram_update_zgp_proxy_tbl_offset(zb_uint8_t page, zb_uint32_t dataset_pos, zb_uint32_t pos); - -extern zb_ret_t zb_nvram_write_zgp_sink_table_dataset(zb_uint8_t page, zb_uint32_t pos); -extern void zb_nvram_read_zgp_sink_table_dataset(zb_uint8_t page, zb_uint32_t pos, zb_uint16_t length, - zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver); -extern zb_uint16_t zb_nvram_zgp_sink_table_length(void); -extern void zb_nvram_update_zgp_sink_tbl_offset(zb_uint8_t page, zb_uint32_t dataset_pos, zb_uint32_t pos); - -extern zb_ret_t zb_zgp_nvram_write_app_tbl_dataset(zb_uint8_t page, zb_uint32_t pos); -extern void zb_zgp_nvram_read_app_tbl_dataset(zb_uint8_t page, zb_uint32_t pos, zb_uint16_t length, - zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver); -extern zb_uint16_t zb_zgp_nvram_app_tbl_length(void); - -extern zb_ret_t zb_nvram_write_zgp_cluster_dataset(zb_uint8_t page, zb_uint32_t pos); -extern void zb_nvram_read_zgp_cluster_dataset( - zb_uint8_t page, zb_uint32_t pos, zb_uint16_t length, zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver); -extern zb_uint16_t zb_nvram_zgp_cluster_length(void); - -#endif - -/****************************/ - -#ifdef APP_ONLY_NVRAM -/** - Initialize local version of nvram. - - @note This function is for utilities which uses nvram but not ZBOSS. - Never call it from your applications linked with ZBOSS. - */ -void zb_nvram_local_init(void *id); -#endif /* APP_ONLY_NVRAM */ - -/** - Load Informational Bases from NVRAM or file - */ -void zb_nvram_load(void); - -#ifdef ZB_ZBOSS_DEINIT -/** - Denit nvram - */ -void zb_nvram_deinit(void); -#endif - -/** - Save Informational Bases to NVRAM or other persistent storage - */ -void zb_nvram_save_all(void); - -#ifdef ZB_USE_INTERNAL_HEADERS -/** - Erase Informational Bases to NVRAM or other persistent storage - */ -void zb_nvram_erase(void); -#endif - -zb_ret_t zb_nvram_write_start(zb_nvram_dataset_hdr_t *hdr); -zb_ret_t zb_nvram_write_end(zb_nvram_dataset_hdr_t *hdr); - -void zb_nvram_erase_finished(zb_uint8_t page); - -void zb_nvram_write_empty_dataset(zb_nvram_dataset_types_t t); - -zb_ret_t zb_osif_erase_nvram_trace_sector(void); - -void zb_nvram_store_addr_n_nbt(void); - - -#ifdef ZB_NVRAM_ENABLE_DIRECT_API -zb_ret_t zb_nvram_write_dataset_direct(zb_nvram_dataset_types_t dataset_type, - zb_uint16_t dataset_version, - zb_uint8_t *buf, zb_uint16_t data_len); - - -zb_ret_t zb_nvram_read_dataset_direct(zb_nvram_dataset_types_t dataset_type, - zb_uint8_t *buf, - zb_size_t buf_len, - zb_uint16_t *dataset_version, - zb_uint16_t *dataset_length, - zb_uint16_t *nvram_version); - -#endif /* defined ZB_NVRAM_ENABLE_DIRECT_API */ - - -#if defined(ZB_ENABLE_ZCL) && !(defined ZB_ZCL_DISABLE_REPORTING) - -void zb_nvram_read_zcl_reporting_dataset( - zb_uint8_t page, zb_uint32_t pos, zb_uint16_t length, zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver); - -zb_ret_t zb_nvram_write_zcl_reporting_dataset(zb_uint8_t page, zb_uint32_t pos); - -zb_uint16_t zb_nvram_zcl_reporting_dataset_length(void); - -#endif /* defined(ZB_ENABLE_ZCL) && !(defined ZB_ZCL_DISABLE_REPORTING) */ - - -#if defined ZB_ENABLE_HA - -void zb_nvram_read_ha_dataset( -zb_uint8_t page, zb_uint32_t pos, zb_uint16_t len, zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver); - -zb_ret_t zb_nvram_write_ha_dataset(zb_uint8_t page, zb_uint32_t pos); - -#endif /* defined ZB_ENABLE_HA*/ - - -#if defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN - -void zb_nvram_read_poll_control_dataset( - zb_uint8_t page, zb_uint32_t pos, zb_uint16_t len, zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver); - -zb_ret_t zb_nvram_write_poll_control_dataset(zb_uint8_t page, zb_uint32_t pos); - -#endif /* defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN */ - -#define ZB_ERROR_NVRAM_READ_FAILURE 1 -#define ZB_ERROR_NVRAM_WRITE_FAILURE 2 - -#if defined(ZDO_DIAGNOSTICS) - -zb_uint16_t zb_nvram_diagnostics_dataset_length(void); - -void zb_nvram_read_diagnostics_dataset( - zb_uint8_t page, zb_uint32_t pos, zb_uint16_t len, zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver); - -zb_ret_t zb_nvram_write_diagnostics_dataset(zb_uint8_t page, zb_uint32_t pos); - -#endif /* ZDO_DIAGNOSTICS */ - -typedef zb_bool_t (*zb_nvram_ds_filter_cb_t)(zb_uint16_t ds_type); -typedef zb_size_t (*zb_nvram_ds_get_length_cb_t)(zb_uint16_t ds_type); -typedef zb_uint16_t (*zb_nvram_ds_get_version_cb_t)(zb_uint16_t ds_type); -typedef void (*zb_nvram_ds_read_cb_t)(zb_uint16_t ds_type, - zb_uint8_t page, - zb_uint32_t pos, - zb_uint16_t len, - zb_nvram_ver_t nvram_ver, - zb_uint16_t ds_ver); -typedef zb_ret_t (*zb_nvram_ds_write_cb_t)(zb_uint16_t ds_type, - zb_uint8_t page, - zb_uint32_t pos); - -zb_ret_t zb_nvram_custom_ds_try_read(zb_uint16_t ds_type, - zb_uint8_t page, - zb_uint32_t pos, - zb_uint16_t len, - zb_nvram_ver_t nvram_ver, - zb_uint16_t ds_ver); - -zb_ret_t zb_nvram_custom_ds_try_write(zb_uint16_t ds_type, - zb_uint8_t page, - zb_uint32_t pos); - -zb_ret_t zb_nvram_custom_ds_try_get_length(zb_uint16_t ds_type, - zb_size_t *len); - -zb_bool_t zb_nvram_custom_ds_is_supported(zb_uint16_t ds_type); - - -zb_ret_t zb_nvram_custom_ds_register(zb_nvram_ds_filter_cb_t filter, - zb_nvram_ds_get_length_cb_t get_length, - zb_nvram_ds_get_version_cb_t get_version, - zb_nvram_ds_read_cb_t read, - zb_nvram_ds_write_cb_t write); - -#endif /* ZB_USE_NVRAM */ - -#endif /* ZB_NVRAM_H */ diff --git a/zboss/development/src/include/zb_nvram_globals.h b/zboss/development/src/include/zb_nvram_globals.h deleted file mode 100644 index d45365c72e..0000000000 --- a/zboss/development/src/include/zb_nvram_globals.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Zigbee nvram management -*/ - -#ifndef ZB_NVRAM_GLOBAL_H -#define ZB_NVRAM_GLOBAL_H 1 - -#if defined ZB_USE_NVRAM || defined doxygen - -#include "zb_nvram.h" - -typedef struct zb_nvram_pos_payload_checker_s -{ - zb_lbitfield_t pos:30; - zb_lbitfield_t page:2; - zb_uint16_t payload_length; - zb_uint16_t crc; /* < CRC field is needed to accumulate crc while writing */ -} zb_nvram_pos_payload_checker_t; - -typedef ZB_PACKED_PRE struct zb_nvram_page_state_s -{ - zb_nvram_ver_t nvram_ver; - zb_bitfield_t erased:1; - zb_bitfield_t erase_in_progress:1; - zb_bitfield_t reserved:6; - zb_bitfield_t alignment:8; -} ZB_PACKED_STRUCT zb_nvram_page_state_t; - -#define ZB_NVRAM_MAX_N_PAGES 2U - -#ifdef ZB_NVRAM_ENABLE_DIRECT_API - -typedef struct zb_nvram_ds_pos_s -{ - zb_uint32_t pos; - zb_uint8_t page; -} zb_nvram_ds_pos_t; - -#endif /* ZB_NVRAM_ENABLE_DIRECT_API */ - -typedef struct zb_nvram_custom_ds_entry_s -{ - zb_nvram_ds_filter_cb_t filter; - zb_nvram_ds_get_length_cb_t get_length; - zb_nvram_ds_get_version_cb_t get_version; - zb_nvram_ds_read_cb_t read; - zb_nvram_ds_write_cb_t write; -} zb_nvram_custom_ds_entry_t; - -#define ZB_NVRAM_CUSTOM_DS_MAX_NUMBER 2U - -typedef struct zb_nvram_custom_ds_ctx_s -{ - zb_nvram_custom_ds_entry_t handlers[ZB_NVRAM_CUSTOM_DS_MAX_NUMBER]; - zb_size_t ds_cnt; -} zb_nvram_custom_ds_ctx_t; - - -/** - NVRAM global context -*/ -typedef struct zb_nvram_globals_s -{ - zb_nvram_read_app_data_t read_app_data_cb[ZB_NVRAM_APP_DATASET_NUMBER]; - zb_nvram_write_app_data_t write_app_data_cb[ZB_NVRAM_APP_DATASET_NUMBER]; - zb_nvram_get_app_data_size_t get_app_data_size_cb[ZB_NVRAM_APP_DATASET_NUMBER]; - zb_nvram_custom_ds_ctx_t custom_ds_ctx; - - zb_nvram_ds_filter_cb_t ds_filter_cb; /*!< If assigned function to be called to filter out some datasets at load */ - zb_nvram_tl_t current_time_label; /*!< Current time label. Max from wrote NVRAM dataset header */ - zb_nvram_page_state_t pages[ZB_NVRAM_MAX_N_PAGES]; - zb_uint32_t current_pos; /*!< Index of first free byte in Current Page NVRAM */ - zb_uint8_t current_page; /*!< Current page NVRAM */ - - zb_bitfield_t refresh_flag:1; /*! flag indicating that device need to store counters as soon as it increment it */ - zb_bitfield_t transaction_ongoing:1; /*!< @see @ref nvram_transaction_state */ - zb_bitfield_t empty:1; /*!< if true, NVRAM is empty (maybe, except NWK - * counter), so device is factory new */ - zb_bitfield_t inited:1; /*!< if true, NVRAM is inited (read/write operations are - * allowed) */ - zb_bitfield_t alignment:4; - -#ifdef ZB_NVRAM_ENABLE_DIRECT_API - /* positions of datasets; updated on each write operation; used for read operations */ - zb_nvram_ds_pos_t ds_pos[ZB_NVRAM_DATASET_NUMBER]; -#endif /* ZB_NVRAM_ENABLE_DIRECT_API */ - - /* Actually useful at Nordic only. Move it out of there? */ - volatile zb_uint_t op_in_progress; - - /* Checker for nvram read/write calls */ - zb_nvram_pos_payload_checker_t gs_nvram_write_checker; - zb_nvram_pos_payload_checker_t gs_nvram_read_checker; - zb_nvram_pos_payload_checker_t gs_nvram_read_checker_cache; - -} zb_nvram_globals_t; - -#define ZB_NVRAM() ZG->nvram - -#endif - - -#endif /* ZB_NVRAM_GLOBAL_H */ diff --git a/zboss/development/src/include/zb_nwk.h b/zboss/development/src/include/zb_nwk.h deleted file mode 100644 index ac449bc123..0000000000 --- a/zboss/development/src/include/zb_nwk.h +++ /dev/null @@ -1,2203 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Network layer API -*/ - -#ifndef ZB_NWK_H -#define ZB_NWK_H 1 - -#include "zb_mac.h" -#include "zb_nwk_nib.h" -#include "zb_nwk_mm.h" -#include "zb_nwk_ed_aging.h" - -/** \addtogroup nwk_api */ -/** @{ */ - -/** @name NWK common constants and API. - * @{ - */ - -/** - * @name NWK layer status values - * @anchor nwk_status - * @see ZB spec, clause 3.7 - */ -/** @{ */ -/** A request has been executed successfully. */ -#define ZB_NWK_STATUS_SUCCESS 0x00U -/** An invalid or out-of-range parameter has been passed to a primitive from the next higher layer. - */ -#define ZB_NWK_STATUS_INVALID_PARAMETER 0xC1U -/** The next higher layer has issued a request that is invalid or cannot be executed given the - * current state of the NWK layer. */ -#define ZB_NWK_STATUS_INVALID_REQUEST 0xC2U -/** An NLME-JOIN.request has been disallowed. */ -#define ZB_NWK_STATUS_NOT_PERMITTED 0xC3U -/** An NLME-NETWORK-FORMATION.request has failed to start a network. */ -#define ZB_NWK_STATUS_STARTUP_FAILURE 0xC4U -/** A device with the address supplied to the NLMEDIRECT-JOIN.request is already present in the - * neighbor table of the device on which the NLMEDIRECT-JOIN.request was issued. */ -#define ZB_NWK_STATUS_ALREADY_PRESENT 0xC5U -/** Used to indicate that an NLME-SYNC.request has failed at the MAC layer. */ -#define ZB_NWK_STATUS_SYNC_FAILURE 0xC6U -/** An NLME-JOIN-DIRECTLY.request has failed because there is no more room in the neighbor table. */ -#define ZB_NWK_STATUS_NEIGHBOR_TABLE_FULL 0xC7U -/** An NLME-LEAVE.request has failed because the device addressed in the parameter list is not in - * the neighbor table of the issuing device. */ -#define ZB_NWK_STATUS_UNKNOWN_DEVICE 0xC8U -/** An NLME-GET.request or NLME-SET.request has been issued with an unknown attribute identifier. - */ -#define ZB_NWK_STATUS_UNSUPPORTED_ATTRIBUTE 0xC9U -/** An NLME-JOIN.request has been issued in an environment where no networks are detectable. */ -#define ZB_NWK_STATUS_NO_NETWORKS 0xCAU -/** Security processing has been attempted on an outgoing frame, and has failed because the frame - * counter has reached its maximum value. */ -#define ZB_NWK_STATUS_MAX_FRM_COUNTER 0xCCU -/** Security processing has been attempted on an outgoing frame, and has failed because no key was - * available with which to process it. */ -#define ZB_NWK_STATUS_NO_KEY 0xCDU -/** Security processing has been attempted on an outgoing frame, and has failed because the security - * engine produced erroneous output. */ -#define ZB_NWK_STATUS_BAD_CCM_OUTPUT 0xCEU -/** An attempt to discover a route has failed due to a lack of routing table or discovery table - * capacity. */ -#define ZB_NWK_STATUS_NO_ROUTING_CAPACITY 0xCFU -/** An attempt to discover a route has failed due to a reason other than a lack of routing capacity. - */ -#define ZB_NWK_STATUS_ROUTE_DISCOVERY_FAILED 0xD0U -/** An NLDE-DATA.request has failed due to a routing failure on the sending device. */ -#define ZB_NWK_STATUS_ROUTE_ERROR 0xD1U -/** An attempt to send a broadcast frame or member mode multicast has failed due to the fact that - * there is no room in the BTT. */ -#define ZB_NWK_STATUS_BT_TABLE_FULL 0xD2U -/** An NLDE-DATA.request has failed due to insufficient buffering available. A non-member mode - * multicast frame was discarded pending route discovery. */ -#define ZB_NWK_STATUS_FRAME_NOT_BUFFERED 0xD3U -/** An attempt was made to use a MAC Interface with state that is currently set to FALSE (disabled) - * or that is unknown to the stack. */ -#define ZB_NWK_STATUS_INVALID_INTERFACE 0xD5U -/** A request was interrupted by a higher layer. */ -#define ZB_NWK_STATUS_INTERRUPTED 0xD6U -/** An error occurred during executing a request. */ -#define ZB_NWK_STATUS_ERROR 0xD7U -/** @} */ - -/** - * @brief Type for NWK layer status values. - * - * Holds one of @ref nwk_status. Kept only for backward compatibility as - * @ref nwk_status were declared previously as enum. - */ -typedef zb_uint8_t zb_nwk_status_t; - -/** @brief Multicast types mode. */ -typedef enum zb_nwk_multicast_mode_e -{ - ZB_NWK_MULTICAST_MODE_NONMEMBER = 0x00, /**< Multicast non-member mode*/ - ZB_NWK_MULTICAST_MODE_MEMBER = 0x01 /**< Multicast member mode*/ -} -zb_nwk_multicast_mode_t; - -#ifdef ZB_APSDE_REQ_ROUTING_FEATURES -/** - * @name NLDE non-spec extension values - * @anchor nlde_tx_opt - * - * Note: These values were members of `enum zb_nlde_tx_opt_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -/** Non-spec extension: Force mesh route discovery */ -#define ZB_NLDE_OPT_FORCE_MESH_ROUTE_DISC (1U << 0) -/** Non-spec extension: Force send route record */ -#define ZB_NLDE_OPT_FORCE_SEND_ROUTE_REC (1U << 1) -/** Non-spec extension: Force send route record. Auxiliary bitfield for marking route as many-to-one - * for force rrec sending */ -#define ZB_NLDE_OPT_TEMPORARY_MARK_ROUTE_AS_MTO (1U << 2) -/** @} */ - -/** - * @brief Type for possible values of NLDE non-spec extension values. - * - * @deprecated holds one of @ref nlde_tx_opt. Kept only for backward - * compatibility as @ref nlde_tx_opt were declared previously as enum. Can be - * removed in future releases. - */ -typedef zb_uint8_t zb_nlde_tx_opt_e; -#endif - -/** @brief 'frame security failed' status mentioned in ZB spec, subclause 4.3.1.2. - * - * Security Processing of Incoming Frames but not defined in the table 3.42 Status Codes for - * Network Status Command Frame - * - * Really need this status for intra-pan portability procedure (AZD601,602). Let's use other - * security status code. - */ -#define ZB_NWK_COMMAND_STATUS_FRAME_SECURITY_FAILED ZB_NWK_COMMAND_STATUS_BAD_KEY_SEQUENCE_NUMBER -/** @brief Check that NWK command status is security-related. - * @param st - status code - * @return 1 if NWK command status is security-related - */ -#define ZB_NWK_COMMAND_STATUS_IS_SECURE(st) \ - ((st) == ZB_NWK_COMMAND_STATUS_BAD_FRAME_COUNTER || (st) == \ - ZB_NWK_COMMAND_STATUS_BAD_KEY_SEQUENCE_NUMBER || (st) == \ - ZB_NWK_COMMAND_STATUS_FRAME_SECURITY_FAILED) - -/** @} */ /* NWK common constants and API. */ - -/** - * @name NWK data service. - * @{ - */ - -/** @brief Parameters for NLDE-DATA.request primitive. */ -typedef struct zb_nlde_data_req_s -{ - zb_uint16_t dst_addr; /**< Destination address. */ - zb_uint8_t radius; /**< The distance, in hops, that a frame will be allowed to travel - * through the network. */ - zb_uint8_t addr_mode; /**< The type of destination address supplied by the DstAddr parameter, - * see @ref address_modes */ - zb_uint8_t nonmember_radius; /**< The distance, in hops, that a multicast frame will be relayed - * by nodes not a member of the group. A value of 0x07 is treated - * as infinity. */ - zb_uint8_t discovery_route; /**< The DiscoverRoute parameter may be used to control route - * discovery operations for the transit of this frame (see - * sub-clause3.6.3.5): 0x00 = suppress route discovery 0x01 = enable - * route discovery */ - zb_uint8_t security_enable; /**< The SecurityEnable parameter may be used to enable NWK layer - * security processing for the current frame. If the - * nwkSecurityLevel attribute of the NIB has a value of 0, meaning - * no security, then this parameter will be ignored. Otherwise, - * a value of TRUE denotes that the security processing specified by - * the security level will be applied, and a value of FALSE denotes - * that no security processing will be applied. */ - zb_uint8_t ndsu_handle; /**< The handle associated with the NSDU to be transmitted by the NWK - * layer entity. */ - /*3.2.1.1.1 spec r21*/ - /* 14/06/2016 CR [AEV] start */ -#ifdef ZB_USEALIAS - zb_uint8_t use_alias; /**nwk.handle.parent); - * TRACE_MSG( - * TRACE_APS3, "parent %hd parent_addr %d", (FMT__H_D, ZG->nwk.handle.parent, dst_addr)); - * - * req->dst_addr = dst_addr; - * req->radius = 0; /-- use default --/ - * req->addr_mode = ZB_ADDR_16BIT_DEV_OR_BROADCAST; - * req->discovery_route = 0; - * req->security_enable = 0; - * req->ndsu_handle = 10; - * - * TRACE_MSG(TRACE_APS3, "Sending nlde_data.request", (FMT__0)); - * ZB_SCHEDULE_CALLBACK(zb_nlde_data_request, ZB_REF_FROM_BUF(buf)); - * } - * @endcode - */ -void zb_nlde_data_request(zb_uint8_t param); - -/** @brief NLDE-DATA.confirm primitive. - * - * This function called via scheduler by the NWK layer to indicate NLDE-DATA.request result to the - * APS layer. - * @note zb_nlde_data_confirm must be defined in the APS layer! - * NWK layer just calls this function. NWK and lower lagers does not free nsdu. APS must do it (or it can reuse - * it, transmit to the another address etc). - * @param param - sent packet, see @ref zb_buf_t. APS must free or reuse it. Following packet - * fields are used: - * @li status - The status of the corresponding request. Can take values: INVALID_REQUEST, - * MAX_FRM_COUNTER, NO_KEY, BAD_CCM_OUTPUT, ROUTE_ERROR, BT_TABLE_FULL, FRAME_NOT_BUFFERED or any - * status values returned from security suite or the MCPS-DATA.confirm primitive. - * @li handle - The handle associated with the NSDU being confirmed. - */ -void zb_nlde_data_confirm(zb_uint8_t param); - -/** @brief NLDE-DATA.indication primitive. - * - * This function called via scheduler by the NWK layer to pass incoming data packet to the APS - * layer. - * @note zb_nlde_data_indication() must be defined in the APS layer! WK layer just calls this function. - * @param param - The set of octets comprising the NSDU to be transferred (with length). - * - * Other fields got from MAC nsdu by macros - */ -void zb_nlde_data_indication(zb_uint8_t param); - -/** @} */ /* NWK data service. */ - -/** - * @name NWK management service. - * @{ - */ - -/** @brief Arguments of the NLME-GET.request routine. */ -typedef ZB_PACKED_PRE struct zb_nlme_get_request_s -{ - zb_nib_attribute_t nib_attribute; /**< Attribute value, see @ref zb_nib_attribute_t. */ - zb_callback_t confirm_cb; /*!< User's callback to be called as NLME-GET.confirm */ -} ZB_PACKED_STRUCT -zb_nlme_get_request_t; - -/** @brief NLME-GET.request primitive. - * - * Perform get NIB attribute. - * @param param - buffer containing parameters, see @ref zb_nlme_get_request_s. - * @return RET_OK on success, error code otherwise. - * - * @snippet start_ze.c zb_nlme_get_request - * - */ -void zb_nlme_get_request(zb_uint8_t param); - -/** @brief Arguments of the NLME-GET.confirm routine. */ -typedef ZB_PACKED_PRE struct zb_nlme_get_confirm_s -{ - zb_nwk_status_t status; /**< The result of the operation. */ - zb_nib_attribute_t nib_attribute; /**< Attribute value, see @ref zb_nib_attribute_t. */ - zb_uint16_t attribute_length; /**< Length of the attribute's value. */ - /* next is attribute value */ -} ZB_PACKED_STRUCT -zb_nlme_get_confirm_t; - -/** @brief Arguments of the NLME-SET.request routine. */ -typedef ZB_PACKED_PRE struct zb_nlme_set_request_s -{ - zb_nib_attribute_t nib_attribute; /**< Attribute value, see @ref zb_nib_attribute_t. */ - zb_uint16_t attr_length; /**< Size of nib_attribute. */ - zb_callback_t confirm_cb; /*!< User's callback to be called as NLME-SET.confirm */ -} ZB_PACKED_STRUCT -zb_nlme_set_request_t; - -/** @brief NLME-SET.request primitive. - * - * Perform set NIB attribute. - * @param param - buffer containing parameters, see @ref zb_nlme_set_request_s. - * @return RET_OK on success, error code otherwise. - * - * @snippet start_ze.c zb_nlme_set_request - * - */ -void zb_nlme_set_request(zb_uint8_t param); - -/** @brief Arguments of the NLME-SET.confirm routine. */ -typedef ZB_PACKED_PRE struct zb_nlme_set_confirm_s -{ - zb_nwk_status_t status; /**< The result of the operation. */ - zb_nib_attribute_t nib_attribute; /**< Attribute value, see @ref zb_nib_attribute_t. */ -} ZB_PACKED_STRUCT -zb_nlme_set_confirm_t; - -/** - Network discovery request parameters. - This structure describe parameters passed to - zb_nlme_network_discovery_request call. - - This structure is not packed intentionally: scan_channels_list should be aligned -*/ -typedef struct zb_nlme_network_discovery_request_s -{ - zb_channel_list_t scan_channels_list; /**< A list of channel pages and the channels - * within those pages that the discovery shall - * be performed upon. */ - zb_uint8_t scan_duration; /**< Time to spend scanning each channel */ - zb_callback_t cb; /* used by zb_zdo_active_scan_request */ -} -zb_nlme_network_discovery_request_t; - -/** - NLME-NETWORK-DISCOVERY.request primitive - - This function return immediately. - Later zb_nlme_network_discovery_confirm will be called to pass NLME-NETWORK-DISCOVERY.confirm result up. - - @param param - buffer containing parameters - @see - zb_nlme_network_discovery_request_t - @return nothing - */ -void zb_nlme_network_discovery_request(zb_uint8_t param); - - -void zb_nwk_cancel_network_discovery(zb_bufid_t buf); - - -/** @brief Network descriptor. - * This is a part of network discovery confirm result. - */ -typedef ZB_PACKED_PRE struct zb_nlme_network_descriptor_s -{ - zb_bitfield_t panid_ref:7; /**< Reference to extended Pan ID - * of the network. Was zb_address_pan_id_ref_t. - * Must be big enough to hold ZB_PANID_TABLE_SIZE. - * ZB_PANID_TABLE_SIZE is now 16, so 7 is more than enough. - */ - zb_bitfield_t channel_page:5; /**< channel page. in r22 0 to 31 */ - zb_bitfield_t logical_channel:6; /**< The current logical channel occupied by - * the network. In r22 0 to 63 */ - /* use bitfields to fit descriptors array to the single buffer */ - zb_bitfield_t stack_profile:2; /**< Stack profile identifier. 4 bits by - * standard, but need 2 bits - * actually. */ -#if 0 - /* Defined by standard, but not actually required for us */ - zb_bitfield_t Zigbee_version:4; /**< The version of the Zigbee protocol */ - zb_bitfield_t beacon_order:4; /**< How often the MAC sub-layer beacon is to - * be transmitted */ - zb_bitfield_t superframe_order:4; /**< The length of the active period of the - * superframe */ -#endif - zb_bitfield_t permit_joining:1; /**< Indicates that at least one router on - * the network currently permits joining */ - zb_bitfield_t router_capacity:1; /**< True if device is capable of accepting - * join requests from router-capable devices */ - zb_bitfield_t end_device_capacity:1; /**< True if device is capable of accepting - * join requests from end devices */ - zb_bitfield_t processed:1; /**< True if record is processed */ - zb_uint8_t nwk_update_id; -} ZB_PACKED_STRUCT -zb_nlme_network_descriptor_t; - -/** @brief Arguments of the NLME-NETWORK-DISCOVERY.confirm routine. */ -typedef ZB_PACKED_PRE struct zb_nlme_network_discovery_confirm_s -{ - zb_ret_t status; /**< Our error or MAC status codes (see Table 3-11 - * NLME-NETWORK-DISCOVERY.confirm Parameters: - * Any status value returned with the - * MLME-SCAN.confirm primitive.) */ - zb_uint8_t network_count; /**< Number of discovered networks */ - /* next here is an array of zb_nlme_network_descriptor_t */ -} ZB_PACKED_STRUCT -zb_nlme_network_discovery_confirm_t; - -/** @brief NLME-NETWORK-DISCOVERY.confirm primitive. - * - * Report the results of the network discovery operation. - * @param param - buffer containing results - see @ref zb_nlme_network_discovery_confirm_s. - * @note This structure is passed as data, not as parameter! - * @b Rationale: it has variable size, so it is - * not easy to define where it should begin in parameter. - * @return RET_OK on success, error code otherwise. - * - * @code - * ((zb_bufid_t )ZB_BUF_FROM_REF(param))->u.hdr.status = RET_BUSY; - * ZB_SCHEDULE_CALLBACK(zb_nlme_network_discovery_confirm, param); - * @endcode - */ -void zb_nlme_network_discovery_confirm(zb_uint8_t param); - -/** - Arguments of the NLME-NETWORK-FORMATION.request routine. -*/ -typedef struct zb_nlme_network_formation_request_s -{ - zb_channel_list_t scan_channels_list; /**< The list of all channel pages and - * the associated channels that shall be scanned. */ - zb_uint8_t scan_duration; /**< Time to spend scanning each channel */ - zb_uint8_t distributed_network; - zb_uint16_t distributed_network_address; - zb_ieee_addr_t extpanid; -#if 0 /* not supported by mac anyway */ - zb_uint8_t beacon_order; /**< The beacon order */ - zb_uint8_t superframe_order; /**< The superframe order */ - zb_uint8_t battery_life_extension; /**< If true - start support battery - * life extension */ -#endif -} -zb_nlme_network_formation_request_t; - -#ifdef ZB_FORMATION -/** - NLME-NETWORK-FORMATION.request primitive - - Starting new Zigbee network with itself as a coordinator. - - @param param - buffer containing parameters - @see - zb_nlme_network_formation_request_t - @return RET_OK on success, error code otherwise. - - @snippet zdo_app.c zb_nlme_network_formation_request - */ -void zb_nlme_network_formation_request(zb_uint8_t param); - -void zb_nwk_cancel_network_formation(zb_bufid_t param); - -#endif /* ZB_FORMATION */ - -/** - Arguments of the NLME-NETWORK-FORMATION.confirm routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_network_formation_confirm_s -{ - zb_nwk_status_t status; /**< MAC status codes */ -} ZB_PACKED_STRUCT -zb_nlme_network_formation_confirm_t; - -#ifdef ZB_FORMATION -/** - NLME-NETWORK-FORMATION.confirm primitive - - Report the results of the network formation request. - - @param param - buffer containing results - @see - zb_nlme_network_formation_confirm_t - @return RET_OK on success, error code otherwise. - */ -void zb_nlme_network_formation_confirm(zb_uint8_t param); -#endif /* ZB_FORMATION */ - -/** - Arguments of the NLME-NETWORK-FORMATION.confirm routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_permit_joining_confirm_s -{ - zb_mac_status_t status; /**< MAC status codes */ -} ZB_PACKED_STRUCT -zb_nlme_permit_joining_confirm_t; - -/** - NLME-PERMIT-JOINING.confirm primitive - - Report the results of the permit joining request. - - @param param - buffer containing results - @see - zb_nlme_permit_joining_confirm_t - @return RET_OK on success, error code otherwise. - - @snippet nwk_cr_permit_join.c zb_nlme_permit_joining_confirm - */ -void zb_nlme_permit_joining_confirm(zb_uint8_t param); - -/** - Arguments of the NLME-START-ROUTER.request routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_start_router_request_s -{ - zb_uint8_t beacon_order; /**< The beacon order */ - zb_uint8_t superframe_order; /**< The superframe order */ - zb_uint8_t battery_life_extension; /**< If true - start support battery - * life extension */ -} ZB_PACKED_STRUCT -zb_nlme_start_router_request_t; - -/** - NLME-START-ROUTER.request primitive - - Start router activity - - @param param - buffer containing parameters - @see - zb_nlme_start_router_request_t - @return RET_OK on success, error code otherwise. - - @snippet nwk_route_disc/nwk_route_discovery.c zb_nlme_start_router_request - - */ -void zb_nlme_start_router_request(zb_uint8_t param); - -/** - Arguments of the NLME-START-ROUTER.confirm routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_start_router_confirm_s -{ - zb_mac_status_t status; /**< MAC status codes */ -} ZB_PACKED_STRUCT -zb_nlme_start_router_confirm_t; - -/** - NLME-START-ROUTER.confirm primitive - - Report the results of the start router request. - - @param param - buffer containing results - @see - zb_nlme_start_router_confirm_t - @return RET_OK on success, error code otherwise. - - @code - NWK_CONFIRM_STATUS((zb_bufid_t )ZB_BUF_FROM_REF(param), ZB_NWK_STATUS_INVALID_REQUEST, zb_nlme_start_router_confirm); - @endcode - */ -void zb_nlme_start_router_confirm(zb_uint8_t param); - -/** - Channel energy info. -*/ -typedef ZB_PACKED_PRE struct zb_energy_detect_channel_info_s -{ - zb_bitfield_t channel_page_idx : 3; - zb_bitfield_t channel_number : 5; /*!< bit # in the channel mask. Note: not a logical channel! */ - zb_uint8_t energy_detected; -} ZB_PACKED_STRUCT zb_energy_detect_channel_info_t; - -/** - The structure is used to convey energy values for each channel that was scanned. -*/ -typedef ZB_PACKED_PRE struct zb_energy_detect_list_s -{ - zb_uint8_t channel_count; - zb_energy_detect_channel_info_t channel_info[ZB_ED_SCAN_MAX_CHANNELS_COUNT]; -} ZB_PACKED_STRUCT zb_energy_detect_list_t; - -/** - Arguments of the NLME-ED-SCAN.request routine. -*/ -typedef struct zb_nlme_ed_scan_request_s -{ - zb_channel_page_t scan_channels_list[ZB_CHANNEL_PAGES_NUM]; /**< The list of all channel pages and the - * associated channels that shall be scanned. */ - zb_uint8_t scan_duration; /**< Time to spend scanning each channel */ -} -zb_nlme_ed_scan_request_t; - - -/* ED Scan functions were under ZB_ROUTER_ROLE ifdef, - * but were switched on for all devices types (for WWAH, PICS item AZD514) */ - -/** - NLME-ED_SCAN.request primitive - - Start energy scan - - @param param - buffer containing parameters - @see - zb_nlme_ed_scan_request_t - @return RET_OK on success, error code otherwise. - */ -void zb_nlme_ed_scan_request(zb_uint8_t param); - -/** - Arguments of the NLME-ED-SCAN.confirm routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_ed_scan_confirm_s -{ - zb_mac_status_t status; /**< MAC status codes */ - zb_uint32_t unscanned_channels; /**< Indicate not scanned channels */ - /* next is the list of zb_uint8_t describes energy measurements */ -} ZB_PACKED_STRUCT -zb_nlme_ed_scan_confirm_t; - -/** - NLME-ED-SCAN.confirm primitive - - Report the results of the ed scan request. - - @param param - buffer containing results - @see - zb_nlme_ed_scan_confirm_t - @return RET_OK on success, error code otherwise. - */ -void zb_nlme_ed_scan_confirm(zb_uint8_t param); - - -/** - * @brief Parameters of the custom NLME-BEACON-SURVEY.request - */ -typedef ZB_PACKED_PRE struct zb_nlme_beacon_survey_scan_request_s -{ - /*!< Channel mask */ - zb_uint32_t channel_mask; - /*!< Channel page */ - zb_uint8_t channel_page; - /*!< Scan type of the 'Beacon Survey' procedure (see @mac_scan_type) */ - zb_uint8_t scan_type; -} -ZB_PACKED_STRUCT zb_nlme_beacon_survey_scan_request_t; - -/** - * @brief Starts of the Beacon Survey scan - * @param param - buffer containing - * @zb_nlme_beacon_survey_scan_request_t - */ -void zb_nlme_beacon_survey_scan(zb_uint8_t param); - -#if defined ZB_BEACON_SURVEY && defined ZB_ZCL_ENABLE_WWAH_SERVER -/** - * @brief Report the results of the Beacon Survey scan - * @param param - buffer containing @zb_mac_scan_confirm_t - */ -void zb_nlme_beacon_survey_scan_confirm(zb_uint8_t param); -#endif /* ZB_BEACON_SURVEY && ZB_ZCL_ENABLE_WWAH_SERVER */ - -/** - Network join method. -*/ -/** - * @name Network join method - * @anchor nlme_rejoin_method - */ -/** @{ */ -#define ZB_NLME_REJOIN_METHOD_ASSOCIATION 0x00U /**< Through association */ -#define ZB_NLME_REJOIN_METHOD_DIRECT 0x01U /**< Join directly or rejoining using the orphaning */ -#define ZB_NLME_REJOIN_METHOD_REJOIN 0x02U /**< Using NWK rejoin procedure */ -#define ZB_NLME_REJOIN_METHOD_CHANGE_CHANNEL 0x03U /**< Changing the network channel */ -/** @} */ - -/** - * @brief Type for network join method. - * - * Holds one of @ref nlme_rejoin_method. Kept only for backward compatibility as - * @ref nlme_rejoin_method were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_nlme_rejoin_method_t; - -/** - Arguments of the NLME-JOIN.request routine. -*/ -typedef struct zb_nlme_join_request_s -{ - zb_ext_pan_id_t extended_pan_id; /**< Extended Pan ID - * of the network */ - zb_channel_list_t scan_channels_list; /**< The list of all channel pages and - * the associated channels that shall be scanned. */ - zb_mac_capability_info_t capability_information; /**< The operating capabilities of the - * device */ - zb_nlme_rejoin_method_t rejoin_network; /**< Join network method @see @ref nlme_rejoin_method */ - zb_uint8_t scan_duration; /**< Time to spend scanning each channel */ - zb_uint8_t security_enable; /*!< If the value of RejoinNetwork is 0x02 and this is TRUE than the device will try to rejoin securely. - Otherwise, this is set to FALSE. */ - - /* There was insecure_rejoin: Insecure rejoining. Originally it was "secure_rejoin, - * as specified in the spec. But because by default it is set to - * ZB_FALSE (zero), let's handle it as "insecure" flag. */ -} -zb_nlme_join_request_t; - -/** - NLME-JOIN.request primitive - - Join to the network - - @param param - buffer containing parameters - @see - zb_nlme_join_request_t - @return RET_OK on success, error code otherwise. - - @snippet nwk_leave/zdo_start_zr.c zb_nlme_join_request - - */ -void zb_nlme_join_request(zb_uint8_t param); - -/** - Arguments of the NLME-JOIN.indication routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_join_indication_s -{ - zb_uint16_t network_address; /**< The network address of an entity */ - zb_ieee_addr_t extended_address; /**< 64-bit IEEE address of an entity */ - zb_mac_capability_info_t capability_information; /**< The operating capabilities of the - * device */ - zb_nlme_rejoin_method_t rejoin_network; /**< Join network method @see - * @ref nlme_rejoin_method */ - zb_uint8_t secure_rejoin; /**< Secure joining */ -} ZB_PACKED_STRUCT -zb_nlme_join_indication_t; - -/** - NLME-JOIN.indication primitive - - Notify about new joined device. - - @param param - buffer containing parameters - @see - zb_nlme_join_indication_t - @return RET_OK on success, error code otherwise. - */ -void zb_nlme_join_indication(zb_uint8_t param); - -/** - Arguments of the NLME-JOIN.confirm routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_join_confirm_s -{ - zb_ret_t status; /**< MAC or NWK status codes */ - zb_uint16_t network_address; /**< Allocated network address */ - zb_ext_pan_id_t extended_pan_id; /**< Extended Pan ID - * of the network */ - zb_uint8_t active_channel; /**< Current network channel */ -} ZB_PACKED_STRUCT -zb_nlme_join_confirm_t; - -/** - NLME-JOIN.confirm primitive - - Report the results of the join request. - - @param param - buffer containing results - @see zb_nlme_join_confirm_t - @return RET_OK on success, error code otherwise. - - @snippet doxygen_snippets.dox zb_nlme_join_confirm_nwk_nwk_join_c - */ -void zb_nlme_join_confirm(zb_uint8_t param); - -/** - Arguments of the NLME-DIRECT-JOIN.request routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_direct_join_request_s -{ - zb_ieee_addr_t device_address; /**< 64-bit IEEE address of the device to be directly joined */ - zb_mac_capability_info_t capability_information; /**< The operating capabilities of the device */ -} ZB_PACKED_STRUCT -zb_nlme_direct_join_request_t; - - -/** - Arguments of the NLME-DIRECT-JOIN.confirm routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_direct_join_confirm_s -{ - zb_nwk_status_t status; /**< MAC status codes */ - zb_ieee_addr_t device_address; /**< 64-bit IEEE address */ -} ZB_PACKED_STRUCT -zb_nlme_direct_join_confirm_t; - - -/** - Arguments of the NLME-LEAVE.request routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_leave_request_s -{ - zb_ieee_addr_t device_address; /**< 64-bit IEEE address of the device to - * remove, zero fill if device itself */ - zb_uint8_t rejoin; /**< If true - Join after leave */ -} ZB_PACKED_STRUCT -zb_nlme_leave_request_t; - -/** - NLME-LEAVE.request primitive - - Leave the network - - @param param - buffer containing parameters - @see - zb_nlme_leave_request_t - @return RET_OK on success, error code otherwise. - - */ -void zb_nlme_leave_request(zb_uint8_t param); - -/** - NLME-LEAVE.indication primitive - - Notify about leave device - - @param param - buffer containing parameters - @see - zb_nlme_leave_indication_t - @return RET_OK on success, error code otherwise. - - @code - zb_nlme_leave_indication_t *request = NULL; - request = ZB_BUF_GET_PARAM(ZB_BUF_FROM_REF(param), zb_nlme_leave_indication_t); - - if (addr_ref == (zb_address_ieee_ref_t)-1) - { - ZB_IEEE_ADDR_ZERO(request->device_address); - } - else - { - zb_address_ieee_by_ref(request->device_address, addr_ref); - } - request->rejoin = rejoin; - ZB_SCHEDULE_CALLBACK(zb_nlme_leave_indication, param); - @endcode - */ -void zb_nlme_leave_indication(zb_uint8_t param); - -/** - Arguments of the NLME-LEAVE.confirm routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_leave_confirm_s -{ - zb_nwk_status_t status; /**< MAC status codes */ - zb_ieee_addr_t device_address; /**< 64-bit IEEE address */ -} ZB_PACKED_STRUCT -zb_nlme_leave_confirm_t; - -/** - NLME-LEAVE.confirm primitive - - Report the results of the direct join request. - - @param param - buffer containing results - @see - zb_nlme_leave_confirm_t - @return RET_OK on success, error code otherwise. - - @code - zb_nlme_leave_confirm_t *lc = ZB_BUF_GET_PARAM(buf, zb_nlme_leave_confirm_t); - lc->status = (zb_nwk_status_t)buf->u.hdr.status; - if (dest_addr != 0xffff) - { - zb_address_ieee_by_short(dest_addr, lc->device_address); - } - else - { - ZB_IEEE_ADDR_ZERO(lc->device_address); - } - ZB_SCHEDULE_CALLBACK(zb_nlme_leave_confirm, param); - @endcode - */ -void zb_nlme_leave_confirm(zb_uint8_t param); - -/** - Arguments of the NLME-RESET.request routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_reset_request_s -{ - zb_bool_t warm_start; /**< if false - reset all stack values */ -} ZB_PACKED_STRUCT -zb_nlme_reset_request_t; - -/** - NLME-RESET.request primitive - - Perform reset operation - - @param param - buffer containing parameters - @see - zb_nlme_reset_request_t - @return RET_OK on success, error code otherwise. - - @snippet zdo_app.c zb_nlme_reset_request - */ -void zb_nlme_reset_request(zb_uint8_t param); - -/** - Arguments of the NLME-RESET.confirm routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_reset_confirm_s -{ - zb_nwk_status_t status; /**< The result of the operation */ -} ZB_PACKED_STRUCT -zb_nlme_reset_confirm_t; - -/** - NLME-RESET.confirm primitive - - Report the results of the reset request. - - @param param - buffer containing results - @see - zb_nlme_reset_confirm_t - @return RET_OK on success, error code otherwise. - - @code - NWK_CONFIRM_STATUS(buf, ZB_NWK_STATUS_INVALID_REQUEST, zb_nlme_reset_confirm); - @endcode - */ -void zb_nlme_reset_confirm(zb_uint8_t param); - -/** - Arguments of the NLME-SYNC.request routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_sync_request_s -{ - zb_uint8_t track; /**< Whether to not the sync should be maintained for - * future beacons */ - zb_time_t poll_rate; /*!< MAC poll rate */ -} ZB_PACKED_STRUCT -zb_nlme_sync_request_t; - -/** - NLME-SYNC.request primitive - - Perform sync operation - - @param param - buffer containing parameters - @see - zb_nlme_sync_request_t - @return RET_OK on success, error code otherwise. - - @snippet nwk_sync_ze.c zb_nlme_sync_request - */ -void zb_nlme_sync_request(zb_uint8_t param); - -/** - Arguments of the NLME-SYNC.confirm routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_sync_confirm_s -{ - zb_nwk_status_t status; /**< The result of the operation */ -} ZB_PACKED_STRUCT -zb_nlme_sync_confirm_t; - -/** - NLME-SYNC.confirm primitive - - Report the results of the sync request. - - @param param - buffer containing results - @see - zb_nlme_sync_confirm_t - @return RET_OK on success, error code otherwise. - */ -void zb_nlme_sync_confirm(zb_uint8_t param); - -/** - NLME-STATUS.indication primitive - - Notifies about network fails. - - @param param - buffer containing parameters - @see - zb_nlme_status_indication_t - @return RET_OK on success, error code otherwise. - - @code - zb_nlme_status_indication_t *cmd = ZB_BUF_GET_PARAM(ZB_BUF_FROM_REF(param), zb_nlme_status_indication_t); - cmd->status = (zb_nwk_command_status_t)status; - cmd->network_addr = addr_short; - ZB_SCHEDULE_CALLBACK(zb_nlme_status_indication, param); - @endcode - */ -void zb_nlme_status_indication(zb_uint8_t param); - -/** - Arguments of the NLME-ROUTE-DISCOVERY.request routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_route_discovery_request_s -{ - zb_addr_mode_t address_mode; /**< Kind of destination address provided, one of @ref address_modes */ - zb_uint16_t network_addr; /**< The destination of the route discovery */ - zb_uint8_t radius; /**< Number of hopes */ - zb_bool_t no_route_cache; /**< True - no route table should be - * established */ -} ZB_PACKED_STRUCT -zb_nlme_route_discovery_request_t; - -#ifndef ZB_LITE_NO_NLME_ROUTE_DISCOVERY -/** - NLME-ROUTE-DISCOVERY.request primitive - - Initiate a route discovery - - @param param - buffer containing parameters - @see - zb_nlme_route_discovery_request_t - @return RET_OK on success, error code otherwise. - - */ -void zb_nlme_route_discovery_request(zb_uint8_t param); - -/** - Arguments of the NLME-ROUTE-DISCOVERY.confirm routine. -*/ -typedef ZB_PACKED_PRE struct zb_nlme_route_discovery_confirm_s -{ - zb_uint8_t status; /**< @see nwk_status indeed */ -} ZB_PACKED_STRUCT -zb_nlme_route_discovery_confirm_t; - -/** - NLME-ROUTE-DISCOVERY.confirm primitive - - Report the results of the route discovery - - @param param - buffer containing results - @see - zb_nlme_route_discovery_confirm_t - @return RET_OK on success, error code otherwise. - */ -void zb_nlme_route_discovery_confirm(zb_uint8_t param); -#endif /* #ifndef ZB_LITE_NO_NLME_ROUTE_DISCOVERY */ - -/** @} */ /* NWK management service. */ - -/** @cond internals_doc */ - -/** @brief Arguments of the NLME-SEND-STATUS.confirm routine. */ -typedef ZB_PACKED_PRE struct zb_nlme_send_status_s -{ - zb_uint16_t dest_addr; /**< address to send status information to */ - zb_nlme_status_indication_t status; /**< status information, @ref zb_nlme_status_indication_s */ - zb_uint8_t ndsu_handle; /**< The handle associated with the NSDU to be transmitted by the NWK - * layer entity */ -} ZB_PACKED_STRUCT -zb_nlme_send_status_t; - - -/** @brief Send status indication primitive. - * - * Send status to the remote device. - * @param param - request params, see @ref zb_nlme_send_status_s. - * @return nothing. - * @b Example: - * @code - * { - * zb_nlme_send_status_t *request = ZB_BUF_GET_PARAM(ZB_BUF_FROM_REF(param), zb_nlme_send_status_t); - * - * request->dest_addr = 0; /-- send status indication to the coordinator --/ - * request->status.status = ZB_NWK_COMMAND_STATUS_LOW_BATTERY_LEVEL; - * request->status.network_addr = ZB_PIBCACHE_NETWORK_ADDRESS(); - * request->ndsu_handle = ZB_NWK_NON_INTERNAL_NSDU_HANDLE ; - * - * ZB_SCHEDULE_CALLBACK(zb_nlme_send_status, param); - * } - * @endcode - */ -void zb_nlme_send_status(zb_uint8_t param); - -/** @endcond */ /* internals_doc */ - -/** @} */ - -/** \addtogroup nwk_ib */ -/** @{ */ - -/** @internal @brief Size of link status command */ -#define ZB_LINK_STATUS_SIZE 3U - -#define ZB_NWK_LS_FIRST_FRAME_BIT 5U -#define ZB_NWK_LS_LAST_FRAME_BIT 6U - -#define ZB_NWK_LS_FIRST_FRAME_MASK (1U<> 4U) & 0x07U) -#define ZB_GET_INCOMING_COST(a) \ - (*((a) + sizeof(zb_uint16_t)) & 0x7U) -#define ZB_LS_SET_INCOMING_COST(a, b) ( *(a) = (*(a) & 0x70U) | ( (b) & 0x07U) ) -#define ZB_LS_SET_OUTGOING_COST(a, b) ( *(a) = (*(a) & 0x07U) | ( ((b) & 0x07U) << 4U) ) - -#define ZB_NWK_LS_GET_COUNT(a) ((a) & ZB_NWK_LS_COUNT_MASK) -#define ZB_NWK_LS_SET_COUNT(_a, _b) ((*(_a)) |= ((*(_a)) & (~ZB_NWK_LS_COUNT_MASK)) | (_b)) - -#define ZB_NWK_LS_SET_FIRST_FRAME(_a, _b) (*(_a)) |= (((*(_a)) & (~ZB_NWK_LS_FIRST_FRAME_MASK)) | ((_b)<> ZB_NWK_LS_FIRST_FRAME_BIT) - -#define ZB_NWK_LS_SET_LAST_FRAME(_a, _b) (*(_a)) |= (((*(_a)) & (~ZB_NWK_LS_LAST_FRAME_MASK)) | ((_b)<> ZB_NWK_LS_FIRST_FRAME_BIT) - - -/** @} */ - -/** @cond internals_doc */ -/** \addtogroup ZB_NWK */ -/** @{ */ - -/** @brief Initialize NWK stack layer. */ -void zb_nwk_init(void); - -/** \par Macros to compare network update ids taking overflow into account. - - No recommendations about compare in the specification. Now suppose overflow if difference - between values > 1/2 of the entire values diapason. Is it right? - */ -#define NWK_UPDATE_ID_MIDDLE 127 - -/** @return true if id1 >= id2, taking overflow into account. */ -#define ZB_NWK_UPDATE_ID1_GE_ID2(id1, id2) (((zb_uint8_t)(id1) - (zb_uint8_t)(id2)) < NWK_UPDATE_ID_MIDDLE) - -/** @return true if id1 < id2, taking overflow into account. */ -#define ZB_NWK_UPDATE_ID1_LT_ID2(id1, id2) (((zb_uint8_t)(id1) - (zb_uint8_t)(id2)) > NWK_UPDATE_ID_MIDDLE) - -/** @brief Check that link quality is good enough to attempt to join. - * - * According to 6.9.8 Link quality indicator (LQI), The minimum and maximum LQI values (0x00 and - * 0xff) should be associated with the lowest and highest quality compliant signals detectable by - * the receiver, and LQI values in between should be uniformly distributed between these two - * limits. At least eight unique values of LQI shall be used. - * - * Also, from 3.6.1.4.1.1 Child Procedure: - * - The link quality for frames received from this device is such that a link cost of at most - * 3 is produced when calculated as described in sub-clause 3.6.3.1. - * @return TRUE if it is ok to join to device with such LQI and FALSE otherwise - */ - -#define ZB_LINK_QUALITY_IS_OK_FOR_JOIN(lqi) (((lqi) / (256U / 8U)) >= 1U) - -/** @brief Compare link quality. - * @return TRUE if lqi1 > lqi2 - */ -#define ZB_LINK_QUALITY_1_IS_BETTER(lqi1, lqi2) ((lqi1) > (lqi2)) - -#if defined ZB_PRO_STACK && !defined ZB_NO_NWK_MULTICAST -/** @brief NWK multicast control. */ -typedef ZB_PACKED_PRE struct zb_nwk_multicast_control_field_s -{ - /* Better not use bitfields for protocols, use bitmask instead. But keep it now: multicast is already obsolete in r21. */ -#ifdef ZB_LITTLE_ENDIAN - zb_bitfield_t multicast_mode:2; /**< */ - zb_bitfield_t nonmember_radius:3; /**< */ - zb_bitfield_t max_nonmember_radius:3; /**< */ -#else - zb_bitfield_t max_nonmember_radius:3; /**< */ - zb_bitfield_t nonmember_radius:3; /**< */ - zb_bitfield_t multicast_mode:2; /**< */ -#endif -} ZB_PACKED_STRUCT -zb_nwk_multicast_control_field_t; -#endif /* multicast */ - -#define ZB_NWK_MULTICAST_CONTROL_FIELD_SIZE 1U - -/** \par macros to manipulate with nwk packet header. */ - -/** @brief NWK packet header. - - Fields up to seq_num always presents, other - depending on frame_control - contents. - - See 3.3.1 for the NWK header definition. - */ -typedef ZB_PACKED_PRE struct zb_nwk_nwk_hdr_s -{ - zb_uint8_t frame_control[2]; /**< Frame Control Field */ - zb_uint16_t dst_addr; /**< Destination 16-bit address */ - zb_uint16_t src_addr; /**< Source 16-bit address */ - zb_uint8_t radius; /**< Radius */ - zb_uint8_t seq_num; /**< Sequence Number */ - zb_ieee_addr_t dst_ieee_addr; /**< Destination 64-bit address */ - zb_ieee_addr_t src_ieee_addr; /**< Source 64-bit address */ -#if defined ZB_PRO_STACK && !defined ZB_NO_NWK_MULTICAST - zb_nwk_multicast_control_field_t mcast_control; /**< NWK multicast control */ -#else - zb_uint8_t mcast_control; -#endif -} ZB_PACKED_STRUCT zb_nwk_hdr_t; - -typedef ZB_PACKED_PRE struct zb_nwk_alloc_hdr_req_s -{ -#ifndef ZB_NO_NWK_MULTICAST - zb_bool_t is_multicast; -#endif - zb_bool_t is_secured; - zb_bool_t is_cmd_frame; - zb_bool_t is_has_src_ieee; - zb_bool_t is_has_dst_ieee; - zb_uint16_t src_addr; - zb_uint16_t dst_addr; - zb_ieee_addr_t dst_ieee_addr; - zb_ieee_addr_t src_ieee_addr; -} ZB_PACKED_STRUCT zb_nwk_alloc_hdr_req_t; - -/** @brief APSDE data indication params transmitted to upper layers */ -typedef ZB_PACKED_PRE struct zb_apsde_data_ind_params_s -{ - zb_uint16_t mac_dst_addr; /**< mac dst address. ZB_MAC_SHORT_ADDR_NOT_ALLOCATED - * if unknown or long */ - zb_uint16_t mac_src_addr; /**< mac src address. ZB_MAC_SHORT_ADDR_NOT_ALLOCATED - * if unknown or long */ - zb_uint8_t lqi; - - zb_int8_t rssi; - - zb_uint8_t handle; /**< handle for transmitted/received packet */ - - zb_uint8_t iface_id; /**< ID of MAC interface that received the packet */ -} ZB_PACKED_STRUCT zb_apsde_data_ind_params_t; - -/** @brief Frame type value from the NWK FCF field: data. */ -#define ZB_NWK_FRAME_TYPE_DATA 0U - -/** @brief Frame type value from the NWK FCF field: command. */ -#define ZB_NWK_FRAME_TYPE_COMMAND 1U - -/** @brief Zigbee protocol version for GPDF frames */ -#define ZB_ZGP_PROTOCOL_VERSION 0x03U - -/** \par NWK FCF stored in the order it transmitted over network. Bits access - macros takes care about using right bytes. No endian conversion is necessary. - See \see ZB_PKT_16B_ZERO_BYTE / \see ZB_PKT_16B_FIRST_BYTE definition for - details. - - See 3.3.1.1 for the NWK FCF definition. - */ - -/** @brief Get frame type from the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - */ -#define ZB_NWK_FRAMECTL_GET_FRAME_TYPE(fctl) ((fctl)[ZB_PKT_16B_ZERO_BYTE] & 3U) - -/** @brief Set frame type in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param t - frame type. - */ -#define ZB_NWK_FRAMECTL_SET_FRAME_TYPE(fctl, t ) ((fctl)[ZB_PKT_16B_ZERO_BYTE] |= (t)) - -/** @brief Get protocol version from the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. -*/ -#define ZB_NWK_FRAMECTL_GET_PROTOCOL_VERSION(fctl) (((fctl)[ZB_PKT_16B_ZERO_BYTE] >> 2U) & 0xfU) - -/** @brief Set protocol version in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param v - protocol version. - */ -#define ZB_NWK_FRAMECTL_SET_PROTOCOL_VERSION(fctl, v) ((fctl)[ZB_PKT_16B_ZERO_BYTE] |= ((v) << 2U)) - -/** @brief Set frame type and protocol version in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param t - frame type. - @param v - protocol version. - */ -#define ZB_NWK_FRAMECTL_SET_FRAME_TYPE_N_PROTO_VER(fctl, t, v) \ - ((fctl)[ZB_PKT_16B_ZERO_BYTE] |= ((t) | ((v) << 2U))) - -/** @brief Get 'discover route' from the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. -*/ -#define ZB_NWK_FRAMECTL_GET_DISCOVER_ROUTE(fctl) (((fctl)[ZB_PKT_16B_ZERO_BYTE] >> 5U) & 3U) - -/** @brief Set 'discover route' in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param r - 'discover route' value. - */ -#define ZB_NWK_FRAMECTL_SET_DISCOVER_ROUTE(fctl, r) ((fctl)[ZB_PKT_16B_ZERO_BYTE] |= ((r) << 6U)) - -#ifndef ZB_NO_NWK_MULTICAST -/** @brief Get multicast flag from the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. -*/ -#define ZB_NWK_FRAMECTL_GET_MULTICAST_FLAG(fctl) (((fctl)[ZB_PKT_16B_FIRST_BYTE]) & 1U) -#else -#define ZB_NWK_FRAMECTL_GET_MULTICAST_FLAG(fctl) 0U -#endif - -/** @brief Set multicast flag in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param m - multicast flag value. - */ -#define ZB_NWK_FRAMECTL_SET_MULTICAST_FLAG(fctl, m) ((fctl)[ZB_PKT_16B_FIRST_BYTE] |= (m)) - -/** @brief Get 'security' from the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. -*/ -#define ZB_NWK_FRAMECTL_GET_SECURITY(fctl) (((fctl)[ZB_PKT_16B_FIRST_BYTE] >> 1U) & 1U) - -/** @brief Set 'security' in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param s - 'security' value. - */ -#define ZB_NWK_FRAMECTL_SET_SECURITY(fctl, s) ((fctl)[ZB_PKT_16B_FIRST_BYTE] |= ((s) << 1U)) - -/** @brief Get 'source route' from the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. -*/ -#define ZB_NWK_FRAMECTL_GET_SOURCE_ROUTE(fctl) (((fctl)[ZB_PKT_16B_FIRST_BYTE] >> 2U) & 1U) - -/** @brief Set 'source route' in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param s - 'source route' value. - */ -#define ZB_NWK_FRAMECTL_SET_SOURCE_ROUTE(fctl, s) ((fctl)[ZB_PKT_16B_FIRST_BYTE] |= ((s) << 2U)) - -/** @brief Set 'source route' from the NWK header Frame Control field to 0. - - @param fctl - Frame Control Field of NWK header. -*/ -#define ZB_NWK_FRAMECTL_CLEAR_SOURCE_ROUTE(fctl) ((fctl)[ZB_PKT_16B_FIRST_BYTE] &= 0xFBU) - -/** @brief Get 'destination IEEE address' from the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. -*/ -#define ZB_NWK_FRAMECTL_GET_DESTINATION_IEEE(fctl) (((fctl)[ZB_PKT_16B_FIRST_BYTE] >> 3U) & 1U) - -/** @brief Set 'destination IEEE address' in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param d - 'destination IEEE address' value. - */ -#define ZB_NWK_FRAMECTL_SET_DESTINATION_IEEE(fctl, d) ((fctl)[ZB_PKT_16B_FIRST_BYTE] |= ((d) << 3U)) - -/** @brief Get 'source IEEE address' from the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - */ -#define ZB_NWK_FRAMECTL_GET_SOURCE_IEEE(fctl) (((fctl)[ZB_PKT_16B_FIRST_BYTE] >> 4U) & 1U) - -/** @brief Set 'source IEEE address' in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param s - 'source IEEE address' value. - */ -#define ZB_NWK_FRAMECTL_SET_SOURCE_IEEE(fctl, s) ((fctl)[ZB_PKT_16B_FIRST_BYTE] |= ((s) << 4U)) - -/** @brief Get 'End Device Initiator' from the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - */ -#define ZB_NWK_FRAMECTL_GET_END_DEVICE_INITIATOR(fctl) (((fctl)[ZB_PKT_16B_FIRST_BYTE] >> 5U) & 1U) - -/** @brief Set 'End Device Initiator' in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param s - 'End Device Initiator' value. - */ -#define ZB_NWK_FRAMECTL_SET_END_DEVICE_INITIATOR(fctl) ((fctl)[ZB_PKT_16B_FIRST_BYTE] |= (1U << 5U)) - -/** @brief Set 'End Device Initiator' in the NWK header Frame Control field. - - @param fctl - Frame Control Field of NWK header. - @param s - 'End Device Initiator' value. - */ -#define ZB_NWK_FRAMECTL_CLR_END_DEVICE_INITIATOR(fctl) ((fctl)[ZB_PKT_16B_FIRST_BYTE] &= ~(1U << 5U)) - -/** @brief Set 'destination IEEE address' & 'source IEEE address' in the NWK header Frame Control - field. - - @param fctl - Frame Control Field of NWK header. - @param s - 'source IEEE address' value. - @param d - 'destination IEEE address' value. - */ -#define ZB_NWK_FRAMECTL_SET_SRC_DEST_IEEE(fctl, s, d) \ - ((fctl)[ZB_PKT_16B_FIRST_BYTE] |= (((d) << 3U) | ((s) << 4U))) - -/** @brief Return size of the header part up to addresses. - - @param is_multicast - use multicast flag. - @return header part size. - */ -#ifdef ZB_NO_NWK_MULTICAST -#define ZB_NWK_SHORT_HDR_SIZE(is_multicast) ZB_OFFSETOF(zb_nwk_hdr_t, dst_ieee_addr) -#else -#define ZB_NWK_SHORT_HDR_SIZE(is_multicast) \ - (ZB_OFFSETOF(zb_nwk_hdr_t, dst_ieee_addr) + ((is_multicast) ? 1U : 0U)) -#endif - -/** @brief Return hdr size with only one extended address present. - - @param is_multicast - is use multicast flag. - @return header part size. - */ -#define ZB_NWK_HALF_HDR_SIZE(is_multicast) \ - (ZB_OFFSETOF(zb_nwk_hdr_t, src_ieee_addr) + ((is_multicast) ? 1U : 0U)) - -/** @brief Return full size of the header with extended addresses. - - @param is_multicast - is use multicast flag. - @return header part size. - */ -#define ZB_NWK_FULL_HDR_SIZE(is_multicast) \ - (ZB_OFFSETOF(zb_nwk_hdr_t, mcast_control) + ((is_multicast) ? 1U : 0U)) - -#if defined ZB_PRO_STACK && !defined ZB_NO_NWK_MULTICAST -#define ZB_NWK_IS_MULTICAST_MEMBER_MODE(mac_dst, nwk_frame_ctl) \ - ( ZB_NWK_IS_ADDRESS_BROADCAST(mac_dst) && ZB_NWK_FRAMECTL_GET_MULTICAST_FLAG(nwk_frame_ctl)) -#else -#define ZB_NWK_IS_MULTICAST_MEMBER_MODE(mac_dst, nwk_frame_ctl) 0U -#endif - -/** @brief Calculate network header size. - @param fctl - pointer on NWK header. - @return header size. - */ -zb_ushort_t zb_nwk_hdr_base_size(zb_uint8_t *fctl); - -#if defined ZB_PRO_STACK && !defined ZB_NO_NWK_MULTICAST - -#define ZB_RREQ_MC_MASK 0xBF -#define ZB_RREP_MC_MASK 0xBF -#define ZB_SET_RREQ_MULTICAST(a,b) ( a = (a & ZB_RREQ_MC_MASK) | b<<6U ) -#define ZB_GET_RREQ_MULTICAST(a) ( (a & (~ZB_RREQ_MC_MASK)) >>6U ) -#define ZB_SET_RREP_MULTICAST(a,b) ( a = (a & ZB_RREP_MC_MASK) | b<<6U ) -#define ZB_GET_RREP_MULTICAST(a) ( (a & (~ZB_RREP_MC_MASK)) >>6U ) - -#else - -#define ZB_SET_RREQ_MULTICAST(a,b) -#define ZB_GET_RREQ_MULTICAST(a) 0 -#define ZB_SET_RREP_MULTICAST(a,b) -#define ZB_GET_RREP_MULTICAST(a) 0 - -#endif /* multicast */ - -/** @brief Get size of base part of NWK header (without src route and security headers). */ -#define ZB_NWK_HDR_GET_BASE_SIZE( nwk_hdr ) \ - zb_nwk_hdr_base_size(((zb_nwk_hdr_t *)nwk_hdr)->frame_control) -/* Get size of NWK header */ - -#define ZB_NWK_HDR_SIZE( nwk_hdr ) zb_get_nwk_header_size(nwk_hdr) - -/** - Remove network header from an NWK packet placed into a packet buffer. - - To be used by APS layer to cut NWK header to get APS packet. - - @param packet - buffer holding packet - @param ptr - (out) pointer to the beginning of packet just after header. - */ -#define ZB_NWK_HDR_CUT(packet, ptr) \ -do \ -{ \ - zb_nwk_hdr_t *_nwk_hdr = (zb_nwk_hdr_t *)zb_buf_begin(packet); \ - ptr = zb_buf_cut_left(packet, ZB_NWK_HDR_SIZE(_nwk_hdr)); \ -} while (0) - -/** - Get source address from the NWK header - - @param nwk_hdr - pointer to the network packet header - @param addr - pointer to the short address - */ -#define ZB_NWK_GET_SRC_ADDR(nwk_hdr, addr) \ -ZB_LETOH16(addr, &((zb_nwk_hdr_t *)nwk_hdr)->src_addr) - - /** - Get destination address from the NWK header - - @param nwk_hdr - pointer to the network packet header - @param addr - pointer to the short address - */ -#define ZB_NWK_GET_DST_ADDR(nwk_hdr, addr) \ -ZB_LETOH16(addr, &((zb_nwk_hdr_t *)nwk_hdr)->dst_addr) - -#define ZB_NWK_ADDR_TO_LE16(addr) ZB_HTOLE16_ONPLACE(addr) - -/** - * @name Network command constants - * @anchor nwk_cmd - * - * Note: These values were members of `enum zb_nwk_cmd_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_NWK_CMD_ROUTE_REQUEST 0x01U /**< Route Request NWK command Id*/ -#define ZB_NWK_CMD_ROUTE_REPLY 0x02U /**< Route Reply NWK command Id*/ -#define ZB_NWK_CMD_NETWORK_STATUS 0x03U /**< Network Status NWK command Id*/ -#define ZB_NWK_CMD_LEAVE 0x04U /**< Leave NWK command Id*/ -#define ZB_NWK_CMD_ROUTE_RECORD 0x05U /**< Route Record NWK command Id*/ -#define ZB_NWK_CMD_REJOIN_REQUEST 0x06U /**< Rejoin Request NWK command Id*/ -#define ZB_NWK_CMD_REJOIN_RESPONSE 0x07U /**< Rejoin Response NWK command Id*/ -#define ZB_NWK_CMD_LINK_STATUS 0x08U /**< Link Status NWK command Id*/ -#define ZB_NWK_CMD_NETWORK_REPORT 0x09U /**< Network Report NWK command Id*/ -#define ZB_NWK_CMD_NETWORK_UPDATE 0x0aU /**< Network Update NWK command Id*/ -#define ZB_NWK_CMD_ED_TIMEOUT_REQUEST 0x0bU /**< End Device Timeout Request NWK command Id*/ -#define ZB_NWK_CMD_ED_TIMEOUT_RESPONSE 0x0cU /**< End Device Timeout Response NWK command Id*/ -#define ZB_NWK_CMD_LINK_POWER_DELTA 0x0dU /**< Link Power Delta command Id */ -/** @} */ - -/** - Get command id from nwk command packet - - @param buf - pointer to the packet buffer - @param nwk_hdr_size - network packet header - */ -#define ZB_NWK_CMD_FRAME_GET_CMD_ID(buf, nwk_hdr_size) ( *(zb_uint8_t *)(zb_buf_data(buf, (nwk_hdr_size)) )) - -/** - Get command pointer to the command payload from nwk command packet - - @param buf - pointer to the packet buffer - @param nwk_hdr_size - network packet header size - */ -#define ZB_NWK_CMD_FRAME_GET_CMD_PAYLOAD(buf, nwk_hdr_size) (zb_buf_data((buf), (zb_uint_t)(nwk_hdr_size) + 1U)) - -/** - Route request command -*/ - -/* Route request command options field */ - -/** - Route request structure -*/ -typedef ZB_PACKED_PRE struct zb_nwk_cmd_rreq_s -{ - zb_uint8_t opt; /**< Command options */ - zb_uint8_t rreq_id; /**< Route request id */ - zb_uint16_t dest_addr; /**< Final destination address */ - zb_uint8_t path_cost; /**< Route request total path cost */ - zb_ieee_addr_t dest_long_addr; /**< Final destination long address. */ -} ZB_PACKED_STRUCT -zb_nwk_cmd_rreq_t; - -/** - Route request types -*/ - -/** - * @name Route request types - * @anchor nwk_rreq_type - * - * Note: These values were members of `enum zb_nwk_rreq_type_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_NWK_RREQ_TYPE_NOT_MTORR 0U -#define ZB_NWK_RREQ_TYPE_MTORR_RREC_TABLE_SUPPORTED 1U -#define ZB_NWK_RREQ_TYPE_MTORR_RREC_TABLE_UNSUPPORTED 2U -/** @} */ - -/** - Route request Many-to-one field mask -*/ -#define ZB_NWK_RREQ_MANY_TO_ONE_FIELD_MASK 0x03U - -/** - Set Route request type -*/ -#define ZB_NWK_SET_RREQ_TYPE(opt, type) ((opt) |= (zb_uint8_t )(((type) & ZB_NWK_RREQ_MANY_TO_ONE_FIELD_MASK) << 3U)) - -/** - Get Route request type -*/ -#define ZB_NWK_GET_RREQ_TYPE(opt) (((opt) >> 3) & ZB_NWK_RREQ_MANY_TO_ONE_FIELD_MASK) - -/** - Route request Destination IEEE address field mask -*/ -#define ZB_NWK_RREQ_DESTINATION_IEEE_ADDRESS_MASK 0x01U - -/** - Set Route request Destination IEEE address field -*/ -#define ZB_NWK_SET_RREQ_HAS_DST_IEEE_ADDR(opt, included) ((opt) |= (zb_uint8_t )(((included) & ZB_NWK_RREQ_DESTINATION_IEEE_ADDRESS_MASK) << 5U)) - -/** - Get Route request Destination IEEE address field -*/ -#define ZB_NWK_GET_RREQ_HAS_DST_IEEE_ADDR(opt) (((opt) >> 5) & ZB_NWK_RREQ_DESTINATION_IEEE_ADDRESS_MASK) - -/** - Set of bits that are supported during forwarding the Route Request. - */ -#define ZB_NWK_RREQ_OPT_SUPPORTED_BITS 0x78U /* 0b01111000 */ - -/** - Route response command -*/ - -/** - Route reply structure -*/ -typedef ZB_PACKED_PRE struct zb_nwk_cmd_rrep_s -{ - zb_uint8_t opt; /**< Command options */ - zb_uint8_t rreq_id; /**< Route request id */ - zb_uint16_t originator; /**< Originator address */ - zb_uint16_t responder; /**< Responder address */ - zb_uint8_t path_cost; /**< Path cost */ -} ZB_PACKED_STRUCT -zb_nwk_cmd_rrep_t; - -/** - Rejoin request command -*/ -typedef ZB_PACKED_PRE struct zb_nwk_rejoin_request_s -{ - zb_mac_capability_info_t capability_information; /**< The operating capabilities of the - * device */ -} ZB_PACKED_STRUCT -zb_nwk_rejoin_request_t; - -/** - Rejoin response command -*/ -typedef ZB_PACKED_PRE struct zb_nwk_rejoin_response_s -{ - zb_uint16_t network_addr; /**< Network address */ - zb_uint8_t rejoin_status; /**< Rejoin status */ -} ZB_PACKED_STRUCT -zb_nwk_rejoin_response_t; - - -#define ZB_NWK_COMMAND_SIZE(payload_size) (1U + (payload_size)) - -#define ZB_LEAVE_PL_SET_REQUEST(pl) (pl) |= (1U << 6U) -#define ZB_LEAVE_PL_SET_REJOIN(pl, v) (pl) |= ((ZB_B2U(ZB_U2B(v))) << 5U) -#define ZB_LEAVE_PL_SET_REMOVE_CHILDREN(pl, v) (pl) |= ((ZB_B2U(ZB_U2B(v))) << 7U) - -#define ZB_LEAVE_PL_GET_REQUEST(pl) (((pl) >> 6U) & 1U) -#define ZB_LEAVE_PL_GET_REJOIN(pl) (((pl) >> 5U) & 1U) -#define ZB_LEAVE_PL_GET_REMOVE_CHILDREN(pl) (((pl) >> 7U) & 1U) - -#ifdef ZB_JOIN_CLIENT -void zb_nwk_do_leave(zb_uint8_t param, zb_uint8_t rejoin); -#else -#define zb_nwk_do_leave(param, rejoin) -#endif - -void zb_nwk_do_rejoin_after_leave(zb_uint8_t param); - -void zb_nwk_rejoin_sync_pibcache_with_mac(zb_uint8_t param, zb_callback_t cb); - -/** - Forget remote device or myself - */ -void zb_nwk_forget_device(zb_uint8_t addr_ref); - -void zb_nwk_source_routing_record_delete(zb_uint16_t addr); - -/** - Update beacon payload in the PIB. - - To be called after any network configuration change: formation, join etc. - As a side effect increments NIB Update id. - */ -void zb_nwk_update_beacon_payload(zb_uint8_t param); - -/** - 3.4.9 Network Report Command - */ -typedef ZB_PACKED_PRE struct zb_nwk_report_cmd_s -{ - zb_uint8_t command_options; /**< Command options */ - zb_ext_pan_id_t epid; /**< 64-bit EPID that identifies the network that the reporting device */ - zb_uint16_t panids[1]; /**< Pan ID Conflict Report list */ -} ZB_PACKED_STRUCT zb_nwk_report_cmd_t; - -#define ZB_NWK_REPORT_INFO_COUNT(options) ((options) & 0xfU) -#define ZB_NWK_REPORT_COMMAND_ID(options) ((((options) >> 4U)) & 0xfU) -#define ZB_NWK_REPORT_IS_PANID_CONFLICT(options) (ZB_NWK_REPORT_COMMAND_ID(options) == 0U) - -#define ZB_NWK_UPDATE_INFO_COUNT(options) ((options) & 0xfU) -#define ZB_NWK_UPDATE_COMMAND_ID(options) ((((options) >> 4U)) & 0xfU) -#define ZB_NWK_UPDATE_IS_PANID_UPDATE(options) (ZB_NWK_UPDATE_COMMAND_ID(options) == 0U) - -/** - 3.4.10 Network Update Command - */ -typedef ZB_PACKED_PRE struct zb_nwk_update_cmd_s -{ - zb_uint8_t command_options; /**< NWK command options*/ - zb_ext_pan_id_t epid; /**< 64-bit Network ID*/ - zb_uint8_t update_id; /**< 16-bit Network ID*/ - zb_uint16_t new_panid; /**< 16-bit new Network ID*/ -} ZB_PACKED_STRUCT zb_nwk_update_cmd_t; - - -typedef ZB_PACKED_PRE struct zb_nwk_cmd_rrec_s -{ - /*zb_uint8_t opt;*/ /**< Command options */ - zb_uint8_t relay_cnt; /** relay count */ - zb_uint16_t relay_addr; /** relay address */ -} ZB_PACKED_STRUCT -zb_nwk_cmd_rrec_t; - -/** - Send Route record command - - @param cbuf - buffer for command data - @param scr_addr - 16-bit source address - @param dst_addr - 16-bit destination address - @return if OK return RET_OK otherwise error code - */ -zb_ret_t zb_nwk_send_rrec(zb_bufid_t cbuf, zb_uint16_t src_addr, zb_uint16_t dst_addr); - -/** - Send Route record command prior to send a packet - - @param cbuf - buffer for command data - @param scr_addr - 16-bit source address - @param dst_addr - 16-bit destination address - @param mac_dst - 16-bit MAC destination address - @return if OK return RET_OK otherwise error code - */ -zb_ret_t zb_nwk_send_rrec_prior(zb_bufid_t cbuf, zb_uint16_t src_addr, zb_uint16_t dst_addr, zb_uint16_t mac_dst); - -/** - Route record response handler - */ -void zb_nwk_rrec_handler(zb_bufid_t buf, zb_nwk_hdr_t *nwk_hdr, zb_uint8_t hdr_size); - -/** - Send Many-to-one-route failure network status - */ -void zb_nwk_many_to_one_route_failure(zb_bufid_t buf); - -/** - Check expiry for the source route table - */ -void zb_nwk_source_route_table_expiry(void); - -/** - Clear the route record required field of the routing table entry - */ -void zb_nwk_source_routing_clear_rrec_req(zb_uint16_t src_addr); - -/** - Start Concentrator mode using parameters from NIB - */ -void zb_nwk_concentrator_start(void); - -/** - Stop Concentrator mode - */ -void zb_nwk_concentrator_stop(void); - -/*Calculate default timeout for keepalive*/ -zb_time_t zb_nwk_get_default_keepalive_timeout(void); - -/*Return ZB_TRUE if nearest aging timeout expired*/ -zb_bool_t zb_nwk_check_aging(void); - -/** -Send End device timeout request command - */ -void zb_nwk_ed_send_timeout_req(zb_uint8_t param); - -/** -End device timeout request command handler - */ -void zb_nwk_ed_timeout_request_handler(zb_bufid_t buf, zb_nwk_hdr_t *nwk_hdr, zb_nwk_ed_timeout_request_t *cmd_ed_time_req); - -/** -Send End device timeout response handler - */ - -void nwk_timeout_resp_handler(zb_bufid_t buf, zb_nwk_hdr_t *nwk_hdr, zb_nwk_ed_timeout_response_t *cmd_ed_time_resp); - -/** - 3.4.13 Link Power Delta command - */ -typedef enum zb_nwk_power_delta_cmd_options_e -{ - ZB_NWK_LPD_CMD_OPTIONS_NOTIFICATION = 0x0U, - ZB_NWK_LPD_CMD_OPTIONS_REQUEST = 0x1U, - ZB_NWK_LPD_CMD_OPTIONS_RESPONSE = 0x2U, - ZB_NWK_LPD_CMD_OPTIONS_RESERVED = 0x3U, -} zb_nwk_power_delta_cmd_options_t; - -#define ZB_NWK_LPD_CMD_OPTIONS_MASK 0x03U - -typedef ZB_PACKED_PRE struct zb_nwk_link_power_delta_payload_s -{ - zb_uint8_t cmd_options; - zb_uint8_t list_count; -} ZB_PACKED_STRUCT -zb_nwk_link_power_delta_payload_t; - - -typedef ZB_PACKED_PRE struct zb_nwk_power_list_entry_s -{ - zb_uint16_t short_addr; - zb_uint8_t power_delta; -} ZB_PACKED_STRUCT -zb_nwk_power_list_entry_t; - -/** - Test Conflict Address - Compare address attributes with data from Address Map - - @param addr - 16-bit address - @param ieee_addr - 64-bit IEEE address - @return if has conflict return RET_CONFLICT otherwise RET_OK - - */ -zb_ret_t zb_nwk_is_conflict_addr(zb_uint16_t addr, zb_ieee_addr_t ieee_addr); - -/** - Test Conflict Address by DevAnnce frame - Compare address attributes with data from Address Map - Data may be not present in Address Map yet - - @param addr - 16-bit address - @param ieee_addr - 64-bit IEEE address - @return if has conflict return RET_CONFLICT otherwise RET_OK - - */ -zb_ret_t zb_nwk_test_dev_annce(zb_uint16_t addr, zb_ieee_addr_t ieee_addr); - - -/** - Set NWK PIB attribute - - @param param - buffer - @param iface_id - MAC interface ID - @param attr - attribute ID - @param value - attribute value - @param value_size - size of attribute value - @param cb - callback for run after - */ -void zb_nwk_pib_set(zb_uint8_t param, zb_uint8_t iface_id, zb_uint8_t attr, void *value, - zb_ushort_t value_size, zb_callback_t cb); - -/** - Get NWK PIB attribute - - @param param - buffer - @param iface_id - MAC interface id - @param attr - attribute ID - @param cb - callback for run after - */ -void zb_nwk_pib_get(zb_uint8_t param, zb_uint8_t iface_id, zb_uint8_t attr, zb_callback_t cb); - -/** @} */ -/** @endcond */ - -/** - Get NWK header size - - @param hdr - NWK header - @return size of NWK header - - @code - zb_uint8_t hdr_size = zb_get_nwk_header_size(hdr); - @endcode - */ -zb_uint8_t zb_get_nwk_header_size(const zb_nwk_hdr_t *hdr); - -/** - zb_nwk_nib_init - Initialize NIB variables - - @return nothing - */ -void zb_nwk_nib_init(zb_bool_t is_first); - -void zb_nwk_handle_init(void); - -#if defined ZB_PRO_STACK && !defined ZB_NO_NWK_MULTICAST -zb_nwk_multicast_control_field_t *zb_get_mc_field_from_header(zb_nwk_hdr_t *hdr); -#define GET_NWK_MCF( nwk_hdr ) (*( zb_get_mc_field_from_header(nwk_hdr))) -#else -#define GET_NWK_MCF( nwk_hdr ) nwk_hdr->mcast_control -#endif - -/* Send network status with value 0x0B-Source route failure */ -#if defined ZB_PRO_STACK && defined ZB_ROUTER_ROLE -void zb_send_nwk_status_source_route_fail(zb_uint8_t param, zb_uint16_t src_addr); -#endif - - -/** \addtogroup nwk_api */ -/** @{ */ - -#if defined ZB_PRO_ADDRESS_ASSIGNMENT_CB || defined DOXYGEN - -/** - Set callback NWK address assignment - - Allow the application to set the desired nwk address to the device. - - @param cb - callback - */ -void zb_nwk_set_address_assignment_cb(zb_addr_assignment_cb_t cb); - - -/** - Set callback to inform about device association - - @param cb - callback - */ -void zb_nwk_set_dev_associate_cb(zb_addr_assignment_cb_t cb); -#endif - -#ifndef ZB_LITE_NO_LINK_COST -/** - Convert lqi to cost - lqi related from device type. - TODO: test algorithm on different platforms. Work with TI CC2520. - Look at incoming and outgoing routing cost values in the link status message. Value 1 - indicates the best link, 7 indicates the worst one. - */ - -#define NWK_LQI_2_COST(lqi) (((lqi) < 0xe0U) ? (7U - (((lqi) >> 5U ) & 0x07U)) : 1U) -#else -#define NWK_LQI_2_COST(lqi) ZB_NWK_STATIC_PATH_COST -#endif - -#ifdef ZB_ROUTER_ROLE - -/** - Calc neighbour path cost - */ -#if defined ZB_NWK_NEIGHBOUR_PATH_COST_RSSI_BASED -#define ZB_NWK_NEIGHBOUR_GET_PATH_COST(nbt) zb_nwk_neighbour_get_path_cost((nbt)) -#elif defined ZB_NWK_NEIGHBOUR_PATH_COST_LQI_BASED -#define ZB_NWK_NEIGHBOUR_GET_PATH_COST(nbt) NWK_LQI_2_COST((nbt)->lqi) -#else -#error Please specify neighbour path cost calculation method! -#endif /* ZB_NWK_NEIGHBOUR_PATH_COST_RSSI_BASED */ - -#endif /* ZB_ROUTER_ROLE */ - -/** - Convert cost to LQI - To be used for testing, like in TP/PRO-BV-04 - */ -#define NWK_COST_TO_LQI(cost) ((7U - (cost)) << 5U) - -/** @} */ - -#ifdef ZB_CHECK_OOM_STATUS -void zb_check_oom_status(zb_uint8_t param); - -#ifdef ZB_SEND_OOM_STATUS -void zb_oom_status_confirm(zb_uint8_t param); -#endif /* ZB_SEND_OOM_STATUS */ -#endif /* ZB_CHECK_OOM_STATUS */ - -#ifdef ZB_NWK_BLACKLIST - -/** - * @brief add new entry to blacklist - * @param ext_pan_id - extended Pan ID of network to be blacklisted - */ -void zb_nwk_blacklist_add(zb_ext_pan_id_t ext_pan_id); - -/** - * @brief clear blacklist - */ -void zb_nwk_blacklist_reset(void); - -/** - * @brief checks whether network with given extended Pan ID is blacklisted - * @param ext_pan_id - extended Pan ID to check - * @return RET_OK - if network is not blacklisted, RET_ERROR otherwise - */ -zb_ret_t zb_nwk_blacklist_check(zb_ext_pan_id_t ext_pan_id); - -/** - * @brief checks whether blacklist is full - * @return RET_OK - if blacklist has unused entries, RET_OVERFLOW otherwise - */ -zb_bool_t zb_nwk_blacklist_is_full(void); - -zb_bool_t zb_nwk_blacklist_is_empty(void); - -#endif - -void zb_nwk_unlock_in(zb_uint8_t param); - - -/** - Increment counter of TX. - - Normalize TX success/failure using tx counters window - */ -void nwk_txstat_tx_inc(void); - -/** - Increment counter of failed TX. Schedule ZDO failures check routine. - - May normalize TX success/failure using tx counters window - */ -void nwk_txstat_fail_inc(void); - -#ifdef ZB_ROUTER_ROLE -/** - Clear TX statistic counters. - - To be used after channel change. - */ -void nwk_txstat_clear(void); -#else -#define nwk_txstat_clear(q) -#endif - -#ifdef ZB_FORMATION -void zb_nwk_cont_without_formation(zb_uint8_t param); -#endif /* ZB_FORMATION */ - -void zb_nwk_reset_route_expire(zb_uint16_t addr); - -void zb_nwk_route_expire(zb_uint16_t addr); - -void zb_nwk_load_pib(zb_uint8_t param); - -#if defined ZB_ASSERT_SEND_NWK_REPORT -/* Send NWK Network Status pkt on assert with custom payload - epid is 0xdeadbeef + file_id + line_number */ -typedef ZB_PACKED_PRE struct zb_nlme_assert_ind_frame_s -{ - /* nwk hdr */ - zb_uint8_t frame_control[2]; /**< Frame Control Field */ - zb_uint16_t dst_addr; /**< Destination 16-bit address */ - zb_uint16_t src_addr; /**< Source 16-bit address */ - zb_uint8_t radius; /**< Radius */ - zb_uint8_t seq_num; /**< Sequence Number */ - zb_ieee_addr_t dst_ieee_addr; /**< Destination 64-bit address */ - - /* cmd - use Network Report */ - zb_uint8_t cmd_id; - zb_uint8_t command_options; - - /* use our structure instead of pan_id */ - zb_uint32_t sig; - zb_uint16_t file_id; - zb_int_t line; -} ZB_PACKED_STRUCT -zb_nlme_assert_ind_frame_t; - -void zb_nlme_send_assert_ind(zb_uint16_t file_id, zb_int_t line); -#endif - -void zb_nwk_restart_aging(void); - -zb_ret_t zb_nwk_validate_leave_req(zb_uint16_t src_addr); - -#ifdef ZB_LIMIT_VISIBILITY -zb_bool_t zb_mac_is_long_addr_visible(const zb_ieee_addr_t ieee_addr); -#endif - -#define ZB_NWK_NEIGHBOR_ERROR_VALUE 0xffU - -zb_uint8_t zb_nwk_get_nbr_rel_by_short(zb_uint16_t addr); -zb_uint8_t zb_nwk_get_nbr_rel_by_ieee(const zb_ieee_addr_t addr); - -zb_uint8_t zb_nwk_get_nbr_dvc_type_by_short(zb_uint16_t addr); -zb_uint8_t zb_nwk_get_nbr_dvc_type_by_ieee(const zb_ieee_addr_t addr); - -zb_uint8_t zb_nwk_get_nbr_rx_on_idle_by_short(zb_uint16_t addr); -zb_uint8_t zb_nwk_get_nbr_rx_on_idle_short_or_false(zb_uint16_t addr); -zb_uint8_t zb_nwk_get_nbr_rx_on_idle_by_ieee(zb_ieee_addr_t addr); - -#if defined ZB_STORE_NBR_INFO_IN_ALIEN_MAC - -#define ALIEN_MAC_NBR_ENT_ADD(ent) zb_mac_alien_nbr_ent_add(ent) -#define ALIEN_MAC_NBR_ENT_DELETE(ent) zb_mac_alien_nbr_ent_delete(ent) -#define ALIEN_MAC_NBR_ENT_DELETE_ALL() zb_mac_alien_nbr_ent_delete_all() - -#else /* ZB_STORE_NBR_INFO_IN_ALIEN_MAC */ - -#define ALIEN_MAC_NBR_ENT_ADD(ent) -#define ALIEN_MAC_NBR_ENT_DELETE(ent) -#define ALIEN_MAC_NBR_ENT_DELETE_ALL() - -#endif /* ZB_STORE_NBR_INFO_IN_ALIEN_MAC */ - -typedef struct zb_nwk_neighbor_element_s -{ - zb_uint8_t relationship; - zb_uint8_t device_type; - zb_bool_t rx_on_when_idle; - zb_uint8_t depth; - zb_uint8_t permit_joining; -} -zb_nwk_neighbor_element_t; - -zb_ret_t zb_nwk_get_neighbor_element(zb_uint16_t addr, zb_bool_t create_if_absent, zb_nwk_neighbor_element_t *update); -zb_ret_t zb_nwk_set_neighbor_element(zb_uint16_t addr, zb_nwk_neighbor_element_t *update); - -zb_ret_t zb_nwk_delete_neighbor_by_short(zb_uint16_t addr); -zb_ret_t zb_nwk_delete_neighbor_by_ieee(zb_ieee_addr_t addr); - -void zb_nwk_send_direct_leave_req(zb_uint8_t param, zb_uint16_t dst_addr); - -zb_bool_t nwk_is_lq_bad_for_direct(zb_int8_t rssi, zb_uint8_t lqi); -void nwk_maybe_force_send_via_routing(zb_uint16_t addr); - -void nwk_internal_lock_in(void); -void nwk_internal_unlock_in(void); - -void zb_mcps_build_data_request(zb_bufid_t buf, zb_uint16_t src_addr_param, zb_uint16_t dst_addr_param, zb_uint8_t tx_options_param, zb_uint8_t msdu_hande_param); - -#ifdef SNCP_MODE -zb_ret_t zb_nwk_force_route_sending(zb_bool_t enable); -#endif - -void nwk_mark_nwk_encr1(zb_bufid_t buf, zb_uint16_t file_id, zb_uint16_t line); -#define nwk_mark_nwk_encr(buf) nwk_mark_nwk_encr1((buf), ZB_TRACE_FILE_ID, __LINE__) - -void nwk_router_start_common(zb_uint8_t param); - -#ifdef ZB_FORMATION -void zb_nwk_formation_force_link(void); -#endif /* ZB_FORMATION */ - -#if defined ZB_PARENT_CLASSIFICATION && defined ZB_ROUTER_ROLE -void nwk_set_tc_connectivity(zb_uint8_t val); - -zb_bool_t nwk_get_tc_connectivity(void); -#endif /* ZB_PARENT_CLASSIFICATION && ZB_ROUTER_ROLE */ - - -#define ZB_NWK_OCTET_DURATION_US (zb_uint32_t)(ZB_2_4_GHZ_OCTET_DURATION_USEC) - - -/* 01/15/2019 EE CR:MINOR For 2.4-only mode this solution is ok from - * the code size point of view: you pass your octets up to the top and - * convert it to BI using a macro, so all calculation are done at - * compile time. But for MM case compiler will insert function call - * and division everywhere. It is not optimal. - * Even while you can't eliminate a function call, you can exclude additional calculations. - * Function call can get time in octets and return time in BE. - */ -#define ZB_NWK_OCTETS_TO_US(octets_cnt) ((octets_cnt) * ZB_NWK_OCTET_DURATION_US) -#define ZB_NWK_OCTETS_TO_BI(octets_cnt) ZB_MILLISECONDS_TO_BEACON_INTERVAL(ZB_NWK_OCTETS_TO_US(octets_cnt) / 1000U) - -#ifdef ZB_CONTROL4_NETWORK_SUPPORT -/* Internal Control4 functions to enable/disable Control4 controller behavior emulation */ -void zb_disable_control4_emulator(); - -void zb_enable_control4_emulator(); -#endif /* ZB_CONTROL4_NETWORK_SUPPORT */ - -zb_ext_neighbor_tbl_ent_t *nwk_choose_parent(zb_address_pan_id_ref_t panid_ref, zb_mac_capability_info_t capability_information); - -#endif /* ZB_NWK_H */ diff --git a/zboss/development/src/include/zb_nwk_ed_aging.h b/zboss/development/src/include/zb_nwk_ed_aging.h deleted file mode 100644 index 85163e3044..0000000000 --- a/zboss/development/src/include/zb_nwk_ed_aging.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: NWK end device aging management -*/ -#ifndef ZB_NWK_ED_AGING_H -#define ZB_NWK_ED_AGING_H 1 - -/** - * @name NWK request timeout status - * @anchor requested_timeout_status - */ -/** @{ */ -#define ED_AGING_SUCCESS 0U -#define ED_AGING_INCORRECT_VALUE 1U -/** @} */ - -/** - * @brief Type for NWK request timeout status. - * - * Holds one of @ref requested_timeout_status. Kept only for backward compatibility as - * @ref requested_timeout_status were declared previously as enum. Can be removed in future - * releases. - */ -typedef zb_uint8_t nwk_requested_timeout_status_t; - -/* - Power negotiation feature to be enabled/disabled. - It's included in 'parent_info' bitmask (3rd LSB => .... .X..). -*/ -#define POWER_NEGOTIATION_SUPPORT 0x04U - -/* - nwk_parent_information is filled in response to ED timeout req. - Non-zero nwk_parent_information means we work with >= r21 parent with ED aging ON. - */ -#define ZB_GET_PARENT_INFO() ZB_NIB().nwk_parent_information -#define ZB_SET_PARENT_INFO(pinf) ZB_NIB().nwk_parent_information = (pinf) - -#define ZB_GET_KEEPALIVE_MODE() ZB_NIB().nwk_keepalive_modes -#define ZB_SET_KEEPALIVE_MODE(mode) ZB_NIB().nwk_keepalive_modes = (mode) - -#ifdef ZB_ED_FUNC -#define ZB_GET_ED_TIMEOUT() ZB_NIB().nwk_ed_timeout_default -#define ZB_GET_KEEPALIVE_TIMEOUT() ZB_NIB().nwk_ed_keepalive_timeout -#endif /* ZB_ED_FUNC */ - -#define NWK_ED_DEVICE_TIMEOUT_DEFAULT 8U /*This is an index into. It indicates the default timeout in minutes for any end device that does not negotiate a different timeout value.*/ - -#define NWK_ED_DEVICE_CONFIG_DEFAULT 0x00U /*At this time there are no enumerated bits in the configuration field. Devices adhering to this standard shall set the field to 0.*/ - -#define ZB_NWK_ED_TIMEOUT_RESP_FAILURE_TMO (5U * ZB_TIME_ONE_SECOND) - -/** - End device timeout request command -*/ -typedef ZB_PACKED_PRE struct zb_nwk_ed_timeout_request_s -{ - zb_uint8_t request_timeout; /**< Request timeout enumeration @see @ref nwk_requested_timeout */ - zb_uint8_t ed_config; /**< End Device Configuration */ -/*NOTE: This is a bitmask indicating the end device's requested - * configuration. At this time there are no enumerated bits in the configuration - * field. Devices adhering to this standard shall set the field to 0. To allow - * for future compatibility this field is left in place. Devices that receive - * the End Device Timeout Request message with an End Device Configuration field - * set to anything other than 0 shall reject the message. The receiving device - * shall send an End Device Timeout Response command with a status of 0x01 (INCORRECT_VALUE).*/ - -} ZB_PACKED_STRUCT zb_nwk_ed_timeout_request_t; - -/** - End device timeout response command -*/ -typedef ZB_PACKED_PRE struct zb_nwk_ed_timeout_response_s -{ - zb_uint8_t status; /**< The success or failure result of - * the previously received End Device - * Timeout Request command. */ - zb_uint8_t parent_info; /**< Parent routers support information - * to the child device. */ -} ZB_PACKED_STRUCT -zb_nwk_ed_timeout_response_t; - -/** - * @name ED keepalive status - * @anchor keepalive_status_internal - * - * Note: These values were members of `enum nwk_keepalive_status_internal_e` type but were converted - * to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ED_KEEPALIVE_SUCCESS 0U -#define ED_KEEPALIVE_REQ_FAILED 1U -#define ED_KEEPALIVE_RESP_FAILED 2U -/** @} */ - -typedef struct zb_nwk_ed_timeout_response_param_s -{ - zb_uint8_t status; /**< General internal status of the - * Keepalive procedure */ - zb_uint8_t resp_status; /**< The success or failure result of - * the previously received End Device - * Timeout Request command. */ - zb_uint8_t parent_info; /**< Parent routers support information - * to the child device. */ - -} zb_nwk_ed_timeout_response_param_t; - -void zb_init_ed_aging(zb_neighbor_tbl_ent_t *nbt, zb_uint8_t timeout, zb_bool_t run_aging); - -void zb_update_ed_aging(void); - -void zb_stop_ed_aging(void); - -void zb_nwk_ed_aging_timeout(zb_uint8_t param); - -/* Convert timeout value from index to seconds */ -zb_uint32_t zb_convert_timeout_value(zb_uint8_t timeout); - -#ifdef ZB_MAC_PENDING_BIT_SOURCE_MATCHING -void zb_nwk_src_match_add(zb_uint8_t param, zb_uint16_t nbt_idx); -void zb_nwk_src_match_delete(zb_uint8_t param, zb_address_ieee_ref_t ieee_ref); -void zb_nwk_src_match_drop(zb_uint8_t param); -void zb_nwk_src_match_restore(zb_uint8_t param); -#endif /* ZB_MAC_PENDING_BIT_SOURCE_MATCHING */ - -void zb_nwk_ed_timeout_resp_recv_fail_trig(zb_uint8_t unused); - -#endif /* ZB_NWK_ED_AGING_H */ diff --git a/zboss/development/src/include/zb_nwk_globals.h b/zboss/development/src/include/zb_nwk_globals.h deleted file mode 100644 index aa32d12d0e..0000000000 --- a/zboss/development/src/include/zb_nwk_globals.h +++ /dev/null @@ -1,571 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: NWK subsystem globals -*/ - -#ifndef ZB_NWK_GLOBALS_H -#define ZB_NWK_GLOBALS_H 1 - -#include "zb_config.h" -#include "zb_mac.h" -#include "zb_nwk_neighbor.h" -#include "zb_nwk.h" - -/*! @cond internals_doc */ -/*! \addtogroup ZB_NWK */ -/*! @{ */ - - -zb_uint_t zb_calc_non_zero_bits_in_bit_vector(zb_uint8_t *vector, zb_uint_t size); - -#define ZB_DUMP_IEEE_ADDR(iee_addr) TRACE_MSG(TRACE_COMMON3, "ieeeaddr " TRACE_FORMAT_64, (FMT__A, TRACE_ARG_64(iee_addr))) - - -/** - * @name NWK State - * @anchor nlme_state - * - * Note: These values were members of `enum zb_nlme_state_t` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_NLME_STATE_IDLE 0U -#define ZB_NLME_STATE_DISC 1U -#define ZB_NLME_STATE_FORMATION_ED_SCAN 2U -#define ZB_NLME_STATE_FORMATION_ACTIVE_SCAN 3U -#define ZB_NLME_STATE_FORMATION 4U -#define ZB_NLME_STATE_ROUTER 5U -#define ZB_NLME_STATE_ED_SCAN 6U -#define ZB_NLME_STATE_REJOIN 7U -#define ZB_NLME_STATE_ORPHAN_SCAN 8U -#define ZB_NLME_STATE_RESET 9U /* unused currently */ -/* Specific case for searching networks in BDB: - * when device failed authentication it leaves network - * but does not clear nib to be able join to other networks. - */ -#define ZB_NLME_STATE_RESET_NO_NIB_REINIT 10U -#define ZB_NLME_STATE_PANID_CONFLICT_RESOLUTION 11U -#define ZB_NLME_STATE_ZDO_STARTING 12U - -#define ZB_NLME_STATE_PIB_LOAD1 13U -#define ZB_NLME_STATE_PIB_LOAD2 14U -#define ZB_NLME_STATE_PIB_LOAD3 15U -#define ZB_NLME_STATE_PIB_LOAD4 16U -#define ZB_NLME_STATE_PIB_LOAD5 17U -#define ZB_NLME_STATE_PIB_LOAD6 18U -#define ZB_NLME_STATE_PIB_LOAD7 19U -#define ZB_NLME_STATE_PIB_LOAD8 20U -#define ZB_NLME_STATE_PIB_LOAD9 21U -#define ZB_NLME_STATE_PIB_LOAD10 22U -#define ZB_NLME_STATE_PIB_LOAD_SRC_MATCH_TBL 23U -#define ZB_NLME_STATE_PIB_LOAD_BEACON_JITTER 24U - -/*!< State to execute the 'Survey Beacon' procedure */ -#define ZB_NLME_STATE_SURVEY_BEACON 25U -/** @} */ - -/* Broadcast transaction record */ -/* 01/15/2019 EE CR:MINOR Why don't pack for IAR? It seems like very old problem of 2012-11-08. Probably can pack and decrease RAM usage */ -typedef ZB_PACKED_PRE struct zb_nwk_btr_s /* do not pack for IAR */ -{ -/* 01/15/2019 EE CR:MINOR May exclude 'used' and operate with special - * value of expiration_time. But in such case can't use - * NWK_ARRAY_GET_ENT and friends. Maybe, it is good. - * Removing of bitfield may decrease code ize. - */ - - /* Using short address itself instead of addr ref in order to avoid problematic - situations during address conflicts. For example, if short address is changed for an address - reference and the same packet is received, a new BTR will be created (and rebroadcasted as well). - */ - zb_uint16_t source_addr; /*!< Source address */ - zb_uint8_t sequence_number; /*!< Sequence address */ - zb_bitfield_t used:1; /*!< Record is used */ - zb_bitfield_t expiration_time:7; /*!< Expiration time */ -} ZB_PACKED_STRUCT -zb_nwk_btr_t; - -/* Passive ack bit array size */ -#define ZB_NWK_BRCST_PASSIVE_ACK_ARRAY_SIZE ((ZB_NEIGHBOR_TABLE_SIZE + 7U) / 8U) - -/** - Broadcast retransmission info - Important! This struct must ZB_PACKED_STRUCT for ZB_NEED_ALIGN - */ -typedef ZB_PACKED_PRE struct zb_nwk_broadcast_retransmit_s -{ - zb_bitfield_t retries_left:2; /*!< Number of currently available transmission attempts */ - - zb_bitfield_t been_broadcasted:1; /*nwk.leave_context.pending_list_bm |= (1U<<(i)) -#define ZB_RESET_LEAVE_PENDING(i) ZG->nwk.leave_context.pending_list_bm &= ~(1U<<(i)) -#define ZB_IS_LEAVE_PENDING(i) (ZG->nwk.leave_context.pending_list_bm & (1U<<(i))) -#define ZB_IS_ANY_LEAVE_PENDING() (ZG->nwk.leave_context.pending_list_bm != 0U) - -/** - rejoin command context - */ -typedef struct zb_rejoin_context_s /* do not pack for IAR */ -{ - zb_uint16_t addr; /*!< */ - zb_address_ieee_ref_t addr_ref; - zb_uint8_t secure_rejoin; - zb_uint8_t rx_on; -} ZB_PACKED_STRUCT zb_rejoin_context_t; - - -#define ZB_NWK_IN_Q_SIZE (ZB_IOBUF_POOL_SIZE/2U) - -#ifndef ZB_CONFIGURABLE_MEM -/* Buffer for pending incoming packets. Big enough to exclude packets loss. */ -ZB_RING_BUFFER_DECLARE(zb_nwk_in_q, zb_uint8_t, (ZB_NWK_IN_Q_SIZE)); -#endif - -#ifdef ZB_NWK_BLACKLIST -/** - Blacklist array - */ -typedef struct zb_nwk_blacklist_s -{ - zb_uint8_t used; /*!< Used records number */ - zb_ext_pan_id_t blacklisted[ZB_NWK_BLACKLIST_SIZE]; -} zb_nwk_blacklist_t; -#endif - -/** - Place to store values between multiply operations -*/ -typedef struct zb_nwk_handle_s /* do not pac for IAR */ -{ - zb_uint8_t state; /*!< Current network subsystem state @ref nlme_state */ - zb_bool_t operation_cancelled; /*!< Network formation or network discovery is cancelled */ - zb_address_ieee_ref_t parent; /*!< parent address (valid if the device is not ZC and joined) */ - - union tmp_u - { - struct join_tmp_s - { - zb_nlme_join_request_t saved_join_req; - zb_ext_neighbor_tbl_ent_t *parent; - } join; - struct rejoin_tmp_s /*!< Rejoin options */ - { - zb_nlme_join_request_t saved_join_req; - zb_ext_pan_id_t extended_pan_id; - zb_mac_capability_info_t capability_information; - zb_ext_neighbor_tbl_ent_t *parent; - zb_uint8_t unsecured_rejoin; - zb_uint8_t poll_attempts; - zb_uint8_t poll_req; - zb_callback_t cb; - } rejoin; -#ifdef ZB_FORMATION - struct formation_s - { - zb_uint8_t channel_pan_count[ZB_CHANNEL_PAGES_NUM][ZB_CHANNEL_PAGE_MAX_CHANNELS_COUNT]; - zb_uint8_t panid_handled_bm[ZB_PANID_TABLE_SIZE / 8U + 1U]; - } formation; -#endif - } tmp; - - zb_callback_t run_after_update_beacon_payload; /*!< Run after update beacon payload */ - - zb_uint16_t status_addr; /* Used to report NWK status indication */ - - zb_uint8_t send_link_status_index; /*!< Current Index of short_sorted address table */ - -#if defined ZB_MAC_POWER_CONTROL - zb_uint8_t send_power_delta_index; /* Current index of short_sorted address - * table for NWK Power Delta command (notification */ - zb_uint16_t lpd_resp_addr; /* Address of recipient, LPD frame - * response to be sent to */ - zb_ieee_addr_t lpd_leave_ieee; /* IEEE to delete from MAC power table */ -#endif - -#ifdef ZB_ROUTER_ROLE -/*Pointer to the end device that expires first*/ - zb_neighbor_tbl_ent_t *next_aging_end_device; -#endif -#if !(defined ZB_ED_ROLE && defined ZB_ED_RX_OFF_WHEN_IDLE) - zb_nwk_btr_t btt[ZB_NWK_BTR_TABLE_SIZE]; /*!< Broadcast transaction - * table see 3.6.5 */ - zb_uint8_t btt_cnt; /*!< */ -#endif - -#ifdef ZB_ROUTER_ROLE - zb_nwk_broadcast_retransmit_t brrt[ZB_NWK_BRR_TABLE_SIZE]; /* Broadcast - * retransmission - table */ - zb_uint8_t brrt_cnt; - zb_uint8_t brrt_in_progress; /* Broadcast retransmission is in progress */ - zb_rejoin_context_t rejoin_req_table[ZB_NWK_REJOIN_REQUEST_TABLE_SIZE]; - zb_uint8_t rejoin_req_table_cnt; -#endif - -#if defined ZB_NWK_STOCHASTIC_ADDRESS_ASSIGN && defined ZB_ROUTER_ROLE - /* When ZR/ZC discovers address conflict for remote device or itself (ZR) - * it places conflicting address into this table (addr_ref for conflicting device - * used as index). Entry will be cleared in 2 cases: - * - Device that discovers conflict sending Network Status - * - another Network Status with identical payload was received - */ -#endif - - zb_uint8_t unsecure_frame_attempt; /*!< current attempt to unsecure frame */ - -#ifndef ZB_CONFIGURABLE_MEM - zb_nwk_in_q_t input_q; /*!< input queue: exclude races */ - /* input_q is a struct here, so need & to access it in the way unified with configurable mem build. */ -#define ZB_NWK_IN_Q (&ZG->nwk.handle.input_q) - -#else - /* If configurable memory, no buffer allocate here. Instead assign a pointer in zb_init_configurable_mem(). */ - zb_byte_array_t *input_q; /*!< input queue: a pointer */ -#define ZB_NWK_IN_Q (ZG->nwk.handle.input_q) - -#endif /* ZB_CONFIGURABLE_MEM */ - - zb_uint8_t input_blocked_by; /*!< buffer which blocked nwk input processing */ - -#ifndef ZB_LITE_NO_PANID_CONFLICT_DETECTION - zb_uint16_t new_panid; /*!< */ - - zb_bitbool_t panid_conflict:1; /*!< Flag 'Has Pan ID conflict' */ -#endif /* panid conflict enabled */ - - zb_bitbool_t permit_join:1; /*!< True if permit join is in progress */ - zb_bitbool_t reserved:1; - /*zb_bitfield_t joined:1; moved to AIB.tcpolicy and defined ZB_JOINED() macro Non-zero if the device is joined into the network */ - - zb_bitbool_t router_started:1; /*!< True if the device is a router and it is started */ - - zb_bitbool_t poll_in_progress:1; /*!< */ - zb_bitbool_t joined_restart:1; /*!< True if the device started - * with NWK parameters from NVRAM */ - zb_bitbool_t rejoin_capability_alloc_address:1; /*!< True if address is selected by the - * parent; False if self-assigned */ - zb_bitbool_t addr_conflict_ctx_send_nwk_status:1; /*!< True if nwk status command must be - * broadcast during address conflict - * resolution */ - zb_bitbool_t nwk_broadcast_delivery_time_passed:1; /*nwk.nib -#endif - -/* For stack internals access PIBCACHE directly */ -#ifdef ZB_PIB_CACHE -#undef ZB_PIB_CACHE -/*cstat !MISRAC2012-Rule-5.2_c99 !MISRAC2012-Rule-5.4_c99 */ -/* The following violation of rules 5.2 and 5.4 seem to be false positive - * At one time, only one macro is currently defined, but MISRA violations - * 5.2 and 5.4 require at least two definitions simultaneously. - * This violation seems to be caused by #undef usage, which cannot - * be analyzed by C-STAT correctly. */ -#define ZB_PIB_CACHE() (&ZG->nwk.pib_cache) -#endif - -#define ZB_NWK_GET_RREQ_ID() (++ZB_NIB().rreq_id) - -#define ZB_NWK_MAC_IFACE_TBL() ZB_NIB().mac_iface_tbl -#define ZB_NWK_MAC_IFACE_TBL_ENTRY(iface_id) (&ZB_NIB().mac_iface_tbl[iface_id]) - -#ifdef ZB_NWK_USE_SEND_JITTER -#define ZB_NWK_JITTER(interval) ((interval) + ZB_RANDOM_JTR(ZB_NWK_OCTETS_TO_BI(ZB_NWKC_MAX_BROADCAST_JITTER_OCTETS))) -#else -#define ZB_NWK_JITTER(interval) (interval) -#endif - -void zb_set_bit_in_bit_vector(zb_uint8_t *v, zb_ushort_t b); - -zb_bool_t zb_check_bit_in_bit_vector(zb_uint8_t *v, zb_ushort_t b); - -void zb_clr_bit_in_bit_vector(zb_uint8_t *v, zb_ushort_t b); - -void zb_add_short_addr_sorted(zb_address_ieee_ref_t ref, zb_uint16_t short_addr); - -zb_ret_t zb_address_reuse_pan_id(zb_uint16_t short_pan_id, zb_ext_pan_id_t pan_id, zb_address_pan_id_ref_t panid_ref); - -zb_ret_t zb_address_delete_pan_id(zb_address_pan_id_ref_t panid_ref); - -void nwk_clear_pending_table(void); -void nwk_clear_pending_table_for_destination(zb_uint16_t dst_addr); - -void zb_nwk_load_pib_confirm(zb_uint8_t param); - -#ifdef ZB_FORMATION -void zb_nwk_call_mlme_start(zb_uint8_t param); -#endif /* ZB_FORMATION */ - -#ifdef ZB_JOIN_CLIENT -void zb_nwk_sync_pibcache_with_mac(zb_uint8_t param, zb_callback_t cb); -#else -#define zb_nwk_sync_pibcache_with_mac(param, cb) -#endif - - -#if defined ZB_MAC_POWER_CONTROL -/* Routine to be called by child (ZED/ZR) */ -void zb_nwk_lpd_joined_child(zb_uint8_t param); - -/* Routine to be called by child (ZED/ZR) */ -void zb_nwk_lpd_joined_parent(zb_uint8_t param, zb_uint16_t short_addr); -#endif /* ZB_MAC_POWER_CONTROL */ - -void zb_nlme_rejoin_request_pre_handler(zb_uint8_t param); - -/*! @} */ -/*! @endcond */ - -#endif /* ZB_NWK_GLOBALS_H */ diff --git a/zboss/development/src/include/zb_nwk_mm.h b/zboss/development/src/include/zb_nwk_mm.h deleted file mode 100644 index 6079e2fa6a..0000000000 --- a/zboss/development/src/include/zb_nwk_mm.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Header file for NWK MultiMAC -*/ -#ifndef ZB_NWK_MM_H -#define ZB_NWK_MM_H 1 - -#define ZB_NWK_MAC_IFACE_SCAN_TYPE_ACTIVE 0U -#define ZB_NWK_MAC_IFACE_SCAN_TYPE_ENH_ACTIVE 1U - -void zb_nwk_mm_mac_iface_table_init(void); - -zb_uint8_t zb_nwk_mm_get_freq_band(void); - -void zb_nlme_set_interface_request(zb_uint8_t param); - -void zb_nlme_get_interface_request(zb_uint8_t param); - -zb_uint8_t zb_multimac_get_iface_id_by_channel_page(zb_uint8_t page_idx, zb_uint8_t channel_idx); - -/* Multi-MAC proxy functions */ -void zb_nwk_handle_mlme_start_confirm(zb_uint8_t param); -void zb_nwk_handle_mlme_reset_confirm(zb_uint8_t param); -void zb_nwk_handle_mcps_data_confirm(zb_uint8_t param); - -void zb_multimac_mlme_start_request_proxy(zb_uint8_t param); -void zb_multimac_mlme_start_confirm_proxy(zb_uint8_t param); -void zb_multimac_mcps_data_request_proxy(zb_uint8_t param); -void zb_multimac_mlme_set_request_proxy(zb_uint8_t param); -void zb_multimac_mlme_reset_request_proxy(zb_uint8_t param); -void zb_multimac_mlme_reset_confirm_proxy(zb_uint8_t param); -void zb_multimac_mlme_get_request_proxy(zb_uint8_t param); - -void zb_multimac_mlme_scan_request_proxy(zb_uint8_t param); -void zb_multimac_mlme_scan_confirm_proxy(zb_uint8_t param); - -void zb_multimac_mcps_data_confirm_proxy(zb_uint8_t param); - -void zb_multimac_mac_init(void); -void zb_multimac_mac_deinit(void); - -#define ZB_MAC_INIT() zb_multimac_mac_init() - -#define ZB_MAC_DEINIT() zb_multimac_mac_deinit() - -/* MAC split interface API */ - -/** - * @brief Synchronizes association parameters (MAC short address, coordinator extended address) - * from primary interface with other interfaces - * - * @param param - */ -void zb_nwk_mm_sync_assoc(zb_uint8_t param); - - -/** - Get the primary MAC interface. -*/ -zb_uint8_t zb_get_primary_interface(void); - -#endif /* ZB_NWK_MM_H */ diff --git a/zboss/development/src/include/zb_nwk_neighbor.h b/zboss/development/src/include/zb_nwk_neighbor.h deleted file mode 100644 index 98dba92ad0..0000000000 --- a/zboss/development/src/include/zb_nwk_neighbor.h +++ /dev/null @@ -1,323 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Neighbor table (base and additional) -*/ - -#ifndef ZB_NWK_NEIGHBOR_H -#define ZB_NWK_NEIGHBOR_H 1 - -/*! @cond internals_doc */ -/*! \addtogroup ZB_NWK */ -/*! @{ */ - -/* to be able to limit addr_ref size to 7 bits, limit address translation table - * size to 127 */ -#ifndef ZB_CONFIGURABLE_MEM -ZB_ASSERT_COMPILE_DECL(ZB_IEEE_ADDR_TABLE_SIZE < 128); -#endif -ZB_ASSERT_COMPILE_DECL(ZB_NWK_ROUTER_AGE_LIMIT < 4); - -/* zb_neighbor_tbl_ent_t moved to zboss_api_internal.h for configurable memory feature. */ - -/* Ext neighbor as an alias to the neighbor entry */ -typedef zb_neighbor_tbl_ent_t zb_ext_neighbor_tbl_ent_t; - -typedef struct zb_nbr_iterator_data_s { - /*! Stores the neighbour table update counter. */ - zb_uint32_t update_count; -} zb_nbr_iterator_data_t; - - -/** - Neighbor table - */ -typedef struct zb_neighbor_tbl_s -{ - /*! base (run-time) neighbor table */ -#ifndef ZB_CONFIGURABLE_MEM - zb_neighbor_tbl_ent_t neighbor[ZB_NEIGHBOR_TABLE_SIZE]; - /*! array for addressing neighbor table by network address ref */ - zb_uint8_t addr_to_neighbor[ZB_IEEE_ADDR_TABLE_SIZE]; -#else - zb_neighbor_tbl_ent_t *neighbor; - zb_uint8_t *addr_to_neighbor; -#endif - zb_nbr_iterator_data_t iterator_data; - /*! clock pointer for incoming_frame_counter expire */ - zb_ushort_t incoming_frame_counter_clock; -/*Pointer to the end device that expires first*/ - zb_neighbor_tbl_ent_t *next_aging_end_device; -#ifdef ZB_ROUTER_ROLE -/*NBT element to start parent_annce from */ - zb_uint8_t parent_annce_position; -#endif - zb_uint8_t transmit_failure_threshold; - zb_uint8_t transmit_failure_timeout; -} -zb_neighbor_tbl_t; - -#define ZB_NWK_NEIGHBOR_GET_INDEX_BY_ENTRY_ADDRESS(ent_addr) \ - ( ZB_ARRAY_IDX_BY_ELEM((zb_uint8_t *)&ZG->nwk.neighbor.neighbor[0], (zb_uint8_t *)ent_addr) / sizeof(*ent_addr) ) - -/** - Neighbor table subsystem init. - */ -void zb_nwk_neighbor_init(void); - -/** - Stop work with extended neighbor table: move some entries to the base table, - give all memory to the base - */ -void zb_nwk_exneighbor_stop(zb_uint16_t parent_short_addr); - -/** - Get extended neighbor table entry by short address - - @param panid_ref - ext Pan ID ref - @param short_addr - 16-bit device address - @param enbt - (out) allocated or found ext neighbor table entry - - @return RET_OK if success, error code if error - */ -zb_ret_t zb_nwk_exneighbor_by_short(zb_address_pan_id_ref_t panid_ref, zb_uint16_t short_addr, zb_ext_neighbor_tbl_ent_t **enbt); - -/** - Get extended neighbor table entry by long address - - @param panid_ref - ext Pan ID ref - @param long_addr - 64-bit device address - @param enbt - (out) allocated or found ext neighbor table entry - - @return RET_OK if success, error code if error - */ -zb_ret_t zb_nwk_exneighbor_by_ieee(zb_address_pan_id_ref_t panid_ref, zb_ieee_addr_t long_addr, zb_ext_neighbor_tbl_ent_t **enbt); - -/** - Check existence of neighbor table entry by IEEE address reference - - @param addr_ref - IEEE address reference - - @return ZB_TRUE if entry exists, ZB_FALSE otherwise - */ -zb_bool_t zb_nwk_neighbor_exists(zb_address_ieee_ref_t addr_ref); - -/** - Get neighbor table entry by address, create if absent - - @param addr_ref - address - @param create_if_absent - create new entry if absent - @param nbt - (out) neighbor table entry - - @return RET_OK if entry is found or was successfully created; RET_NOT_FOUND if entry doesn't exist; error code - if error - */ -zb_ret_t zb_nwk_neighbor_get(zb_address_ieee_ref_t addr_ref, zb_bool_t create_if_absent, zb_neighbor_tbl_ent_t **nbt); - - -/** - Get neighbor table entry by short address, does not create if absent - - @param short_addr - address - @param nbt - (out) neighbor table entry - - @return RET_OK if forund, else RET_NOT_FOUND - if error - */ -zb_ret_t zb_nwk_neighbor_get_by_short(zb_uint16_t short_addr, zb_neighbor_tbl_ent_t **nbt); - -/** - Get neighbor table entry by long address, does not create if absent - - @param long_addr - address - @param nbt - (out) neighbor table entry - - @return RET_OK if forund, else RET_NOT_FOUND - if error - */ -zb_ret_t zb_nwk_neighbor_get_by_ieee(const zb_ieee_addr_t long_addr, zb_neighbor_tbl_ent_t **nbt); - - -/** - Remove entity by IEEE address - - @param ieee_ref - IEEE address reference - - @return RET_OK if success, error code if error - */ -zb_ret_t zb_nwk_neighbor_delete(zb_address_ieee_ref_t ieee_ref); - -/** - Remove all entities - - @return nothing - */ -void zb_nwk_neighbor_clear(void); - - -/** - Remove all non-extneighbors. -*/ -void zb_nwk_neighbor_remove_non_extnbrs(void); - -/** - Copy ext entry to base, to be able to send packet to it. - - @param ext_ent - pointer to external table entry - @param do_cp - if ZB_TRUE, create new entry, else convert ext to base neighbor - - @return RET_OK if success, error code if error - */ -zb_ret_t zb_nwk_neighbor_ext_to_base(zb_ext_neighbor_tbl_ent_t *ent, zb_bool_t do_cp); - - -/** - Run one iteration of the incoming frame counter expiration clock algorithm - - The goal is to clear (drop to 0) counters for too old entries (with distance - between it and key_seq_number > 3). - Do it one entry at a time to exclude unpredictable delays. - - @param key_seq_number - current key sequence number - */ -void zb_nwk_neighbor_incoming_frame_counter_clock(zb_uint8_t key_seq_number); - - -/** - Get next device with rx_on_when_idle == 1 - - @param i - current index in the neighbor table. Use 0 to start iteration. - @return index in the neighbor table (0 is valid index) or ~0 if no more such entry - */ -zb_ushort_t zb_nwk_neighbor_next_rx_on_i(zb_ushort_t i); - -#define ZB_NWK_NEIGHBOR_BY_I(i) (&ZG->nwk.neighbor.neighbor[(i)]) - -/** - Get next child to retransmit broadcast frame to - - @param addr - broadcast address - @param i - current index in the neighbor table. Use 0 to start iteration. - @return index in the neighbor table or ~0 if no more such children - */ -zb_ushort_t zb_nwk_nbr_next_ze_children_i(zb_uint16_t addr, zb_ushort_t i); - -/** - Get next child with rx_on_when_idle == 1 - - @param i - current index in the neighbor table. Use 0 to start iteration. - @return index in the neighbor table or ~0 if no more such children - */ -zb_ushort_t zb_nwk_nbr_next_ze_children_rx_off_i(zb_ushort_t i); - -#if defined ZB_NWK_STOCHASTIC_ADDRESS_ASSIGN && defined ZB_ROUTER_ROLE /* Zigbee pro */ - -/** - Get neighbor table entry with flag need_rejoin==1 - - @param nbt - (out) neighbor table entry - - @return RET_OK if found, else RET_NOT_FOUND - if error - */ -zb_ret_t zb_nwk_neighbor_with_need_rejoin(zb_neighbor_tbl_ent_t **nbt); - -#endif - -/** - Get neighbor table size -*/ -zb_uint8_t zb_nwk_neighbor_table_size(void); - - -zb_ret_t zb_nwk_exneigbor_sort_by_lqi(void); - -zb_ret_t zb_nwk_exneighbor_remove_by_panid(zb_address_pan_id_ref_t panid_ref); - -zb_uint8_t zb_nwk_neighbor_get_ed_cnt(void); -zb_uint8_t zb_nwk_neighbor_get_ed_short_list(zb_uint8_t start_index, zb_uint8_t max_records, zb_uint8_t** ed_list); - -zb_uint8_t zb_nwk_neighbor_get_zc_zr_cnt(void); -zb_ret_t zb_nwk_neighbor_get_by_idx(zb_uint8_t idx, zb_neighbor_tbl_ent_t **nbt); - -zb_ret_t zb_nwk_get_sorted_neighbor(zb_uint8_t *index, zb_neighbor_tbl_ent_t **p_nbt); - -void zb_nwk_neighbor_complete_deletion(zb_address_ieee_ref_t ieee_ref, zb_uint8_t neighbor_index); - -#ifdef ZB_ROUTER_ROLE -void zb_nwk_neighbour_rssi_store(zb_neighbor_tbl_ent_t *nbt, zb_int8_t rssi); - -#ifdef ZB_NWK_NEIGHBOUR_PATH_COST_RSSI_BASED -zb_uint8_t zb_nwk_neighbour_get_path_cost(zb_neighbor_tbl_ent_t *nbt); -#endif /* ZB_NWK_NEIGHBOUR_PATH_COST_RSSI_BASED */ - -#endif /* ZB_ROUTER_ROLE */ - - -#if !defined ZB_ED_ROLE && defined ZB_MAC_DUTY_CYCLE_MONITORING -/** @fn zb_uint8_t zb_nwk_neighbor_get_subghz_list(zb_uint8_t *ref_list, zb_uint8_t max_records) - * @brief Builds list of Sub-GHz devices - * @details Returns list of references to Sub-GHz devices entries in neighbor table sorted by - * pkt_count in descending order. - * @param[out] ref_list - pointer to the array which will store references to the neighbor table entries - * @param[in] max_records - max number of elements that ref_list can store - * @return number of items in ref_list - */ -zb_uint8_t zb_nwk_neighbor_get_subghz_list(zb_address_ieee_ref_t *ref_list, zb_uint8_t max_records); -#endif - -/** - Update the neighbour table update counter. - */ -void zb_nwk_nbr_iterator_update_counter(void); - -/*! @} */ -/*! @endcond */ - -/* reserve slot 0 for the parent */ -#define EXN_START_I 1U - -#ifdef ZB_ROUTER_ROLE -zb_bool_t zb_nwk_ed_is_our_child(zb_uint16_t addr); -#endif /* ZB_ROUTER_ROLE */ - -void zb_nwk_nbt_print(void); - -#endif /* ZB_NWK_NEIGHBOR_H */ diff --git a/zboss/development/src/include/zb_nwk_nib.h b/zboss/development/src/include/zb_nwk_nib.h deleted file mode 100644 index 129959745a..0000000000 --- a/zboss/development/src/include/zb_nwk_nib.h +++ /dev/null @@ -1,873 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: NWK NIB database -*/ - -#ifndef ZB_NWK_NIB_H -#define ZB_NWK_NIB_H 1 - -/** - * \addtogroup nwk_ib - * @{ - * @par NWK NIB - * Some NIB fields are indeed PIB fields. Use macros to access it. - */ - - -/*! NWK NIB Attributes */ -typedef enum zb_nib_attribute_e -{ - /** - A sequence number used to identify outgoing frames. - */ - ZB_NIB_ATTRIBUTE_SEQUENCE_NUMBER = 0X81, - /** - The maximum time duration in OctetDurations allowed for the parent and - all child devices to retransmit a broadcast message - (passive acknowledgment timeout). - */ - ZB_NIB_ATTRIBUTE_PASSIVE_ASK_TIMEOUT = 0X82, - /** - The maximum number of retries allowed after a broadcast transmission failure. - */ - ZB_NIB_ATTRIBUTE_MAX_BROADCAST_RETRIES = 0X83, - /** - The number of children a device is allowed to have on its current network. - @note When nwkAddrAlloc has a value of 0x02, indicating stochastic - addressing, the value of this attribute is implementation-dependent. - */ - ZB_NIB_ATTRIBUTE_MAX_CHILDREN = 0X84, - /** - The depth a device can have. - */ - ZB_NIB_ATTRIBUTE_MAX_DEPTH = 0X85, - /** The number of routers any one device is allowed to have as children. - This value is determined by the Zigbee coordinator for all devices - in the network. If nwkAddrAlloc is 0x02 this value not used. - */ - ZB_NIB_ATTRIBUTE_MAX_ROUTERS = 0X86, - /** - The current set of neighbor table entries in the device. - */ - ZB_NIB_ATTRIBUTE_NEIGHBOR_TABLE = 0X87, - /** - Time duration in OctetDurations that a broadcast message needs to encompass - the entire network. This is a calculated quantity based on other NIB - attributes. - */ - ZB_NIB_ATTRIBUTE_BROADCAST_DELIVERY_TIME = 0X88, - /** - If this is set to 0, the NWK layer shall calculate link cost from all - neighbor nodes using the LQI values reported by the MAC layer; other-wise, - it shall report a constant value. - */ - ZB_NIB_ATTRIBUTE_REPORT_CONSTANT_COST = 0X89, - /** - Reserved. - */ - ZB_NIB_ATTRIBUTE_ROUTE_DISCOVERY_RETRIES_PERMITTED = 0X8A, - /** - The current set of routing table entries in the device. - */ - ZB_NIB_ATTRIBUTE_ROUTE_TABLE = 0X8B, - /** - The current route symmetry setting: - - TRUE means that routes are considered to be comprised of symmetric links. - Backward and forward routes are created during one-route discovery - and they are identical. - - FALSE indicates that routes are not consider to be comprised of symmetric - links. Only the forward route is stored during route discovery. - */ - ZB_NIB_ATTRIBUTE_SYM_LINK = 0X8E, - /** - This field shall contain the device capability information established at - network joining time. - */ - ZB_NIB_ATTRIBUTE_CAPABILITY_INFORMATION = 0X8F, - /** - A value that determines the method used to assign addresses: - - 0x00 = use distributed address allocation - - 0x01 = reserved - - 0x02 = use stochastic address allocation - */ - ZB_NIB_ATTRIBUTE_ADDR_ALLOC = 0X90, - /** - A flag that determines whether the NWK layer should assume the ability to - use hierarchical routing: - - TRUE = assume the ability to use hierarchical routing. - - FALSE = never use hierarchical routing. - */ - ZB_NIB_ATTRIBUTE_USE_TREE_ROUTING = 0X91, - /** - The address of the designated network channel manager function. - */ - ZB_NIB_ATTRIBUTE_MANAGER_ADDR = 0X92, - /** - The maximum number of hops in a source route. - */ - ZB_NIB_ATTRIBUTE_MAX_SOURCE_ROUTE = 0X93, - /** - The value identifying a snapshot of the network settings with which this - node is operating with. - */ - ZB_NIB_ATTRIBUTE_UPDATE_ID = 0X94, - /** - The maximum time (in superframe periods) that a transaction is stored by a - coordinator and indicated in its beacon. This attribute reflects the value - of the MAC PIB attribute macTransaction-PersistenceTime and any changes - made by the higher layer will be reflected in the MAC PIB attribute value - as well. - */ - ZB_NIB_ATTRIBUTE_TRANSACTION_PERSISTENCE_TIME = 0X95, - /** - The 16-bit address that the device uses to communicate with the PAN. - This attribute reflects the value of the MAC PIB attribute macShortAddress - and any changes made by the higher layer will be reflected in the MAC PIB - attribute value as well. - */ - ZB_NIB_ATTRIBUTE_NETWORK_ADDRESS = 0X96, - /** - The identifier of the Zigbee stack profile in use for this device. - */ - ZB_NIB_ATTRIBUTE_STACK_PROFILE = 0X97, - /** - The current set of broadcast transaction table entries in the device. - */ - ZB_NIB_ATTRIBUTE_BROADCAST_TRANSACTION_TABLE = 0X98, - /** - The set of group identifiers, in the range 0x0000 - 0xffff, for groups of - which this device is a member. - */ - ZB_NIB_ATTRIBUTE_GROUP_ID_TABLE = 0X99, - /** - The Extended PAN Identifier for the PAN of which the device is a member. - The value 0x0000000000000000 means the Extended PAN Identifier is unknown. - */ - ZB_NIB_ATTRIBUTE_EXTENDED_PANID = 0X9A, - /** - A flag determining the layer where multicast messaging occurs. - - TRUE = multicast occurs at the network layer. - - FALSE= multicast oc-curs at the APS layer and using the APS header. - */ - ZB_NIB_ATTRIBUTE_USE_MULTICAST = 0X9B, - /** - The route record table. - */ - ZB_NIB_ATTRIBUTE_ROUTE_RECORD_TABLE = 0X9C, - /** - A flag determining if this device is a concentrator. - - TRUE = Device is a concentrator. - - FALSE = Device is not a concentrator. - */ - ZB_NIB_ATTRIBUTE_IS_CONCENTRATOR = 0X9D, - /** - The hop count radius for concentrator route discoveries. - */ - ZB_NIB_ATTRIBUTE_CONCENTRATOR_RADIUS = 0X9E, - /** - The time in seconds between concentrator route discoveries. - If set to 0x0000, the discoveries are done at start up and by - the next higher layer only. - */ - ZB_NIB_ATTRIBUTE_CONCENTRATOR_DESCOVERY_TIME = 0X9F, - /** - Security attribute defined in Chapter 4. @see ZB R21 specification. - */ - ZB_NIB_ATTRIBUTE_SECURITY_LEVEL = 0XA0, - /** - Security attribute defined in Chapter 4. @see ZB R21 specification. - */ - ZB_NIB_ATTRIBUTE_SECURITY_MATERIAL_SET = 0XA1, - /** - Security attribute defined in Chapter 4. @see ZB R21 specification. - */ - ZB_NIB_ATTRIBUTE_ACTIVE_KEY_SEQ_NUMBER = 0XA2, - /** - Security attribute defined in Chapter 4. @see ZB R21 specification. - */ - ZB_NIB_ATTRIBUTE_ALL_FRESH = 0XA3, - /** - Not used. - */ - ZB_NIB_ATTRIBUTE_SECURE_ALL_FRAMES = 0XA5, - /** - The time in seconds between link status command frames. - */ - ZB_NIB_ATTRIBUTE_LINK_STATUS_PERIOD = 0XA6, - /** - The number of missed link status command frames before resetting the - link costs to zero. - */ - ZB_NIB_ATTRIBUTE_ROUTER_AGE_LIMIT = 0XA7, - /** - A flag that determines whether the NWK layer should detect and correct - conflicting addresses: - - TRUE = assume ad-dresses are unique. - - FALSE = addresses may not be unique. - */ - ZB_NIB_ATTRIBUTE_UNIQUE_ADDR = 0XA8, - /** - The current set of 64-bit IEEE to 16-bit network address map. - */ - ZB_NIB_ATTRIBUTE_ADDRESS_MAP = 0XA9, - /** - A flag that determines if a time stamp indication is provided on incoming - and outgoing packets. - - TRUE= time indication provided. - - FALSE = no time indication provided. - */ - ZB_NIB_ATTRIBUTE_TIME_STAMP = 0X8C, - /** - This NIB attribute should, at all times, have the same value as macPANId. - */ - ZB_NIB_ATTRIBUTE_PAN_ID = 0X80, - /** - A count of unicast transmissions made by the NWK layer on this device. - Each time the NWK layer transmits a unicast frame, by invoking the - MCPS-DATA.request primitive of the MAC sub-layer, it shall increment this - counter. When either the NHL performs an NLME-SET.request on this attribute - or if the value of nwkTxTotal rolls over past 0xffff the NWK layer shall - reset to 0x00 each Transmit Failure field contained in the neighbor table. - */ - ZB_NIB_ATTRIBUTE_TX_TOTAL = 0X8D, - /** - This policy determines whether or not a remote NWK leave request command - frame received by the local device is accepted. - */ - ZB_NIB_ATTRIBUTE_LEAVE_REQ_ALLOWED = 0xAA, - - /* TODO: FILL MISSING ATTRIBUTES!!! */ - - /** - A table of lower-layer interfaces managed by the network layer. - */ - ZB_NIB_ATTRIBUTE_MAC_INTERFACE_TABLE = 0xAF, -} -zb_nib_attribute_t; - -/** @brief return NWK sequence number used to identify outgoing frames */ -#define ZB_NIB_SEQUENCE_NUMBER() ZB_NIB().sequence_number -/** @brief increment NWK sequence number used to identify outgoing frames */ -#define ZB_NIB_SEQUENCE_NUMBER_INC() (ZB_NIB().sequence_number++) - -/** @brief Maximum network depth a device can have */ -#define ZB_NIB_MAX_DEPTH() ZB_NIB().max_depth -/** @brief Device network depth */ -#define ZB_NIB_DEPTH() ZB_NIB().depth - -/** - * Returns current type of the device. - */ -zb_bool_t zb_is_device_zc(void); - -zb_bool_t zb_is_device_zr(void); - -zb_bool_t zb_is_device_zed(void); - -zb_bool_t zb_is_device_zc_or_zr(void); - -#if defined ZB_ED_ROLE || defined DOXYGEN - -/** - @cond DOXYGEN_GENERAL_SECTION - @} - @{ - \addtogroup zboss_general_api - */ - -/* ZED-only build */ - -/** @brief returns true if device is Coordinator */ -#define ZB_IS_DEVICE_ZC() ZB_FALSE -/** @brief returns true if device is Router */ -#define ZB_IS_DEVICE_ZR() ZB_FALSE -/** @brief returns true if device is End Device */ -#define ZB_IS_DEVICE_ZED() ZB_TRUE -/** @brief returns true if device is Coordinator or Router */ -#define ZB_IS_DEVICE_ZC_OR_ZR() ZB_FALSE -/** @brief returns true if device is not Router */ -#define ZB_IS_DEVICE_NOT_ZR() ZB_TRUE - -/** - @{ - \addtogroup nwk_ib - @} - @endcond - */ - -#elif (defined ZB_ROUTER_ROLE && !defined ZB_ED_FUNC && !defined ZB_COORDINATOR_ROLE) - -/* ZR-only build, can't switch into ED mode */ - -/** @brief returns true if device is Coordinator */ -#define ZB_IS_DEVICE_ZC() ZB_FALSE -/** @brief returns true if device is Router */ -#define ZB_IS_DEVICE_ZR() ZB_TRUE -/** @brief returns true if device is End Device */ -#define ZB_IS_DEVICE_ZED() ZB_FALSE -/** @brief returns true if device is Coordinator or Router */ -#define ZB_IS_DEVICE_ZC_OR_ZR() ZB_TRUE -/** @brief returns true if device is not Router */ -#define ZB_IS_DEVICE_NOT_ZR() ZB_FALSE - -#elif (defined ZB_ROUTER_ROLE && defined ZB_ED_FUNC && !defined ZB_COORDINATOR_ROLE) - -/* ZR-ZED only build, ZR can switch into ED mode at runtime */ - -/** @brief returns true if device is Coordinator */ -#define ZB_IS_DEVICE_ZC() ZB_FALSE -/** @brief returns true if device is Router */ -/** @brief returns true if device is Router */ -#define ZB_IS_DEVICE_ZR() (zb_is_device_zr()) -/** @brief returns true if device is End Device */ -#define ZB_IS_DEVICE_ZED() (zb_is_device_zed()) -/** @brief returns true if device is Coordinator or Router */ -#define ZB_IS_DEVICE_ZC_OR_ZR() (ZB_IS_DEVICE_ZR()) -/** @brief returns true if device is not Router */ -#define ZB_IS_DEVICE_NOT_ZR() (!ZB_IS_DEVICE_ZR()) - -#elif (defined ZB_COORDINATOR_ROLE && defined ZB_COORDINATOR_ONLY) - -/* ZC-only build */ - -/** @brief returns true if device is Coordinator */ -#define ZB_IS_DEVICE_ZC() ZB_TRUE -/** @brief returns true if device is Router */ -#define ZB_IS_DEVICE_ZR() ZB_FALSE -/** @brief returns true if device is End Device */ -#define ZB_IS_DEVICE_ZED() ZB_FALSE -/** @brief returns true if device is Coordinator or Router */ -#define ZB_IS_DEVICE_ZC_OR_ZR() ZB_TRUE -/** @brief returns true if device is not Router */ -#define ZB_IS_DEVICE_NOT_ZR() ZB_TRUE - -#else - -/* Full build: zc-zr-zed switchable at runtime */ - -/** @brief returns true if device is Coordinator */ -#define ZB_IS_DEVICE_ZC() (zb_is_device_zc()) -/** @brief returns true if device is Router */ -#define ZB_IS_DEVICE_ZR() (zb_is_device_zr()) -/** @brief returns true if device is End Device */ -#define ZB_IS_DEVICE_ZED() (zb_is_device_zed()) -/** @brief returns true if device is Coordinator or Router */ -#define ZB_IS_DEVICE_ZC_OR_ZR() (zb_is_device_zc_or_zr()) -/** @brief returns true if device is not Router */ -#define ZB_IS_DEVICE_NOT_ZR() (!ZB_IS_DEVICE_ZR()) - -#endif /* roles select */ - -/** - Check that the device at ZC working in Switch mode (routing between 2.4 and sub-ghz). - - Currently Switch is not implemented, so always return 0. - */ -#define ZB_SUBGHZ_SWITCH_MODE() ZB_FALSE - -#define ZB_SET_SUBGHZ_SWITCH_MODE(mode) - -/** @brief logical device type, @see @ref nwk_device_type */ -#define ZB_NIB_DEVICE_TYPE() (ZB_NIB().device_type + 0U) - - -/** @brief number of source routes in device source routing table */ -#define ZB_NIB_SRCRT_CNT() ZB_NIB().nwk_src_route_cnt - -/** @brief Device extended Pan ID */ -#define ZB_NIB_EXT_PAN_ID() ZB_NIB().extended_pan_id -/** @brief The value of ZB_NIB_ATTRIBUTE_UPDATE_ID attribute */ -#define ZB_NIB_UPDATE_ID() ZB_NIB().update_id - -#ifndef ZB_LITE_ALWAYS_SECURE -/** @brief Device security level; by default is 5 */ -#define ZB_NIB_SECURITY_LEVEL() ZB_NIB().security_level -/** @brief Set Device security level to value 'v' */ -#define ZB_SET_NIB_SECURITY_LEVEL(v) ZB_NIB().security_level = (v) -#else -/** @brief Device security level; always is 5 */ -#define ZB_NIB_SECURITY_LEVEL() 5U -/** @brief \deprecated unsupported */ -#define ZB_SET_NIB_SECURITY_LEVEL(v) -#endif /* ZB_LITE_ALWAYS_SECURE */ - -/* use tree routing? */ -#ifdef ZB_NWK_TREE_ROUTING -/** @brief returns USE_TREE_ROUTING attribute value */ -#define ZB_NIB_GET_USE_TREE_ROUTING() ZB_NIB().use_tree_routing -/** @brief Set USE_TREE_ROUTING attribute value to 'v' */ -#define ZB_NIB_SET_USE_TREE_ROUTING(v) (ZB_NIB().use_tree_routing = (v)) -#else -/** @brief Use tree routing - unsupported */ -#define ZB_NIB_GET_USE_TREE_ROUTING() 0 -/** @brief \deprecated unsupported */ -#define ZB_NIB_SET_USE_TREE_ROUTING(v) -#endif - -/* use nwk multicast? */ -#ifndef ZB_NO_NWK_MULTICAST -/** @brief returns ZB_NIB_GET_USE_MULTICAST attribute value */ -#define ZB_NIB_GET_USE_MULTICAST() ZB_NIB().nwk_use_multicast -/** @brief Set ZB_NIB_SET_USE_MULTICAST attribute value to 'v' */ -#define ZB_NIB_SET_USE_MULTICAST( v ) (ZB_NIB().nwk_use_multicast = ( v )) -#else -/** @brief Use multicast - unsupported */ -#define ZB_NIB_GET_USE_MULTICAST() 0 -/** @brief \deprecated unsupported */ -#define ZB_NIB_SET_USE_MULTICAST( v ) -#endif - -#ifndef ZB_LITE_NO_CONFIGURABLE_LINK_STATUS -/** @brief LINK_STATUS_PERIOD attribute */ -#define ZB_NIB_GET_LINK_STATUS_PERIOD() ZB_NIB().link_status_period -/** @brief ROUTER_AGE_LIMIT attribute */ -#define ZB_NIB_GET_ROUTER_AGE_LIMIT() ZB_NIB().router_age_limit -#else -/** @brief LINK_STATUS_PERIOD attribute */ -#define ZB_NIB_GET_LINK_STATUS_PERIOD() ZB_NWK_LINK_STATUS_PERIOD -/** @brief ROUTER_AGE_LIMIT attribute */ -#define ZB_NIB_GET_ROUTER_AGE_LIMIT() ZB_NWK_ROUTER_AGE_LIMIT -#endif - -#ifndef ZB_LITE_NO_CONFIGURABLE_POWER_DELTA -/* [R22STUBS]: TODO: Implement proper comments */ -#define ZB_NIB_GET_POWER_DELTA_PERIOD(i) \ - ZB_NWK_RANDOM_TIME_PERIOD(ZB_NIB().mac_iface_tbl[i].link_power_data_rate * ZB_TIME_ONE_SECOND, \ - ZB_NWK_LINK_POWER_DELTA_TRANSMIT_RATE_JITTER * ZB_TIME_ONE_SECOND) - -/** @brief use custom value for mac_iface_tbl[i].link_power_data_rate */ -#define ZB_NIB_SET_POWER_DELTA_PERIOD(i, v) (ZB_NIB().mac_iface_tbl[i].link_power_data_rate = ( v )) - -/** @brief mode for Link Power Delta Negotiation */ -#define ZB_NIB_NWK_LPD_CMD_MODE() (ZB_NIB().nwk_lpd_cmd_mode) - -#else -/* [R22STUBS]: TODO: Implement proper comments */ -#define ZB_NIB_GET_POWER_DELTA_PERIOD(i) \ - ZB_NWK_RANDOM_TIME_PERIOD(ZB_NWK_LINK_POWER_DELTA_TRANSMIT_RATE * ZB_TIME_ONE_SECOND, \ - ZB_NWK_LINK_POWER_DELTA_TRANSMIT_RATE_JITTER * ZB_TIME_ONE_SECOND) - -#define ZB_NIB_SET_POWER_DELTA_PERIOD(i, v) -#define ZB_NIB_NWK_LPD_CMD_MODE() 0 - -#endif - -/* is leave request allowed? */ -/** Is leave request allowed */ -/** @brief LEAVE_REQ_ALLOWED attribute */ -#define ZB_NIB_GET_LEAVE_REQ_ALLOWED() ZB_NIB().leave_req_allowed -/** @brief Set LEAVE_REQ_ALLOWED attribute value to 'v' */ -#define ZB_NIB_SET_LEAVE_REQ_ALLOWED( v ) (ZB_NIB().leave_req_allowed = ( v )) - -#ifdef SNCP_MODE -/** Force route record sending */ -/** @brief Get force route record attribute */ -#define ZB_NIB_GET_FORCE_RREC_SENDING() ZB_NIB().nwk_force_rrec_sending -/** @brief Set force route record attribute value to 'v' */ -#define ZB_NIB_SET_FORCE_RREC_SENDING( v ) (ZB_NIB().nwk_force_rrec_sending = ( v )) -#endif - -/** @brief LEAVE_REQ_WITHOUT_REJOIN_ALLOWED attribute */ -#define ZB_NIB_GET_LEAVE_REQ_WITHOUT_REJOIN_ALLOWED() ZB_NIB().leave_req_without_rejoin_allowed -/** @brief Set LEAVE_REQ_WITHOUT_REJOIN_ALLOWED attribute value to 'v' */ -#define ZB_NIB_SET_LEAVE_REQ_WITHOUT_REJOIN_ALLOWED( v ) (ZB_NIB().leave_req_without_rejoin_allowed = ( v )) - -#ifndef ZB_LITE_NO_SOURCE_ROUTING -/** @brief IS_CONCENTRATOR attribute */ -#define ZB_NIB_GET_IS_CONCENTRATOR() ZB_NIB().nwk_is_concentrator -/** @brief Set IS_CONCENTRATOR attribute to 'v' */ -#define ZB_NIB_SET_IS_CONCENTRATOR( v ) (ZB_NIB().nwk_is_concentrator = ( v )) -/** @brief CONCENTRATOR_RADIUS attribute */ -#define ZB_NIB_GET_CONCENTRATOR_RADIUS() ZB_NIB().nwk_concentrator_radius -/** @brief Set CONCENTRATOR_RADIUS attribute to 'v' */ -#define ZB_NIB_SET_CONCENTRATOR_RADIUS( v ) (ZB_NIB().nwk_concentrator_radius = ( v )) -/** @brief CONCENTRATOR_DISC_TIME attribute */ -#define ZB_NIB_GET_CONCENTRATOR_DISC_TIME() ZB_NIB().nwk_concentrator_disc_time -/** @brief Set CONCENTRATOR_DISC_TIME attribute to 'v' */ -#define ZB_NIB_SET_CONCENTRATOR_DISC_TIME( v ) (ZB_NIB().nwk_concentrator_disc_time = ( v )) -#else -/** @brief IS_CONCENTRATOR attribute */ -#define ZB_NIB_GET_IS_CONCENTRATOR() ZB_FALSE -/** @brief Set IS_CONCENTRATOR attribute to 'v' */ -#define ZB_NIB_SET_IS_CONCENTRATOR( v ) -/** @brief CONCENTRATOR_RADIUS attribute */ -#define ZB_NIB_GET_CONCENTRATOR_RADIUS() 0 -/** @brief Set CONCENTRATOR_RADIUS attribute to 'v' */ -#define ZB_NIB_SET_CONCENTRATOR_RADIUS( v ) -/** @brief CONCENTRATOR_DISC_TIME attribute */ -#define ZB_NIB_GET_CONCENTRATOR_DISC_TIME() 0 -/** @brief Set CONCENTRATOR_DISC_TIME attribute to 'v' */ -#define ZB_NIB_SET_CONCENTRATOR_DISC_TIME( v ) -#endif /* ZB_LITE_NO_SOURCE_ROUTING */ - -/** @brief SECURITY_MATERIAL attribute */ -#define ZB_NIB_SECURITY_MATERIAL() ZB_NIB().secur_material_set -/** @brief NWK_MANAGER_ADDR attribute */ -#define ZB_NIB_NWK_MANAGER_ADDR() ZB_NIB().nwk_manager_addr - -/** @brief total number of transmissions made by NWK */ -#define ZB_NIB_NWK_TX_TOTAL() (ZB_NIB().tx_stat.tx_total + 0U) -/** @brief number of transmissions failed by NWK */ -#define ZB_NIB_NWK_TX_FAIL() (ZB_NIB().tx_stat.tx_fail + 0U) - -/** - NWK route discovery -*/ -typedef struct zb_nwk_route_discovery_s /* do not pack for IAR */ -{ - zb_bitfield_t used:1; /*!< 1 if entry is used, 0 - otherwise */ - zb_bitfield_t expiration_time:7; /*!< Countdown timer indicating when route - * discovery expires. ZB_NWK_ROUTE_DISCOVERY_EXPIRY 10 */ - zb_uint8_t request_id; /*!< Sequence number for a route request */ - /* TODO: use 1 byte - index in the translation table */ - zb_uint16_t source_addr; /*!< 16-bit network address of the route - * requests initiator */ - /* TODO: use 1 byte - index in the translation table */ - zb_uint16_t sender_addr; /*!< 16-bit network address of the device that - * has sent the most recent lowest cost route - * request */ - zb_uint16_t dest_addr; /*!< 16-bit network destination address of this - * request */ - zb_uint8_t forward_cost; /*!< Path cost from the source of the route request - * to the current device */ - zb_uint8_t residual_cost; /*!< Path cost from the current to the destination - * device */ -} ZB_PACKED_STRUCT -zb_nwk_route_discovery_t; - -/** - NWK pending list element -*/ -typedef struct zb_nwk_pend_s /* do not pack for IAR */ -{ - zb_uint16_t dest_addr; /*!< 16-bit network destination address of this - * request */ - zb_uint8_t param; /*!< buffer waiting for route discovery */ - zb_bitfield_t used:1; /*!< 1 if entry is used, 0 - otherwise */ - zb_bitfield_t expiry:5; /*!< expiration time. ZB_NWK_PENDING_ENTRY_EXPIRY 20, - * 5-bits i */ - zb_bitfield_t waiting_buf:1; /*!< if pending buffer waits new buffer to - * start route discovery */ - zb_bitfield_t reserved:1; - - zb_uint8_t handle; -} ZB_PACKED_STRUCT -zb_nwk_pend_t; - -/** - Part of the secured material stored in array. - - Other secured material components stored elsewhere: - OutgoingFrameCounter - NIB - IncomingFrameCounterSet - neighbor table - */ -typedef struct zb_secur_material_set_t -{ - zb_uint8_t key[ZB_CCM_KEY_SIZE]; /*!< NWK security key */ - zb_uint8_t key_seq_number; /*!< NWK security key sequence number */ -} zb_secur_material_set_t; - -/** - TX counters window size. - */ -/* ZB_TX_STAT_WINDOW_SIZE must be bigger than ZB_TX_TOTAL_THRESHOLD, else of - * transmitted packets never reach ZB_TX_TOTAL_THRESHOLD in case of continuous - * failed transfers. */ -#define ZB_TX_STAT_WINDOW_SIZE (ZB_TX_TOTAL_THRESHOLD + 1U) - -/** - Data structure for TX statistics - */ -typedef struct zb_tx_stat_window_s -{ - zb_uint8_t tx_ok_cnts[ZB_TX_STAT_WINDOW_SIZE]; - zb_uint8_t tx_ok_used; - zb_uint8_t tx_ok_i; - zb_uint16_t tx_total; - zb_uint16_t tx_fail; -} zb_tx_stat_window_t; - -/** - nwkMacInterfaceTable -*/ -typedef ZB_PACKED_PRE struct zb_nwk_mac_iface_tbl_ent_s -{ - /* [0] */ - zb_bitfield_t index:5; /**< A unique index that can be used to - * identify an entry */ - zb_bitfield_t state:1; /**< State indicates the interface is enabled - * or disabled */ - zb_bitfield_t routers_allowed:1; /**< Indicates whether routers are allowed to - * join to this device on this interface */ - zb_bitfield_t beacons_supported:1; /**< Indicates whether the current - * interface supports beacons */ - - /* [1] */ - zb_bitfield_t ehn_beacons_supported:1; /**< Indicates whether the current - * interface supports Enhanced beacons */ - zb_bitfield_t scan_type:1; /**< The type of scan to be used when - * performing a scan for NLME-NETWORK-DISCOVERY.req */ - zb_bitfield_t reserved:6; /**< Fit into zb_uint16_t */ - - /* [2] */ - zb_uint16_t link_power_data_rate; /**< The rate, in seconds, of how often a - * Link Power Delta request is - * generated. In bands where this is - * optional, it should be set to 0, - * disabling the function. The default - * value should be 16. */ - - /* [4] */ - zb_channel_page_t channel_in_use; /**< The current channel in use by the - * device. Only a single channel may be - * selected at one time. */ - - /* [8] */ - zb_channel_list_t supported_channels; /**< Indicates the pages and channels that - * are supported by this interface. */ - /* [8 + 4*{1 or 5}] */ - /* Total: 12 or 28 bytes */ -} -ZB_PACKED_STRUCT zb_nwk_mac_iface_tbl_ent_t; - -/** - This is NWK NIB residential in memory. - It is not clear yet when it will be save to nvram and when read. -*/ -typedef struct zb_nib_s -{ - zb_uint16_t passive_ack_timeout; /*!< Maximum time duration (in octets) allowed for - the parent and all child to retransmit a broadcast message */ - zb_uint8_t sequence_number; /*!< A sequence number used to identify outgoing frames */ - zb_uint8_t max_broadcast_retries; /*!< The maximum number of retries allowed after a broadcast transmission failure. */ - zb_ext_pan_id_t extended_pan_id; /*!< Extended Pan ID for the PAN for which the device is a member */ - zb_nwk_device_type_t device_type; /*!< Current device role, @see @ref nwk_device_type */ - zb_uint8_t update_id; /*!< nwkUpdateId - The value identifying a snapshot of the network settings with which this node is operating with. */ -#if defined ZB_NWK_MESH_ROUTING && defined ZB_ROUTER_ROLE -#ifndef ZB_CONFIGURABLE_MEM - zb_nwk_routing_t routing_table[ZB_NWK_ROUTING_TABLE_SIZE]; /*!< Routing table */ -#else - zb_nwk_routing_t *routing_table; -#endif - zb_nwk_pend_t pending_table[ZB_NWK_PENDING_TABLE_SIZE]; /*!< store pending buffers while route discovery is in progress */ - zb_nwk_route_discovery_t route_disc_table[ZB_NWK_ROUTE_DISCOVERY_TABLE_SIZE]; /*!< Route discovery table */ -#ifndef ZB_LITE_NO_NLME_ROUTE_DISCOVERY - zb_uint16_t aps_rreq_addr; /*!< APS layer call us to find path to this address */ -#endif - zb_uint8_t routing_table_cnt; /*!< Routing table used elements */ - zb_uint8_t route_disc_table_cnt; /*!< Discovery table used elements */ - - zb_uint8_t rreq_id; /*!< ID, increments each new route discovery procedure */ - zb_uint8_t pending_table_cnt; /*!< number of used elements inside pending buffer */ -#endif /* ZB_NWK_MESH_ROUTING && ZB_ROUTER_ROLE */ - - zb_uint8_t max_depth; /*!< The depth a device can have */ - -#ifdef ZB_ROUTER_ROLE - zb_uint8_t max_children; /*!< The number of children a device is allowed to have */ - zb_uint8_t router_child_num; /*!< Number of child devices with router capability */ - zb_uint8_t ed_child_num; /*!< Number of child ed devices */ -#endif - -#if defined ZB_NWK_DISTRIBUTED_ADDRESS_ASSIGN && defined ZB_ROUTER_ROLE - zb_uint8_t max_routers; /*!< The number of routers any one device is allowed to have as children. */ - zb_uint16_t cskip; /*!< Cskip value - size of the address sub-block being distributed */ -#endif - zb_uint8_t depth; /*!< current node depth */ - - - zb_secur_material_set_t secur_material_set[ZB_SECUR_N_SECUR_MATERIAL]; /*!< Set of network security - material descriptors - capable of maintaining - an active and alternate - network key. */ - zb_uint8_t active_key_seq_number; /*!< The sequence number of - the active network key in - nwkSecurityMaterialSet. */ - zb_uint32_t outgoing_frame_counter; /*!< OutgoingFrameCounter - * stored here (not in the - * secured material). - * Rationale: will never use - * "old" key - why store more - * then 1 counter? - */ - zb_uint32_t prev_outgoing_frame_counter; - - - zb_uint16_t nwk_manager_addr; /*!< The address of the designated - * network channel manager function. */ - -#ifndef ZB_LITE_NO_SOURCE_ROUTING -#ifndef ZB_CONFIGURABLE_MEM - zb_nwk_rrec_t nwk_src_route_tbl[ZB_NWK_MAX_SRC_ROUTES]; -#else - zb_nwk_rrec_t *nwk_src_route_tbl; -#endif - zb_uint8_t nwk_src_route_cnt; - zb_bool_t nwk_is_concentrator; /*!< A flag determining if this device is a concentrator */ - zb_uint8_t nwk_concentrator_radius; /*!< The hop count radius for concentrator route discoveries */ - zb_uint32_t nwk_concentrator_disc_time; /*!< The time in seconds between concentrator route discoveries. If set to 0x0000, - the discoveries are done at start up and by the next higher layer only */ -#endif - -#ifndef ZB_LITE_NO_CONFIGURABLE_LINK_STATUS - zb_uint8_t link_status_period; /*!< Table 3.44 NIB Attributes - nwkLinkStatusPeriod */ - zb_uint8_t router_age_limit; /*!< Table 3.44 NIB Attributes - nwkRouterAgeLimit */ -#endif - /*zb_uint8_t dummy_8_bit; ES: dummy 8 bit for aligning next bitfield for 32bit word. TI Compiler 18.1.3 at optimization_level=4 rewrite all word at assigning value to bitfield. */ - zb_bitfield_t leave_req_allowed:1; /*!< See: docs-11-5378-12-0csg-Zigbee-pro-errata-for-r20 NIB entry nwkLeaveRequestAllowed */ - zb_bitfield_t leave_req_without_rejoin_allowed:1; /* DA: parameter set to ignore leave requests w/o rejoin. Reason: R21 core stack spec. */ - /* DA: please note, that I set default value to 1, can't find it in current version of spec */ -#ifndef ZB_NO_NWK_MULTICAST - zb_bitfield_t nwk_use_multicast:1; /*!< Multicast determination flag */ -#endif - - zb_bitfield_t disable_rejoin:1; /*!< Forbid rejoin - for Rejoin request set Rejoin response with error status */ -#ifdef ZB_NWK_TREE_ROUTING - zb_bitfield_t use_tree_routing:1; /*!< if device is able to use tree routing */ -#endif - zb_bitfield_t addr_alloc:1; /*!< Address assign method see @ref nwk_address_allocation */ - - zb_bitfield_t uniq_addr:1; /*!< Table 3.44 NIB Attributes - nwkUniqueAddr */ - - - zb_bitfield_t reserve:1; - - zb_bitfield_t security_level:3; /*!< The security level for - outgoing and incoming - NWK frames; the - allowable security level - identifiers are presented - in Table 4.38. - For ZB 2007 (Standard security only) - only values 0 and 5 are possible. - Or, seems, only value 5 is possible? - */ - /* all_fresh is always 0 for Standard security */ - zb_bitfield_t active_secur_material_i:2; /*!< index in - * secur_material_set for - * keys with - * key_seq_number == active_key_seq_number */ - - zb_bitfield_t nwk_hub_connectivity:1; /*!< This indicates whether - * the router has Hub Connectivity as defined by a - * higher level application. - * The higher level application sets this value and the - * stack advertises it. - * - * see r23 spec, 3.5.2 NWK Information Base - */ - - zb_bitfield_t nwk_long_uptime:1; /*!< Custom attribute! - * - * Long Uptime is defined to be a device that has - * been up for 24 hours or more. Short Uptime is - * less than 24 hours - * - * see Zigbee WWAH Requirements, - * C-20 Prioritized Parent Functionality - */ - - zb_bitfield_t nwk_report_constant_cost:1; /*!< If this is set to 0, the NWK - * layer shall calculate link cost - * from all neighbor nodes using the - * LQI values reported by the MAC - * layer; otherwise, it shall report - * a constant value. */ - -#ifdef ZB_LOW_SECURITY_MODE - zb_bitfield_t ieee_policy:1; /*! If 1, put DST and SRC IEEE for NWK commands (it - * is mandatory by ZB spec). If 0, include - * it for all frame types. - * Default value is 0. */ -#endif - -#ifdef SNCP_MODE - zb_bitfield_t nwk_force_rrec_sending:1; /*!< If the flag is set to 1, local Zigbee Router device - * considers it's working with Low-RAM concentrator - * unless MTORR is received and sends Route record - * before each packet */ -#endif - - zb_tx_stat_window_t tx_stat; /*!< TX/TX fail counters */ - zb_uint8_t nwk_keepalive_modes; - zb_uint8_t nwk_parent_information; - zb_uint8_t nwk_ed_timeout_default; -/** - The period for sending the keepalive to the router parent shall be determined by the - * manufacturer of the device and is not specified by this standard. It is - * recommended that the period allows the end device to send 3 keepalive - * messages during the Device Timeout period. This will help insure that a - * single missed keepalive message will not age out the end device on the router - * parent. - */ - zb_time_t nwk_ed_keepalive_timeout; - - zb_nwk_mac_iface_tbl_ent_t mac_iface_tbl[ZB_NWK_MAC_IFACE_TBL_SIZE]; /*!< nwkMacInterfaceTable */ - - zb_uint8_t nwk_lpd_cmd_mode; /*!< Current method of link power delta negotiation. - * See: 3.4.13 Link Power Delta Command - * Table 3-56: Command Options: Type Values */ -} zb_nib_t; - -#ifdef ZB_NIB -#undef ZB_NIB -#endif -/** - Function used to access NWK Information Base. - @return pointer to NWK Information Base. - */ -zb_nib_t *zb_nwk_get_nib(void); -/** - Macro used to access NWK Information Base. - @return pointer to NWK Information Base. - */ -/*cstat !MISRAC2012-Rule-5.2_c99 !MISRAC2012-Rule-5.4_c99 */ -/* The following violation of rules 5.2 and 5.4 seem to be false positive - * At one time, only one macro is currently defined, but MISRA violations - * 5.2 and 5.4 require at least two definitions simultaneously.. - * This violation seems to be caused by #undef usage, which cannot - * be analyzed by C-STAT correctly. */ -#define ZB_NIB() zb_nwk_get_nib() - -/** @} */ - -#endif /* ZB_NWK_NIB_H */ diff --git a/zboss/development/src/include/zb_scheduler.h b/zboss/development/src/include/zb_scheduler.h deleted file mode 100644 index d622f3f05a..0000000000 --- a/zboss/development/src/include/zb_scheduler.h +++ /dev/null @@ -1,484 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Zigbee scheduler: cooperative multitasking. -*/ - -#ifndef ZB_SCHEDULER_H -#define ZB_SCHEDULER_H 1 -#include "zboss_api_core.h" -#include "zb_osif.h" -#include "zb_pooled_list.h" -#include "zboss_api_internal.h" /* zb_cb_q_ent_t */ - -/*! \addtogroup sched */ -/*! @{ */ - -#include "zb_time.h" -#include "zb_ringbuffer.h" - -/*! @cond internals_doc */ - -#ifdef ZB_INTERRUPT_SAFE_ALARMS -#define ZB_ALARM_INT_DISABLE() ZB_OSIF_GLOBAL_LOCK() -#define ZB_ALARM_INT_ENABLE() ZB_OSIF_GLOBAL_UNLOCK() -#else /* ZB_INTERRUPT_SAFE_ALARMS */ -#define ZB_ALARM_INT_DISABLE() -#define ZB_ALARM_INT_ENABLE() -#endif /* ZB_INTERRUPT_SAFE_ALARMS */ - -#ifdef ZB_INTERRUPT_SAFE_CALLBACKS -#define ZB_CB_INT_DISABLE() ZB_OSIF_GLOBAL_LOCK() -#define ZB_CB_INT_ENABLE() ZB_OSIF_GLOBAL_UNLOCK() -#else /* ZB_INTERRUPT_SAFE_CALLBACKS */ -#define ZB_CB_INT_DISABLE() -#define ZB_CB_INT_ENABLE() -#endif /* ZB_INTERRUPT_SAFE_CALLBACKS */ - -/* When running in multithreaded environment, is it possible -when a callback is scheduled from another thread. -The scheduler itself if thread-safe, so, this is possible. -However, if scheduler is sleeping in a main ZBOSS thread now, -it should be signalled somehow. -In this case there is a zb_scheduler_wakeup() routine shall be defined. -Since it is a platform-specific item, it shall be defined in OSIF */ -#if defined(ZB_THREADS) && !defined(ZB_SCHEDULER_NO_AUTOWAKEUP) -#define ZB_SCHEDULER_WAKEUP() zb_scheduler_wakeup() -#else -#define ZB_SCHEDULER_WAKEUP() -#endif - -#if defined ZB_NWK_STOCHASTIC_ADDRESS_ASSIGN && defined ZB_ROUTER_ROLE /* Zigbee pro */ - -/** - Callback function typedef. - Callback is function planned to execute by another function. - @note The callback must be declared as reentrant for dscc. - - @param param - callback parameter equals schedule record param fields - @param param2 - callback parameter contains test value - - @return is equal. - */ -typedef zb_bool_t (ZB_CODE * zb_callback_compare_t)(zb_uint8_t param, void* param2); - -#endif - -#ifdef ZB_PRO_ADDRESS_ASSIGNMENT_CB -/** @endcond */ /* internals_doc */ - -/** - Callback function typedef. - Callback is function planned to execute by another function. - @note The callback must be declared as reentrant for dscc. - - @param param - callback parameter equals schedule record param fields - @return short address for joining device, or -1 (0xFFFF) which means using the internal mechanisms of addresses assignment - */ -typedef zb_uint16_t (ZB_CODE * zb_addr_assignment_cb_t)(zb_ieee_addr_t ieee_addr); - -/*! @cond internals_doc */ -#endif - -/* zb_cb_q_ent_t moved to zboss_api_internal.h */ - -#define ZB_SCHEDULER_SET_2PARAM_CB(i) (ZG->sched.cb_flag_bm[(i)/32U] |= (1UL << ((i)%32U))) -#define ZB_SCHEDULER_RESET_2PARAM_CB(i) (ZG->sched.cb_flag_bm[(i)/32U] &= ~(1UL << ((i)%32U))) -#define ZB_SCHEDULER_IS_2PARAM_CB(i) (ZG->sched.cb_flag_bm[(i)/32U] & (1UL << ((i)%32U))) - -typedef ZB_PACKED_PRE struct zb_mac_cb_ent_s -{ - zb_callback_t func; /* currently, it is the same as common queue, */ - zb_uint8_t param; /* but, possibly, it is better to remove param from it */ -} -ZB_PACKED_STRUCT -zb_mac_cb_ent_t; - -/* zb_tm_q_ent_t moved to zboss_api_core.h */ - -/** - Immediate pending callbacks queue (ring buffer) - */ -#ifndef ZB_CONFIGURABLE_MEM -ZB_RING_BUFFER_DECLARE(zb_cb_q, zb_cb_q_ent_t, ZB_SCHEDULER_Q_SIZE); -#else -/* declare a header and 1 entry */ -ZB_RING_BUFFER_DECLARE(zb_cb_q, zb_cb_q_ent_t, 1); -#endif -/* Mac "clear to tx" queue. */ -ZB_RING_BUFFER_DECLARE(zb_mac_tx_q, zb_mac_cb_ent_t, ZB_MAC_QUEUE_SIZE); - -/* Ring buffer for storing callbacks waiting for delayed buffers */ -ZB_RING_BUFFER_DECLARE(zb_delayed_cb_q, zb_delayed_buf_q_ent_t, ZB_BUF_Q_SIZE); - -/** - Data structures for the delayed execution. - */ - -typedef void (ZB_CODE * zb_zdo_sleep_ind_cb_t)(zb_uint32_t sleep_tmo); - -typedef struct zb_sched_globals_s -{ -#ifndef ZB_CONFIGURABLE_MEM - zb_cb_q_t cb_q; /*!< immediate callbacks queue */ -#define ZB_CB_Q (&ZG->sched.cb_q) - zb_uint32_t cb_flag_bm[(ZB_SCHEDULER_Q_SIZE + 31U)/32U]; -#else - zb_cb_q_t *cb_q; -#define ZB_CB_Q (ZG->sched.cb_q) - zb_uint32_t *cb_flag_bm; -#endif -#ifndef ZB_ALIEN_SCHEDULER - zb_mac_tx_q_t mac_tx_q; /* queue of callback's waiting for tx */ -#endif -#if defined( ENABLE_USB_SERIAL_IMITATOR ) - zb_callback_t usbc_rx_cb; /*!< Callback to be called on USB data presence. */ -#endif /* defined( ENABLE_USB_SERIAL_IMITATOR ) */ -#ifndef ZB_CONFIGURABLE_MEM - zb_tm_q_ent_t tm_buffer[ZB_SCHEDULER_Q_SIZE]; /*!< buffer for the timer queue entries */ -#else - zb_tm_q_ent_t *tm_buffer; -#endif - /* Use list macros for indexed lists and use byte instead pointer here. */ - ZB_POOLED_LIST8_DEFINE(tm_queue); /*!< delayed callbacks queue */ - ZB_POOLED_LIST8_DEFINE(tm_freelist); /*!< freelist of the timer queue entries */ - zb_delayed_cb_q_t delayed_queue[2]; /*!< queue to store delayed callbacks for getting in and out buffers (@ref buffer_types)*/ - zb_uint8_t tm_buffer_usage; /*!< Usage of timer queue */ - zb_uint8_t delayed_buf_usage; /*!< Usage of waiting for free buffer queue */ - zb_bool_t stop; - zb_bool_t stopping; -} zb_sched_globals_t; - -/** - Initialize scheduler subsystem. - */ -void zb_sched_init(void); - -/** - * Stop scheduler subsystem. - */ -void zb_sched_stop(void); - -/** - Call all callbacks. - All cooperative multitasking done here. - - Call all callbacks from the queue. Callbacks can schedule other callbacks, so - potentially stay here infinite. - In practice at some point callbacks ring buffer became empty. - Put device into asleep waiting for interrupts (8051) or wait for data from - other source (Linux). - - This function usually placed into main loop. - - This function MUST be reentrant in Keil: must not share its xdata segment with - functions called from it by pointers. - - @return none - - See sched sample - */ -void zb_sched_loop_iteration(void); - -#ifndef ZB_ALIEN_SCHEDULER -/* Schedules a callback, that requires NORMAL_FIFO for transfer or security operations, -it will be called after current tx finished or just during next scheduler loop */ -#define ZB_SCHEDULE_TX_CB(func, param) zb_schedule_tx_cb(func, param, 0) -#define ZB_SCHEDULE_TX_CB_WITH_HIGH_PRIORITY(func, param) zb_schedule_tx_cb(func, param, 1) -#else - -#define ZB_SCHEDULE_TX_CB ZB_SCHEDULE_CALLBACK -#endif - -#if defined ZB_TRACE_LEVEL && defined ZB_TRACE_MASK -void zb_scheduler_trace_file_line(zb_uint32_t file_id, zb_uint32_t line_number, zb_callback_t func); -#endif /* ZB_TRACE_LEVEL && ZB_TRACE_MASK */ - -#if defined ZB_NWK_STOCHASTIC_ADDRESS_ASSIGN && defined ZB_ROUTER_ROLE /* Zigbee pro */ - -#ifndef ZB_MINIMAL_CONTEXT -/** - Cancel scheduled alarm with test by custom compare function. - - This function cancel previously scheduled alarm. Function is identified by - the pointer. Parameter is identified by compare func (comp) and default parameter (param). - - Record (rec) if found if rec.func==func and comp(rec.param, param)=true - - @param func - function to cancel - @param comp - custom comparer - @param param - default parameter for comparer - @return param of scheduled function or 0 if not found. - */ -zb_uint8_t zb_schedule_alarm_cancel_compare(zb_callback_t func, zb_callback_compare_t comp, void* param); -#endif /* !ZB_MINIMAL_CONTEXT */ - -#endif - -/** - Return true if scheduler has any pending callbacks - */ -#define ZB_SCHED_HAS_PENDING_CALLBACKS() !ZB_RING_BUFFER_IS_EMPTY(&ZG->sched.cb_q) - - -/** - Wait (block, go idle) until condition will not be true. - - @param condition - condition to check for - */ -#define ZB_SCHED_WAIT_COND(condition) \ -do \ -{ \ - ZB_SCHED_GLOBAL_LOCK(); \ - while ( !(condition) ) \ - { \ - ZB_SCHED_GLOBAL_UNLOCK(); \ - ZB_GO_IDLE(); \ - ZB_SCHED_GLOBAL_LOCK(); \ - } \ - ZB_SCHED_GLOBAL_UNLOCK(); \ -} \ -while(0) - - -/** - Global lock operation - Protect manipulation with queues in the main loop by this macro. - It disables interrupts on 8051 device and locks mutex in Linux. - */ -#define ZB_SCHED_GLOBAL_LOCK ZB_OSIF_GLOBAL_LOCK - - -/** - Global unlock operation - Protect manipulation with queues by this macro. - It enables interrupts on 8051 device and unlocks mutex in Linux. - */ -#define ZB_SCHED_GLOBAL_UNLOCK ZB_OSIF_GLOBAL_UNLOCK - -/** - Global lock operation - call from the interrupt handler - - @return RET_OK if success, RET_BUSY if locked by userspace - */ -#define ZB_SCHED_GLOBAL_LOCK_INT() ZB_OSIF_GLOBAL_LOCK_INT - -/** - Global unlock operation - call from the interrupt handler - */ -#define ZB_SCHED_GLOBAL_UNLOCK_INT() ZB_OSIF_GLOBAL_UNLOCK_INT - -#ifndef ZB_MINIMAL_CONTEXT -/** - * @brief Schedules a callback, that requires NORMAL_FIFO for transfer or security operations, it - * will be called after current tx finished or just during next scheduler loop. - * @param func - callback function. - * @param param - parameter for callback. - * @returns schedule status. - */ -zb_ret_t zb_schedule_tx_cb(zb_callback_t func, zb_uint8_t param, zb_uint8_t prior); -#endif /* !ZB_MINIMAL_CONTEXT */ - - -/** - Set a callback to be called when USB serial data is available. - - Callback is called with param 0. - To actually read serial data, call @ref usbc_serial_data_rx. - This function could be called, for example, after successful join. - - - @param usbc_rx_cb - callback to be called. If NULL, effectively - unregister USB rx callback. - */ -void zb_sched_register_usbc_rx_cb(zb_callback_t usbc_rx_cb); - -#ifdef ZB_LWIP -/** - Set a callback to be called when ethernet data is available. - */ -void zb_sched_register_ethernet_cb(zb_callback_t usbc_rx_cb); -#endif /* ZB_LWIP */ - -#define ZB_SCHED_TX_CB_HIGH_PRIOR_RESERVE 1U - -/** - Schedule callback from another thread - - * @param func - callback function. - * @param param - parameter for callback. - */ -void zb_schedule_callback_from_alien(zb_callback_t func, zb_uint8_t param); - -#ifdef ZB_DEBUG_BUFFERS_EXT - void zb_schedule_trace_queue(); -#define ZB_SCHEDULE_TRACE_QUEUE() zb_schedule_trace_queue() -#else -#define ZB_SCHEDULE_TRACE_QUEUE() -#endif - -zb_ret_t zb_schedule_callback(zb_callback_t func, zb_uint8_t param); - -/** - Schedule single-param callback execution. - - Schedule execution of function `func' in the main scheduler loop. - - The return was intentionally suppressed to avoid MISRA 17.7 violation. - If its return is needed the API should be called directly - - @param func - function to execute - @param param - callback parameter - usually, but not always ref to packet buffer - - See sched sample - */ -#define ZB_SCHEDULE_CALLBACK(func, param) (void)zb_schedule_callback(func, param) - -zb_ret_t zb_schedule_callback2(zb_callback2_t func, zb_uint8_t param, zb_uint16_t user_param); - -/** - Schedule two-param callback execution. - Schedule execution of function `func' in the main scheduler loop. - - The return was intentionally suppressed to avoid MISRA 17.7 violation. - If its return is needed the API should be called directly - - @param func - function to execute - @param param - zb_uint8_t callback parameter - usually, but not always ref to - packet buffer - @param user_param - zb_uint16_t user parameter - usually, but not - always short address - - See sched sample - */ -#define ZB_SCHEDULE_CALLBACK2(func, param, user_param) (void)zb_schedule_callback2(func, param, user_param) - -zb_ret_t zb_schedule_callback_prior(zb_callback_t func, zb_uint8_t param); - -/** - Schedule single-param high priority callback execution. - - Schedule high priority execution of function `func' in the main scheduler loop. - - The return was intentionally suppressed to avoid MISRA 17.7 violation. - If its return is needed the API should be called directly - - @param func - function to execute - @param param - callback parameter - usually, but not always ref to packet buffer - - See sched sample - */ -#define ZB_SCHEDULE_CALLBACK_PRIOR(func, param) (void)zb_schedule_callback_prior(func, param) - -zb_ret_t zb_schedule_alarm(zb_callback_t func, zb_uint8_t param, zb_time_t timeout_bi); - -/** - Schedule alarm - callback to be executed after timeout. - - Function will be called via scheduler after timeout expired (maybe, plus some - additional time). - Timer resolution depends on implementation. - Same callback can be scheduled for execution more then once. - - The return was intentionally suppressed to avoid MISRA 17.7 violation. - If its return is needed the API should be called directly - - @param func - function to call via scheduler - @param param - parameter to pass to the function - @param timeout_bi - timeout, in beacon intervals - - See any sample - */ -#define ZB_SCHEDULE_ALARM(func, param, timeout_bi) (void)zb_schedule_alarm(func, param, timeout_bi) - -/** - Cancel scheduled alarm. - - This function cancel previously scheduled alarm. Function is identified by - the pointer. - - @param func - function to cancel - @param param - parameter to cancel. \see ZB_ALARM_ANY_PARAM. \see ZB_ALARM_ALL_CB - @return RET_OK or error code - - See reporting_srv sample - */ -#define ZB_SCHEDULE_ALARM_CANCEL(func, param) (void)zb_schedule_alarm_cancel((func), (param), NULL) - -/** - Cancel scheduled alarm and get buffer. - - This function cancel previously scheduled alarm and returns buffer ref associated with alarm. - Function is identified by the pointer. - - @param func - function to cancel - @param param - parameter to cancel. \see ZB_ALARM_ANY_PARAM. \see ZB_ALARM_ALL_CB - @param p_param - [out] pointer of ref buffer from cancelled flag: free buffer if its alarm will be cancel - @return RET_OK or error code - - @b Example: - @code - { - zb_uint8_t cancelled_param; - - ZB_SCHEDULE_ALARM_CANCEL_AND_GET_BUF(my_func1, ZB_ALARM_ANY_PARAM, &cancelled_param); - my_func1(cancelled_param); - } - @endcode - - See reporting_srv sample - */ -#define ZB_SCHEDULE_ALARM_CANCEL_AND_GET_BUF(func, param, p_param) (void)zb_schedule_alarm_cancel((func), (param), (p_param)) - - -/** - Start ZBOSS shutdown procedure in the scheduler. - - Drop all callbacks and alarms, disable alarms planning - but keep callbacks - planning and scheduler working. - That is necessary to complete MAC reset at shut. - */ -void zb_scheduler_start_shutting(void); - -/** @endcond */ /* internals_doc */ -/*! @} */ - - -#endif /* ZB_SCHEDULER_H */ diff --git a/zboss/development/src/include/zb_secur.h b/zboss/development/src/include/zb_secur.h deleted file mode 100644 index feabcd3961..0000000000 --- a/zboss/development/src/include/zb_secur.h +++ /dev/null @@ -1,1371 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Security services and routines - internals -*/ - -#ifndef ZB_SECUR_H -#define ZB_SECUR_H 1 - -#include "zb_common.h" -#include "zb_mac.h" - -/*! @cond internals_doc */ -/*! \addtogroup ZB_SECUR */ -/*! @{ */ - - -#define ZB_NONCE_LENGTH 13U -#define ZB_KEY_LENGTH 16U - -/** - * @name Secur key attributes - * @anchor secur_key_attributes - * - * Note: These values were members of `enum zb_secur_key_attributes_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_SECUR_PROVISIONAL_KEY 0U -#define ZB_SECUR_UNVERIFIED_KEY 1U -#define ZB_SECUR_VERIFIED_KEY 2U -#define ZB_SECUR_APPLICATION_KEY 3U /*!< non-standard - for quick check for !TCLK */ -#define ZB_SECUR_ANY_KEY_ATTR 0xFFU /*!< Any key attribute - for zb_secur_get_link_key_by_address() */ -/** @} */ - -/** - * @name Secur link key type. - * @anchor secur_aps_link_key_type - * - * Note: These values were members of `enum zb_secur_aps_link_key_type_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_SECUR_UNIQUE_KEY 0U -#define ZB_SECUR_GLOBAL_KEY 1U -/** @} */ - -/** - * @name BDB node join link key type. - * @anchor bdb_node_join_link_key_type - * - * Note: These values were members of `enum zb_bdb_node_join_link_key_type_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define BDB_DEFAULT_GLOBAL_TRUST_CENTER_LINK_KEY 0U -#define BDB_DISTRIBUTED_SECURITY_GLOBAL_LINK_KEY 1U -#define BDB_INSTALL_CODE_DERIVED_PRECONFIGURED_LINK_KEY 2U -/** @cond touchlink */ -#define BDB_TOUCHLINK_PRECONFIGURED_LINK_KEY 3U -/** @endcond */ /* touchlink */ -/** @} */ - -/** - * @name Secur key sources. - * @anchor secur_key_sources - * - * Note: These values were members of `enum zb_secur_key_sources_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_SECUR_KEY_SRC_UNKNOWN 0U /*!< key source is unknown/doesn't matter */ -#define ZB_SECUR_KEY_SRC_CBKE 1U /*!< key was obtained via CBKE (key establishment) */ -/* NOTE: if extended with more key sources, don't forget to adjust - * - zb_aps_device_key_pair_set_t::key_source - * - zb_zcl_parsed_hdr_t::key_source - * - zb_aps_hdr_t::key_source - */ -/** @} */ - - -/** - APS Device Key Pair Set structure - - Structure contain record Application key with attributes (address, global/unique, etc.) - */ -/* Since that structure used to save into nvram, pack it! */ -typedef ZB_PACKED_PRE struct zb_aps_secur_common_data_s -{ - zb_uint8_t coordinator_version; - zb_uint8_t align[3]; -} ZB_PACKED_STRUCT zb_aps_secur_common_data_t; - -typedef ZB_PACKED_PRE struct zb_aps_device_key_pair_set_s -{ - zb_ieee_addr_t device_address; /*!< Partner address */ - zb_uint8_t link_key[ZB_CCM_KEY_SIZE]; /*!< Link key, see Spec. Not use in current - * release */ - /* 4.4.1.1[2] Security Processing of Outgoing[Incoming] Frames */ -/* Moved to zb_aps_device_key_pair_array_t */ -/* This fields were commented out after discussion with EE. - * ZB spec does not require to save APS key frame counters into NVRAM. - */ -#ifndef ZB_LITE_NO_GLOBAL_VS_UNIQUE_KEYS - zb_bitfield_t aps_link_key_type:1; /*!< @ref secur_aps_link_key_type */ -#endif - zb_bitfield_t key_source:1; /*!< how the key was obtained @ref secur_key_sources */ - zb_bitfield_t key_attributes:2; /*!< attributes of the key @ref secur_key_attributes */ - zb_bitfield_t reserved:4; - zb_uint8_t align[3]; -} ZB_PACKED_STRUCT zb_aps_device_key_pair_set_t; - -typedef zb_aps_device_key_pair_set_t zb_aps_device_key_pair_nvram_t; - -ZB_ASSERT_IF_NOT_ALIGNED_TO_4(zb_aps_device_key_pair_nvram_t); - -#define ZB_APS_DEVICE_KEY_PAIR_CACHED (zb_uint32_t)0x07ffffffU - -/* zb_aps_device_key_pair_array_t moved to zboss_api_internal.h */ - -typedef struct zb_aps_device_key_pair_storage_s -{ - zb_uint8_t nvram_page; - zb_uint8_t cached_i; - zb_aps_device_key_pair_set_t cached; -#ifndef ZB_CONFIGURABLE_MEM - zb_aps_device_key_pair_array_t key_pair_set[ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE]; /*!< APS Application Key pair table */ -#else - zb_aps_device_key_pair_array_t *key_pair_set; -#endif -} zb_aps_device_key_pair_storage_t; - -typedef ZB_PACKED_PRE struct zb_aps_device_key_pair_set_nvram_1_0_s -{ - zb_ieee_addr_t device_address; /*!< Partner address */ - zb_uint8_t master_key[ZB_CCM_KEY_SIZE]; /*!< Master key */ - zb_uint8_t global_link_key; /*!< 1 - Global key, 0 - Unique key */ -#ifdef ZB_PLATFORM_CORTEX_M3 - zb_uint8_t aligned[3]; -#endif /* ZB_PLATFORM_CORTEX_M3 */ -} ZB_PACKED_STRUCT zb_aps_device_key_pair_set_nvram_1_0_t; - - -/** - APS Installcode structure for NVRAM - */ -typedef ZB_PACKED_PRE struct zb_aps_installcode_nvram_s -{ - zb_ieee_addr_t device_address; /*!< Partner address */ - /*AEV:Here data was a filler: align[2]; - remove it for storage of IC type for now. - options lowest 2 bits [0-1]: 00-48, 01-64, 10-96, 11-128 bits ic type.*/ - zb_uint8_t options; - zb_uint8_t align; - zb_uint8_t installcode[ZB_CCM_KEY_SIZE+ZB_CCM_KEY_CRC_SIZE]; /*!< 16b installcode +2b crc */ - /*hint:we can remove 2b crc at the end of installcode, but we must keep ic type, thus align to dword and don't change it*/ -} ZB_PACKED_STRUCT zb_aps_installcode_nvram_t; - -#ifdef ZB_SECURITY_INSTALLCODES -extern const zb_uint8_t zb_ic_size_by_type[ZB_IC_TYPE_MAX]; - -#define ZB_IC_TYPE_MAX_SIZE 16U - -#define ZB_IC_SIZE_BY_TYPE(t) ( ( t ) < ZB_IC_TYPE_MAX ? zb_ic_size_by_type[( t )]:zb_ic_size_by_type[(ZB_IC_TYPE_MAX - 1U)] ) - -#define ZB_IC_GET_TYPE_FROM_OPT(opt) ( (opt) & 0x7U ) -/* zb_aps_installcode_storage_t moved to zboss_api_internal.h */ - -typedef struct zb_secur_ic_add_s -{ - zb_uint8_t *address; - zb_uint8_t *ic; - zb_uint8_t do_update; - zb_uint8_t type; -} zb_secur_ic_add_t; -#endif - - -/** - * @name Network key types - * @anchor secur_key_types - * @see r20 4.4.3.1.1 - * @see r21 Table 4.9 StandardKeyType Parameter of the Transport-Key, Verify-Key, and Confirm-Key - * Primitives - * - * Note: These values were members of `enum zb_secur_key_types_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_TC_MASTER_KEY_OBSOLETE 0U /*!< reserved */ -#define ZB_STANDARD_NETWORK_KEY 1U /*!< NWK key */ -#define ZB_APP_MASTER_KEY_OBSOLETE 2U /*!< reserved */ -#define ZB_APP_LINK_KEY 3U /*!< Application link key */ -#define ZB_TC_LINK_KEY 4U /*!< Trust-center link key */ -#define ZB_HIGH_SECUR_NETWORK_KEY_OBSOLETE 5U /*!< reserved */ -/** @} */ - -/** - * @brief Type for Network key types values. - * - * Holds one of @ref secur_key_types. Kept only for backward compatibility as - * they were declared previously as 'enum zb_secur_key_types_e'. - */ -typedef zb_uint8_t zb_secur_key_type_t; - -/** - * @name RequestKey type values - * @anchor secur_request_key_types - * @see r21 Table 4-19 RequestKeyType Values - * - * Note: These values were members of `enum zb_secur_request_key_types_e` type but were - * converted to a set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_REQUEST_APP_LINK_KEY 2U /*!< Application link key */ -#define ZB_REQUEST_TC_LINK_KEY 4U /*!< Trust-center link key */ -/** @} */ - -/** - * @brief Type for RequestKey type values. - * - * Holds one of @ref secur_request_key_types. Kept only for backward compatibility as - * they were declared previously as 'enum zb_secur_key_attributes_e'. - */ -typedef zb_uint8_t zb_secur_key_attributes_t; - -/** - * @name Key ID - * @see r20 4.5.1.1.2, r21 Table 4.31 Encoding of the Key Identifier Sub-Field - * and 4.5.3 Cryptographic Key Hierarchy - * @anchor secur_key_id - */ -/** @{ */ -#define ZB_SECUR_DATA_KEY 0U /*!< Data key - Link key without a hash */ -#define ZB_SECUR_NWK_KEY 1U /*!< NWK key - use NWK key*/ -#define ZB_SECUR_KEY_TRANSPORT_KEY 2U /*!< Transport key - use hash of TC Link key with 2. Used to protect NWK key send. */ -#define ZB_SECUR_KEY_LOAD_KEY 3U /*!< Load key - use hash of TC key with 3. Used to protect APS LC send */ -#define ZB_SECUR_DATA_KEY_N_UNENCR 0xFEU /*!< Send 2 copy: encrypted and not encrypted at APS */ -#define ZB_NOT_SECUR 0xFFU /*!< Not use APS security */ -/** @} */ - -/** - * @brief Type for key ID. - * - * Holds one of @ref secur_key_id. Kept for backward compatibility as - * @ref secur_key_id were declared previously as enum. - */ -typedef zb_uint8_t zb_secur_key_id_t; - -/** - Auxiliary frame header (4.5.1) for NWK frame and NWK key - - Extended nonce subfield set to 1 (4.3.1.1). - source_address amd key_seq_number exist. - */ -typedef ZB_PACKED_PRE struct zb_nwk_aux_frame_hdr_s -{ - zb_uint8_t secur_control; /*!< Security Control Field */ - zb_uint32_t frame_counter; /*!< Frame Counter */ - zb_ieee_addr_t source_address; /*!< Extended Source */ - zb_uint8_t key_seq_number; /*!< Key Sequence Number */ -} ZB_PACKED_STRUCT zb_nwk_aux_frame_hdr_t; - - -/** - Auxiliary frame header (4.5.1) for APS frame encrypted by NWK key - - Extended nonce subfield set to 0 (4.4.1.1). - source_address absent, key_seq_number exists. - */ -typedef ZB_PACKED_PRE struct zb_aps_nwk_aux_frame_hdr_s -{ - zb_uint8_t secur_control; /*!< Security Control Field */ - zb_uint32_t frame_counter; /*!< Frame Counter */ - zb_uint8_t key_seq_number; /*!< Key Sequence Number */ -} ZB_PACKED_STRUCT zb_aps_nwk_aux_frame_hdr_t; - -/** - Auxiliary frame header (4.5.1) for APS frame encrypted by Data key - - Extended nonce subfield set to 0 (4.4.1.1). - source_address and key_seq_number are absent. - */ -typedef ZB_PACKED_PRE struct zb_aps_data_aux_frame_hdr_s -{ - zb_uint8_t secur_control; /*!< Security Control Field */ - zb_uint32_t frame_counter; /*!< Frame Counter */ -} ZB_PACKED_STRUCT zb_aps_data_aux_frame_hdr_t; - -/** - Auxiliary frame header (4.5.1) for APS frame encrypted by Data key - - Extended nonce subfield set to 1 - source_address is present, key_seq_number is absent. - */ -typedef ZB_PACKED_PRE struct zb_aps_data_aux_nonce_frame_hdr_s -{ - zb_uint8_t secur_control; /*!< Security Control Field */ - zb_uint32_t frame_counter; /*!< Frame Counter */ - zb_ieee_addr_t source_address; /*!< Extended Source */ -} ZB_PACKED_STRUCT zb_aps_data_aux_nonce_frame_hdr_t; - - - -/** - CCM nonce (see 4.5.2.2) - */ -typedef ZB_PACKED_PRE struct zb_secur_ccm_nonce_s -{ - zb_ieee_addr_t source_address; /*!< Extended Source */ - zb_uint32_t frame_counter; /*!< Frame Counter */ - zb_uint8_t secur_control; /*!< Security Control Field */ -} ZB_PACKED_STRUCT zb_secur_ccm_nonce_t; - -/** - * See 4.5.1.1 - */ - -#define ZB_NWK_STD_SECUR_CONTROL \ - ( 5U /*security level */ | (ZB_SECUR_NWK_KEY << 3U) /* key identifier - NWK key */ | 1U << 5U /* ext nonce */) - -#define ZB_APS_NWK_STD_SECUR_CONTROL \ - ( 5U /*security level */ | (ZB_SECUR_NWK_KEY << 3U) /* key identifier - NWK key */ | 0U /* ext nonce */) - -#define ZB_APS_MASTEP_STD_SECUR_CONTROL \ - ( 5U /*security level */ | (ZB_SECUR_KEY_TRANSPORT_KEY << 3U) /* key identifier - APS master key */ | 0U /* ext nonce */) - -#define ZB_APS_LINK_STD_SECUR_CONTROL \ - ( 5U /*security level */ | (ZB_SECUR_KEY_LOAD_KEY << 3U) /* key identifier - APS link key */ | 0U /* ext nonce */) - -#define ZB_APS_DATA_STD_SECUR_CONTROL \ - ( 5U /*security level */ | (ZB_SECUR_DATA_KEY << 3U) /* key identifier - APS data key */ | 0U /* ext nonce */) - -#define ZB_APS_SET_SECUR_CONTROL(security_level, key_identifier, ext_nonce) \ - ( (security_level) | ((key_identifier) << 3U) | ((((ext_nonce) != 0u) ? 1U : 0U) << 5U) ) - -#define ZB_SECUR_SET_ZEROED_LEVEL(ctrl) (ctrl) = (ctrl) & (~0x07U) - -#define ZB_SECUR_AUX_HDR_GET_KEY_TYPE(ctrl) (((ctrl) >> 3U) & 0x3U) - -#define ZB_SECUR_AUX_HDR_SET_KEY_TYPE(ctrl, key_type) ( (ctrl) = ((ctrl) & ~(0x3U << 3U)) | (((key_type) & 0x3U) << 3U)) - -#define ZB_SECUR_GET_SECURITY_LEVEL(ctrl) ((ctrl) & 0x7U) - -#define ZB_SECUR_SET_SECURITY_LEVEL(ctrl, level) ( (ctrl) = ((ctrl) & ~0x07U) | ((level) & 0x07U) ) - -#define ZB_SECUR_GET_SECURITY_NONCE(ctrl) (((ctrl) >> 5U) & 0x1U) - - -#if 0 -#define ZB_SECUR_SET_BUF_MAC_ENCR(_pbuf) ((_pbuf)->u.hdr.encrypt_type |= ZB_SECUR_MAC_ENCR) - -#define ZB_SECUR_SET_BUF_NWK_ENCR(_pbuf) ((_pbuf)->u.hdr.encrypt_type |= ZB_SECUR_NWK_ENCR) - -#define ZB_SECUR_SET_BUF_APS_ENCR(_pbuf) ((_pbuf)->u.hdr.encrypt_type |= ZB_SECUR_APS_ENCR) - -#define ZB_SECUR_CLR_BUF_MAC_ENCR(_pbuf) ((_pbuf)->u.hdr.encrypt_type &= ~ZB_SECUR_MAC_ENCR) - -#define ZB_SECUR_CLR_BUF_NWK_ENCR(_pbuf) ((_pbuf)->u.hdr.encrypt_type &= ~ZB_SECUR_NWK_ENCR) - -#define ZB_SECUR_CLR_BUF_APS_ENCR(_pbuf) ((_pbuf)->u.hdr.encrypt_type &= ~ZB_SECUR_APS_ENCR) - -#define ZB_SECUR_GET_BUF_MAC_ENCR(_pbuf) (((_pbuf)->u.hdr.encrypt_type & ZB_SECUR_MAC_ENCR) >> 2U) - -#define ZB_SECUR_GET_BUF_NWK_ENCR(_pbuf) ((_pbuf)->u.hdr.encrypt_type & ZB_SECUR_NWK_ENCR) - -#define ZB_SECUR_GET_BUF_APS_ENCR(_pbuf) (((_pbuf)->u.hdr.encrypt_type & ZB_SECUR_APS_ENCR) >> 1U) -#endif - - -/** - Initialize APS security data structures - */ -void zb_aps_secur_init(void); - -/** - Zigbee Keyed Hash Function. Described in Zigbee specification - section B.1.4, and in FIPS Publication 198. Strictly speaking - there is nothing about the Keyed Hash Function which restricts - it to only a single byte input, but that's all Zigbee ever uses. - - The output of this function is an ep_allocated buffer containing - the key-hashed output, and is guaranteed never to return NULL. - - @param key - Zigbee Security Key (must be ZBEE_SEC_CONST_KEYSIZE) in length. - @param input - key index - @param hash_key - hash key - */ -void zb_cmm_key_hash(zb_uint8_t *key, zb_uint8_t input, zb_uint8_t *hash_key); - - -/** - * Size of one hash block. - * @note THe result of hashing is exactly one hash block. - */ -#define ZBEE_SEC_CONST_BLOCKSIZE 16U - -/** - * @brief Zigbee Cryptographic Hash Function, described in Zigbee - * specification sections B.1.3 and B.6. - * - * This is a Matyas-Meyer-Oseas hash function using the AES-128 - * cipher. The ECB mode of libgcrypt is used to get a raw block - * cipher. - * - * Input may be any length, and the output must be exactly 1-block in length. - * - * Implements the function: - * Hash(text) = Hash[t]; - * Hash[0] = 0^(blocksize). - * Hash[i] = E(Hash[i-1], M[i]) XOR M[j]; - * M[i] = i'th block of text, with some padding and flags concatenated. - * - * @param input Hash Input (any length). - * @param input_len Hash Input Length. - * @param output Hash Output (exactly one block in length). - */ -zb_bool_t zb_sec_b6_hash(zb_uint8_t *input, zb_uint32_t input_len, zb_uint8_t *output); - -/** - Search for link key by pair address and attribute. - - @note Up to 2 keys to the same address can exist: one is - VERIFIED/PROVISIONING, another is UNVERIFIED. - See BDB 10.3.3 Behavior when a known node joins. - - @param address - IEEE address - @param attr - key attribute to search. - @return Key Pair Set structure - */ -zb_aps_device_key_pair_set_t *zb_secur_get_link_key_by_address(zb_ieee_addr_t address, - zb_secur_key_attributes_t attr); - -/** - Search for link key index by pair address and attribute. - - @note Up to 2 keys to the same address can exist: one is - VERIFIED/PROVISIONING, another is UNVERIFIED. - See BDB 10.3.3 Behavior when a known node joins. - - @param address - IEEE address - @param attr - key attribute to search. - @return keypair index if link key exists, -1 otherwise - */ -zb_uint16_t zb_aps_keypair_get_index_by_addr(zb_ieee_addr_t dev_addr, - zb_secur_key_attributes_t attr); - -#ifndef ZB_HW_ZB_AES128 -/* - Encrypt a single 128-bit block by a 128-bit key using AES - url: en.wikipedia.org/wiki/Advanced_Encryption_Standard -*/ -void zb_aes128(zb_uint8_t *key, zb_uint8_t *msg, zb_uint8_t *c); -#endif - - -#ifndef ZB_HW_ZB_AES128_DEC -void zb_aes128_dec(zb_uint8_t *key, zb_uint8_t *msg, zb_uint8_t *c); -#endif - - -#ifdef ZB_SOFT_SECURITY - -/** - CCM* encryption and authentication procedure for Standard security - - This implementation may be not optimal. It done for debug only: be able to - encrypt in Linux to be able to compare results with real HW. - To be debugged using test vectors from the spec. - - - @param key - 16-bytes key - @param nonce - 16-bytes nonce - see 4.5.2.2 "CCM nonce" for details - @param string_a - 'a' parameter - authentication string - - NwkHeader||AuxiliaryHeader for Standard security. See 4.3.1.1 for details - @param string_a_len - l(a) - @param string_m - 'm' parameter - text data - - Payload for Standard security. See 4.3.1.1 for details - @param string_m_len - l(m) - @param crypted_text - encryption result - user supplied buffer. Must have size - string_m_len + ccm_m rounded to 16. - Result len is always string_m_len + ccm_m. - - - @return RET_OK if success, RET_ERROR in case of error - */ -zb_ret_t -zb_ccm_encrypt_n_auth( - zb_uint8_t *key, - zb_uint8_t *nonce, - zb_uint8_t *string_a, - zb_uint32_t string_a_len, - zb_uint8_t *string_m, - zb_uint32_t string_m_len, - zb_bufid_t crypted_text); - - -/** - CCM* decryption and authentication procedure for Standard security - - @param key - 16-bytes key - @param nonce - 16-bytes nonce - see 4.5.2.2 "CCM nonce" for details - @param buf - buffer with encrypted_text [IN], for decryption result [OUT] - @param string_a_len - length string_a - authentication string - - NwkHeader||AuxiliaryHeader for Standard security. See 4.3.1.1 for details - @param string_c_len - length text data - - Payload for Standard security. See 4.3.1.1 for details - - @return RET_OK if success, RET_ERROR in case of error (authentication failure) - */ -zb_ret_t -zb_ccm_decrypt_n_auth( - zb_uint8_t *key, - zb_uint8_t *nonce, - zb_bufid_t buf, - zb_uint32_t string_a_len, - zb_uint32_t string_c_len); - - -/** - Decryption and authentication according to standard security requirements. - - Decrypt "on place". Use HW if possible, - */ -#define zb_ccm_decrypt_n_auth_stdsecur zb_ccm_decrypt_n_auth - -#endif /* ZB_SOFT_SECURITY */ - - -void zb_ccm_auth_trans( - zb_ushort_t ccm_m, - zb_uint8_t *key, - zb_uint8_t *nonce, - zb_uint8_t *string_a, - zb_uint32_t string_a_len, - zb_uint8_t *string_m, - zb_uint32_t string_m_len, - zb_uint8_t *t); - -/* -void encrypt_trans( - zb_ushort_t ccm_m, - zb_uint8_t *key, - zb_uint8_t *nonce, - zb_uint8_t *string_m, - zb_uint16_t string_m_len, - zb_uint8_t *t, - zb_uint8_t *encrypted); -*/ - -/** - Secure frame at NWK level according to the current security mode - This procedure secures frame 'on place' increasing its size. - It is supposed that buffer tail has enough free space. - - @param src - nwk packet to secure - @param mac_hdr_size - size of header placed before mac hdr - @param dst - buffer for the secured frame - - - @return RET_OK if ok, else error code - */ -zb_ret_t zb_nwk_secure_frame(zb_bufid_t src, zb_uint_t mac_hdr_size, zb_bufid_t dst); - - -/** - Unsecure NWK frame at NWK level according to the current security mode - This procedure secures frame 'on place' decreasing its size. - - @param param - ref to nwk packet to unsecure - - @return RET_OK if success or RET_ERROR if unsecure failed - Attention: if frame unsecure failed, this function reuses packet buffer to - send NWK status. Don't use the buffer if return code != RET_OK! - */ -zb_ret_t zb_nwk_unsecure_frame(zb_uint8_t param); - - -/** - Allocate and fill space for auxiliary security header in the APS data or command frame. - - @param p - pointer to the aux hdr - @param key_type - key type for aux header see 4.5.1.1.2, @see @ref secur_key_id - @param ext_nonce - extended nonce flag - - If nwk_key is false and transport_key is false then use APS data key - */ -void zb_secur_aps_aux_hdr_fill(zb_uint8_t *p, zb_secur_key_id_t key_type, zb_bool_t ext_nonce); - -/** - Add security to the APS command frame. Allocate space for APS header. Fill APS Aux security header. - - @param buf - buffer with command payload - @param command_id - command id to assign into APS command header - @param secure_aps - secure type APS level - */ -void zb_aps_command_add_secur(zb_bufid_t buf, zb_uint8_t command_id, zb_secur_key_id_t secure_aps); - -/** - Encrypt APS frame before its send. - - Need to put secured frame into another buffer because original buffer will be - passed back to APS in CONFIRM primitive and, potentially, will be - retransmitter by APS layer, so must keep it unencrypted. - - @param src - source buffer with all headers filled, including MHR - @param mac_hdr_size - size of MAC header - @param dst - destination buffer (for secure result) - @param is_tunnel - APS command has tunnel header - - @return RET_OK if successfully encrypted frame, error code otherwise - */ -zb_ret_t zb_aps_secure_frame(zb_bufid_t src, zb_uint_t mac_hdr_size, zb_bufid_t dst, zb_bool_t is_tunnel); - - -/** - Decrypt APS frame "on place" - - @param buf - (in/out) buffer holding frame - @param keypair_i_p - (out) index of APS keypair used to decrypt or (zb_uint16_t)-1 if used default TCLK - @param key_id_p - pointer to variable that contains key used to protect the frame - @param is_verified_tclk - (out) ZB_TRUE if the frame was decrypted successfully using TCLK, ZB_FALSE otherwise - - @return RET_OK if successfully decrypted frame, error code otherwise - */ -zb_ret_t zb_aps_unsecure_frame(zb_bufid_t buf, zb_uint16_t *keypair_i_p, zb_secur_key_id_t *key_id_p, zb_bool_t *is_verified_tclk); - -/** - Return size of APS aux secure header - - @param secur_control - aux APS header secur_control field - @return aux header size if ok or -1 if error (unknown key type) - */ -zb_ushort_t zb_aps_secur_aux_size(zb_uint8_t secur_control); - -#ifdef ZB_MAC_SECURITY -/** - Encrypt MAC frame before its send. - - Need to put secured frame into another buffer because original buffer will be - passed back to APS in CONFIRM primitive and, potentially, will be - retransmitter by APS layer, so must keep it unencrypted. - - @param src - source buffer with all headers filled, including MHR - @param mac_hdr_size - size of MAC header - @param dst - destination buffer (for secure result) - - @return RET_OK if successfully encrypted frame, error code otherwise - */ -zb_ret_t zb_mac_secure_frame(zb_bufid_t src, zb_uint_t mac_hdr_size, zb_bufid_t dst); - -/** - Encrypt MAC frame "on place" - - @param param - (in/out) buffer holding frame - - @return RET_OK if successfully decrypted frame, error code otherwise - */ -zb_ret_t zb_mac_unsecure_frame(zb_uint8_t param); -#endif - -/** - Parameters for APSME-TRANSPORT-KEY.request primitive - */ -typedef struct zb_apsme_transport_key_req_s -{ - zb_addr_u dest_address; /*!< destination address */ - zb_uint8_t addr_mode; /*!< The type of destination address supplied by - the DstAddr parameter - see @ref address_modes. - This field is non-standard: according to table 4.11 - dest_address can be 64-bit only. - But, according to 4.6.3.4.1 Trust Center Operation, - TC must issue APSME-TRANSPORT-KEY.request with - broadcast address - means, need 16-bit address here! - */ - zb_uint8_t key_type; /*!< @see @ref secur_key_types */ - union key_holder_u { - struct apsme_transport_key_nwk_s - { - zb_uint8_t key[ZB_CCM_KEY_SIZE]; /*!< Key */ - zb_uint8_t key_seq_number; /*!< Sequence Number */ - zb_uint8_t use_parent; /*!< Use parent - see 4.6.3 */ - zb_ieee_addr_t parent_address; /*!< Parent Address */ - } nwk; /*!< Use for transmit NWK key */ - struct apsme_transport_key_app_s - { - zb_uint8_t key[ZB_CCM_KEY_SIZE]; /*!< Key */ - zb_ieee_addr_t partner_address; /*!< Partner address */ - zb_uint8_t initiator; /*!< Is initiator. - @note Exists in r20, no in r21, seems, still necessary. */ - } app; /*!< Use for transmit Application key */ - } key; - /* mega-hack: zb_aps_secure_frame uses dest_address to seek APS key. But, - zb_aps_secure_frame is called from MAC when NWK also put parameter into - buffer tail. Let's reserve a space for mcps data request parameters. - Agree, this is ugly solution. The alternative is to parse packet contents, - but is is more complex: must analyze for tunnel/direct send. - */ - zb_uint8_t filler[sizeof(zb_mcps_data_req_params_t) > sizeof(union key_holder_u) ? sizeof(zb_mcps_data_req_params_t) - sizeof(union key_holder_u) : 4]; -} zb_apsme_transport_key_req_t; - -/** - Variable part of Transport key command for translate NWK key - */ -typedef ZB_PACKED_PRE struct zb_transport_key_nwk_pkt_s -{ - zb_uint8_t seq_number; /*!< Sequence Number */ - zb_ieee_addr_t dest_address; /*!< Destination address */ - zb_ieee_addr_t source_address; /*!< Source address */ -} ZB_PACKED_STRUCT zb_transport_key_nwk_pkt; - -/** - Variable part of Transport key command for translate TC key - */ -typedef ZB_PACKED_PRE struct zb_transport_key_tc_pkt_s -{ - zb_ieee_addr_t dest_address; /*!< Destination address */ - zb_ieee_addr_t source_address; /*!< Source address */ -} ZB_PACKED_STRUCT zb_transport_key_tc_pkt; - -/** - Variable part of Transport key command for translate Application key - */ -typedef ZB_PACKED_PRE struct zb_transport_key_app_pkt_s -{ - zb_ieee_addr_t partner_address; /*!< Partner address */ - zb_uint8_t initiator; /*!< Is initiator */ -} ZB_PACKED_STRUCT zb_transport_key_app_pkt; - -/** - Transport key command data structure - - - */ -typedef ZB_PACKED_PRE struct zb_transport_key_dsc_pkt_s -{ - zb_uint8_t key_type; /*!< indeed, not part of the nwk key descriptor, - * but it simplifies code */ - - zb_uint8_t key[ZB_CCM_KEY_SIZE]; /*!< Key*/ - ZB_PACKED_PRE union { - zb_transport_key_nwk_pkt nwk; /*!< Variable part for translate NWK key */ - zb_transport_key_tc_pkt tc; /*!< Variable part for translate TC key */ - zb_transport_key_app_pkt app; /*!< Variable part for translate Application key */ - } key_data; -} ZB_PACKED_STRUCT zb_transport_key_dsc_pkt_t; - -/** - Update device command data structure - */ -typedef ZB_PACKED_PRE struct zb_apsme_update_device_pkt_s -{ - zb_ieee_addr_t device_address; /*!< 64-bit address of update device */ - zb_uint16_t device_short_address; /*!< 16-bit address of update device */ - zb_uint8_t status; /*!< @see @ref secur_upd_device_status */ -} ZB_PACKED_STRUCT zb_apsme_update_device_pkt_t; - -#ifdef ZB_FORMATION -/** - APSME-TRANSPORT-KEY.request primitive - - @param param - packet buffer filled be \see zb_transport_key_dsc_pkt_t - */ -void zb_apsme_transport_key_request(zb_uint8_t param); -#endif - -/** - Parameter for APSME-UPDATE-DEVICE.request - */ -typedef struct zb_apsme_update_device_req_s -{ - zb_ieee_addr_t dest_address; /*!< 64-bit Destination address */ - zb_ieee_addr_t device_address; /*!< 64-bit address of update device */ - zb_uint16_t device_short_address; /*!< 16-bit address of update device */ - zb_uint8_t status; /*!< @see @ref secur_upd_device_status */ -} zb_apsme_update_device_req_t; - - - -/** - Parameter for APSME-UPDATE-DEVICE.indication - */ -typedef struct zb_apsme_update_device_ind_s -{ - zb_ieee_addr_t src_address; /*!< 64-bit Destination address */ - zb_ieee_addr_t device_address; /*!< 64-bit address of update device */ - zb_uint16_t device_short_address; /*!< 16-bit address of update device */ - zb_uint8_t status; /*!< @see @ref secur_upd_device_status */ -} zb_apsme_update_device_ind_t; - - -/** - Parameter for APSME-SWITCH-KEY.request - - Note about addr_mode: it is spec violation, but it necessary to satisfy TC. - */ -typedef struct zb_apsme_switch_key_req_s -{ - zb_ieee_addr_t dest_address; /*!< Destination address */ - zb_uint8_t key_seq_number; /*!< Sequence Number */ -} zb_apsme_switch_key_req_t; - - -#ifdef ZB_COORDINATOR_ROLE -/** - APSME-SWITCH-KEY.request primitive - - @param param - packet buffer filled be \see zb_apsme_switch_key_req_t - */ -void zb_apsme_switch_key_request(zb_uint8_t param); -#endif - -/** - APSME-SWITCH-KEY APS command body - */ -typedef ZB_PACKED_PRE struct zb_apsme_switch_key_pkt_s -{ - zb_uint8_t key_seq_number; /*!< Key Number */ -} ZB_PACKED_STRUCT zb_apsme_switch_key_pkt_t; - - -/** - APSME-SWITCH-KEY.indication - */ -typedef struct zb_apsme_switch_key_ind_s -{ - zb_ieee_addr_t src_address; /*!< Source Address*/ - zb_uint8_t key_seq_number; /*!< Key Number */ -} zb_apsme_switch_key_ind_t; - - -void zb_aps_in_switch_key(zb_uint8_t param); - - -/** - APSME-REMOVE-DEVICE.request primitive parameters structure - */ -typedef ZB_PACKED_PRE struct zb_apsme_remove_device_req_s -{ - zb_ieee_addr_t parent_address; /*!< Parent Address*/ - zb_ieee_addr_t child_address; /*!< Child Address*/ -} ZB_PACKED_STRUCT zb_apsme_remove_device_req_t; - - -/** - Remove device command data structure - */ -typedef ZB_PACKED_PRE struct zb_apsme_remove_device_pkt_s -{ - zb_ieee_addr_t child_address; /*!< Child Address*/ -} ZB_PACKED_STRUCT zb_apsme_remove_device_pkt_t; - - -/** - APSME-REMOVE-DEVICE.indication primitive parameters structure - */ -typedef ZB_PACKED_PRE struct zb_apsme_remove_device_ind_s -{ - zb_ieee_addr_t src_address; /*!< Source Address */ - zb_ieee_addr_t child_address; /*!< Child Address */ -} ZB_PACKED_STRUCT zb_apsme_remove_device_ind_t; - -#ifdef ZB_COORDINATOR_ROLE -/** - APSME-REMOVE-DEVICE.request command - - @param param - packet buffer filled be \see zb_apsme_request_key_req_t - */ -void zb_secur_apsme_remove_device(zb_uint8_t param); -#endif - -/** - APSME-REMOVE-DEVICE.indication primitive - - @param param - packet buffer filled be \see zb_apsme_remove_device_pkt_t - */ -void zb_aps_in_remove_device(zb_uint8_t param); - -/** - APSME-REQUEST-KEY.request primitive parameters structure - */ -typedef ZB_PACKED_PRE struct zb_apsme_request_key_req_s -{ - zb_ieee_addr_t dest_address; /*!< Destination address */ - zb_uint8_t key_type; /*!< \see secur_request_key_types */ - zb_ieee_addr_t partner_address; /*!< Partner address */ -} ZB_PACKED_STRUCT zb_apsme_request_key_req_t; - -typedef ZB_PACKED_PRE struct zb_apsme_request_key_pkt_s -{ - zb_uint8_t key_type; /*!< \see secur_request_key_types */ - zb_ieee_addr_t partner_address; /*!< Partner address */ -} ZB_PACKED_STRUCT zb_apsme_request_key_pkt_t; - -/** - APSME-REQUEST-KEY.indication primitive parameters structure - */ -typedef ZB_PACKED_PRE struct zb_apsme_request_key_ind_s -{ - zb_ieee_addr_t src_address; /*!< Source address */ - zb_uint8_t key_type; /*!< \see secur_request_key_types */ - zb_ieee_addr_t partner_address; /*!< Partner address */ - - zb_uint16_t keypair_i; /*!< index of keypair used to decrypt cmd */ -} ZB_PACKED_STRUCT zb_apsme_request_key_ind_t; - -/** - APSME-VERIFY-KEY.request - - See 4.4.7.1 APSME-VERIFY-KEY.request - */ -typedef struct zb_apsme_verify_key_req_s -{ - zb_ieee_addr_t dest_address; /*!< Destination address. ONly TC is valid */ - zb_uint8_t key_type; /*!< key type. Only ZB_TC_LINK_KEY is legal. */ -} zb_apsme_verify_key_req_t; - - -/** -4.4.10.7 Verify-Key Command - */ -typedef ZB_PACKED_PRE struct zb_apsme_verify_key_pkt_s -{ - zb_uint8_t key_type; /*!< key type. Only ZB_TC_LINK_KEY is legal. */ - zb_ieee_addr_t src_address; /*!< Source address. */ - zb_uint8_t key_hash[ZB_CCM_KEY_SIZE]; /*!< Initiator Verify-Key Hash Value */ -} ZB_PACKED_STRUCT zb_apsme_verify_key_pkt_t; - - -/** -4.4.7.2 APSME-VERIFY-KEY.indication - */ -typedef struct zb_apsme_verify_key_ind_s -{ - zb_ieee_addr_t src_address; /*!< Source address. */ - zb_uint8_t key_type; /*!< key type. Only ZB_TC_LINK_KEY is legal. */ - zb_uint8_t key_hash[ZB_CCM_KEY_SIZE]; /*!< Initiator Verify-Key Hash Value */ -} ZB_PACKED_STRUCT zb_apsme_verify_key_ind_t; - -/** -4.4.8.1 APSME-CONFIRM-KEY.request - */ -typedef struct zb_apsme_confirm_key_req_s -{ - zb_uint8_t status; /*!< A value indicating the success or failure of a previous attempt to verify the trust center link key. See Table 2.27*/ - zb_ieee_addr_t dest_address; /*!< Destination address. */ - zb_uint8_t key_type; /*!< key type. Only ZB_TC_LINK_KEY is legal. */ -} zb_apsme_confirm_key_req_t; - - -/** -4.4.10.8 Confirm-Key Command - */ -typedef ZB_PACKED_PRE struct zb_apsme_confirm_key_pkt_s -{ - zb_uint8_t status; /*!< A value indicating the success or failure of a previous attempt to - verify the trust center link key. See Table 2.27*/ - zb_uint8_t key_type; /*!< key type. Only ZB_TC_LINK_KEY is legal. */ - zb_ieee_addr_t dest_address; /*!< Dest address. */ -} ZB_PACKED_STRUCT zb_apsme_confirm_key_pkt_t; - - -/** -4.4.8.2 APSME-CONFIRM-KEY.indication - */ -typedef struct zb_apsme_confirm_key_ind_s -{ - zb_uint8_t status; /*!< A value indicating the success or failure of a previous attempt to - verify the trust center link key. See Table 2.27*/ - zb_uint8_t key_type; /*!< key type. Only ZB_TC_LINK_KEY is legal. */ - zb_ieee_addr_t src_address; /*!< The extended 64-bit address of the device that sent the - verify-key command. */ -} zb_apsme_confirm_key_ind_t; - - -/** - APSME-REQUEST-KEY.request command - - @param param - packet buffer filled be \see zb_apsme_request_key_req_t - */ -void zb_secur_apsme_request_key(zb_uint8_t param); - -/** - APSME-REQUEST-KEY.indication primitive - - @param param - packet buffer filled be \see zb_apsme_request_key_pkt_t - @param keypair_i - index of APS key used to decrypt APS packet of -1 if default TCLK - @param key_id - the key used to protect the frame - */ -#ifdef ZB_COORDINATOR_ROLE -void zb_aps_in_request_key(zb_uint8_t param, zb_uint16_t keypair_i - , zb_secur_key_id_t key_id - ); -#endif - -/** - APSME-UPDATE-DEVICE.request command - - @param param - packet buffer filled be \see zb_apsme_update_device_req_t - */ -void zb_apsme_update_device_request(zb_uint8_t param); - -#ifdef ZB_FORMATION -/** - Initialize Trust Center functionality - */ -void secur_tc_init(void); - - -/** - Generate NWK keys as random numbers - */ -void secur_nwk_generate_keys(void); -#endif - -/** - Authenticate child after join - */ -void secur_authenticate_child(zb_uint8_t param); - - -/** - Generate NWK key by key sequence number - - @param key_seq_number - key sequence number - @return ref to NWK key from NWK keys table - */ -zb_uint8_t *secur_nwk_key_by_seq(zb_ushort_t key_seq_number); - -/** - Update AIB Key-Pair table - - @param address - partner address - @param key - application key - @param key_type - @see @ref secur_key_types - @param key_attr - @see secur_key_attributes - @param key_source - @see secur_key_sources - - @return pointer to the keypair updated/created or NULL in case of error - - */ -zb_aps_device_key_pair_set_t * zb_secur_update_key_pair(zb_ieee_addr_t address, - zb_uint8_t* key, - zb_uint8_t key_type, - zb_uint8_t key_attr, - zb_uint8_t key_source - ); - -/** - Get address from link key pair by specified index. - - @param idx - index from link key pair set - @param dev_addr - pointer to store device address (addr from key pair if found, zero addr otherwise) - */ -void zb_aps_keypair_get_addr_by_idx(zb_uint_t idx, zb_uint8_t *dev_addr); - -/** - Get link key pair by specified index. - - @param idx - index from link key pair set - @return pointer to the keypair if it is found and NULL otherwise - */ -zb_aps_device_key_pair_set_t* zb_aps_keypair_get_ent_by_idx(zb_uint_t idx); - -/** - Write/add key pair to AIB Key-Pair table - - @param ent - pointer to key pair entry - @param idx - index from link key pair set to write (or -1 to add new element) - - @return status of operation - RET_OK for success, RET_ERROR otherwise - */ -zb_ret_t zb_aps_keypair_write(zb_aps_device_key_pair_set_t *ent, zb_uint32_t idx); - -/** - Load link key pair by specified index. - - @param idx - index from link key pair set - @return status of operation - RET_OK for success, RET_NOT_FOUND if key pair is not found - */ -zb_ret_t zb_aps_keypair_load_by_idx(zb_uint_t idx); - -/** - Read link key pair by specified index. - - @param idx - index from link key pair set - @param ent - pointer to the loaded key pair - @return status of operation - RET_OK for success, RET_NOT_FOUND if key pair is not found - */ -zb_ret_t zb_aps_keypair_read_by_idx(zb_uint_t idx, zb_aps_device_key_pair_nvram_t *ent); - -/** - Parameters for APSME-TRANSPORT-KEY.indication primitive - */ -typedef struct zb_apsme_transport_key_indication_s -{ - zb_ieee_addr_t src_address; /*!< Source address */ - zb_uint8_t key_type; /*!< @see @ref secur_key_types */ - union { - struct apsme_transport_key_nwk_ind_s - { - zb_uint8_t key[ZB_CCM_KEY_SIZE]; /*!< Key */ - zb_uint8_t key_seq_number; /*!< Sequence number */ - } nwk; - struct apsme_transport_key_app_ind_s - { - zb_uint8_t key[ZB_CCM_KEY_SIZE]; /*!< app link Key */ - zb_ieee_addr_t partner_address; /*!< The extended 64-bit address of the device that was also sent this link key. */ - } app; - struct apsme_transport_key_tc_ind_s - { - zb_uint8_t key[ZB_CCM_KEY_SIZE]; /*!< TC LiKey */ - } tc; - } key; -} zb_apsme_transport_key_indication_t; - - - -/** - APSME-TRANSPORT-KEY.indication primitive - - @param param - packet buffer filled be \see zb_apsme_transport_key_indication_t - */ -void zb_apsme_transport_key_indication(zb_uint8_t param); - - -/** - Switch NWK key - - @param key_number - NWK key number - */ -void secur_nwk_key_switch(zb_uint8_t key_number); - -/** - Switch NWK key and send it via broadcast - */ -#ifdef ZB_COORDINATOR_ROLE -void zb_secur_switch_nwk_key_br(zb_uint8_t param); -#endif - -/** - Return true if network key is empty (all zeroes). - - @param key - key - @return ZB_TRUE if key is empty, ZB_FALSE otherwise - */ -zb_bool_t secur_nwk_key_is_empty(zb_uint8_t *key); - - -/** - APSME-REMOVE-DEVICE.indication primitive - - @param param - packet buffer filled be \see zb_apsme_remove_device_ind_t - */ -void zb_apsme_remove_device_indication(zb_uint8_t param); - - -/** - APSME-REQUEST-KEY.indication primitive - - @param param - packet buffer filled be \see zb_apsme_request_key_ind_t - */ -#ifdef ZB_COORDINATOR_ROLE -void zb_apsme_request_key_indication(zb_uint8_t param); -#endif - -/** - APSME-SWITCH-KEY.indication primitive - - @param param - packet buffer filled be \see zb_apsme_switch_key_ind_t - */ -void zb_apsme_switch_key_indication(zb_uint8_t param); - - -/** - Reaction on TRANSPORT-KEY APS command (indication) - - @param param - buffer index with transport key command data - @param keypair_i - index of APS key used to decrypt APS packet or -1 if used default TCLK - @param key_id - the key used to protect the frame - @return nothing - */ -void zb_aps_in_transport_key(zb_uint8_t param, zb_uint16_t keypair_i, zb_secur_key_id_t key_id); - -/** - Analyze trust frame by command ID, security level and key type - - @param cmd_id - command ID - @param secured - frame is crypt - @param is_global_key - key is global - - @return 'frame is trust' - */ -zb_bool_t zb_secur_aps_accept_policy(zb_uint8_t cmd_id, zb_bool_t secured, zb_uint16_t keypair_i); - -/** - APSME-TUNNEL.indication primitive - Wrap APS command from tunnel command - - @param param - packet buffer filled be and APS command - */ -void zb_aps_in_tunnel_cmd(zb_uint8_t param); - -/** - - */ -void zb_secur_rejoin_after_security_failure(zb_uint8_t param); - - -#if defined ZB_HW_ZB_AES128 || defined ZB_HW_ZB_AES128 || !defined ZB_SOFT_SECURITY -#include "hw_crypto_api.h" -#endif - -#ifdef ZB_COORDINATOR_ROLE -void zb_aps_in_verify_key(zb_uint8_t param); -#endif - -void zb_aps_in_confirm_key(zb_uint8_t param); - -void zb_apsme_verify_key_req(zb_uint8_t param); - -void zb_zdo_update_tclk(zb_uint8_t param); - -void zb_zdo_verify_tclk(zb_uint8_t param); - -#ifdef ZB_COORDINATOR_ROLE -void zb_apsme_verify_key_indication(zb_uint8_t param); - -void zb_apsme_confirm_key_request(zb_uint8_t param); -#endif - -void zb_apsme_confirm_key_indication(zb_uint8_t param); - -void zdo_secur_init(void); - -void bdb_initiate_key_exchange(zb_uint8_t param); - -void bdb_initiate_key_verify(zb_uint8_t param); -zb_bool_t bdb_verify_tclk_in_progress(void); - -#if defined ZB_COORDINATOR_ROLE && !defined ZB_LITE_NO_TRUST_CENTER_REQUIRE_KEY_EXCHANGE -void bdb_link_key_transport_with_alarm(zb_uint8_t param2, zb_uint16_t param); - -zb_uint8_t bdb_cancel_link_key_refresh_alarm(zb_callback_t func, zb_uint8_t param); - -void bdb_link_key_refresh_alarm(zb_uint8_t param); -#endif - -void zdo_authentication_failed(zb_uint8_t param); - -/* CR : 04/19/2016 [VP]: Start: put it here to call this functions from apsme_secur.c */ -void bdb_request_tclk_alarm(zb_uint8_t param); - -void bdb_update_tclk_failed(zb_uint8_t param); -/* CR : 04/19/2016 [VP]: Stop */ - -void zb_secur_delete_link_keys_by_addr_ref(zb_address_ieee_ref_t addr_ref); - -void zb_secur_delete_link_keys_by_long_addr(zb_ieee_addr_t ieee_address); - -void zb_secur_delete_link_key_by_idx(zb_uint16_t idx); - -zb_ret_t zb_secur_changing_tc_policy_check(void); - -zb_aps_device_key_pair_set_t *zb_secur_get_link_key_pair_set(zb_ieee_addr_t address, zb_bool_t valid_only); - -zb_aps_device_key_pair_set_t *zb_secur_get_verified_or_provisional_link_key(zb_ieee_addr_t address); - -zb_aps_device_key_pair_set_t *zb_secur_create_best_suitable_link_key_pair_set(zb_ieee_addr_t address); - -zb_ret_t zb_secur_ic_get_key_by_address(zb_ieee_addr_t address, zb_uint8_t *key); - -#if defined ZB_COORDINATOR_ROLE && defined ZB_SECURITY_INSTALLCODES && defined ZB_USE_NVRAM && !defined APP_ONLY_NVRAM && !defined NCP_MODE_HOST -zb_int8_t zb_secur_ic_get_from_tc_storage(zb_ieee_addr_t address, zb_uint8_t *ic_type, zb_uint8_t *buf); -#endif - -zb_uint8_t *zb_secur_ic_get_from_client_storage(zb_uint8_t* ic_type); - -zb_ret_t zb_secur_ic_check_crc(zb_uint8_t ic_type, zb_uint8_t *ic); - -zb_ret_t zb_secur_ic_from_string(char *ic_str, zb_uint8_t *ic_type, zb_uint8_t *ic); - -zb_bool_t zb_secur_aps_cmd_is_encrypted_by_good_key(zb_uint8_t cmd_id, zb_uint16_t src_addr, zb_uint16_t keypair_i); - -void zdo_secur_update_tclk_done(zb_uint8_t param); - -#ifdef ZB_FORMATION -void secur_generate_key(zb_uint8_t *key); -#endif - -zb_bool_t zb_secur_has_verified_key_by_short(zb_uint16_t addr_short); - -void zb_secur_trace_all_key_pairs(zb_uint8_t param); - -#ifdef DEBUG -#define ZB_SECUR_TRACE_ALL_KEY_PAIRS() zb_secur_trace_all_key_pairs(0) -#else -#define ZB_SECUR_TRACE_ALL_KEY_PAIRS() -#endif - -#ifdef ZB_SE_KE_WHITELIST -void zb_secur_ke_whitelist_add(zb_ieee_addr_t addr); - -void zb_secur_ke_whitelist_del(zb_ieee_addr_t addr); - -void zb_secur_ke_whitelist_del_all(void); - -zb_int16_t zb_secur_search_ke_whitelist(zb_ieee_addr_t addr); -#endif /* ZB_SE_KE_WHITELIST */ - -/*! @} */ -/*! @endcond */ - -#ifdef ZB_USE_OSIF_OTA_ROUTINES -zb_bool_t zb_sec_b6_hash_iter_start(void *dev, zb_uint32_t input_addr, zb_uint32_t input_len); -void zb_sec_b6_hash_iter_done(void *dev, zb_uint32_t input_len, zb_uint8_t *calc_hash); -#endif - -void zdo_initiate_tclk_gen_over_aps(zb_uint8_t param); - -zb_uint8_t zb_secur_gen_upd_dev_status(zb_ushort_t rejoin_network, zb_ushort_t secure_rejoin); - -#ifdef ZB_FORMATION -void secur_nwk_generate_key(zb_uint8_t i, zb_uint_t key_seq); - -void secur_authenticate_child_directly(zb_uint8_t param); -#endif - -#ifdef ZB_COORDINATOR_ROLE -zb_ret_t zb_authenticate_dev(zb_bufid_t param, zb_apsme_update_device_ind_t *ind); -#endif - -zb_uint8_t zb_secur_aps_send_policy(zb_uint_t command, zb_uint16_t dest_addr, zb_uint8_t key_type); - -#endif /* ZB_SECUR_H */ diff --git a/zboss/development/src/include/zb_secur_api.h b/zboss/development/src/include/zb_secur_api.h deleted file mode 100644 index 51a92b5836..0000000000 --- a/zboss/development/src/include/zb_secur_api.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Security - API to be used from the applications level -*/ - -#ifndef ZB_SECUR_API_H -#define ZB_SECUR_API_H 1 -/** @cond (!DOXYGEN_ERL_SECTION) */ -/*! \addtogroup secur_api */ -/*! @{ */ - -#ifdef ZB_COORDINATOR_ROLE -/** - Send new network key to all devices in the net via broadcast - - 4.6.3.4 Network Key Update - 4.6.3.4.1 Trust Center Operation - - @param param - buffer with single parameter - short broadcast address. Valid - values are 0xffff, 0xfffd - - */ -void zb_secur_send_nwk_key_update_br(zb_uint8_t param); - - - -/** - Generate switch key. - - According to test 14.24TP/SEC/BV-01-I Security NWK Key Switch (No Pre- - configured Key)-ZR, this command can be send either to broadcast or unicast - to all rx-on-when-idle from the neighbor. - - When send unicast, it encrypted by the new (!) key, when send proadcast - by - the old key. - - That mean, switch our key _after_ this frame transfer and secure - in the - command send confirm. - - @param param - packet buffer with single parameter - broadcast address. If 0, - send unicast. - */ -void zb_secur_send_nwk_key_switch(zb_uint8_t param); -#endif /* ZB_COORDINATOR_ROLE */ - -/*! @} */ -/** @endcond */ /* (!DOXYGEN_ERL_SECTION) */ -#endif /* ZB_SECUR_API_H */ diff --git a/zboss/development/src/include/zb_sleep.h b/zboss/development/src/include/zb_sleep.h deleted file mode 100644 index 60bb19129d..0000000000 --- a/zboss/development/src/include/zb_sleep.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ -#ifndef ZB_SLEEP_H -#define ZB_SLEEP_H 1 - -#if defined ZB_USE_SLEEP - -/* Sleep time when it is no delayed cbs. */ -#ifdef ZB_SCHED_SLEEP_NO_TM_MS -#define ZB_SCHED_SLEEP_NO_TM_BI ZB_MILLISECONDS_TO_BEACON_INTERVAL(ZB_SCHED_SLEEP_NO_TM_MS) -#else -#define ZB_SCHED_SLEEP_NO_TM_BI ZB_MILLISECONDS_TO_BEACON_INTERVAL(10000U) -#endif - -#define ZB_SLEEP_INVALID_VALUE (zb_uint32_t)(~0u) - -typedef struct zb_sleep_ctx_s -{ - zb_bool_t permit_sleep_signal; - zb_time_t last_timestamp; - zb_time_t timer; - zb_uint32_t threshold; - zb_bitbool_t enabled:1; - zb_bitbool_t sleeping_now:1; - zb_bitbool_t intr:1; -} zb_sleep_ctx_t; - -void zb_sleep_init(void); -zb_uint32_t zb_sleep_calc_sleep_tmo(void); -void zb_sleep_can_sleep(zb_uint32_t sleep_tmo); - -#endif /* ZB_USE_SLEEP */ - -#endif /* ZB_SLEEP_H */ diff --git a/zboss/development/src/include/zb_test_profile.h b/zboss/development/src/include/zb_test_profile.h deleted file mode 100644 index b2f3f041d9..0000000000 --- a/zboss/development/src/include/zb_test_profile.h +++ /dev/null @@ -1,427 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Test profile API -*/ - -#ifndef ZB_TEST_PROFILE_H -#define ZB_TEST_PROFILE_H 1 - -#ifdef ZB_TEST_PROFILE - -/*! @cond internals_doc */ -/*! \addtogroup zb_test_profile */ -/*! @{ */ - -#ifdef ZB_TEST_PROFILE - -#define ZB_TEST_CUSTOM_LINK_STATUS -#define USE_RESP_FOR_COUNTED_BUFS -#define USE_COUNTER_RES_REQ - -#define ZB_TEST_PROFILE_ID 0x7f01U /*!< test profile id */ -#define ZB_TEST_PROFILE_EP 0xF0U /*!< test profile endpoint number (hardcoded) */ - -#define TP_TRANSMIT_COUNTED_PACKETS_REQ_CLID 0x0001U -/* Only for testing purpose (incorrect clid for test profile) */ -#define TP_TRANSMIT_COUNTED_PACKETS_RES_CLID 0xABCDU - -#define TP_BUFFER_TEST_REQUEST_CLID 0x001CU -#define TP_BUFFER_TEST_RESPONSE_CLID 0x0054U - -#define TP_BUFFER_TEST_REQUEST_CLID2 0x001DU - -#define TP_RESET_PACKET_COUNT_CLID 0x0002U /* Reset packet count */ -#define TP_RETRIEVE_PACKET_COUNT_CLID 0x0003U /* Retrieve packet count */ -#define TP_PACKET_COUNT_RESPONSE_CLID 0x0004U /* Packet count response */ - -#define MAX_NWK_RADIUS 0x1EU - -#if 0 -/** -* Cluster ID definitions for Test Profile 2 - */ -#define TP_TRANSMIT_COUNTED_PACKETS_CLID 0x0001 /*Transmit counted packets */ -#define TP_RESET_PACKET_COUNT_CLID 0x0002 /* Reset packet count */ -#define TP_RETRIEVE_PACKET_COUNT_CLID 0x0003 /* Retrieve packet count */ -#define TP_PACKET_COUNT_RESPONSE_CLID 0x0004 /* Packet count response */ -#define TP_TEST_REQUEST_CLID 0x001c /* Buffer test request */ -#define TP_TEST_GROUP_REQUEST_CLID 0x001d /* Buffer test group request */ -#define TP_TEST_RESPONSE_CLID 0x0054 /* Buffer test response */ -#define TP_TEST_GROUP_RESPONSE_CLID 0x0055 /* Buffer test group response */ -#define TP_DISCOVERY_REQUEST_CLID 0x1000 /* Route discovery request */ -#define TP_ROUTE_DISCOVERY_RESPONSE_CLID 0x1001 /* Route discovery response */ -#define TP_FREEFORM_REQUEST_CLID 0xa0a8 /* Freeform request */ -#define TP_FREEFORM_RESOPONSE_CLID 0xe000 /* Freeform response */ -#define TP_FREEFORM_NO_DATA_RESPONSE_CLID 0xe001 /* Freeform no data response */ -#define TP_BROADCAST_REQUEST_CLID 0xf000 /* Broadcast request */ -#define TP_BROADCAST_ALL_DEVICE_RESPONSE_CLID 0xf001 /* Broadcast to all devices response */ -#define TP_BROADCAST_TO_ALL_IDLE_DEVICES_RESPONSE_CLID 0xf00a /* Broadcast to all RxOnWhenIdle devices response */ -#define TP_BROACAST_TO_ALL_RC_RESPONSE_CLID 0xf00e /* Broadcast to all routers and coordinator response */ -#endif - -/* Check cluster id for membership in Test Profile 2 */ - -#define IS_CLUSTERID_TEST_PROFILE_BASE( _p ) ( ( _p == TP_BUFFER_TEST_REQUEST_CLID) \ - || (_p == TP_BUFFER_TEST_REQUEST_CLID2) \ - || (_p == TP_BUFFER_TEST_RESPONSE_CLID) ) -#ifdef USE_RESP_FOR_COUNTED_BUFS -#define IS_CLUSTER_TEST_PROFILE_COUNTED( _p ) ( (_p == TP_TRANSMIT_COUNTED_PACKETS_REQ_CLID) || (_p == TP_TRANSMIT_COUNTED_PACKETS_RES_CLID) ) -#else -#define IS_CLUSTER_TEST_PROFILE_COUNTED( _p ) ( ZB_FALSE ) -#endif - -#ifdef USE_COUNTER_RES_REQ -#define IS_CLUSTER_TEST_PROFILE_COUNT_RETRIVE( _p ) ( (_p == TP_RESET_PACKET_COUNT_CLID) \ - || (_p == TP_RETRIEVE_PACKET_COUNT_CLID) \ - || (_p == TP_PACKET_COUNT_RESPONSE_CLID) ) -#else -#define IS_CLUSTER_TEST_PROFILE_COUNT_RETRIVE( _p ) ( ZB_FALSE ) -#endif - -#define IS_CLUSTERID_TEST_PROFILE2( _p ) ( IS_CLUSTERID_TEST_PROFILE_BASE(_p) || USE_COUNTER_RES_REQ(_p) || IS_CLUSTER_TEST_PROFILE_COUNT_RETRIVE(_p) ) - -/** - Transmit counted packets request - */ -typedef ZB_PACKED_PRE struct zb_tp_transmit_counted_packets_req_s -{ - zb_uint8_t len; /*!< Length (in bytes) of the packet */ - zb_uint16_t counter; /*!< Octet sequence counter */ - /* #AT */ - zb_uint8_t req_data[1]; /*!< Data for transmit */ -} -ZB_PACKED_STRUCT -zb_tp_transmit_counted_packets_req_t; - -/** - Transmit counted packets parameters - */ -typedef struct zb_tp_transmit_counted_packets_param_s -{ - zb_uint8_t len; /*!< Length (in bytes) of the packet */ - zb_uint16_t packets_number; /*!< packets number to send */ - zb_uint16_t idle_time; /*!< time before next packet is sent */ - zb_uint16_t dst_addr; /*!< destination address */ - zb_uint8_t addr_mode; /*!< address type (group or device address) */ - zb_uint8_t src_ep; /*!< source endpoint id */ - zb_uint8_t dst_ep; /*!< destination endpoint id */ - zb_uint8_t radius; /*!< radius (set to 0 to use default) */ -} -zb_tp_transmit_counted_packets_param_t; - -/** - Buffer test request - */ -typedef ZB_PACKED_PRE struct zb_buffer_test_req_s -{ - zb_uint8_t len; /*!< Length (in bytes) of the packet */ - /* #AT */ - zb_uint8_t req_data[1]; /*!< Data for request */ -} -ZB_PACKED_STRUCT -zb_buffer_test_req_t; - -/** - Buffer test request parameters - */ -typedef struct zb_buffer_test_req_param_s -{ - zb_uint8_t len; /*!< Length (in bytes) of the packet */ - zb_uint16_t dst_addr; /*!< destination address */ - zb_uint8_t addr_mode; /*!< address type (group or device address) */ - zb_uint8_t src_ep; /*!< Source endpoint */ - zb_uint8_t dst_ep; /*!< Destination endpoint */ - zb_uint8_t radius; /*!< Radius */ - zb_uint8_t tx_options; /*!< TX Options */ - zb_uint16_t profile_id; /*!< profile id */ -} -zb_buffer_test_req_param_t; - -/** - Set default data - length - 10; - address - coordinator; - address mode - device address; - src and dst ep - 240; - */ -#define BUFFER_TEST_REQ_SET_DEFAULT( _p ) _p->len = 0x0AU; \ - _p->dst_addr = 0x0000U; \ - _p->addr_mode = ZB_APS_ADDR_MODE_16_ENDP_PRESENT; \ - _p->src_ep = ZB_TEST_PROFILE_EP; \ - _p->dst_ep = ZB_TEST_PROFILE_EP; \ - _p->radius = MAX_NWK_RADIUS; \ - _p->tx_options = 0; \ - _p->profile_id = ZB_TEST_PROFILE_ID - -/** - Set default data - length - 10; - address - coordinator; - address mode - device address; - src and dst ep - 240; - */ -#define BUFFER_COUNTED_TEST_REQ_SET_DEFAULT( _p ) _p->len = 0x0AU; \ - _p->packets_number = 5U; \ - _p->idle_time = 3U; \ - _p->dst_addr = 0x0000; \ - _p->addr_mode = ZB_APS_ADDR_MODE_16_ENDP_PRESENT; \ - _p->src_ep = ZB_TEST_PROFILE_EP; \ - _p->dst_ep = ZB_TEST_PROFILE_EP; \ - _p->radius = MAX_NWK_RADIUS; -/** - Buffer test request parameters, send by endpoint and cluster id - */ -typedef struct zb_buffer_test_req_param_EP_s -{ - zb_uint8_t len; /*!< Length (in bytes) of the packet */ - zb_uint8_t src_ep; /*!< Source endpoint */ - zb_uint8_t dst_ep; /*!< Destination endpoint */ -} -zb_buffer_test_req_param_EP_t; - - -#define ZB_TP_BUFFER_TEST_OK 0x00U /* Successful buffer test */ -#define ZB_TP_BUFFER_TEST_FAIL 0x01U /* Transmission failure on first attempt */ - -/** - Transmit buffer test response -*/ -typedef ZB_PACKED_PRE struct zb_buffer_test_response_s -{ - zb_uint8_t len; /*!< Length (in bytes) of the packet */ - zb_uint8_t status; /*!< Status of the response */ -} -ZB_PACKED_STRUCT -zb_buffer_test_response_t; - -/** - Transmit buffer test response parameters -*/ -typedef ZB_PACKED_PRE struct zb_buffer_test_response_param_s -{ - zb_uint8_t len; /*!< Length (in bytes) of the packet */ - zb_uint8_t status; /*!< Status of the response */ - zb_uint16_t dst_addr; /*!< Status of the response */ - zb_uint8_t addr_mode; /*!< address type (group or device address) */ - zb_uint8_t src_ep; /*!< Source endpoint */ - zb_uint8_t dst_ep; /*!< Destination endpoint */ - zb_uint8_t tx_options;/*!< TX Options */ -} -ZB_PACKED_STRUCT -zb_buffer_test_response_param_t; - -/** - Test Profile indication primitive - - @param param - buffer with command data - - @snippet tp_aps_bv_21_i_zed2.c zb_test_profile_indication - - */ -void zb_test_profile_indication(zb_uint8_t param); - -/** - Send counted packet - Every next packet send by confirm send command - - @param param - buffer with command data - */ -void tp_send_counted_packet(zb_uint8_t param); - - -/** - Send counted packet with ACK request field set as TRUE in APS frame - Every next packet send by confirm send command - - @param param - buffer with command data - */ -void tp_send_counted_packet_ext(zb_uint8_t param); - -/** - Send packet by short address destination - - Difference from tp_send_req_by_short: - - This function only copies its params into apsde_data_request. - - APS_SECURITY set in tx_options - not by default - - Network Radius always copied from param radius - - @param command_id - command ID - @param param - buffer with command data - @param profile_id - profile id (typically ZB_TEST_PROFILE_ID) - @param addr - destination address - @param addr_mode - destination address mode - @param src_ep - source endpoint - @param dst_ep - destination endpoint - @param tx_options - any options (security, etc) - @param radius - network radius - - @snippet doxygen_snippets.dox? tp_send_req_by_short_zdo_test_profile_c - */ -void tp_send_req_by_short_ext(zb_uint16_t command_id, - zb_uint8_t param, - zb_uint16_t profile_id, - zb_uint16_t addr, - zb_uint8_t addr_mode, - zb_uint8_t src_ep, - zb_uint8_t dst_ep, - zb_uint8_t tx_options, - zb_uint8_t radius); - -/** - Send packet and set callback on confirm - - @param param - buffer with command data - @param cb - callback *.confirm - - @snippet tp_r21_bv-25_gzr_c.c zb_tp_transmit_counted_packets_req_ext - @snippet tp_r21_bv-25_gzr_r.c zb_tp_transmit_counted_packets_req_ext - - */ -void zb_tp_transmit_counted_packets_req_ext(zb_uint8_t param, zb_callback_t cb); - - -/** - Send packet by short address destination - @param command_id - command ID - @param param - buffer with command data - @param profile_id - profile id (typically ZB_TEST_PROFILE_ID) - @param addr - destination address - @param addr_mode - destination address mode - @param src_ep - source endpoint - @param dst_ep - destination endpoint - @param tx_options - any options (security, etc) - @param radius - network radius - - @snippet doxygen_snippets.dox tp_send_req_by_short_zdo_test_profile_c - */ -void tp_send_req_by_short(zb_uint16_t command_id, - zb_uint8_t param, - zb_uint16_t profile_id, - zb_uint16_t addr, - zb_uint8_t addr_mode, - zb_uint8_t src_ep, - zb_uint8_t dst_ep, - zb_uint8_t tx_options, - zb_uint8_t radius); - -/** - Send packet and set callback on confirm - - @param param - buffer with command data - @param cb - callback *.confirm - - @snippet tp_aps_bv_09_zc.c zb_tp_transmit_counted_packets_req - - */ -void zb_tp_transmit_counted_packets_req(zb_uint8_t param, zb_callback_t cb); - -/** - Send ACK - - @param param - buffer for send ack data - - Internal - */ -void tp_packet_ack(zb_uint8_t param); - -/** - Send packet - - @param param - buffer with data see zb_tp_buffer_test_request_s - @param cb - callback *.confirm - - @snippet TP_PRO_BV-46/tp_pro_bv-46_zc.c tp_pro_bv-46_zc - - */ -void zb_tp_buffer_test_request(zb_uint8_t param, zb_callback_t cb); - -/** - Send packet - - @param param - buffer with data see zb_tp_buffer_test_request_s - @param cb - callback *.confirm - - @snippet tp_zdo_bv_12_zed1.c zb_tp_buffer_test_request_EP - - */ -void zb_tp_buffer_test_request_EP(zb_uint8_t param, zb_callback_t cb); - -/** - Send packet broadcast - - @param param - buffer with data see zb_tp_buffer_test_request_s - @param cb - callback *.confirm - - Not implemented - */ -void zb_tp_buffer_test_request_EP_brdcast(zb_uint8_t param, zb_callback_t cb); - -/** - Send Device Announce APS command - - @param param - buffer for send request - - @code - void func1(zb_uint8_t param) - { - zb_tp_device_announce(param); - } - @endcode - */ -void zb_tp_device_announce(zb_uint8_t param); - -#ifdef USE_COUNTER_RES_REQ -void zb_tp_retrive_packet_count(zb_uint8_t param); -#endif - -#if defined ZB_PRO_STACK && defined ZB_TEST_CUSTOM_LINK_STATUS && defined ZB_ROUTER_ROLE -/* Custom link status command for testing purpose only - * (allow to send cmd from some predefined address) - */ -zb_bool_t zb_tp_send_link_status_command(zb_uint8_t param, zb_uint16_t short_addr); -#endif - -#endif /* #ifdef ZB_TEST_PROFILE */ -/*! @} */ -/*! @endcond */ -#endif /* ZB_TEST_PROFILE */ - -#endif /* ZB_TEST_PROFILE_H */ diff --git a/zboss/development/src/include/zb_th_dummy.h b/zboss/development/src/include/zb_th_dummy.h deleted file mode 100644 index 6ddd5e0883..0000000000 --- a/zboss/development/src/include/zb_th_dummy.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Dummy macro for build without TH -*/ - -#ifndef ZB_TH_INTERNAL_H -#define ZB_TH_INTERNAL_H 1 - -#ifndef ZB_TH_ENABLED - -#define ZB_TH_PUSH_PACKET(primitive_type, call_type, bufid) -#define ZB_TH_PUSH_PACKET_TAIL(primitive_type, call_type, bufid, size) -#define ZB_TH_PUSH_NLDE_DATA_CONFIRM(bufid) -#define ZB_TH_PUSH_APSDE_DATA_CONFIRM(bufid) - -#endif /* ZB_TH_ENABLED */ -#endif /* ZB_TH_INTERNAL_H */ diff --git a/zboss/development/src/include/zb_time.h b/zboss/development/src/include/zb_time.h deleted file mode 100644 index 851dd7d3f8..0000000000 --- a/zboss/development/src/include/zb_time.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Common definitions for time functionality -*/ - -#ifndef ZB_TIME_H -#define ZB_TIME_H 1 - -#include "zboss_api_core.h" - - -/*! @cond internals_doc */ -/*! \addtogroup time */ -/*! @{ */ - -#define ZB_HALF_MAX_TIME32_VAL (ZB_UINT32_MAX / 2U) - - /** - Time subtraction: subtract 'b' from 'a'for 32bit-time - - Take overflow into account: change sign (subtraction order) if result > - values_diapason/2. - Suppose a always >= b, so result is never negative. - This macro will be used to calculate, for example, amount of time to sleep - - it is positive by definition. - Do not use it to compare time values! Use ZB_TIME32_GE() instead. - @note Both a and b is of type @ref zb_time_t. Can't decrease time (subtract - constant from it) using this macro. - - @param a - time to subtract from - @param b - time to subtract - @return subtraction result - */ -#define ZB_TIME32_SUBTRACT(a, b) ((zb_uint32_t)((a) - (b)) < ZB_HALF_MAX_TIME32_VAL ? (zb_uint32_t)((a) - (b)) : (zb_uint32_t)((b) - (a))) - - /** - Time add: add 'a' to 'b' for 32-bit time - - Overflow is possible, but this is ok - it handled by subtraction and compare macros. - - @param a - time to add to - @param b - value to add - @return addition result - */ -#define ZB_TIME32_ADD(a, b) (zb_uint32_t)((a) + (b)) - - /** - Compare times a and b - check that a >= b for 32-bit time - - Taking into account overflow and unsigned values arithmetic and supposing - difference between a and b can't be > 1/2 of the overall time values - diapason, - a >= b only if a - b < values_diapason/2 - - @param a - first time value to compare - @param b - second time value to compare - @return 1 is a >= b, 0 otherwise - */ -#define ZB_TIME32_GE(a, b) ((zb_uint32_t)((a) - (b)) < ZB_HALF_MAX_TIME32_VAL) - -#ifndef ZB_ALIEN_TIMER -/** - Start timer - assign time to sleep - - @param timeout - time in internal format to sleep before delayed callback run - */ -void zb_timer_start(zb_time_t timeout); - -/** - Stop timer - timer stop and callback not run - */ -void zb_timer_stop(void); - -#endif - -/** - Timer internals - - 'timer' always ticks (if some timer is started), usually with overflow. - Timer unit is beacon interval, for every system. - */ -typedef struct zb_timer_s -{ - zb_time_t timer; /*!< current time, measured in beacon intervals */ - -#ifndef ZB_ALIEN_TIMER - zb_uint32_t sleep_tmo_remainder_ms; /*!< slept time remainder, used for timer corrections */ - zb_time_t timer_stop; /*!< time to stop timer (disable timer interrupts etc) */ - zb_bool_t started; /*!< flag - timer is started */ - zb_bool_t canstop; /*!< flag - Can the timer be stopped? */ -#endif -} -zb_timer_t; - -/** - Enable ability to stop times saving power. - - Might be used for ZED. Not sure will use it for now. - */ -void zb_timer_enable_stop(void); - -/** - Disable ability to stop times saving power. - */ -void zb_timer_disable_stop(void); - -/** - Get current transceiver time value in usec - */ -zb_uint64_t osif_transceiver_time_get_long(void); - -/** - Get current transceiver time value in usec - */ -zb_time_t osif_transceiver_time_get(void); - -/** - Sleep for required interval using transceiver timer. - - Can be implemented as a busy wait or as a real sleep. - - @param interval - time to sleep in microseconds - */ -void osif_sleep_using_transc_timer(zb_time_t interval); - - -/*! @} */ -/*! @endcond */ - -#endif /* ZB_TIME_H */ diff --git a/zboss/development/src/include/zb_watchdog.h b/zboss/development/src/include/zb_watchdog.h deleted file mode 100644 index 964a9ae447..0000000000 --- a/zboss/development/src/include/zb_watchdog.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: General purpose software watchdog for ZB apps -*/ - -#ifndef ZB_WATCHDOG_H -#define ZB_WATCHDOG_H 1 - -#define ZB_WATCHDOG_DISABLED 0U -#define ZB_WATCHDOG_ENABLED 1U - -#include "zb_common.h" -typedef struct zb_watchdow_s -{ - zb_time_t timeout; - zb_time_t last_kick; - zb_uint8_t state; /* 0 - disabled, 1 - enabled */ -} zb_watchdog_t; - -typedef enum zb_watchdog_types_e -{ - ZB_WD_ZB_TRAFFIC, - - ZB_WD_CHECKIN, - - ZB_N_STD_WATCHDOGS -} zb_watchdog_types_t; - -#define ZB_N_WATCHDOG 8U - -/* error codes for error indication */ -/* a watchdog type will be put in additional_info */ -#define ZB_ERROR_WATCHDOG_TRIGGERED 1U - -#ifdef USE_ZB_WATCHDOG - -void zb_add_watchdog(zb_uint8_t wd_number, zb_time_t timeout); -void zb_kick_watchdog(zb_uint8_t wd_number); -void zb_watchdog_scheduler(zb_uint8_t param); -void zb_stop_watchdog(zb_uint8_t wd_number); -void zb_enable_watchdog(zb_uint8_t wd_number); -void zb_disable_watchdog(zb_uint8_t wd_number); - -#define ZB_KICK_WATCHDOG(n) zb_kick_watchdog((zb_uint8_t)(n)) -#define ZB_ENABLE_WATCHDOG(n) zb_enable_watchdog((zb_uint8_t)(n)) -#define ZB_DISABLE_WATCHDOG(n) zb_disable_watchdog((zb_uint8_t)(n)) - -#else - -#define ZB_KICK_WATCHDOG(n) -#define ZB_ENABLE_WATCHDOG(n) -#define ZB_DISABLE_WATCHDOG(n) - -#endif - -#ifdef ZB_USE_CHECKIN_WATCHDOG - -#ifndef ZB_WD_CHECKIN_MIN_TO -#define ZB_WD_CHECKIN_MIN_TO (60U*60U*ZB_TIME_ONE_SECOND) -#endif - -#endif /* ZB_USE_CHECKIN_WATCHDOG */ - - -#ifdef ZB_USE_ZB_TRAFFIC_WATCHDOG - -#ifndef ZB_WD_ZB_TRAFFIC_TO -#define ZB_WD_ZB_TRAFFIC_TO (240U*60U*ZB_TIME_ONE_SECOND) -#endif - -#endif /* ZB_USE_ZB_TRAFFIC_WATCHDOG */ - -#endif /* ZB_WATCHDOG_H */ diff --git a/zboss/development/src/include/zb_zcl.h b/zboss/development/src/include/zb_zcl.h deleted file mode 100644 index 7b807409a0..0000000000 --- a/zboss/development/src/include/zb_zcl.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Zigbee cluster library -*/ -#ifndef ZB_ZCL_H -#define ZB_ZCL_H 1 - -#include "zboss_api_zcl.h" -#ifndef ZB_ZCL_DISABLE_REPORTING -#include "zcl/zb_zcl_reporting.h" -#endif - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_WWAH -#define WWAH_CTX() ZCL_CTX().wwah_ctx -#endif /* ZB_ZCL_SUPPORT_CLUSTER_WWAH */ - - -/** @cond internals_doc */ - -/** @addtogroup zcl_api - * @{ - */ - -/** @brief ZCL command handler - * @param param - reference to the buffer with packet. - */ -void zb_zcl_process_device_command(zb_uint8_t param); - - -/** @brief Parsed ZCL command handler - * @param param - reference to the buffer with parsed ZCL header - * of type @ref zb_zcl_parsed_hdr_t stored as buffer parameter. - */ -void zb_zcl_process_parsed_zcl_cmd(zb_uint8_t param); -/********************** ZCL main functions declaration ******************************/ -/** @brief Initialize Zigbee cluster library. */ -void zb_zcl_init(void); - -/** @brief Deinitialize Zigbee cluster library. */ -void zb_zcl_deinit(void); - -/** @brief ZCL main loop. */ -void zcl_main_loop(void); - -/** @brief Parse ZCL header. - * @param param - reference to the buffer containing ZCL packet. - * @param cmd_info - pointer to the resulting parsed header representation (in the buffer). - * @return - header not contain error - */ -zb_zcl_status_t zb_zcl_parse_header(zb_uint8_t param, zb_zcl_parsed_hdr_t *cmd_info); - -#ifndef ZB_ZCL_DISABLE_REPORTING -void zb_zcl_put_default_reporting_info_for_cluster(zb_uint8_t endpoint, zb_uint16_t profile_id, struct zb_zcl_cluster_desc_s *cluster_desc); - -void zb_zcl_mark_report_not_sent(zb_zcl_reporting_info_t *rep_info); - -void zb_zcl_update_reporting_info(zb_zcl_reporting_info_t *rep_info); - -void zb_zcl_adjust_reporting_timer(zb_uint8_t param); -#endif /* ZB_ZCL_DISABLE_REPORTING */ - -/** Internal functions for gettings ZCL cluster handlers */ -zb_zcl_cluster_handler_t zb_zcl_get_cluster_handler_internal(zb_uint8_t endpoint, zb_uint16_t cluster_id, zb_uint8_t cluster_role); -zb_zcl_cluster_check_value_t zb_zcl_internal_get_cluster_check_value(zb_uint8_t endpoint, zb_uint16_t cluster_id, zb_uint8_t cluster_role); -zb_zcl_cluster_write_attr_hook_t zb_zcl_internal_get_cluster_write_attr_hook(zb_uint8_t endpoint, zb_uint16_t cluster_id, zb_uint8_t cluster_role); - -/** @endcond */ /* internals_doc */ - -/*! @} */ /* zcl_api */ - -#endif /* ZB_ZCL_H */ diff --git a/zboss/development/src/include/zb_zdo.h b/zboss/development/src/include/zb_zdo.h deleted file mode 100644 index 7a7d2065d7..0000000000 --- a/zboss/development/src/include/zb_zdo.h +++ /dev/null @@ -1,1551 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZDO API -*/ - -#ifndef ZB_ZDO_H -#define ZB_ZDO_H 1 - -#include "zboss_api_zdo.h" -#include "zboss_api_zcl.h" - - -/*! @cond internals_doc */ -/*! \addtogroup ZB_ZDO */ -/*! @{ */ - - -/** - Cluster ids for ZDO commands - */ -#define ZDO_NWK_ADDR_REQ_CLID 0x0000U -#define ZDO_IEEE_ADDR_REQ_CLID 0x0001U -#define ZDO_NODE_DESC_REQ_CLID 0x0002U -#define ZDO_POWER_DESC_REQ_CLID 0x0003U -#define ZDO_SIMPLE_DESC_REQ_CLID 0x0004U -#define ZDO_ACTIVE_EP_REQ_CLID 0x0005U -#define ZDO_MATCH_DESC_REQ_CLID 0x0006U -#define ZDO_COMPLEX_DESC_REQ_CLID 0x0010U -#define ZDO_USER_DESC_REQ_CLID 0x0011U -#define ZDO_DEVICE_ANNCE_CLID 0x0013U -#define ZDO_SYSTEM_SERVER_DISCOVERY_REQ_CLID 0x0015U -#define ZDO_PARENT_ANNCE_CLID 0x001FU -#define ZDO_BIND_REQ_CLID 0x0021U -#define ZDO_UNBIND_REQ_CLID 0x0022U -#define ZDO_MGMT_LQI_REQ_CLID 0x0031U -#define ZDO_MGMT_BIND_REQ_CLID 0x0033U -#define ZDO_MGMT_LEAVE_REQ_CLID 0x0034U -#define ZDO_MGMT_PERMIT_JOINING_CLID 0x0036U -#define ZDO_MGMT_NWK_UPDATE_REQ_CLID 0x0038U -#define ZDO_MGMT_NWK_ENHANCED_UPDATE_REQ_CLID 0x0039U -#define ZDO_MGMT_NWK_IEEE_JOINING_LIST_REQ_CLID 0x003AU - -#ifndef R23_DISABLE_DEPRECATED_ZDO_CMDS -#define ZDO_USER_DESC_SET_CLID 0x0014U -#define ZDO_EXTENDED_SIMPLE_DESC_REQ_CLID 0x001DU -#define ZDO_EXTENDED_ACTIVE_EP_REQ_CLID 0x001EU -#define ZDO_END_DEVICE_BIND_REQ_CLID 0x0020U -#define ZDO_MGMT_RTG_REQ_CLID 0x0032U -#endif /* R23_DISABLE_DEPRECATED_ZDO_CMDS */ - -#define ZDO_NWK_ADDR_RESP_CLID 0x8000U -#define ZDO_IEEE_ADDR_RESP_CLID 0x8001U -#define ZDO_NODE_DESC_RESP_CLID 0x8002U -#define ZDO_POWER_DESC_RESP_CLID 0x8003U -#define ZDO_SIMPLE_DESC_RESP_CLID 0x8004U -#define ZDO_ACTIVE_EP_RESP_CLID 0x8005U -#define ZDO_MATCH_DESC_RESP_CLID 0x8006U -#define ZDO_COMPLEX_DESC_RESP_CLID 0x8010U -#define ZDO_USER_DESC_RESP_CLID 0x8011U -#define ZDO_USER_DESC_CONF_CLID 0x8014U -#define ZDO_SYSTEM_SERVER_DISCOVERY_RESP_CLID 0x8015U -#define ZDO_PARENT_ANNCE_RESP_CLID 0x801FU -#define ZDO_BIND_RESP_CLID 0x8021U -#define ZDO_UNBIND_RESP_CLID 0x8022U -#define ZDO_MGMT_LQI_RESP_CLID 0x8031U -#define ZDO_MGMT_BIND_RESP_CLID 0x8033U -#define ZDO_MGMT_LEAVE_RESP_CLID 0x8034U -#define ZDO_MGMT_PERMIT_JOINING_RESP_CLID 0x8036U -#define ZDO_MGMT_NWK_UPDATE_NOTIFY_CLID 0x8038U -#define ZDO_MGMT_NWK_ENHANCED_UPDATE_NOTIFY_CLID 0x8039U -#define ZDO_MGMT_NWK_IEEE_JOINING_LIST_RESP_CLID 0x803AU -#define ZDO_MGMT_NWK_UNSOLICITED_ENHANCED_UPDATE_NOTIFY_CLID 0x803BU - -#ifndef R23_DISABLE_DEPRECATED_ZDO_CMDS -#define ZDO_END_DEVICE_BIND_RESP_CLID 0x8020U -#define ZDO_MGMT_RTG_RESP_CLID 0x8032U -#endif /* R23_DISABLE_DEPRECATED_ZDO_CMDS */ - -/*! @} */ -/*! @endcond */ - -/*! \addtogroup zdo_base */ -/*! @{ */ - -/*Redefine zb_zdo_startup_complete to zboss_signal_handler*/ -#define zb_zdo_startup_complete zboss_signal_handler - -#define ZB_ZDO_IS_SRV_CMD(_cluster) (((_cluster) & (0x8000U))>>15U) -#define ZB_ZDO_IS_CLI_CMD(_cluster) (ZB_ZDO_IS_SRV_CMD(_cluster) == 0U) - -#define ZB_ZDO_RESP_FROM_REQ_CLUSTER(_cli_cluster) ((_cli_cluster) | 0x8000U) - -typedef void (*zb_apsme_update_device_ind_cb)(zb_apsme_update_device_ind_t *ind, zb_bool_t auth_allowed); -typedef void (*zb_assert_indication_cb_t)(zb_uint16_t file_id, zb_int_t line_number); -struct zb_zdo_device_annce_s; -typedef void (ZB_CODE * zb_device_annce_cb_t)(struct zb_zdo_device_annce_s *da); -typedef zb_ret_t (ZB_CODE * zb_zdo_responce_cb_t)(zb_uint8_t param, zb_uint16_t clusterid); -typedef void (*zb_zdo_set_channel_confirm_cb_t) (zb_uint8_t status); -typedef void (*zb_zdo_duty_cycle_mode_ind_cb_t) (zb_uint8_t mode); - -/** - \par Device start - - Startup procedure as defined in 2.5.5.5.6.2 Startup Procedure -*/ - - -/* If any parameters are needed to be passed to the zdo_startup_complete, it - * will be better to inherit zb_zdo_app_signal_hdr_t and introduce the structure - * something like this: - * - * typedef struct zb_zdo_app_my_custom_event_s - * { - * zb_zdo_app_signal_hdr_t super; - * zb_my_custom_data_type_t my_custom_data; - * } - * - */ - -/*! @} */ - - -/*! \addtogroup zdo_init */ -/*! @{ */ - -/** @brief ZDO start function. - * - * Typical device start: init, load some parameters from nvram and proceed with startup. - * - * Startup means either Formation (for ZC), rejoin or discovery/association join. After startup - * complete @ref zb_zdo_startup_complete callback is called, so application will know when to do - * some useful things. - * - * Precondition: stack must be inited by @ref zb_init() call. @ref zb_init() loads IB from NVRAM - * or set its defaults, so caller has a chance to change some parameters. - * @note: ZB is not looped in this routine. Instead, it schedules callback and returns. Caller - * must run @ref zdo_main_loop() after this routine. - * - * @b Example: - * @code - * zb_init("zdo_zc"); - * ZB_AIB().aps_designated_coordinator = 1; - * ZB_IEEE_ADDR_COPY(ZB_PIBCACHE_EXTENDED_ADDRESS(), &g_zc_addr); - * ZB_PIBCACHE_PAN_ID() = 0x1aaa; - * ZB_NIB().max_children = 1; - * if (zdo_dev_start() != RET_OK) - * { - * TRACE_MSG(TRACE_ERROR, "zdo_dev_start failed", (FMT__0)); - * } - * else - * { - * zdo_main_loop(); - * } - * @endcode - * @return RET_OK on success. - * - */ -zb_ret_t zdo_dev_start(void); - - -/* TODO: [Multi-MAC] do not use PIB in samples here, do not use direct contexts access, - * rewrite example with modern ZBOSS public API */ -/** - Application main loop. - - Must be called after zb_init() and zdo_dev_start(). - - @b Example: -@code - zb_init("zdo_zc"); - ZB_AIB().aps_designated_coordinator = 1; - ZB_IEEE_ADDR_COPY(ZB_PIB_EXTENDED_ADDRESS(), &g_zc_addr); - ZB_PIBCACHE_PAN_ID() = 0x1aaa; - ZB_NIB().max_children = 1; - if (zdo_dev_start() != RET_OK) - { - TRACE_MSG(TRACE_ERROR, "zdo_dev_start failed", (FMT__0)); - } - else - { - zdo_main_loop(); - } -@endcode - - */ -void zdo_main_loop(void); - -/** - ZDO device init - - May be called as alter zdo_dev_start(). - Initialize ZDO without schedule zb_zdo_dev_start_cont - - @b Example: -@code - zb_init("zdo_zc"); - ZB_AIB().aps_designated_coordinator = 1; - ZB_IEEE_ADDR_COPY(ZB_PIB_EXTENDED_ADDRESS(), &g_zc_addr); - ZB_PIBCACHE_PAN_ID() = 0x1aaa; - ZB_NIB().max_children = 1; - zdo_dev_init(); - ZB_SCHEDULE_CALLBACK(zb_zdo_dev_start_cont, 0); - zdo_main_loop(); -@endcode - - */ -zb_ret_t zb_zdo_dev_init(void); - -/** - Initiate ZBOSS start without zb_send_no_autostart_event auto-start - */ -zb_ret_t zb_zdo_start_no_autostart(void); - -/** - ZDO device start procedure - Use when init device and start device process cut HW test/init procedure - - */ -void zb_zdo_dev_start_cont(zb_uint8_t param); - -/** - Callback which will be called after device startup complete or other event happen - - Must be defined in the application. - - @param param - ref to buffer with application event - @see zb_get_app_signal - -@b Example: -@snippet tp_pro_bv_20_zc.c zb_af_set_data_indication - - */ -void zb_zdo_startup_complete(zb_uint8_t param); - -/*! @} */ - -/* internal zdo_startup_complete */ -void zb_zdo_startup_complete_int(zb_uint8_t param); -void zb_zdo_startup_complete_int_delayed(zb_uint8_t param, zb_uint16_t user_param); -void zb_zdo_device_first_start_int_delayed(zb_uint8_t param, zb_uint16_t user_param); -void zb_zdo_device_reboot_int_delayed(zb_uint8_t param, zb_uint16_t user_param); - -/*! @cond internals_doc */ -/*! \addtogroup ZB_ZDO ZDO Internals */ -/*! @{ */ - -/** - Send Device annonce command for custom params - */ -void zdo_send_device_annce_ex(zb_uint8_t param, - zb_zdo_device_annce_t *dev_annce -#ifdef ZB_USEALIAS - ,zb_bool_t use_alias -#endif - ); - -/** - Actually send Device annonce command - */ -void zdo_send_device_annce(zb_uint8_t param); - - -/** - Node_desc_resp/Power_Node_desc_resp primitive. - - @param param - index of buffer to fill with primitive parameters. -*/ -void zdo_send_desc_resp(zb_uint8_t param); - -/** - Simple_desc_resp primitive. - - @param param - index of buffer to fill with primitive parameters. -*/ -void zdo_send_simple_desc_resp(zb_uint8_t param); - -#ifdef ZB_FIXED_OPTIONAL_DESC_RESPONSES -/** - Complex_Desc_rsp primitive - - @param param - index of buffer that has complex descriptor request. - Will be reused to send response. -*/ -void zb_zdo_send_complex_desc_resp(zb_uint8_t param); - -/** - User_Desc_rsp primitive - - @param param - index of buffer that has user descriptor request. - Will be reused to send response. -*/ -void zb_zdo_send_user_desc_resp(zb_uint8_t param); - -/** - User_Desc_conf primitive - - @param param - index of buffer containing User_Desc_set primitive. - Will be reused to send confirm. -*/ -void zb_zdo_send_user_desc_conf(zb_uint8_t param); -#endif - -/** - simple_desc_resp_convert_zboss convert payload from ZibBee ZDO format to ZBOSS ZDO format - - change order cluster count - cluster ids - see @ref zb_zdo_simple_desc_resp_t and ZDO spec - - @param param - index of buffer with zb_zdo_simple_desc_resp_t. - @return RET_OK or RET_IGNORE for malformed payload in response. -*/ -zb_ret_t zb_zdo_simple_desc_resp_convert_zboss(zb_uint8_t param); - -/** - Copies node descriptor, taking into account endian - @param dst_desc - destination descriptor - @param src_desc - source descriptor -*/ -void zb_copy_node_desc(zb_af_node_desc_t *dst_desc, zb_af_node_desc_t *src_desc); - -/** - Copies node power descriptor, taking into accaunt endian - @param dst_desc - destination descriptor - @param src_desc - source descriptor -*/ -void zb_copy_power_desc(zb_af_node_power_desc_t *dst_desc, zb_af_node_power_desc_t *src_desc); - -/** - Copies simple descriptor, taking into accaunt endian - @param dst_desc - destination descriptor - @param src_desc - source descriptor -*/ -void zb_copy_simple_desc(zb_af_simple_desc_1_1_t* dst_desc, zb_af_simple_desc_1_1_t*src_desc); - -/** - NWK_addr_req primitive. - - @param param - index of buffer to fill with primitive parameters. - @param fc - APS FC of the response -*/ -void zdo_device_nwk_addr_res(zb_uint8_t param, zb_uint8_t fc); - -#define ZB_ZDO_SINGLE_DEV_RESPONSE 0x00U -#define ZB_ZDO_EXTENDED_RESPONSE 0x01U - -/** - IEEE_addr_req primitive. - - @param param - index of buffer to fill with primitive parameters. - @param fc - APS FC of the response -*/ -void zdo_device_ieee_addr_res(zb_uint8_t param, zb_uint8_t fc); - -typedef struct zb_zdo_ed_scan_param_s -{ - zb_callback_t cb; - zb_nlme_ed_scan_request_t nwk_param; -} -zb_zdo_ed_scan_param_t; - -/** - Performs energy scan. - @param param - index of buffer -*/ -void zb_zdo_ed_scan_request(zb_uint8_t param); - -/** - Sends update notify command - @param param - index of buffer -*/ -void zb_zdo_nwk_upd_notify(zb_uint8_t param); - -/** - Active_EP_res primitive. - - @param param - index of buffer to fill with primitive parameters. -*/ -void zdo_active_ep_res(zb_uint8_t param); - -/** - Match_Desc_res primitive. - - @param param - index of buffer to fill with primitive parameters. -*/ -void zdo_match_desc_res(zb_uint8_t param); - -/** - Performs channel interference reporting and resolution - @param param - unused -*/ -void zb_zdo_check_fails(zb_uint8_t param); - -/** - Timer callback to set limit for channel check action - @param param - unused - */ -void zb_zdo_channel_check_timer_cb(zb_uint8_t param); - -/** - Callback to finish channel check action, is called on - Mgmt_NWK_Update_notify acknowledgement - @param param - index of buffer with results -*/ -void zb_zdo_channel_check_finish_cb(zb_uint8_t param); - -#ifdef ZB_JOIN_CLIENT -/** - * @brief Checks whether the rejoin process is active - * - * @return rejoin activeness status - */ -zb_bool_t zb_zdo_is_rejoin_active(void); - -/** - * @brief Initiate rejoin to the (same) PAN. - * @param buf [IN] - pointer to the zb_buf_t "buffer" used to perform rejoin - * @param ext_pan_id [IN] - Extended Pan ID of PAN to rejoin to; use same Pan ID - * (either aps_use_extended_pan_id or nib_ext_pan_id) - * @param channels_list [IN] - scanned channels - * @param secure [IN] - if set to ZB_TRUE, device will perform secured rejoin; - * if ZB_FALSE - device will do unsecure rejoin - * @return NLME-JOIN.request schedule result. - * TODO: write comments - */ -zb_ret_t zdo_initiate_rejoin(zb_bufid_t buf, zb_uint8_t *ext_pan_id, - zb_channel_page_t *channels_list, zb_bool_t secure_rejoin); -#else -#define zdo_initiate_rejoin(buf, ext_pan_id, channels_list, secure_rejoin) -#endif - -/** - Handles NWK_addr_resp and Extended_addr_resp responses - - @param param - index of buffer with request - */ -void zb_zdo_addr_resp_handle(zb_uint8_t param); - - -/** - Handles Mgmt_NWK_Update_req request - - @param param - index of buffer with request - */ -void zb_zdo_mgmt_nwk_update_handler(zb_uint8_t param); - - -#ifdef ZB_MGMT_NWK_ENHANCED_UPDATE_ENABLED -/** - Handles Mgmt_NWK_Enhanced_Update_req request - - @param param - index of buffer with request - */ -void zb_zdo_mgmt_nwk_enhanced_update_handler(zb_uint8_t param); - - -/** - Handles Mgmt_NWK_Unsolicited_Enhanced_Update_notification request - - @param param - index of buffer with request - */ -void zb_zdo_mgmt_unsol_enh_nwk_update_notify_handler(zb_uint8_t param); -#endif /* ZB_MGMT_NWK_ENHANCED_UPDATE_ENABLED */ - - -/** - Handles unsolicited Mgmt_NWK_Update_notification request - - @param param - index of buffer with request - */ -void zb_zdo_mgmt_handle_unsol_nwk_update_notify(zb_uint8_t param); - -/** - Bind/Unbind response primitive - - @param param - index of buffer with request - @param bind - true for bind, false for unbind - */ -void zb_zdo_bind_unbind_res(zb_uint8_t param, zb_bool_t bind); - -/** - Sends 2.4.4.3.2 Mgmt_Lqi_rsp - @param param - index of buffer with Lqi request - */ -void zdo_lqi_resp(zb_uint8_t param); - -#if defined ZB_JOINING_LIST_SUPPORT && defined ZB_ROUTER_ROLE - -/** - Sends 2.4.4.4.11 Mgmt_NWK_IEEE_Joining_List_rsp - @param param - index of buffer with nwk ieee joining list request - */ -void zdo_nwk_joining_list_resp(zb_uint8_t param); - -/** - Helper function that is responsible for actual Mgmt_NWK_IEEE_Joining_List_rsp sending - To be used as a callback for mlme-get.confirm -*/ -void zdo_nwk_joining_list_resp_send(zb_uint8_t param); - -/** - Sends 2.4.3.3.11 Mgmt_NWK_IEEE_Joining_List_req - @param param - index of buffer with nwk ieee joining list request - */ -zb_uint8_t zb_zdo_mgmt_nwk_ieee_joining_list_req(zb_uint8_t param, zb_callback_t cb); - -#endif /* defined ZB_JOINING_LIST_SUPPORT && defined ZB_ROUTER_ROLE */ - -/** - Allocates buffer and schedules to execute zb_get_peer_short_addr() - @param dst_addr_ref - reference to destination IEEE address - @param cb - callback to run on get peer address finish - @param param - parameter for callback function - */ -void zb_start_get_peer_short_addr(zb_address_ieee_ref_t dst_addr_ref, zb_callback_t cb, zb_uint8_t param); - -/** - Sends response for System_Server_Discovery_req - @param param - index of buffer with request - */ -void zdo_system_server_discovery_res(zb_uint8_t param); - -/** - Sends 2.4.4.2.1 End_Device_Bind_rsp command - @param param - index of buffer to use for i/o - @param status - End_Device_Bind_req command status -*/ -void zb_zdo_end_device_bind_resp(zb_uint8_t param, zb_zdp_status_t status); - -/** - Handle end_device_bind_req command - @param param - index of buffer with request - */ -void zb_zdo_end_device_bind_handler(zb_uint8_t param); - -/** - Handle incoming mgmt_leave_req - - @param param - buffer with request - */ -void zdo_mgmt_leave_srv(zb_uint8_t param); - -/** - Try to send mgmt_leave_rsp if somebody waiting for it. - - mgmt_leave operation is registered in the leave pending list: after LEAVE - command send confirm must send response. - Search is done using buffer ref: it always same. - If nothing found in the pending list, can proceed with leave.confirm - operations (clear addresses), else need to wait until response sent. - - @param param - ref to the buffer used for overall LEAVE operation - @param status - status to pass to the peer - - @return TRUE if resp sent, FALSE otherwise - */ -zb_bool_t zdo_try_send_mgmt_leave_rsp(zb_uint8_t param, zb_uint8_t status); - -void zb_zdo_register_addr_resp_cb(zb_callback_t addr_resp_cb); - -#if !defined NCP_MODE_HOST && !defined ZB_LITE_NO_OLD_CB -void zb_zdo_register_leave_cb(zb_callback_t leave_cb); -#endif - -/** - Register a callback which should be called when application falls into assert - */ -void zb_zdo_register_assert_indication_cb(zb_assert_indication_cb_t assert_cb); - -/** - Register a callback which will be called when TC received device update - */ - -void zb_zdo_register_update_device_indication_cb(zb_apsme_update_device_ind_cb cb); - - -#ifdef ZB_MAC_DUTY_CYCLE_MONITORING -void zb_zdo_register_duty_cycle_mode_indication_cb(zb_zdo_duty_cycle_mode_ind_cb_t cb); -#endif - -/** - handle Mgmt_Permit_Joining_req request - - @param param - permit joining parameters - - @return nothing - */ -void zb_zdo_mgmt_permit_joining_handle(zb_uint8_t param); - -/** - changes channel - - @param channel - channel number - - @return nothing - */ -void zb_zdo_set_channel_cb(zb_uint8_t channel); - -/** - changes channel without updating NWKUpdateID field - - @param channel - channel number - - @return nothing - */ -void zb_zdo_do_set_channel(zb_uint8_t channel); - -#ifdef ZB_ROUTER_ROLE - -void zb_zdo_mgmt_permit_joining_confirm_handle(zb_uint8_t param); - -#ifdef ZB_CERTIFICATION_HACKS -/* ZB_UINT8_MAX used as a special value - (this value forces stack to not consider this value at all) -*/ -void zb_set_max_joins(zb_uint8_t max_joins); - -zb_uint8_t zb_get_max_joins(void); - -#endif /* ZB_CERTIFICATION_HACKS */ -#endif /* ZB_ROUTER_ROLE */ - -#ifndef ZB_LITE_NO_ZDO_RESPONSE_VALIDATION -zb_bool_t zb_zdo_validate_reponse(zb_bufid_t buf, zb_uint16_t cluster_id); -#endif - -/*! @} */ -/*! @endcond */ - - -/* FIXME: why invented special macro? Kill it! */ -#if 0 -#ifndef ZB_LITTLE_ENDIAN -#define ZB_LETOH16_XOR(val) \ - ((zb_uint8_t*)&val)[0] = ((zb_uint8_t)val)^(*((zb_uint8_t*)&val));\ - ((zb_uint8_t*)&val)[1] = (*((zb_uint8_t*)&val))^((zb_uint8_t)val);\ - ((zb_uint8_t*)&val)[0] = (*((zb_uint8_t*)&val))^(zb_uint8_t)val; -#else -#define ZB_LETOH16_XOR(val) -#endif -#endif /* 0 */ - -#define ZB_LETOH16_XOR ZB_LETOH16_ONPLACE - - -/* - Run-time hide of some clusters. - Introduced to filter out sub-ghz cluster in 2.4-only mode. - */ -typedef zb_int_t (*zdo_cluster_filter_t)(zb_uint16_t clid); - -#ifdef ZB_FILTER_OUT_CLUSTERS -void zdo_add_cluster_filter(zdo_cluster_filter_t filter); -zb_int_t zdo_check_cluster_filtered_out(zb_uint16_t clid); -#define ZDO_CLUSTER_FILTERED_OUT(clid) zdo_check_cluster_filtered_out(clid) -#else -#define ZDO_CLUSTER_FILTERED_OUT(clid) 0 -#endif - - -void zdo_clear_after_leave(zb_uint8_t param); - -/** @brief Callback registration function. */ -zb_bool_t register_zdo_cb( - zb_uint8_t tsn, zb_callback_t cb, - zb_uint8_t resp_counter, zb_uint8_t cb_type, - zb_bool_t rx_on_when_idle); - -/** @brief Call confirm callback by index from buffer list. - * - * This routine called from functions to pass confirm to the upper layer. Use @ref register_zdo_cb - * with callback search type @brief CB_TYPE_INDEX to register user callback. - */ -zb_ret_t zdo_run_cb_by_index(zb_uint8_t param); - -/** @addtogroup zdo_disc - * @{ - */ - - -/** @brief Reset all registered ZDO callbacks. - * There are some cases when ZDO callbacks are not needed anymore (for example, on - * leave). Reset the callbacks and free the space for more actual and important routines - * (for example, leave confirm). - */ -void zdo_cb_reset(void); - -/** @} */ /* group zdo_disc */ - -/* If forget device param is true - then remove all information related to device; - * otherwise - remove device from neighbors, childs and unlock its address entry, - * save application data (bindings e.t.c) */ -void zdo_device_removed(zb_uint8_t param, zb_uint16_t forget_device); -void zb_send_leave_signal(zb_uint8_t param, zb_uint16_t user_param); - -void zb_zdo_register_device_annce_cb(zb_device_annce_cb_t cb); - -void zb_zdo_register_zb_zdo_responce_cb(zb_zdo_responce_cb_t cb); - -void zb_zdo_register_leave_indication_cb(zb_callback_t cb); - -void zb_zdo_register_set_channel_confirm_cb(zb_zdo_set_channel_confirm_cb_t cb); - -/* **************************** Device Updated Signal functions **************************** */ - -/** - * @brief Send @ZB_ZDO_SIGNAL_DEVICE_UPDATE signal - * - * @param param - reference to the buffer - * @param long_addr - long address of the updated device - * @param short_addr - short address of the updated device - * @param status - the updated status of the device - * (see r21 spec, Table 4.14 APSME-UPDATE-DEVICE.request Parameters) - * @param parent_short - short address of the device parent, 0xffff if unknown - * @param action - action TC made - @see secur_tc_action - */ -void zb_send_device_update_signal(zb_uint8_t param, - zb_ieee_addr_t long_addr, - zb_uint16_t short_addr, - zb_uint8_t status, - zb_uint16_t parent_short, - zb_uint8_t action); -/** - * @brief Prepare parameters and send - * @ZB_ZDO_SIGNAL_DEVICE_UPDATE signal with delay - * - * @param long_addr - long address of the updated device - * (need to getting @zb_address_ieee_ref_t) - * @param status - status of the updated device - * (see r21 spec, Table 4.14 APSME-UPDATE-DEVICE.request Parameters) - * @param parent_addr - long address of the parent - * @param ret - return status of TC authorization procedure - */ -void zb_prepare_and_send_device_update_signal(zb_ieee_addr_t long_addr, zb_uint8_t status, zb_ieee_addr_t parent_addr, zb_ret_t ret); - -/* **************************** Device Authorized Signal functions **************************** */ - -#define ZB_GET_AUTHORIZATION_STATUS(var) ((var) >> 2U) -#define ZB_GET_AUTHORIZATION_TYPE(var) ((var) & 0x03U) - -#define ZB_PACK_AUTHORIZATION_PARAMS(status, type) (((status) << 2U) | ((type) & 0x03U)) - -/** - * @brief Send @ZB_ZDO_SIGNAL_DEVICE_AUTHORIZED signal - * - * @param param - reference to the buffer - * @param long_addr - long address of the authorized device - * @param short_addr - short address of the authorized device - * @param authorization_type - authorization type (legacy, r21 TCLK) - * @param authorization_status - authorization status (depends on authorization_type) - */ -void zb_send_device_authorized_signal(zb_uint8_t param, - zb_ieee_addr_t long_addr, - zb_uint16_t short_addr, - zb_uint8_t authorization_type, - zb_uint8_t authorization_status); - -/** - * @brief Prepare parameters and send the - * @ZB_ZDO_SIGNAL_DEVICE_AUTHORIZED signal with delay - * - * @param long_addr - long address of the authorized device - * (need to getting the @zb_address_ieee_ref_t) - * @param authorization_type - authorization type (legacy, r21 TCLK, ) - * @param authorization_status - authorization status (depends on authorization_type) - */ -void zb_prepare_and_send_device_authorized_signal(zb_ieee_addr_t long_addr, - zb_uint8_t authorization_type, - zb_uint8_t authorization_status); - -/** - * @brief Alarm to send @ZB_ZDO_SIGNAL_DEVICE_AUTHORIZED signal - * for legacy devices ( < r21) - * - * @param param - address reference - */ -void zb_legacy_device_auth_signal_alarm(zb_uint8_t param); - -/* @brief Cancel zb_legacy_device_auth_signal_alarm - * for legacy devices ( < r21) - * - * @param long_addr - IEEE64 address reference - */ -void zb_legacy_device_auth_signal_cancel(zb_ieee_addr_t long_addr); - -/* MM: For unicast, counter should be set to 1 and callback can be freed in two - * ways: timeout or ZDO response recept - * For broadcast, counter should be set to 0xFF(?) and callback can be - * freed only in one way: timeout - * - * EE: Really, unicast must be 1. That values were from pre-historic logic. - * I still keep DEFAULT_COUNTER (but changed const): seems, in some cases we can - * send broadcast ZDO packets and receive more than 1 answer. - */ - -void zb_send_no_active_links_left_signal(zb_uint8_t param); - -#define ZB_ZDO_CB_UNICAST_COUNTER 1U /* 1 resp for Unicast */ -#define ZB_ZDO_CB_BROADCAST_COUNTER 0xFFU /* wait for timeout */ -#define ZB_ZDO_CB_DEFAULT_COUNTER 0xFEU /* Default value (just for check) */ - -#define ZB_ZDO_CB_KILLER_QUANT (5U * ZB_TIME_ONE_SECOND) -#define ZB_ZDO_CB_KILLER_CRITICAL_TIME(_rx_on_when_idle) \ - (2U*ZB_N_APS_MAX_FRAME_RETRIES * ZB_N_APS_ACK_WAIT_DURATION(_rx_on_when_idle)) -#define ZB_ZDO_CB_CLOCK_COUNTER(_rx_on_when_idle) \ - (ZB_ZDO_CB_KILLER_CRITICAL_TIME(_rx_on_when_idle) / ZB_ZDO_CB_KILLER_QUANT + 1U) - -void zdo_aps_decryption_failed(zb_uint8_t param); - -#define ZB_ZDO_NEIGHBOR_ERROR_VALUE 0xffU - -typedef struct zb_zdo_get_channel_req_s -{ - zb_callback_t cb; -} zb_zdo_get_channel_req_t; - -typedef struct zb_zdo_get_channel_resp_t -{ - zb_uint8_t status; - zb_uint8_t channel; -} zb_zdo_get_channel_resp_t; - -void zb_zdo_get_channel(zb_uint8_t param); - -/* Poll control */ - -/** - Running poll mode - */ -typedef enum zb_poll_mode_e -{ - ZB_ZDO_PIM_FAST, /*!< Fast poll */ - ZB_ZDO_PIM_LONG, /*!< Long poll */ - ZB_ZDO_PIM_TURBO /*!< Turbo poll */ -#ifdef SNCP_MODE - , - ZB_ZDO_PIM_STOP /*!< Poll stopped */ -#endif -} zb_poll_mode_t; - -/** - Arguments of asynchronous Get In Fast Poll Status response. -*/ -typedef ZB_PACKED_PRE struct zb_zdo_pim_get_in_fast_poll_flag_resp_s -{ - zb_bool_t in_fast_poll; /**< in fast poll status flag */ -} ZB_PACKED_STRUCT -zb_zdo_pim_get_in_fast_poll_flag_resp_t; - -/** - * @name Fast poll stopping result - * @anchor stop_fast_poll_result - */ -/** @{ */ -#define ZB_ZDO_PIM_STOP_FAST_POLL_RESULT_NOT_STARTED 0U /*!< Fast poll was not started */ -/** Fast poll was not stopped because ZDO_CTX().pim.fast_poll_on value still not equals to zero - * after decreasing */ -#define ZB_ZDO_PIM_STOP_FAST_POLL_RESULT_NOT_STOPPED 1U -#define ZB_ZDO_PIM_STOP_FAST_POLL_RESULT_STOPPED 2U /*!< Fast poll was stopped */ -/** @} */ - -/** - * @brief Type for fast poll stopping result. - * - * Holds one of @ref stop_fast_poll_result. Kept only for backward compatibility as - * @ref stop_fast_poll_result were declared previously as enum. Can be removed in future releases. - */ -typedef zb_uint8_t zb_stop_fast_poll_result_t; - -/** - Arguments of asynchronous Stop Fast Poll Extended response. -*/ -typedef ZB_PACKED_PRE struct zb_zdo_pim_stop_fast_poll_extended_resp_s -{ - zb_stop_fast_poll_result_t stop_result; /**< fast poll stopping result */ -} ZB_PACKED_STRUCT -zb_zdo_pim_stop_fast_poll_extended_resp_t; - - -#ifdef ZB_ED_FUNC -/** - Initialize Poll Interval Management default settings - */ -void zb_zdo_pim_init_defaults(void); -void zb_zdo_pim_start_fast_poll(zb_uint8_t param); -void zb_zdo_fast_poll_leave(zb_uint8_t param); -void zb_zdo_pim_stop_fast_poll(zb_uint8_t param); -void zb_zdo_pim_reset_turbo_poll_min(zb_uint8_t param); -void zb_zdo_pim_reset_turbo_poll_max(zb_uint8_t param); -void zb_zdo_pim_got_data(zb_uint8_t param); -void zb_zdo_pim_continue_polling_for_pkt(void); -zb_poll_mode_t zb_zdo_pim_get_mode(void); -void zb_zdo_pim_set_fast_poll_interval(zb_time_t ms); -void zb_zdo_pim_set_fast_poll_timeout(zb_time_t ms); -zb_bool_t zb_zdo_pim_in_fast_poll(void); -zb_time_t zb_zdo_get_pim_fast_poll_interval_ms(void); -zb_time_t zb_zdo_get_pim_fast_poll_timeout_ms(void); -void zb_zdo_pim_set_turbo_poll_max(zb_time_t turbo_poll_max_ms); -void zb_zdo_pim_set_turbo_poll_min(zb_time_t turbo_poll_min_ms); -zb_time_t zb_zdo_get_pim_turbo_poll_min_ms(void); -zb_time_t zb_zdo_get_poll_interval_ms(void); -void zb_zdo_pim_start_poll(zb_uint8_t param); -void zb_zdo_pim_stop_poll(zb_uint8_t param); -void zb_zdo_turbo_poll_packets_leave(zb_uint8_t param); -void zb_zdo_update_long_poll_int(zb_uint8_t param); -void zb_zdo_pim_continue_turbo_poll(void); -zb_time_t zb_zdo_pim_get_long_poll_ms_interval(void); -void zb_zdo_pim_turbo_poll_cancel_packet(void); - -#ifdef ZB_USE_INTERNAL_HEADERS -void zb_zdo_pim_set_long_poll_interval(zb_time_t ms); -void zb_zdo_pim_start_turbo_poll_packets(zb_uint8_t n_packets); -#endif -/** - * @brief Sends asynchronous request to check whether the device is in fast poll mode - * - * @param param buffer that will be used to store response parameters. - * - * @param cb - */ -void zb_zdo_pim_get_in_fast_poll_flag_req(zb_uint8_t param, zb_callback_t cb); - - -/** - * @brief Sends asynchronous request to stop fast poll and get stopping result - * - * @param param buffer that will be used to store response parameters. - * - * @param cb - */ -void zb_zdo_pim_stop_fast_poll_extended_req(zb_uint8_t param, zb_callback_t cb); - -#else -/* No any polling if not ZED-only or ZR switched to ZED */ -#define zb_zdo_pim_init_defaults() -#define zb_zdo_pim_start_fast_poll(param) -#define zb_zdo_fast_poll_leave(param) -#define zb_zdo_pim_stop_fast_poll(param) -#define zb_zdo_pim_reset_turbo_poll_min(param) -#define zb_zdo_pim_reset_turbo_poll_max(param) -#define zb_zdo_pim_got_data(param) -#define zb_zdo_pim_continue_polling_for_pkt() -#define zb_zdo_pim_get_mode() 0U -#define zb_zdo_pim_set_fast_poll_interval(ms) -#define zb_zdo_pim_set_fast_poll_timeout(ms) -#define zb_zdo_pim_set_long_poll_interval(ms) -#define zb_zdo_pim_in_fast_poll() 0U -#define zb_zdo_get_pim_fast_poll_interval_ms() 0U -#define zb_zdo_get_pim_fast_poll_timeout_ms() 0U -#define zb_zdo_pim_set_turbo_poll_max(turbo_poll_max_ms) -#define zb_zdo_pim_set_turbo_poll_min(turbo_poll_min_ms) -#define zb_zdo_get_pim_turbo_poll_min_ms() 0U -#define zb_zdo_pim_start_poll(param) -#define zb_zdo_pim_stop_poll(param) -#define zb_zdo_update_long_poll_int(param) -#define zb_zdo_turbo_poll_packets_leave(param) -#define zb_zdo_pim_continue_turbo_poll(param) -#define zb_zdo_pim_start_turbo_poll_packets(n_packets) -#define zb_zdo_pim_get_long_poll_ms_interval() 0U -#define zb_zdo_pim_get_in_fast_poll_flag_req(param, cb) -#define zb_zdo_pim_stop_fast_poll_extended_req(param, cb) -#define zb_zdo_pim_turbo_poll_cancel_packet() - -#endif /* ZB_ED_FUNC */ - -void zb_zdo_device_is_unreachable(zb_uint8_t addr_ref); - -zb_uint8_t zdo_get_aging_timeout(void); - -/** - Set Request Timeout Enumeration value that will be used in End Device Timeout Request - command (see 3.4.11 - r21 Zigbee spec) - - @param timeout - Request Timeout Enumeration value (see 3.4.11.3.1) - */ -void zdo_set_aging_timeout(zb_uint8_t timeout); - -zb_time_t zdo_get_ed_keepalive_timeout(void); - -void zb_zdo_start_router(zb_uint8_t param); - -void zdo_mgmt_permit_joining_resp_cli(zb_uint8_t param); - -void zb_set_zdo_descriptor(void); - -/*! \addtogroup zdo_general_api */ -/*! @{ */ - -void zdo_rejoin_clear_prev_join(void); - -typedef enum zb_zdo_tsn_policy_e -{ - ZDO_TSN_POLICY_FULL_RANGE, /*!< ZBOSS is allowed to manage full the range of ZDO TSN */ - ZDO_TSN_POLICY_RANGE_128_254, /*!< ZBOSS TSN pool is reduced to the range of ZDO TSN from 128 to 254 - (it is assumed that APP is in charge to manage ZDO TSN range from 0 to 127) */ -} zb_zdo_tsn_policy_t; - -/** - set the policy to update ZDO TSN value - */ -void zdo_tsn_policy_set(zb_zdo_tsn_policy_t policy); - -/** - predict (not really increment) ZDO TSN value according to the policy - - @return ZDO TSN predicted value - */ -zb_uint8_t zdo_tsn_predict(void); - -/** - update (increment) ZDO TSN value according to the policy - - @return ZDO TSN updated value - */ -zb_uint8_t zdo_tsn_inc(void); - -/** - get current ZDO TSN value - - @return ZDO TSN current value - */ -zb_uint8_t zdo_tsn_get(void); - -#ifdef ZBOSS_ZDO_APP_TSN_ENABLE -/* Yes, it is not so good solution. - But it allows an application to generate its own ZDO requests - with custom ZDO sequence numbers. - Unfortunately, some of application requires such a behaviour. - - The main idea is to assign a ZDO sequence number with buffer ID of the request, - so zdo_send_req function can use this sequence number instead of internal counter. - Unfortunately, we can't pass the ZDO sequence number in the same buffer - as a parameter due to the different implementations of ZDO interface functions. - These parameters sometime are passed as buffer param, but sometime in the beginning - of the buffer as a data ready to be used for the low level apsde data request interface. - */ -typedef struct zdo_app_tsn_entry_s -{ - zb_bufid_t buf_ref; - zb_uint8_t app_tsn; -} zdo_app_tsn_entry_t; - -/** - allocate an entry of ZDO APP TSN - - @return ZDO APP TSN entry or NULL in case there's no available slot in the table - */ -zdo_app_tsn_entry_t * zdo_app_tsn_allocate(zb_bufid_t buf_ref); - -/** - release an entry of ZDO APP TSN - */ -void zdo_app_tsn_release(zb_bufid_t buf_ref); - -/** - get an entry of ZDO APP TSN by buffer id - */ -zdo_app_tsn_entry_t * zdo_app_tsn_get_by_buf_ref(zb_bufid_t buf_ref); -#endif /* ZBOSS_ZDO_APP_TSN_ENABLE */ - -/** - ZBOSS commissioning type - */ -typedef enum zb_commissioning_type_e -{ - /* Note: classic must 1 for backward compatibility with apps used ZBOSS r21 API */ - ZB_COMMISSIONING_CLASSIC = 0, /*!< Classic == core certification tests == HA. Nearly obsolete now. */ - /* Note: BDB mode must 1 for backward compatibility with apps used ZBOSS r21 API */ - ZB_COMMISSIONING_BDB = 1, /*!< BDB mode. */ - ZB_COMMISSIONING_SE, -/* ZB_COMMISSIONING_ZLL, / !< ZLL not via BDB (is it ever usable?) */ -} zb_commissioning_type_t; - - -/* ZB_COMMISSIONING_TYPE() can be either hard-coded or selectable depending on build type. */ -#if defined ZB_BDB_MODE && defined ZB_LITE_BDB_ONLY_COMMISSIONING && !defined ZB_SE_COMMISSIONING - -#define ZB_COMMISSIONING_TYPE() ZB_COMMISSIONING_BDB - -#elif defined ZB_SE_COMMISSIONING && !defined ZB_BDB_MODE && defined ZB_SE_ONLY_COMMISSIONING - -#define ZB_COMMISSIONING_TYPE() ZB_COMMISSIONING_SE - -#else - -#define ZB_CONFIGURABLE_COMMISSIONING_TYPE - -#endif /* commissioning type selector */ - - -#ifdef ZB_CONFIGURABLE_COMMISSIONING_TYPE - -#ifdef ZB_COMMISSIONING_TYPE -#undef ZB_COMMISSIONING_TYPE -#endif - -#define ZB_COMMISSIONING_TYPE() COMM_CTX().commissioning_type -/* Classic is required for cert tests only, so have it in configurable case */ -#ifndef ZB_COMMISSIONING_CLASSIC_SUPPORT -#define ZB_COMMISSIONING_CLASSIC_SUPPORT -#endif - -#endif /* ZB_CONFIGURABLE_COMMISSIONING_TYPE */ - -/** - * @name Rejoin reasons - * @anchor rejoin_reason - * - * Note: These values were members of `enum zb_rejoin_reason_t` type but were converted to a - * set of macros due to MISRA violations. - */ -/** @{ */ -#define ZB_REJOIN_REASON_SELF_INITIATED 0U /*!< Local device initiated rejoin */ -#define ZB_REJOIN_REASON_BACKOFF_REJOIN 1U /*!< Backoff rejoin */ -#define ZB_REJOIN_REASON_PARENT_LOST 2U /*!< Rejoin caused by parent lost */ -#define ZB_REJOIN_REASON_DEV_ANNCE_SENDING_FAILED 3U /*!< Rejoin caused by failed device announcement transmission */ -#define ZB_REJOIN_REASON_LEAVE_WITH_REJOIN 4U /*!< Rejoin cause by leave command with rejoin bit enabled */ -/** @} */ - -#ifdef ZB_COMMISSIONING_CLASSIC_SUPPORT -void zdo_classic_initiate_commissioning(zb_uint8_t param); -#endif - -#if defined ZB_JOINING_LIST_SUPPORT - -typedef ZB_PACKED_PRE struct zb_jl_q_ent_s -{ - zb_callback_t func; /*!< function to call */ - zb_uint8_t param; /*!< parameter to pass to 'func' */ -} -ZB_PACKED_STRUCT -zb_jl_q_ent_t; - -ZB_RING_BUFFER_DECLARE(zb_joining_list_op_q, zb_jl_q_ent_t, ZB_JOINING_LIST_Q_SIZE); - -#endif /* ZB_JOINING_LIST_SUPPORT */ - -/*! @} */ - -/*Legacy API for device role selection. Used in some old tests*/ -#ifdef ZB_COORDINATOR_ROLE -void zb_set_network_coordinator_role_with_mode(zb_uint32_t channel_mask, zb_uint8_t bdb_mode); -void zb_set_nwk_coordinator_role_legacy_ext(zb_channel_list_t channel_list); -#endif /* ZB_COORDINATOR_ROLE */ - -#ifdef ZB_ROUTER_ROLE -void zb_set_network_router_role_with_mode(zb_uint32_t channel_mask, zb_commissioning_type_t bdb_mode); -void zb_set_nwk_router_role_legacy_ext(zb_channel_list_t channel_list); -#endif /* ZB_ROUTER_ROLE */ - -#ifdef ZB_ED_FUNC -void zb_set_network_ed_role_with_mode(zb_uint32_t channel_mask, zb_commissioning_type_t bdb_mode); -void zb_set_nwk_ed_role_legacy_ext(zb_channel_list_t channel_list); -#endif /* ZB_ED_FUNC */ - -#ifdef ZB_USE_INTERNAL_HEADERS -#ifdef ZB_COORDINATOR_ROLE -void zb_set_network_coordinator_role_legacy(zb_uint32_t channel_mask); -#endif /* ZB_COORDINATOR_ROLE */ - -#ifdef ZB_ROUTER_ROLE -void zb_set_network_router_role_legacy(zb_uint32_t channel_mask); -#endif /* ZB_ROUTER_ROLE */ - -#ifdef ZB_ED_FUNC -void zb_set_network_ed_role_legacy(zb_uint32_t channel_mask); -#endif /* ZB_ED_FUNC */ -#endif /* ZB_USE_INTERNAL_HEADERS */ - -/** - Set simple descriptor parameters - @param simple_desc - pointer to simple descriptor - @param endpoint - Endpoint - @param app_profile_id - Application profile identifier - @param app_device_id - Application device identifier - @param app_device_version - Application device version - @param app_input_cluster_count - Application input cluster count - @param app_output_cluster_count - Application output cluster count - -*/ -void zb_set_simple_descriptor(zb_af_simple_desc_1_1_t *simple_desc, - zb_uint8_t endpoint, zb_uint16_t app_profile_id, - zb_uint16_t app_device_id, zb_bitfield_t app_device_version, - zb_uint8_t app_input_cluster_count, zb_uint8_t app_output_cluster_count); - -/** - Set input cluster item - @param simple_desc - pointer to simple descriptor - @param cluster_number - cluster item number - @param cluster_id - cluster ID - -*/ -void zb_set_input_cluster_id(zb_af_simple_desc_1_1_t *simple_desc, zb_uint8_t cluster_number, zb_uint16_t cluster_id); - -/*! @brief Set output cluster item - @param simple_desc - pointer to simple descriptor - @param cluster_number - cluster item number - @param cluster_id - cluster ID - -*/ -void zb_set_output_cluster_id(zb_af_simple_desc_1_1_t *simple_desc, zb_uint8_t cluster_number, zb_uint16_t cluster_id); - -/** - Set default descriptors values for FFD. - @param device_type - device type ZB_COORDINATOR or ZB_ROUTER - - @code - zb_set_default_ffd_descriptor_values(ZB_COORDINATOR); - @endcode - - */ -void zb_set_default_ffd_descriptor_values(zb_logical_type_t device_type); - -/** - Set default descriptors values for end device. - */ -void zb_set_default_ed_descriptor_values(void); - -/** - Adds simple descriptor. - @param simple_desc - pointer to simple descriptor to add - @return RET_OK, RET_OVERFLOW - - @par Example - @snippet tp_zdo_bv_09_zc.c zb_set_simple_descriptor - @par - - */ -zb_ret_t zb_add_simple_descriptor(zb_af_simple_desc_1_1_t *simple_desc); - -/** - Set node descriptor for FFD - @param device_type - FFD device type ZB_COORDINATOR or ZB_ROUTER -*/ -void zb_set_ffd_node_descriptor(zb_logical_type_t device_type); - -/** - Set node descriptor for end device - @param power_src - true if the current power source is mains power, false otherwise - @param rx_on_when_idle - receiver on when idle sub-field - @param alloc_addr - allocate address sub-field -*/ -void zb_set_ed_node_descriptor(zb_bool_t power_src, zb_bool_t rx_on_when_idle, zb_bool_t alloc_addr); - -/** @cond internals_doc */ -#define ZB_NODE_DESC_LOGICAL_TYPE_MASK 0x7U /* 0000.0000 0000.0111 */ -#define ZB_NODE_DESC_COMPLEX_DESC_AVAIL_MASK 0x8U /* 0000.0000 0000.1000 */ -#define ZB_NODE_DESC_USER_DESC_AVAIL_MASK 0x10U /* 0000.0000 0001.0000 */ -#define ZB_NODE_DESC_APS_FLAGS_MASK 0x700U /* 0000.0111 0000.0000 */ -#define ZB_NODE_DESC_FREQ_BAND_MASK 0xF800U /* 1111.1000 0000.0000 */ - -#define ZB_SET_NODE_DESC_LOGICAL_TYPE(desc, value) \ - ( (desc)->node_desc_flags &= (zb_uint16_t)~ZB_NODE_DESC_LOGICAL_TYPE_MASK, \ - (desc)->node_desc_flags |= (zb_uint16_t)(value) ) - -#define ZB_GET_NODE_DESC_LOGICAL_TYPE(desc) \ - ( (desc)->node_desc_flags & ZB_NODE_DESC_LOGICAL_TYPE_MASK ) - -#define ZB_SET_NODE_DESC_COMPLEX_DESC_AVAIL(desc, value) \ - ( (desc)->node_desc_flags &= (zb_uint16_t)~ZB_NODE_DESC_COMPLEX_DESC_AVAIL_MASK, \ - (desc)->node_desc_flags |= (zb_uint16_t)((value) << 3U) ) - -#define ZB_GET_NODE_DESC_COMPLEX_DESC_AVAIL(desc) \ - ( ((desc)->node_desc_flags & ZB_NODE_DESC_COMPLEX_DESC_AVAIL_MASK) >> 3U ) - -#define ZB_SET_NODE_DESC_USER_DESC_AVAIL(desc, value) \ - ( (desc)->node_desc_flags &= (zb_uint16_t)~ZB_NODE_DESC_USER_DESC_AVAIL_MASK, \ - (desc)->node_desc_flags |= (zb_uint16_t)((value) << 4U) ) - -#define ZB_GET_NODE_DESC_USER_DESC_AVAIL(desc) \ - ( ((desc)->node_desc_flags & ZB_NODE_DESC_USER_DESC_AVAIL_MASK) >> 4U ) - -#define ZB_SET_NODE_DESC_APS_FLAGS(desc, value) \ - ( (desc)->node_desc_flags &= (zb_uint16_t)~ZB_NODE_DESC_APS_FLAGS_MASK, \ - (desc)->node_desc_flags |= (zb_uint16_t)((value) << 8U) ) - -#define ZB_GET_NODE_DESC_APS_FLAGS(desc) \ - ( ((desc)->node_desc_flags & ZB_NODE_DESC_APS_FLAGS_MASK) >> 8U ) - -#define ZB_SET_NODE_DESC_FREQ_BAND(desc, value) \ - ( (desc)->node_desc_flags &= (zb_uint16_t)~ZB_NODE_DESC_FREQ_BAND_MASK, \ - (desc)->node_desc_flags |= (zb_uint16_t)((value) << 11U) ) - -#define ZB_GET_NODE_DESC_FREQ_BAND(desc) \ - ( ((desc)->node_desc_flags & ZB_NODE_DESC_FREQ_BAND_MASK) >> 11U ) -/** @endcond */ /*internals_doc */ - -/** - Set node descriptor - @param device_type - FFD device type ZB_COORDINATOR or ZB_ROUTER or RFD device type - ZB_END_DEVICE - @param power_src - 1 if the current power source is mains power, 0 otherwise - @param rx_on_when_idle - receiver on when idle sub-field - @param alloc_addr - allocate address sub-field - - @b Example - @code - zb_set_node_descriptor(ZB_END_DEVICE, ZB_TRUE, ZB_FALSE, ZB_TRUE); - @endcode - - NOTE: zboss_start() overwrites this descriptor with default values. -*/ -void zb_set_node_descriptor(zb_logical_type_t device_type, zb_bool_t power_src, zb_bool_t rx_on_when_idle, zb_bool_t alloc_addr); - -/** @cond internals_doc */ -/* Macro to set node descriptor, 2.3.2.3 Node Descriptor */ -#define ZB_SET_NODE_DESCRIPTOR(logical_type_p, frequency_band_p, mac_capability_flags_p, manufacturer_code_p, \ - max_buf_size_p, max_incoming_transfer_size_p, server_mask_p, \ - max_outgoing_transfer_size_p, desc_capability_field_p) \ - do \ - { \ - ZB_SET_NODE_DESC_LOGICAL_TYPE(ZB_ZDO_NODE_DESC(), (logical_type_p)); \ - ZB_SET_NODE_DESC_COMPLEX_DESC_AVAIL(ZB_ZDO_NODE_DESC(), 0U); /* complex desc is not supported */ \ - ZB_SET_NODE_DESC_USER_DESC_AVAIL(ZB_ZDO_NODE_DESC(), 0U); /* usr desc is not supported */ \ - ZB_SET_NODE_DESC_APS_FLAGS(ZB_ZDO_NODE_DESC(), 0U); /* not supported by spec */ \ - ZB_SET_NODE_DESC_FREQ_BAND(ZB_ZDO_NODE_DESC(), ((zb_uint16_t)frequency_band_p)); \ - ZB_ZDO_NODE_DESC()->mac_capability_flags = (mac_capability_flags_p); \ - ZB_ZDO_NODE_DESC()->manufacturer_code = (zb_uint16_t)(manufacturer_code_p); \ - ZB_ZDO_NODE_DESC()->max_buf_size = (zb_uint8_t)(max_buf_size_p); \ - ZB_ZDO_NODE_DESC()->max_incoming_transfer_size = (zb_uint16_t)(max_incoming_transfer_size_p); \ - ZB_ZDO_NODE_DESC()->server_mask = ((zb_uint16_t)(server_mask_p)) | (ZB_STACK_SPEC_VERSION << 9); /*see 2.3.2.3.10 Server Mask Field*/ \ - ZB_ZDO_NODE_DESC()->max_outgoing_transfer_size = (zb_uint16_t)(max_outgoing_transfer_size_p); \ - ZB_ZDO_NODE_DESC()->desc_capability_field = (zb_uint8_t)(desc_capability_field_p); \ - } while (ZB_FALSE) -/** @endcond */ /* internals_doc */ - -/** @cond internals_doc */ -#define ZB_POWER_DESC_CUR_POWER_MODE_MASK 0x000FU /* 0000.0000 0000.1111 */ -#define ZB_POWER_DESC_AVAIL_POWER_SOURCES_MASK 0x00F0U /* 0000.0000 1111.0000 */ -#define ZB_POWER_DESC_CUR_POWER_SOURCE_MASK 0x0F00U /* 0000.1111 0000.0000 */ -#define ZB_POWER_DESC_CUR_POWER_SOURCE_LEVEL_MASK 0xF000U /* 1111.0000 0000.0000 */ - -#define ZB_SET_POWER_DESC_CUR_POWER_MODE(desc, value) \ - ( (desc)->power_desc_flags &= (zb_uint16_t)~ZB_POWER_DESC_CUR_POWER_MODE_MASK, \ - (desc)->power_desc_flags |= (zb_uint16_t)(value) ) - -#define ZB_GET_POWER_DESC_CUR_POWER_MODE(desc) \ - ( (desc)->power_desc_flags & ZB_POWER_DESC_CUR_POWER_MODE_MASK ) - -#define ZB_SET_POWER_DESC_AVAIL_POWER_SOURCES(desc, value) \ - ( (desc)->power_desc_flags &= (zb_uint16_t)~ZB_POWER_DESC_AVAIL_POWER_SOURCES_MASK, \ - (desc)->power_desc_flags |= (zb_uint16_t)(((zb_uint16_t)value) << 4U) ) - -#define ZB_GET_POWER_DESC_AVAIL_POWER_SOURCES(desc) \ - ( ((desc)->power_desc_flags & ZB_POWER_DESC_AVAIL_POWER_SOURCES_MASK) >> 4U ) - -#define ZB_SET_POWER_DESC_CUR_POWER_SOURCE(desc, value) \ - ( (desc)->power_desc_flags &= (zb_uint16_t)~ZB_POWER_DESC_CUR_POWER_SOURCE_MASK, \ - (desc)->power_desc_flags |= (zb_uint16_t)(((zb_uint16_t)value) << 8U) ) - -#define ZB_GET_POWER_DESC_CUR_POWER_SOURCE(desc) \ - ( ((desc)->power_desc_flags & ZB_POWER_DESC_CUR_POWER_SOURCE_MASK) >> 8U ) - -#define ZB_SET_POWER_DESC_CUR_POWER_SOURCE_LEVEL(desc, value) \ - ( (desc)->power_desc_flags &= (zb_uint16_t)~ZB_POWER_DESC_CUR_POWER_SOURCE_LEVEL_MASK, \ - (desc)->power_desc_flags |= (zb_uint16_t)(((zb_uint16_t)value) << 12U) ) - -#define ZB_GET_POWER_DESC_CUR_POWER_SOURCE_LEVEL(desc) \ - ( ((desc)->power_desc_flags & ZB_POWER_DESC_CUR_POWER_SOURCE_LEVEL_MASK) >> 12U ) - - -/** - Set node power descriptor - @param current_power_mode - current power mode - @param available_power_sources - available power sources - @param current_power_source - current power source - @param current_power_source_level - current power source level - - NOTE: zboss_start() overwrites this descriptor with default values - if ZB_SET_DEFAULT_POWER_DESCRIPTOR is defined -*/ -void zb_set_node_power_descriptor(zb_current_power_mode_t current_power_mode, zb_uint8_t available_power_sources, - zb_uint8_t current_power_source, zb_power_source_level_t current_power_source_level); - -/** - * Set node descriptor manufacturer code - * - * @param manuf_code - current power mode -*/ -void zdo_set_node_descriptor_manufacturer_code(zb_uint16_t manuf_code); - -/** @endcond */ /*internals_doc */ - -/** - * Parent announce handler - * - * @param param - reference to buffer to construct response in - * @param param_req - reference to buffer containing device announce being handled - */ -void zdo_parent_annce_handler(zb_uint8_t param, zb_uint16_t param_req); - -#ifdef ZB_ROUTER_ROLE -/** - * @brief Sends Parent_Annce - * - * @param param - reference to buffer containing command - * - * @see ZB R21 spec, subclause 2.4.3.1.12. - */ -void zdo_send_parent_annce(zb_uint8_t param); - -void zdo_send_parent_annce_at_formation(zb_uint8_t param); -#endif - -zb_uint8_t zb_commissioning_default_permit_duration(void); - -#ifdef ZB_FORMATION -void zdo_formation_force_link(void); - -void zdo_start_formation(zb_uint8_t param); - -void zdo_commissioning_formation_done(zb_uint8_t param); - -void zdo_commissioning_formation_failed(zb_uint8_t param); -#endif - -void zdo_comm_set_permit_join(zb_uint8_t param, zb_callback_t cb); - -void zdo_commissioning_leave(zb_bufid_t buf, zb_bool_t rejoin, zb_bool_t remove_children); - -#ifdef ZB_DISTRIBUTED_SECURITY_ON -zb_bool_t zb_tc_is_distributed(void); - -void zb_sync_distributed(void); -#endif - -void zdo_load_production_config(void); -void zb_send_no_autostart_signal(zb_uint8_t param); -void zb_nlme_leave_indication_cont(zb_uint8_t param_buf, zb_uint16_t param_req); - -/** - * Returns if the device is authenticated in the network. - */ -zb_bool_t zb_zdo_authenticated(void); - -/** - * Returns if the device has a valid TCLK. - */ -zb_bool_t zb_zdo_tclk_valid(void); - -#define ZB_IS_TC() ZB_IS_DEVICE_ZC() - -void zb_get_use_extended_pan_id(zb_ext_pan_id_t ext_pan_id); - -void zb_set_use_extended_pan_id(const zb_ext_pan_id_t ext_pan_id); - -void zb_set_nwk_role_mode_common(zb_nwk_device_type_t device_type, - zb_uint32_t channel_mask, - zb_commissioning_type_t mode); - -#ifndef NCP_MODE_HOST -void zb_set_nwk_role_mode_common_ext(zb_nwk_device_type_t device_type, - zb_channel_list_t channel_list, - zb_commissioning_type_t mode); -#endif - -zb_commissioning_type_t zb_zdo_get_commissioning_type(void); - -void zb_zdo_data_indication(zb_uint8_t param); - -void zb_zdo_init(void); - -#ifdef ZB_ENABLE_ZCL -zb_bool_t zb_af_is_confirm_for_zcl_frame(zb_uint8_t param); - -void zb_af_handle_zcl_frame_data_confirm(zb_uint8_t param); - -zb_bool_t zb_af_handle_zcl_frame(zb_uint8_t param); -#endif /* ZB_ENABLE_ZCL */ - -void zb_send_leave_indication_signal(zb_uint8_t param); - -void zdo_send_signal_no_args(zb_uint8_t param, zb_uint16_t signal); - -#if defined NCP_MODE && !defined NCP_MODE_HOST -void zdo_send_ncp_join_signal(zb_uint8_t param); -#endif /* defined NCP_MODE && !defined NCP_MODE_HOST */ - -#ifdef ZB_PRODUCTION_CONFIG -/** - * Check whether production configuration block is present in device - * - * @return production configuration presence status - */ -zb_bool_t zb_production_configuration_check_presence(void); - -/** - * Read data from production configuration header - * - * @param prod_cfg_hdr - pointer to production configuration header - * @param hdr_len - size of production configuration header - * - * @return RET_OK is success, RET_ERROR otherwise - */ -zb_ret_t zb_production_cfg_read_header(zb_uint8_t *prod_cfg_hdr, zb_uint16_t hdr_len); - -/** - * Read data from production configuration block - * - * @param buffer - buffer to read into - * @param len - length of block to read - * @param offset - offset to read from - * - * @return RET_OK is success, RET_ERROR otherwise - */ -zb_ret_t zb_production_cfg_read(zb_uint8_t *buffer, zb_uint16_t len, zb_uint16_t offset); - -#endif - -/** - Performs active scan. - @param param - index of buffer with zb_nlme_network_discovery_request_t param -*/ -void zb_zdo_active_scan_request(zb_uint8_t param); - -#endif /* ZB_ZDO_H */ diff --git a/zboss/development/src/include/zb_zdo_globals.h b/zboss/development/src/include/zb_zdo_globals.h deleted file mode 100644 index d6b4a1779d..0000000000 --- a/zboss/development/src/include/zb_zdo_globals.h +++ /dev/null @@ -1,505 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZDO globals definition -*/ - -#ifndef ZB_ZDO_GLOBALS_H -#define ZB_ZDO_GLOBALS_H 1 - -#ifdef ZB_TEST_PROFILE -#include "zb_test_profile.h" -#endif /* ZB_TEST_PROFILE */ -#include "zb_zdo_rjb.h" -#include "zb_zdo.h" -#include "zdo_diagnostics.h" -#ifdef ZB_PHY_TESTING_MODE -#include "zboss_api_mac.h" -#endif /* ZB_PHY_TESTING_MODE */ - -/*! @cond internals_doc */ -/*! \addtogroup zdo_ib */ -/*! @{ */ - -#define ZB_ZDO_NODE_DESC() (&ZG->zdo.conf_attr.node_desc) -#define ZB_ZDO_NODE_POWER_DESC() (&ZG->zdo.conf_attr.node_power_desc) -#define ZB_ZDO_SIMPLE_DESC() (&ZG->zdo.conf_attr.zdo_simple_desc) -#define ZB_ZDO_SIMPLE_DESC_LIST() (ZG->zdo.conf_attr.simple_desc_list) -#define ZB_ZDO_SIMPLE_DESC_NUMBER() (ZG->zdo.conf_attr.simple_desc_number) - -/** - ZDO Configuration Attributes - */ -typedef struct zb_zdo_configuration_attributes_e -{ - /* nwk_time_btwn_scans and nwk_scan_attempts moved to zb_commissioning_ctx_t */ - - zb_af_node_desc_t node_desc; /*!< Node Descriptors */ - zb_af_node_power_desc_t node_power_desc; /*!< Node Power Descriptors */ - zb_af_simple_desc_8_9_t zdo_simple_desc; /* TODO: remove it, ZDO simple descriptor is not needed - simple descriptors for EP >= 1 are used */ - /* TODO: make real list support, if multiple EP are supported */ - /* TODO: each Zigbee device application declares a device context and a list of EPs. Each EP - stores its simple descriptor => no need store it here, it is better to use that storage */ - zb_af_simple_desc_1_1_t *simple_desc_list[ZB_MAX_EP_NUMBER]; /*!< Simple Descriptors table */ - zb_uint8_t simple_desc_number; /*!< Number elements of Simple Descriptors table */ - -#ifndef ZB_LITE_NO_END_DEVICE_BIND - zb_uint8_t enddev_bind_timeout; /* Timeout value in seconds employed - * in End Device Binding */ -#endif - zb_uint8_t permit_join_duration; /*!< Permit join duration, 0x00 - disable - * join, 0xff - join is allowed forever */ - - -} zb_zdo_configuration_attributes_t; - - -/*! @} */ - -/*! \addtogroup ZB_ZDO */ -/*! @{ */ - - -/** - Some ZDO private data - */ -#define ZB_TEST_DATA_SIZE 10U - -#define ZB_ZDO_MAX_CLUSTER_LIST 15U - -#define ZB_ZDO_MAX_JOINING_TRY_ATTEMPTS 3U - -typedef struct zb_zdo_rejoin_ctx_s -{ - zb_channel_list_t channels_list; - zb_ext_pan_id_t ext_pan_id; - zb_bool_t secure_rejoin; -} zb_zdo_rejoin_ctx_t; - - -/** - Some ZDO internal flags - */ -typedef struct zp_zdo_handle_s -{ - zb_bitbool_t rejoin:1; /*!< if !0, this is rejoin */ - zb_bitbool_t tc_significance:1; /*!< data for permit_joining */ - zb_bitbool_t channel_update_disabled:1; /*!< if !0, Channel update is disabled */ - zb_uint8_t permit_joining_param; /*!< if !0, nlme-permit_joining will - * be executed */ - zb_uint8_t permit_duration; /*!< data for permit_joining */ - zb_uint8_t dev_annce_param; /*!< if !0, this is buffer id - device annonce - * is sent */ - zb_uint8_t key_sw; /*!< if !0, key switch is sent and must switch - * the key after this buffer sent */ - zb_uint8_t mgmt_leave_resp_buf; /*!< if !0, nlme_leave_request for itself will be executed - * set after device was requested to leave the network - * via mgmt_leave_req */ - zb_zdo_rejoin_ctx_t rejoin_ctx; -} zp_zdo_handle_t; - -/* Flag to set and check if channel update is disabled */ -#define ZB_ZDO_NETWORK_MGMT_CHANNEL_UPDATE_IS_DISABLED() (ZG->zdo.handle.channel_update_disabled != 0U) - -/* Flag to set and check if channel update is disabled */ -#define ZB_ZDO_IS_REJOIN_SECURE() (ZG->zdo.handle.rejoin_ctx.secure_rejoin != 0U) - -typedef struct zb_zdo_pim_s -{ - zb_time_t fast_poll_interval; - zb_time_t fast_poll_timeout; - zb_time_t long_poll_interval; - zb_time_t turbo_poll_interval; - zb_time_t turbo_poll_min; - zb_time_t turbo_poll_max; - zb_time_t turbo_poll_timeout; - zb_time_t work_poll_max; - zb_time_t work_poll_interval; - zb_uint_t turbo_poll_n_packets; - zb_time_t first_poll_time; - zb_uint_t n_polls_per_data; - zb_time_t turbo_leave_alarm_time; -#ifdef SNCP_MODE - zb_callback_t single_poll_cb; /* set when executed Single Poll from Host */ -#endif - zb_bitbool_t turbo_prohibit:1; - zb_bitbool_t fast_poll_on:1; - zb_bitbool_t poll_in_progress:1; - zb_bitbool_t poll_stop:1; - zb_bitbool_t was_in_turbo_poll:1; /* special value to indicate that pkt was not received, - * the turbo poll should be restarted*/ -} zb_zdo_pim_t; - -/* Callback types */ -#define CB_TYPE_DEFAULT 0x00U -#define CB_TYPE_TSN 0x01U -#define CB_TYPE_INDEX 0x02U - -typedef ZB_PACKED_PRE struct zdo_cb_hash_ent_s -{ - zb_callback_t func; - zb_uint8_t tsn; - zb_uint8_t resp_counter; - zb_bitfield_t type:2; - zb_bitfield_t clock_counter:6; /*!< Used to track entry's life-time in hash */ -} ZB_PACKED_STRUCT zdo_cb_hash_ent_t; - -#define ZB_ZDO_CHECK_FAILS_MASK 1U /* flag to check if channel interference check is in progress */ -#define ZB_ZDO_SEND_WITH_ACK_MASK (1U << 1U) /* flag to specify sending with acknowledgement */ -#define ZB_ZDO_CHANNEL_CHANGED_MASK (1U << 2U) /* flag shows that channel change operation was performed recently (server side) */ -#define ZB_ZDO_TC_REJOIN_ENABLE_MASK (1U << 3U) /* flag that allows or disallows Trust Center Rejoin (Unsequred rejoin) */ -#define ZB_ZDO_UNAUTH_MASK (1U << 4U) /* indicates unauthenticated join case */ - -/* TODO: kill bitmasks here - use bitfields */ -#define ZB_ZDO_SET_CHECK_FAILS() (ZG->zdo.flags |= ZB_ZDO_CHECK_FAILS_MASK) -#define ZB_ZDO_CLEAR_CHECK_FAILS() (ZG->zdo.flags &= ~ZB_ZDO_CHECK_FAILS_MASK) -#define ZB_ZDO_GET_CHECK_FAILS() (ZG->zdo.flags & ZB_ZDO_CHECK_FAILS_MASK) - -#define ZB_ZDO_SET_SEND_WITH_ACK() (ZG->zdo.flags |= ZB_ZDO_SEND_WITH_ACK_MASK) -#define ZB_ZDO_CLEAR_SEND_WITH_ACK() (ZG->zdo.flags &= ~ZB_ZDO_SEND_WITH_ACK_MASK) -#define ZB_ZDO_GET_SEND_WITH_ACK() (ZG->zdo.flags & ZB_ZDO_SEND_WITH_ACK_MASK) - -#define ZB_ZDO_SET_CHANNEL_CHANGED() (ZG->zdo.flags |= ZB_ZDO_CHANNEL_CHANGED_MASK) -#define ZB_ZDO_CLEAR_CHANNEL_CHANGED() (ZG->zdo.flags &= ~ZB_ZDO_CHANNEL_CHANGED_MASK) -#define ZB_ZDO_GET_CHANNEL_CHANGED() (ZG->zdo.flags & ZB_ZDO_CHANNEL_CHANGED_MASK) - -#define ZB_ZDO_SET_UNAUTH() (ZG->zdo.flags |= ZB_ZDO_UNAUTH_MASK) -#define ZB_ZDO_CLEAR_UNAUTH() (ZG->zdo.flags &= ~ZB_ZDO_UNAUTH_MASK) -#define ZB_ZDO_GET_UNAUTH() (ZG->zdo.flags & ZB_ZDO_UNAUTH_MASK) -#ifdef ZB_ZDO_DENY_LEAVE_CONFIG -#define ZB_ZDO_SET_LEAVE_REQ_ALLOWED( v ) (ZG->zdo.leave_req_allowed = ( v )) -#endif -#define MAX_N_CLUSTER_FILTERS 2U - -typedef struct zdo_cluster_filters_s -{ - zb_uint_t n_filters; - zdo_cluster_filter_t filters[MAX_N_CLUSTER_FILTERS]; -} zdo_cluster_filters_t; - -struct zb_zdo_device_annce_s; -/*! @endcond */ - -#if defined ZB_JOINING_LIST_SUPPORT && defined ZB_ROUTER_ROLE -typedef struct zb_joining_list_ctx_s -{ - zb_joining_list_op_q_t operation_queue; - zb_callback_t current_op_cb; - zb_bool_t is_consistent; - zb_uint8_t update_id; - zb_uint16_t list_expiry_interval; /* mibIeeeExpiryInterval (minutes) - must be in mac PIB, - but the strict implementation isn't worth the effort for now */ - - /* context for zdo_nwk_joining_list_resp */ - zb_uint8_t tsn; - zb_uint16_t dst_addr; - zb_callback_t broadcast_confirm_cb; - zb_uint8_t original_buffer; - - /* context for announce */ - zb_uint8_t next_start_index; - zb_uint8_t current_list_size; - - /* context for request */ - zb_uint8_t prev_update_id; -} zb_joining_list_ctx_t; -#endif /* defined ZB_JOINING_LIST_SUPPORT && defined ZB_ROUTER_ROLE */ - -#if defined ZB_ZCL_SUPPORT_CLUSTER_WWAH -typedef ZB_PACKED_PRE struct -{ -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER - /* Flags and vars moved there from WWAH cluster ctx or used instead of direct access to WWZH cluster attributes. */ - zb_bitfield_t parent_classification_enabled:1; - zb_bitfield_t key_commands_broadcast_disallowed:1; /* note: allowed by default */ - zb_bitfield_t configuration_mode_disabled:1; /* note: enabled by default */ - zb_bitfield_t leave_without_rejoin_disallowed:1; /* note: allowed by default */ - zb_bitfield_t interpan_disabled:1; /* note: enabled by default */ - - /* ======= Survey Beacon related context ======= */ - /** - * @brief Reference to a buffer with Survey Beacons Response parameters - * - */ - zb_bufid_t survey_beacons_resp_ref; -#endif -} zb_zdo_hubs_context_t; -#endif /* ZB_ZCL_SUPPORT_CLUSTER_WWAH */ - -typedef zb_bool_t (*zb_zdo_match_desc_resp_handler_t)(zb_bufid_t); - -typedef struct zb_zdo_func_selector_s -{ - zb_zdo_match_desc_resp_handler_t match_desc_resp_handler; - zb_callback_t app_link_key_ind_handler; -} zb_zdo_func_selector_t; - -/** - ZDO_CTX structure - */ -typedef struct zb_zdo_globals_s -{ - zp_zdo_handle_t handle; /*!< */ - zb_uint8_t tsn; /*!< */ - zb_zdo_tsn_policy_t tsn_policy; /*!< see zb_zdo_tsn_policy_e */ -#ifdef ZBOSS_ZDO_APP_TSN_ENABLE - zdo_app_tsn_entry_t app_tsn_table[ZBOSS_ZDO_APP_TSN_TABLE_SIZE]; -#endif - zb_device_handler_t af_data_cb; /*!< Callback of zb_apsde_data_indication - * function */ - /*!< callback which called when ZDO command is sent (except cases when it - * failed to be sent, or when no answers are supposed - in such case ZDO - * callback passed to ZDO call is called) */ - zb_callback_t af_zdo_data_conf_cb; - zb_uint8_t max_parent_threshold_retry; /*!< */ - zb_uint8_t parent_threshold_retry; /*!< */ - zdo_cb_hash_ent_t zdo_cb[ZDO_TRAN_TABLE_SIZE]; /*!< */ -#ifndef ZB_LITE_NO_ZDO_SYSTEM_SERVER_DISCOVERY - zb_callback_t system_server_discovery_cb; /*!< Callback of System server discovery */ - zb_uint8_t system_server_discovery_tsn; /*!< */ -#endif -#ifndef ZB_LITE_NO_OLD_CB - zb_callback_t app_leave_cb; /*!< Indication for application that leave - * performed and no further actions scheduled*/ -#endif - zb_callback_t app_addr_resp_cb; /*!< Callback of zb_zdo_addr_resp_handle - * function */ - /* TODO: change flags to bitfields */ - zb_uint8_t flags; /*!< */ - zb_bitfield_t zdo_ed_scan_busy:1; -#ifdef ZB_ZDO_DENY_LEAVE_CONFIG - zb_bitfield_t leave_req_allowed:1; /*! allow/deny ZDO leave request */ -#endif - zb_uint8_t long_timer; /*!< Long timer, in minutes */ - zb_callback_t long_timer_cb; /*!< Callback for long timer */ - zb_uint8_t long_timer_param; /*!< Parameter for long timer */ -#ifdef ZB_ED_FUNC - zb_uint8_t parent_link_failure; /*!< */ -#endif - zb_uint16_t num_packets; /*!< Number of packets for diag purpose*/ - zb_uint16_t num_retries; /*!< Number of retries for diag purpose*/ - -#if defined ZB_COORDINATOR_ROLE || defined ZB_ROUTER_ROLE - zb_uint8_t permit_join_time; /*!< LAst permit join time in seconds */ -#endif - -#ifdef ZB_ROUTER_ROLE -/*NBT element to start parent_annce from */ - zb_uint8_t parent_annce_position; -#endif - -#if defined ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL - zb_af_inter_pan_handler_t af_inter_pan_data_cb; /*!< Application callback called when inter-pan packet is received */ -#endif - - zb_zdo_configuration_attributes_t conf_attr; /*!< Device Configuration - * Attributes */ - union zb_zdo_ctx_u - { - struct zb_nwk_upd_req_ctx_s - { - zb_uint8_t tsn; /*!< */ - zb_uint16_t dst_addr; /*!< */ - zb_callback_t cb; - zb_bitfield_t ed_scan_busy:1; - zb_bitfield_t enhanced:1; - } - nwk_upd_req; - struct zb_get_peer_short_addr_s - { - zb_address_ieee_ref_t dst_addr_ref; /*!< */ - zb_callback_t cb; /*!< */ - zb_uint8_t param; /*!< */ - } - get_short_addr_ctx; -#ifndef ZB_LITE_NO_END_DEVICE_BIND - struct zb_zdo_end_device_bind_ctx_s - { -#define ZB_ZDO_BIND_DEV_1 0U -#define ZB_ZDO_BIND_DEV_2 1U -#define ZB_ZDO_PEER_DEVICE_NUM(num) (((num) + 1U) % 2U) - - struct zb_zdo_bind_device_info_s - { - zb_uint8_t end_device_bind_param; /*!< Reference to buffer with - * end_device_bind_req command */ - zb_uint16_t binding_target; /*!< The address of the target for the binding */ - zb_uint8_t src_endp; /*!< The endpoint on the binding device */ - zb_uint16_t cluster_list[ZB_ZDO_MAX_CLUSTER_LIST]; /* matched clusters list */ - zb_uint8_t cluster_num; /*!< number of matched clusters, - * found during end device bind */ - } bind_device_info[2]; - zb_uint8_t current_device; /*!< current device to send bind/unbind requests */ - } - end_device_bind_ctx; -#endif /* #ifndef ZB_LITE_NO_END_DEVICE_BIND */ - } - zdo_ctx; /*!< */ - -#ifdef ZB_TEST_PROFILE - union zb_test_profile_ctx_u - { - struct zb_tp_counted_packets_s - { - zb_tp_transmit_counted_packets_param_t params; /*!< */ - zb_callback_t user_cb; /*!< */ - zb_uint16_t counter; /*!< */ - } - tp_counted_packets; - struct zb_tp_buffer_test_request_s - { - zb_callback_t user_cb; /*!< */ - } - zb_tp_buffer_test_request; - } - test_prof_ctx; -#endif - -#ifdef ZB_REJOIN_BACKOFF - zb_zdo_rejoin_backoff_t zdo_rejoin_backoff; -#endif - - zb_device_annce_cb_t device_annce_cb; /*!< This CB is called on receiving device_annce command */ - zb_callback_t leave_ind_cb; /*!< Callback for NWK leave indication from child */ - zb_zdo_responce_cb_t zb_zdo_responce_cb; - zb_zdo_set_channel_confirm_cb_t set_channel_confirm_cb; - zb_apsme_update_device_ind_cb update_device_ind_cb /*!< This callback will be called when application receives APSME_UPDATE_DEVICE */; -#ifdef ZB_MAC_DUTY_CYCLE_MONITORING - zb_zdo_duty_cycle_mode_ind_cb_t duty_cycle_mode_ind_cb; /*!< This callback will be called when MAC Duty Cycle mode changed */ -#endif - zb_assert_indication_cb_t assert_indication_cb; /*!< This callback will be called when application falls into ZB_ASSERT() */ - - zb_zdo_pim_t pim; - - zb_uint8_t nwk_upd_notify_pkt_limit; - -#ifndef ZB_CONFIGURABLE_MEM - zb_uint8_t nwk_addr_req_pending_tsns[ZB_N_BUF_IDS]; /* Address search feature: TSNs of nwk_addr_req pkt for - * every buffer */ - zb_uint8_t nwk_addr_req_pending_mask[(ZB_N_BUF_IDS + 7U) / 8U]; /* Address search feature: mask of pending pkt for - * every buffer */ -#else - /* Pointers are set in zb_init_configurable_mem() */ - zb_uint8_t *nwk_addr_req_pending_tsns; - zb_uint8_t *nwk_addr_req_pending_mask; -#endif /* ZB_CONFIGURABLE_MEM */ - -#ifdef APS_FRAGMENTATION -#ifndef ZB_CONFIGURABLE_MEM - zb_uint8_t node_desc_req_pending_mask[(ZB_N_BUF_IDS + 7U) / 8U]; /* Node Desc feature: mask of pending pkt for - * every buffer */ -#else - zb_uint8_t *node_desc_req_pending_mask; -#endif /* ZB_CONFIGURABLE_MEM */ -#endif /* APS_FRAGMENTATION */ - - zb_callback_t continue_start_after_nwk_cb; - zb_callback_t nlme_reset_cb; - -#ifdef ZB_FILTER_OUT_CLUSTERS - zdo_cluster_filters_t cluster_filters; -#endif - -#if defined ZB_JOINING_LIST_SUPPORT && defined ZB_ROUTER_ROLE - zb_joining_list_ctx_t joining_list_ctx; -#endif /* defined ZB_JOINING_LIST_SUPPORT && defined ZB_ROUTER_ROLE */ -#ifdef ZB_ZCL_SUPPORT_CLUSTER_WWAH - /* Part of WWAH context noved into SoC part of NCP / r23 All Hubs context */ - zb_zdo_hubs_context_t hubs_ctx; -#endif - -#if defined(ZDO_DIAGNOSTICS) - zdo_diagnostics_ctx_t diagnostics_ctx; -#endif /* defined(ZDO_DIAGNOSTICS) */ - - zb_zdo_func_selector_t selector; -#ifdef ZB_PHY_TESTING_MODE - zb_phy_test_mode_notification_cb_t test_mode_notification_cb; -#endif -} zb_zdo_globals_t; - - -#define ZDO_CTX() ZG->zdo - -#define ZDO_SELECTOR() ZDO_CTX().selector - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_WWAH -/* IN-core part of WWAH context / r23 All Hubs context */ -#define HUBS_CTX() ZDO_CTX().hubs_ctx -#endif /* ZB_ZCL_SUPPORT_CLUSTER_WWAH */ - -#if defined(ZDO_DIAGNOSTICS) -#define ZDO_DIAGNOSTICS_CTX() ZDO_CTX().diagnostics_ctx -#endif /* defined(ZDO_DIAGNOSTICS) */ - -#define ZB_ZDO_SET_ED_SCAN_BUSY() (ZG->zdo.zdo_ed_scan_busy = 1U) -#define ZB_ZDO_CLEAR_ED_SCAN_BUSY() (ZG->zdo.zdo_ed_scan_busy = 0U) -#define ZB_ZDO_GET_ED_SCAN_BUSY() ZG->zdo.zdo_ed_scan_busy - -/* Internally inside the stack use direct context access */ -#define ZB_SET_JOINED_STATUS(v) ZB_TCPOL().node_is_on_a_network = (v) - -/* Converts a buffer with data into a packed signal with the data */ -void zb_app_signal_pack_with_data(zb_uint8_t param, zb_uint32_t signal_code, zb_int16_t status); -/* Buffer is replaced with signal information, data_size bytes are reserved for additional signal data */ -void *zb_app_signal_pack(zb_uint8_t param, zb_uint32_t signal_code, zb_int16_t status, zb_uint8_t data_size); - -void *zb_app_signal_pack_with_detailed_status(zb_uint8_t param, zb_uint32_t signal_code, - zb_ret_t status, zb_uint8_t data_size); -/* NWK channel manager */ -void zb_zdo_check_channel_conditions(zb_uint8_t param); - -#if defined ZB_JOINING_LIST_SUPPORT && defined ZB_ROUTER_ROLE -zb_bool_t zb_ieee_joining_list_schedule(zb_callback_t func, zb_uint8_t param); -void zb_ieee_joining_list_cb_completed(void); -void zb_ieee_joining_list_op_delay(void); -zb_bool_t zb_ieee_joining_list_put_cb(zb_callback_t func, zb_uint8_t param); -void zb_joining_list_reset_clear_timer(void); -#endif /* defined ZB_JOINING_LIST_SUPPORT && defined ZB_ROUTER_ROLE */ - -void zb_zdo_forced_parent_link_failure(zb_uint8_t param); - -#ifdef SNCP_MODE -void zb_zdo_poll_parent_single(zb_uint8_t param, zb_callback_t cb); -#endif - -/*! @endcond */ - -#endif /* ZB_ZDO_GLOBALS_H */ diff --git a/zboss/development/src/include/zb_zdo_rjb.h b/zboss/development/src/include/zb_zdo_rjb.h deleted file mode 100644 index 58d56aca65..0000000000 --- a/zboss/development/src/include/zb_zdo_rjb.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Rejoin backoff -*/ - -#ifndef ZB_ZDO_REJOIN_BACKOFF_H -#define ZB_ZDO_REJOIN_BACKOFF_H 1 - -#ifdef ZB_REJOIN_BACKOFF - -#define ZB_ZDO_REJOIN_BACKOFF_MAX_TIMEOUT (30U*60U * ZB_TIME_ONE_SECOND) /* 30 minutes */ -#define ZB_ZDO_REJOIN_BACKOFF_MAX_COUNT 11U -#define ZB_ZDO_REJOIN_BACKOFF_TIMEOUT(_cnt) (((_cnt) == 11U) ? ZB_ZDO_REJOIN_BACKOFF_MAX_TIMEOUT : (1U << (_cnt)) * ZB_TIME_ONE_SECOND) /* timeout value: 2, 4, 8, ... */ - -enum zb_zdo_rejoin_backoff_state_e -{ - ZB_ZDO_REJOIN_BACKOFF_IDLE = 0, - ZB_ZDO_REJOIN_BACKOFF_TIMER_RUNNING, - ZB_ZDO_REJOIN_BACKOFF_COMMAND_SCHEDULED, - ZB_ZDO_REJOIN_BACKOFF_COMMAND_SENT, - ZB_ZDO_REJOIN_BACKOFF_COMMAND_DONE -}; - -/** Rejoin backoff context */ -typedef struct zb_zdo_rejoin_backoff_s -{ - enum zb_zdo_rejoin_backoff_state_e rjb_state; - zb_uint8_t rjb_cnt; - /* Determines whether device goes secure rejoin. */ - zb_bool_t rjb_do_secure; - /* If set to ZB_FALSE device will search on current channel only */ - zb_bool_t rjb_scan_all_chan_mask; - zb_bool_t rjb_insecure; - zb_channel_page_t rjb_chan_mask_list[ZB_CHANNEL_PAGES_NUM]; -} -zb_zdo_rejoin_backoff_t; - -/** Set ZB_ZDO_REJOIN_BACKOFF_COMMAND_DONE state. For internal use. */ -void zb_zdo_rejoin_backoff_iteration_done(void); - -#endif /* ZB_REJOIN_BACKOFF */ - -#endif /* ZB_ZDO_REJOIN_BACKOFF_H */ diff --git a/zboss/development/src/include/zboss_api_buf_legacy.h b/zboss/development/src/include/zboss_api_buf_legacy.h deleted file mode 100644 index d0434c393f..0000000000 --- a/zboss/development/src/include/zboss_api_buf_legacy.h +++ /dev/null @@ -1,780 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Public legacy packet buffers API -*/ -#ifndef ZBOSS_API_BUF_LEGACY_H -#define ZBOSS_API_BUF_LEGACY_H 1 - -/** - * @addtogroup bufleg - * @{ - * @par Pass parameters via packet buffers - * - * Usual sequence of the data send/receive primitives is aps-nwk-mac down and up packet pass. - * Packets passed not by direct function calls but via scheduler to limit used stack size. - * Callback has single parameter only. - * Pass packet buffer as parameter. - * When possible, pass parameters by filling lower layer header (it is possible for nwk-mac data primitive). - * But usually will need a place for some additional arguments. - * Will put it into packet tail. Does not formally 'allocate' space at packet tail - just use it. - * Packet must have size enough to keep biggest possible frame + parameters. - * Function for getting packet tail for parameters checks for overflow and move - * data left if it is possible to free space at packet buffer tail. - * - * Management calls have no data. All parameters passed via packet buffers. - * - * @par Blockable memory allocation, reaction on memory absence - * - * Main limited resource is RAM: controller has 16k only. - * - * RAM used for i/o (packet) buffers, routing tables, neighbor tables, (what else?) - * and smaller data structures. - * - * Packet buffers pool is common for in and out but its usage for In and Out is - * limited (50/50 initially, maybe, will tune it). The rationale is to prevent - * stack stop due to inability to send data due to buffers absence if all buffers - * "eaten" as input. - * - * Packet buffer allocation could be asynchronous operation - it means, allocate - * call does not return directly but via scheduler (callback call). It allows - * packet allocation to block. In general, all allocation inside stack are blocked. - * - * Output packets allocates at some upper layers (ZD0, ZCL, application etc). It - * packet pool is empty, it means some buffers are sitting in the output queue or - * indirect transmit queue waiting for send. When it will be sent and freed, - * allocation operation unblocks (callback calls) and goes thru. - * - * Input packets are always allocated in the MAC. If no space available, MAC receive - * blocks. It does not begin packet read if no space for it. If it blocks for a - * short time, it will be ok. If it blocks for long time, transceiver will probably - * skip next packet receive. Anyway, we will not split the packet: MAC transport - * will either have memory for entire packet or have no memory at all. - */ - -#ifdef ZB_LEGACY_BUFS - -#define zb_buf_t zb_leg_buf_t - - -/** - BIG Packet buffer header. - - Never used yet. - */ -typedef ZB_PACKED_PRE struct zb_bigbuf_hdr_s -{ - zb_uint16_t len; /*!< current layer buffer length */ - zb_uint16_t data_offset; /*!< data offset in buffer buf*/ - zb_uint8_t handle; /*!< The handle associated with the NSDU to be - * transmitted by the NWK layer entity. */ - zb_bitfield_t is_in_buf:1; /*!< if 1, this is input buffer */ - - zb_bitfield_t encrypt_type:3; /*!< payload must be encrypted before send, if - * !0. \see zb_secur_buf_encr_type_e. - */ - zb_bitfield_t use_same_key:1; /*!< if 1, use same nwk key# packet was - * encrypted by */ - zb_bitfield_t zdo_cmd_no_resp:1; /*!< if 1, this is ZDO command with no - * response - call callback at confirm */ - zb_bitfield_t is_rx_buf:1; /*!< if 1, this is buffer with received packet and - * nwk_mac_addrs_t is at buffer tail */ - zb_bitfield_t has_aps_payload:1; /*!< if 1, than packet comes from APS */ - - zb_int16_t status; /*!< some status to be passed with packet */ -} ZB_PACKED_STRUCT zb_bigbuf_hdr_t; - -/** - BIG Packet buffer - */ -#ifdef ZB_BIGBUF -typedef struct zb_bigbuf_s -{ - union - { - zb_bigbuf_hdr_t hdr; /*!< Buffer header, if buffer is used */ - //struct zb_bigbuf_s *next; /*!< Ref to next free buffer, if buffer is not used*/ - } u; /*!< Buffer header */ - //zb_uint8_t *buf; /*!< Dynamically allocated buffer for payload */ - zb_uint8_t *buf; /*!< Allocated buffer Data*/ - zb_uint16_t buf_len; /*!< Allocated buffer Len*/ - //zb_uint8_t flag; /*!< busy and other flags possible*/ -#ifdef ZB_DEBUG_BUFFERS_EXT - zb_buf_usage_t buf_allocation; - zb_buf_usage_t buf_usages[ZB_DEBUG_BUFFERS_EXT_USAGES_COUNT]; -#endif -} zb_bigbuf_t; -#endif /*ZB_BIGBUF*/ - -#define ZB_IS_BIGBUF(x) (((x)&0x80)>0) -#define ZB_BIGBUF_ID_FROM_REF(x) ((x)-0x80) -#define ZB_BIGBUF_REF_FROM_ID(x) ((x)+0x80) -/** - * @brief Return pointer to the beginning of the buffer - * - * @param zbbuf - pointer to buffer @ref zb_buf_t - * - * @return pointer to beginning of buffer - * - * @note see @ref ZB_BUF_BEGIN(), which returns pointer to the beginning of data written - */ -#define ZB_BUF_GET_ARRAY_PTR(zbbuf) ((zbbuf)->buf) - -#ifdef ZB_BUF_SHIELD - -zb_bool_t zb_buf_check_full(zb_int_t file_id,zb_uint8_t param); - - -#define ZB_BUF_CHECK_INLINE(param) \ - ZB_INLINE_ASSERT(zb_buf_check_full(ZB_TRACE_FILE_ID, param)) - -#define ZB_BUF_CHECK(param) ZB_ASSERT(zb_buf_check_full(ZB_TRACE_FILE_ID, param)) - -#else - -#define ZB_BUF_CHECK(param) -#define ZB_BUF_CHECK_INLINE(param) - -#endif - -/* Function prototypes. - Do not use it directly. Use macro instead. - */ -#ifdef ZB_BIGBUF -zb_uint8_t zb_add_bigbuf(zb_uint8_t *data, uint16_t size); -zb_bigbuf_t *zb_get_bigbuf( -#ifdef ZB_DEBUG_BUFFERS - zb_uint16_t from_file, zb_uint16_t from_line, -#endif - zb_uint8_t priority); -#endif - -/** - * @copydoc ZB_BUF_BEGIN() - * - * @param file_id - TRACE_ID of the file from which function is invoked - * - * @note don't call it directly, use @ref ZB_BUF_BEGIN() instead - */ -zb_uint8_t* zb_buf_begin_leg(TRACE_PROTO zb_buf_t *zbbuf); - - -/** - * @copydoc ZB_BUF_LEN() - * - * @param file_id - TRACE_ID of the file from which function is invoked - * - * @note don't call it directly, use @ref ZB_BUF_LEN() instead - */ -#ifdef ZB_BIGBUF -zb_uint16_t zb_buf_len_leg(TRACE_PROTO zb_buf_t *zbbuf); -#else - zb_uint8_t zb_buf_len_leg(TRACE_PROTO zb_buf_t *zbbuf); -#endif - -/** - Get IN buffer from the buffers list. - If no buffers available, does not block. - - @return pointer to the buffer or NULL if no buffer available. - */ -#ifdef ZB_DEBUG_BUFFERS -zb_buf_t *zb_get_in_buf(zb_uint16_t from_file, zb_uint16_t from_line); - -/** - Get IN buffer from the buffers list. - If no buffers available, does not block. - - @return pointer to the buffer or NULL if no buffer available. - */ -#define ZB_GET_IN_BUF() zb_get_in_buf(ZB_TRACE_FILE_ID, __LINE__) -#else -zb_buf_t *zb_get_in_buf(void); - -/** - Get IN buffer from the buffers list. - If no buffers available, does not block. - - @return pointer to the buffer or NULL if no buffer available. - */ -#define ZB_GET_IN_BUF() zb_get_in_buf() -#endif - -/** - Get OUT buffer from the buffers list. - If no buffers available, does not block. - @return pointer to the buffer. - */ -#ifdef ZB_DEBUG_BUFFERS -zb_buf_t *zb_get_out_buf(zb_uint16_t from_file, zb_uint16_t from_line); - -/** - Get OUT buffer from the buffers list. - If no buffers available, does not block. - @return pointer to the buffer. - */ -#define ZB_GET_OUT_BUF() zb_get_out_buf(ZB_TRACE_FILE_ID, __LINE__) -#else -zb_buf_t *zb_get_out_buf(void); - -/** - Get OUT buffer from the buffers list. - If no buffers available, does not block. - @return pointer to the buffer. - */ -#define ZB_GET_OUT_BUF() zb_get_out_buf() -#endif -/** @endcond */ /* internals_doc */ - - -/** - * @copydoc ZB_BUF_FROM_REF() - * - * @note Don't call it directly, use @ref ZB_BUF_FROM_REF() instead. - * - * @param from_file - TRACE_ID of the file from which function is invoked - * @param from_line - line from which function is invoked - */ -zb_buf_t* zb_buf_from_ref(zb_uint8_t ref, zb_uint16_t from_file, zb_uint16_t from_line); - -/** - * Calculate pointer of the buffer by buffer reference. - * - * @param ref - buffer reference - * - * @return pointer to buffer header -*/ -#ifdef ZB_USE_STD_MALLOC -#define ZB_BUF_FROM_REF(ref) (ZG->bpool.pool[ref]) -#else -#define ZB_BUF_FROM_REF(ref) (zb_buf_from_ref((ref), ZB_TRACE_FILE_ID, __LINE__)) -#endif - -#ifdef ZB_USE_STD_MALLOC -#define ZB_REF_FROM_BUF(buf) get_buf_ref(buf) -#else - -/** - * @copydoc ZB_REF_FROM_BUF() - * - * @note don't call it directly, use @ref ZB_REF_FROM_BUF() instead - */ -zb_uint8_t zb_ref_from_buf(zb_buf_t *buf); - -/** - * @brief get buffer reference which can be passed to scheduler callback - * - * @param buf - buffer of interest - * - * @return reference to buffer - */ -#define ZB_REF_FROM_BUF(buf) zb_ref_from_buf(buf) - -#endif - - -/** - * @brief get buffer reference which can be passed to scheduler callback - * - * @param ptr - direct pointer to buffer's content - * - * @return reference to buffer - */ -#if defined ZB_USE_STD_MALLOC && defined ZB_USE_ALLOC_FOR_PAYLOAD_DATA -#error This macro still needs to be implemented! -#else -#define ZB_REF_FROM_BUF_PTR(ptr) ZB_REF_FROM_BUF((zb_buf_t*)(void*)((zb_int8_t *)(ptr) - ZB_OFFSETOF(zb_buf_t, buf))) -#endif - - -/** - * Return pointer to data stored in buffer - * - * @param zbbuf - buffer - * - * @return pointer to beginning of data in buffer - * - * @note see @ref ZB_BUF_GET_ARRAY_PTR() which returns beginning of buffer - */ -#define ZB_BUF_BEGIN(zbbuf) zb_buf_begin_leg(TRACE_CALL zbbuf) - -/** - * Return current buffer length - * - * @param zbbuf - pointer to buffer - * - * @return size of data placed in buffer - */ - -#define ZB_BUF_LEN(zbbuf) zb_buf_len_leg(TRACE_CALL zbbuf) - -/** - Return current buffer length by buffer reference. - */ -#define ZB_BUF_LEN_BY_REF(param) ZB_BUF_LEN(ZB_BUF_FROM_REF(param)) - -/** - Return pointer to data stored in buffer by buffer reference. - */ -#define ZB_BUF_BEGIN_FROM_REF(_ref) ZB_BUF_BEGIN(ZB_BUF_FROM_REF(_ref)) - -/** - * @copydoc ZB_BUF_COPY() - * - * @note don't call it directly, use @ref ZB_BUF_COPY() instead - */ -void zb_buf_copy_leg(TRACE_PROTO zb_buf_t *dst_buf, zb_buf_t *src_buf); - -/** - Copy one buffer to another - - @param src_buf - source buffer - @param dst_buf - destination buffer - */ -#define ZB_BUF_COPY(dst_buf, src_buf) zb_buf_copy_leg(TRACE_CALL dst_buf, src_buf) - -/** - * @copydoc ZB_BUF_OFFSET() - * - * @param file_id - TRACE_ID of the file from which function is invoked - * - * @note don't call it directly, use @ref ZB_BUF_OFFSET() instead - */ -#ifdef ZB_BIGBUF -zb_uint16_t zb_buf_offset(zb_int_t file_id, zb_buf_t *zbbuf); -#else -zb_uint8_t zb_buf_offset(zb_int_t file_id, zb_buf_t *zbbuf); -#endif - -/** - * Return current buffer offset - * - * @param zbbuf - pointer to buffer - * - * @return offset of the data in the buffer - */ -#define ZB_BUF_OFFSET(zbbuf) zb_buf_offset(ZB_TRACE_FILE_ID, zbbuf) - - -void zb_buf_clear_param(zb_buf_t *zbbuf); - -/** - * Clear param area in buffer - * - * @param zbbuf - pointer to buffer - */ -#define ZB_BUF_CLEAR_PARAM(zbbuf) zb_buf_clear_param(zbbuf) - -/** - * @copybrief ZB_BUF_INITIAL_ALLOC() - * - * @param zbbuf - buffer - * @param size - size to allocate - * - * @note don't call it directly, use @ref ZB_BUF_INITIAL_ALLOC() instead - */ -#ifdef ZB_BIGBUF -void *zb_buf_initial_alloc_leg(TRACE_PROTO zb_buf_t *zbbuf, zb_uint16_t size); -#else -void *zb_buf_initial_alloc_leg(TRACE_PROTO zb_buf_t *zbbuf, zb_uint8_t size); -#endif - -/** - @brief Initial space allocation in buffer. - - Allocate space in the buffer center (keep space in both buffer head - and tail). Use it at upper layers before filling buffer by data. - Old buffer contents is lost. - - @param zbbuf - buffer - @param size - size to allocate - @param ptr - (out) pointer to the new buffer begin - - @return pointer to the allocated space - */ -#define ZB_BUF_INITIAL_ALLOC(zbbuf, size, ptr) (ptr) = zb_buf_initial_alloc_leg(TRACE_CALL (zbbuf), (size)) - -/** - * @copybrief ZB_BUF_ALLOC_LEFT() - * - * @param zbbuf - buffer - * @param size - size to allocate - * - * @note don't call it directly, use @ref ZB_BUF_ALLOC_LEFT() instead -*/ -#ifdef ZB_BIGBUF -void *zb_buf_smart_alloc_left(zb_buf_t *zbbuf, zb_uint16_t size); -#else -void *zb_buf_smart_alloc_left(zb_buf_t *zbbuf, zb_uint8_t size); -#endif - -/** - * Allocate space at the beginning of buffer - * - * @param zbbuf - buffer - * @param size - size to allocate - * @param ptr - (out) pointer to the new buffer begin - */ -#define ZB_BUF_ALLOC_LEFT(zbbuf, size, ptr) (ptr) = zb_buf_smart_alloc_left((zbbuf), (size)) - -/** - * @copybrief ZB_BUF_ALLOC_RIGHT() - * - * @param zbbuf - buffer - * @param size - size to allocate - * - * @note don't call it directly, use @ref ZB_BUF_ALLOC_RIGHT() instead - */ -#ifdef ZB_BIGBUF -void *zb_buf_smart_alloc_right(zb_buf_t *zbbuf, zb_uint16_t size); -#else -void *zb_buf_smart_alloc_right(zb_buf_t *zbbuf, zb_uint8_t size); -#endif - -/** - Allocate space at buffer end - - @param zbbuf - buffer - @param size - size to allocate - @param ptr - (out) pointer to the space allocated - */ -#define ZB_BUF_ALLOC_RIGHT(zbbuf, size, ptr) (ptr) = zb_buf_smart_alloc_right((zbbuf), (size)) - -/** - * @copybrief ZB_BUF_CUT_LEFT() - * - * @param zbbuf - buffer - * @param size - size to cut - * - * @note don't call it directly, use @ref ZB_BUF_CUT_LEFT() instead - */ -#ifdef ZB_BIGBUF -void *zb_buf_cut_left_leg(zb_buf_t *zbbuf, zb_uint16_t size); -#else -void *zb_buf_cut_left_leg(zb_buf_t *zbbuf, zb_uint8_t size); -#endif - -/** - * Cut space at the beginning of buffer - * - * @param zbbuf - buffer - * @param size - size to cut - * @param ptr - (out) pointer to the new buffer begin -*/ -#define ZB_BUF_CUT_LEFT(zbbuf, size, ptr) (ptr) = zb_buf_cut_left_leg((zbbuf), (size)) - -#ifdef ZB_BIGBUF -void zb_buf_cut_left2(zb_int_t file_id, zb_buf_t *zbbuf, zb_uint16_t size); -#else -void zb_buf_cut_left2(zb_int_t file_id, zb_buf_t *zbbuf, zb_uint8_t size); -#endif -#define ZB_BUF_CUT_LEFT2(zbbuf, size) zb_buf_cut_left2(ZB_TRACE_FILE_ID, zbbuf, size) - -/** - * @copybrief ZB_BUF_CUT_RIGHT() - * - * @param zbbuf - buffer - * @param size - size to cut - * - * @note don't call it directly, use @ref ZB_BUF_CUT_RIGHT() instead - */ -#ifdef ZB_BIGBUF -void zb_buf_cut_right_leg(zb_buf_t *zbbuf, zb_uint16_t size); -#else -void zb_buf_cut_right_leg(zb_buf_t *zbbuf, zb_uint8_t size); -#endif - -/** - * Cut space at the end of buffer - * - * @param zbbuf - buffer - * @param size - size to cut - */ -#define ZB_BUF_CUT_RIGHT(zbbuf, size) zb_buf_cut_right_leg((zbbuf), (size)) - -/** - * @copydoc ZB_GET_BUF_TAIL() - * - * @note don't call directly, use @ref ZB_GET_BUF_TAIL() instead - */ -#ifdef ZB_BIGBUF -void *zb_get_buf_tail(zb_buf_t *zbbuf, zb_uint16_t size); -#else -void *zb_get_buf_tail(zb_buf_t *zbbuf, zb_uint8_t size); -#endif - -/** - Get buffer tail of size 'size' - - Usually used to place external information (some parameters) to the buffer. - - @param zbbuf - buffer - @param size - requested size - - @return pointer to the buffer tail - */ -#define ZB_GET_BUF_TAIL(zbbuf, size) zb_get_buf_tail(zbbuf, size) - -/** - Get buffer tail of size sizeof(type) - - Usually used to place external information (some parameters) to the buffer - - @param zbbuf - buffer - @param type - data type that will be placed at the buffer end - - @return pointer to the buffer tail casted to (type*) - - @b Example - @code - zb_zdo_nwk_addr_req_param_t *req = ZB_GET_BUF_PARAM(buf, zb_zdo_nwk_addr_req_param_t); - - req->dst_addr = 0xffff; - ZB_IEEE_ADDR_COPY(req->ieee_addr, g_ieee_addr_r4); - req->start_index = 0; - req->request_type = 0x00; - zb_zdo_nwk_addr_req(ZB_REF_FROM_BUF(buf), NULL); - @endcode - */ -#define ZB_GET_BUF_PARAM(zbbuf, type) ((type *)ZB_GET_BUF_TAIL((zbbuf), sizeof(type))) - -/** - Place data of size sizeof(type) at the end of buffer - - Macro used to copy external information (some data) at the - end of buffer - - @param zbbuf - buffer - @param param - data to be placed in the end of buffer - @param type - data type that will be placed at the buffer end - - @b Example - @code - zb_zdo_nwk_addr_req_param_t req; - - req.dst_addr = 0xffff; - ZB_IEEE_ADDR_COPY(req.ieee_addr, g_ieee_addr_r4); - req.start_index = 0; - req.request_type = 0x00; - ZB_SET_BUF_PARAM(buf, req, zb_zdo_nwk_addr_req_param_t); - zb_zdo_nwk_addr_req(ZB_REF_FROM_BUF(buf), NULL); - @endcode - */ - #define ZB_SET_BUF_PARAM(zbbuf, param, type) (ZB_BUF_IS_BUSY_INLINE(ZB_REF_FROM_BUF(zbbuf)) *((type *)ZB_GET_BUF_TAIL(zbbuf, sizeof(type))) = (param) ) - -/** - Place data of size sizeof(type) at the end of buffer - - Macro used to copy external information (some data) at the end - of buffer - - @param zbbuf - buffer - @param param - data to be placed in the end of buffer - @param type - data type that will be placed at the buffer end - */ -#define ZB_SET_BUF_PARAM_PTR(zbbuf, param, type) ( ZB_MEMCPY((type *)ZB_GET_BUF_TAIL(zbbuf, sizeof(type)), (param), sizeof(type)) ) - -/** - * @copydoc ZB_BUF_REUSE() - * - * @note Don't call directly, use ZB_BUF_REUSE() instead - */ -void zb_buf_reuse_leg( -#ifdef ZB_DEBUG_BUFFERS - zb_uint16_t from_file, zb_uint16_t from_line, -#endif - zb_buf_t *zbbuf); - -/** - * @brief Reuse previously used buffer - * - * @param zbbuf - buffer - */ -#ifdef ZB_DEBUG_BUFFERS -#define ZB_BUF_REUSE(zbbuf) zb_buf_reuse_leg(ZB_TRACE_FILE_ID, __LINE__, zbbuf) -#else -#define ZB_BUF_REUSE(zbbuf) zb_buf_reuse_leg(zbbuf) -#endif - - -/** - * @copydoc ZB_FREE_BUF() - * - * @note Don't call it directly, use @ref ZB_FREE_BUF() instead - */ -void zb_free_buf(TRACE_PROTO zb_buf_t *buf); - -/** - * @brief Free packet buffer and put it into freelist. - * - * Can be called from the main loop. - * - * @param buf - packet buffer. - * - */ -#define ZB_FREE_BUF(buf) zb_free_buf_leg(buf) - -#define ZB_FREE_BUF_BY_REF(param) \ -do { \ - if(param) \ - { \ - zb_free_buf(ZB_BUF_FROM_REF(param)); \ - } \ -} while(0) - -/** - * @copydoc ZB_GET_IN_BUF_DELAYED() - * - * @note Don't call it directly, use @ref ZB_GET_IN_BUF_DELAYED() instead - */ -zb_ret_t zb_get_in_buf_delayed( -#ifdef ZB_DEBUG_BUFFERS - zb_uint16_t from_file, zb_uint16_t from_line, -#endif - zb_callback_t callback); - -/** - * @brief Allocate IN buffer, call a callback when the buffer is available. - * - * If buffer is available, schedules callback for execution immediately. If no buffers are available now, - * schedule callback later, when buffer will be available. - * - * @param callback to call. - * @return RET_OK or error code. - * - * @code - * ZB_GET_IN_BUF_DELAYED(new_buffer_allocated); - * @endcode - */ -#ifdef ZB_DEBUG_BUFFERS -#define ZB_GET_IN_BUF_DELAYED(callback) zb_get_in_buf_delayed(ZB_TRACE_FILE_ID, __LINE__, callback) -#else -#define ZB_GET_IN_BUF_DELAYED(callback) zb_get_in_buf_delayed(callback) -#endif - -/** - * @copydoc ZB_GET_OUT_BUF_DELAYED() - * - * @note Don't call it directly, use @ref ZB_GET_OUT_BUF_DELAYED() instead - */ -zb_ret_t zb_get_out_buf_delayed( -#ifdef ZB_DEBUG_BUFFERS - zb_uint16_t from_file, zb_uint16_t from_line, -#endif - zb_callback_t callback); - -/** - * @brief Allocate OUT buffer, call a callback when the buffer is available. - * - * If buffer is available, schedules callback for execution immediately. If no buffers are available now, - * schedule callback later, when buffer will be available. - * - * @param callback to call. - * @return RET_OK or error code. - * - * @code - * ZB_GET_OUT_BUF_DELAYED(new_buffer_allocated); - * @endcode - */ -#ifdef ZB_DEBUG_BUFFERS -#define ZB_GET_OUT_BUF_DELAYED(callback) zb_get_out_buf_delayed(ZB_TRACE_FILE_ID, __LINE__, callback) -#else -#define ZB_GET_OUT_BUF_DELAYED(callback) zb_get_out_buf_delayed(callback) -#endif - -/** - * @brief Allocate buffer of given type and call a callback with extra user parameter - * when buffer of this type is available. - * - * If buffer is available, schedules callback for execution immediately. If no buffers are available now, - * schedule callback later, when buffer will be available. - * - * @note Don't call it directly, use @ref ZB_GET_OUT_BUF_DELAYED2() (for out buffers) instead - * - * @param callback - callback to call - * @param buf_type - buffer type (either input or output) - * @param use_2_param - whether additional param is used - * @param user_param - will be passed to callback. - * - * @return RET_OK or error code. - */ -zb_ret_t zb_get_buf_delayed_2param( -#ifdef ZB_DEBUG_BUFFERS - zb_uint16_t from_file, zb_uint16_t from_line, -#endif - zb_callback2_t callback, - zb_uint8_t buf_type, - zb_bool_t use_2_param, - zb_uint16_t user_param); - -/** - * @brief Allocate out buffer, call a callback with extra user parameter when the buffer is available. - * - * If buffer is available, schedules callback for execution immediately. If no buffers are available now, - * schedule callback later, when buffer will be available. - * - * @param callback - callback to call - * @param user_param - will be passed to callback. - * - * @return RET_OK or error code. - * - * @code - * ZB_GET_OUT_BUF_DELAYED2(new_buffer_allocated, user_data); - * @endcode - */ -#ifdef ZB_DEBUG_BUFFERS -#define ZB_GET_OUT_BUF_DELAYED2(callback, user_param) zb_get_buf_delayed_2param(ZB_TRACE_FILE_ID, __LINE__, callback, ZB_OUT_BUFFER, ZB_TRUE, user_param) -#else -#define ZB_GET_OUT_BUF_DELAYED2(callback, user_param) zb_get_buf_delayed_2param(callback, ZB_OUT_BUFFER, ZB_TRUE, user_param) -#endif -/** @cond internals_doc */ - - -/** - Do nothing in ZB_SWITCH_BUF - */ -#define ZB_SWITCH_BUF(buf, to_in) - - -/*! @} */ - -#endif /* #ifdef ZB_LEGACY_BUFS */ - -#endif /* ZBOSS_API_BUF_LEGACY_H */ diff --git a/zboss/development/src/include/zboss_api_error.h b/zboss/development/src/include/zboss_api_error.h deleted file mode 100644 index 5692dafcdb..0000000000 --- a/zboss/development/src/include/zboss_api_error.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZBOSS error API header. Error handling API. -*/ - -#ifndef ZB_ZBOSS_API_ERROR_H -#define ZB_ZBOSS_API_ERROR_H 1 - -#define ZB_ERROR_SEVERITY_MINOR 0x01 -#define ZB_ERROR_SEVERITY_MAJOR 0xFE -#define ZB_ERROR_SEVERITY_FATAL 0xFF - -typedef struct zb_verify_additional_info_s { - zb_uint16_t file_id; - zb_int_t line_number; - void *caller_additional_info; -} zb_verify_additional_info_t; - -/** - * @brief Definition of error handler. It must be registered by application using - * @ref zb_error_register_app_handler . - * - * @note Severity @ref ZB_ERROR_SEVERITY_FATAL is excusive for errors raised by ZB_VERIFY - * or ZB_VERIFY_INFO - * - * @note If the registered callback is called with severity @ref ZB_ERROR_SEVERITY_FATAL , - * the argument additional_info will point to a structure of type - * @ref zb_verify_additional_info_t , in which its parameter @ref caller_additional_info - * will point to the original additional info used by the caller in @ref ZB_VERIFY_INFO - * (or NULL, in case of @ref ZB_VERIFY) - * - * @param severity severity level of the error - * @param error_code error code being raised - * @param additional_info additional error-dependent info - */ -typedef zb_bool_t (*zb_error_handler_t)(zb_uint8_t severity, - zb_ret_t error_code, - void *additional_info); - -typedef struct zb_error_indication_ctx_s -{ - zb_error_handler_t app_err_handler; -} zb_error_indication_ctx_t; - -/** - * Set application error handler. - * - * @param cb - an error handler to setAddr - */ -void zb_error_register_app_handler(zb_error_handler_t cb); - -/** - Verify: Raise error and interrupt application - - @param file_id source file id - @param line_number line in the source - @param error_code error code to be used - @param additional_info any additional error-dependent info -*/ -ZB_NORETURN void zb_verify(zb_uint16_t file_id, zb_int_t line_number, zb_ret_t error_code, void *additional_info); -/** - Check for expression in runtime and call zb_verify() if it is false. - - @param condition expression to check - @param error_code error code to be used if the expression is false - @param additional_info any additional error-dependent info -*/ -#define ZB_VERIFY_INFO(condition, error_code, additional_info) {if(!(condition)) { zb_verify(ZB_TRACE_FILE_ID, __LINE__, error_code, additional_info);} } - -/** - Check for expression in runtime and call zb_verify() if it is false. - - @param condition expression to check - @param error_code error code to be used if the expression is false - @ref ERROR_CODE macro -*/ -#define ZB_VERIFY(condition, error_code) ZB_VERIFY_INFO(condition, error_code, NULL) - -#endif /* ZB_ZBOSS_API_ERROR_H */ diff --git a/zboss/development/src/include/zcl/zcl_ota_upgrade_commands.h b/zboss/development/src/include/zcl/zcl_ota_upgrade_commands.h deleted file mode 100644 index aea5563864..0000000000 --- a/zboss/development/src/include/zcl/zcl_ota_upgrade_commands.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL OTA Upgrade cluster specific command declarations -*/ - -#ifndef ZCL_OTA_UPGRADE_COMMANDS_H -#define ZCL_OTA_UPGRADE_COMMANDS_H 1 - -#endif /* ZCL_OTA_UPGRADE_COMMANDS_H */ diff --git a/zboss/development/src/include/zdo_diagnostics.h b/zboss/development/src/include/zdo_diagnostics.h deleted file mode 100644 index 6891db3c64..0000000000 --- a/zboss/development/src/include/zdo_diagnostics.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Diagnostics cluster definitions -*/ - -#ifndef ZDO_DIAGNOSTICS_H -#define ZDO_DIAGNOSTICS_H 1 - -#if defined(ZDO_DIAGNOSTICS) || defined(DOXYGEN) - -#include "zboss_api_internal.h" - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** @addtogroup ZB_ZCL_DIAGNOSTICS - * @{ - * @details - * ZCL Diagnostics cluster definitions - */ - - -/* Cluster ZB_ZCL_CLUSTER_ID_DIAGNOSTICS */ - -/*! @name Diagnostics cluster attributes - @{ -*/ - -typedef ZB_PACKED_PRE struct zdo_diagnostics_ctx_s -{ - zdo_diagnostics_info_t diagnostics_info; - zb_callback_t get_stats_cb; -} ZB_PACKED_STRUCT zdo_diagnostics_ctx_t; - -typedef ZB_PACKED_PRE struct zdo_diagnostics_full_stats_s -{ - zb_mac_diagnostic_info_t mac_stats; - zdo_diagnostics_info_t zdo_stats; - zb_uint8_t status; -} ZB_PACKED_STRUCT zdo_diagnostics_full_stats_t; - -/*! @brief Diagnostics cluster attribute identifiers - @see HA spec, Diagnostics Cluster 9.3.2.2.2 -*/ -typedef enum zdo_diagnostics_counter_id_e -{ - /** @brief number_of_resets, Zigbee Diagnostic Cluster spec 1.2.2.1.1 */ - ZDO_DIAGNOSTICS_NUMBER_OF_RESETS_ID = 0, - /** This attribute keeps track of the number of writes to persistent memory. */ - ZDO_DIAGNOSTICS_PERSISTENT_MEMORY_WRITES_ID = 1, - /** APSRxBcast Attribute A counter that is incremented each time - * the APS layer receives a broadcast. */ - ZDO_DIAGNOSTICS_APS_RX_BCAST_ID = 2, - /** @brief aps_tx_bcast, HA spec 9.3.2.2.2 */ - ZDO_DIAGNOSTICS_APS_TX_BCAST_ID = 3, - /** APSRxUcast Attribute A counter that is incremented each time - * the APS layer receives a unicast. */ - ZDO_DIAGNOSTICS_APS_RX_UCAST_ID = 4, - /** @brief aps_tx_ucast_success, HA spec 9.3.2.2.2 */ - ZDO_DIAGNOSTICS_APS_TX_UCAST_SUCCESS_ID = 5, - /** APSTxUcastRetry Attribute A counter that is incremented each time - * the APS layer retries the sending of a unicast. */ - ZDO_DIAGNOSTICS_APS_TX_UCAST_RETRY_ID = 6, - /** @brief aps_tx_ucast_fail, HA spec 9.3.2.2.2 */ - ZDO_DIAGNOSTICS_APS_TX_UCAST_FAIL_ID = 7, - /** RouteDiscInitiated Attribute. A counter that is incremented each time the - * network layer submits a route discovery message to the MAC. HA spec 9.2.2.2.2.13 */ - ZDO_DIAGNOSTICS_ROUTE_DISC_INITIATED_ID = 8, - /** NeighborAdded Attribute A counter that is incremented each time - * an entry is added to the neighbor table. */ - ZDO_DIAGNOSTICS_NEIGHBOR_ADDED_ID = 9, - /** NeighborRemoved Attribute A counter that is incremented each time - * an entry is removed from the neighbor table. */ - ZDO_DIAGNOSTICS_NEIGHBOR_REMOVED_ID = 10, - /** A counter that is incremented each time a neighbor table entry becomes stale - * because the neighbor has not been heard from. */ - ZDO_DIAGNOSTICS_NEIGHBOR_STALE_ID = 11, - /** @brief join_indication, HA spec 1.2.2.2.17 */ - ZDO_DIAGNOSTICS_JOIN_INDICATION_ID = 12, - /** A counter that is incremented each time an entry is removed from the child table. */ - ZDO_DIAGNOSTICS_CHILD_MOVED_ID = 13, - /** A counter that is incremented each time a message is dropped at the network - * layer because the APS frame counter was not higher than the last message seen - * from that source. */ - ZDO_DIAGNOSTICS_NWKFC_FAILURE_ID = 14, - /** A counter that is incremented each time a message is dropped at the APS layer - * because the APS frame counter was not higher than the last message seen from - * that source. */ - ZDO_DIAGNOSTICS_APSFC_FAILURE_ID = 15, - /** A counter that is incremented each time a message is dropped at the APS layer - * because it had APS encryption but the key associated with the sender has - * not been authenticated, and thus the key is not authorized for use - * in APS data messages. */ - ZDO_DIAGNOSTICS_APS_UNAUTHORIZED_KEY_ID = 16, - /** A counter that is incremented each time a NWK encrypted message was received - * but dropped because decryption failed. */ - ZDO_DIAGNOSTICS_NWK_DECRYPT_FAILURES_ID = 17, - /** A counter that is incremented each time an APS encrypted message was received - * but dropped because decryption failed. */ - ZDO_DIAGNOSTICS_APS_DECRYPT_FAILURES_ID = 18, - /** @brief average_mac_retry_per_aps_message_sent, HA spec 9.3.2.2.2.27 */ - ZDO_DIAGNOSTICS_PACKET_BUFFER_ALLOCATE_FAILURES_ID = 19, - /** A counter that is incremented each time a unicast packet is relayed. */ - ZDO_DIAGNOSTICS_RELAYED_UCAST_ID = 20, - ZDO_DIAGNOSTICS_PHYTOMACQUEUELIMITREACHED_ID = 21, - /** A counter that is incremented each time a packet was dropped due to a packet - * validation error. This could be due to length or other formatting problems - * in the packet. */ - ZDO_DIAGNOSTICS_PACKET_VALIDATEDROPCOUNT_ID = 22, - /** @brief PacketBufferAllocateFeatures, Zigbee Diagnostic Cluster spec 1.2.2.2.24 */ - ZDO_DIAGNOSTICS_AVERAGE_MAC_RETRY_PER_APS_ID = 23, -#ifdef ZB_ENABLE_NWK_RETRANSMIT - /** A counter that is incremented on the NWK layer - * each time tries number of a packet resending are gone. - * - * @note It's a non-standard counter that depends on ZB_ENABLE_NWK_RETRANSMIT and - * will be zero always when the macro isn't set. */ - ZDO_DIAGNOSTICS_NWK_RETRY_OVERFLOW_ID = 24, -#endif /* ZB_ENABLE_NWK_RETRANSMIT */ - /** A non-standard counter of the number of times the NWK broadcast was dropped - * because the broadcast table was full. */ - ZDO_DIAGNOSTICS_NWK_BCAST_TABLE_FULL = 25 -} zdo_diagnostics_counter_id_t; - -/*! @} */ /* Diagnostics cluster attributes */ - - -/** @cond internals_doc */ -/*! @brief Increment diagnostic attribute - @param attr_id - attribute Id, see @ref zdo_diagnostics_counter_id_e -*/ -#ifdef ZDO_DIAGNOSTICS_DEBUG_TRACE -void zdo_diagnostics_inc(zdo_diagnostics_counter_id_t counter_id, zb_uint_t trace_file_id, zb_uint_t trace_line); -#else -void zdo_diagnostics_inc(zdo_diagnostics_counter_id_t counter_id); -#endif - -/*! @brief Increment ZDO_DIAGNOSTICS_ROUTE_DISC_INITIATED_ID diagnostics counter - @param param - buffer Id, verifies that it contains the NWK Command - and the NWK Command == ZB_NWK_CMD_ROUTE_REQUEST -*/ -void zdo_diagnostics_route_req_inc(zb_uint8_t param); - -/** - * @brief Get full statistics from ZDO and MAC. @see zdo_diagnostics_full_stats_t - * - * @note Don't call this function directly! - * Use @ZDO_DIAGNOSTICS_GET_STATS or @ZDO_DIAGNOSTICS_GET_AND_CLEANUP_STATS - * - * @param cb - callback that will be called with the users parameter. - * @param pib_attr - MAC PIB attribute to get stats from MAC. - * @return RET_BUSY if another request is active; RET_OK otherwise. - */ -zb_ret_t zdo_diagnostics_get_stats(zb_callback_t cb, zb_uint8_t pib_attr); - -/** - * @brief Initialize diagnostics context - */ -void zdo_diagnostics_init(void); - -#ifdef ZDO_DIAGNOSTICS_DEBUG_TRACE -#define ZDO_DIAGNOSTICS_INC(counter_id) zdo_diagnostics_inc(counter_id, ZB_TRACE_FILE_ID, __LINE__) -#else -#define ZDO_DIAGNOSTICS_INC(counter_id) zdo_diagnostics_inc(counter_id) -#endif - -#define ZDO_DIAGNOSTICS_ROUTE_REQ_INC(param) zdo_diagnostics_route_req_inc(param) - -#define ZDO_DIAGNOSTICS_INIT() zdo_diagnostics_init() - -#define ZDO_DIAGNOSTICS_GET_STATS(cb) \ - zdo_diagnostics_get_stats((cb), ZB_PIB_ATTRIBUTE_IEEE_DIAGNOSTIC_INFO) - -#define ZDO_DIAGNOSTICS_GET_AND_CLEANUP_STATS(cb) \ - zdo_diagnostics_get_stats((cb), ZB_PIB_ATTRIBUTE_GET_AND_CLEANUP_DIAG_INFO) - -/*! @} - * @endcond */ /* internals_doc */ - -/*! @} */ /* ZCL Diagnostics cluster definitions */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#else /* defined(ZDO_DIAGNOSTICS) || defined(DOXYGEN) */ - -#define ZDO_DIAGNOSTICS_INC(counter_id) -#define ZDO_DIAGNOSTICS_ROUTE_REQ_INC(param) -#define ZDO_DIAGNOSTICS_INIT() - -#define ZDO_DIAGNOSTICS_GET_STATS(cb) -#define ZDO_DIAGNOSTICS_GET_AND_CLEANUP_STATS(cb) - -#endif /* defined(ZDO_DIAGNOSTICS) || defined(DOXYGEN) */ - -#endif /* ZDO_DIAGNOSTICS_H */ diff --git a/zboss/development/src/include/zdo_hubs.h b/zboss/development/src/include/zdo_hubs.h deleted file mode 100644 index e87db4d93b..0000000000 --- a/zboss/development/src/include/zdo_hubs.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Routines to support WWAH moved there from ZCL, then All Hubs in r23 -*/ - -#ifndef ZDO_HUBS_H -#define ZDO_HUBS_H - -#if defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && defined ZB_ZCL_ENABLE_WWAH_SERVER - -zb_bool_t zb_wwah_check_nwk_key_commands_broadcast_allowed(void); -void zb_wwah_set_nwk_key_commands_broadcast_allowed(zb_bool_t allowed); - -zb_bool_t zb_wwah_in_configuration_mode(void); -void zb_wwah_set_configuration_mode(zb_bool_t allowed); -zb_bool_t zb_wwah_check_zdo_command(zb_apsde_data_indication_t *di); - -zb_bool_t zb_wwah_check_if_leave_without_rejoin_allowed(void); -void zb_wwah_set_leave_without_rejoin_allowed(zb_bool_t allowed); - -zb_bool_t zb_wwah_check_if_interpan_supported(void); -void zb_wwah_set_interpan_supported(zb_bool_t enabled); - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_WWAH && ZB_ZCL_ENABLE_WWAH_SERVER */ - -#endif /* ZDO_HUBS_H */ diff --git a/zboss/development/src/include/zdo_wwah_parent_classification.h b/zboss/development/src/include/zdo_wwah_parent_classification.h deleted file mode 100644 index 5b62ba2f72..0000000000 --- a/zboss/development/src/include/zdo_wwah_parent_classification.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#ifndef ZDO_WWAH_PARENT_CLASSIFICATION_H -#define ZDO_WWAH_PARENT_CLASSIFICATION_H 1 - -#include "zb_config.h" -#include "zb_common.h" - -#ifdef ZB_PARENT_CLASSIFICATION - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** - * @addtogroup ZB_ZCL_WWAH - * @{ - */ - -/** - * @addtogroup ZDO_WWAH_PARENT_CLASSIFICATION - * @{ - */ - -/** - * @brief Attribute to determine min RSSI for receiving packets - * - * See Zigbee WWAH Requirements spec, - * 6.2 Commissioning Requirements, C-20 - * - * @ZDO_WWAH_RSSI_FOR_GOOD_LINK_QUALITY_GROUP - */ -/* - * TODO: ZDO_WWAH_MIN_RSSI_FOR_RECEIVING_PACKETS is platform dependent!!! - * - * Now ZDO_WWAH_MIN_RSSI_FOR_RECEIVING_PACKETS and - * ZDO_WWAH_RSSI_FOR_RECEIVING_PACKETS_ADDING are zero to put all - * beacons in the Good Link Quality group and check only TC Connectivity - * and Long Uptime flags. - */ -#define ZDO_WWAH_MIN_RSSI_FOR_RECEIVING_PACKETS 0 - -/** - * @brief Additional RSSI value to determine beacons by two groups: - * Good and Marginal Link Quality - * - * See Zigbee WWAH Requirements spec, - * 6.2 Commissioning Requirements, C-20 - * - * @ZDO_WWAH_RSSI_FOR_GOOD_LINK_QUALITY_GROUP - */ -/* TODO: maybe need to move it into the MAC module */ -#define ZDO_WWAH_RSSI_FOR_RECEIVING_PACKETS_ADDING 0 - -/** - * @brief Min RSSI to determine a beacon in the Good Link Quality Group - * - * Received beacons with an RSSI less that value, - * are put in the Marginal Link Quality group - * - * See Zigbee WWAH Requirements spec, - * 6.2 Commissioning Requirements, C-20 - */ -#define ZDO_WWAH_RSSI_FOR_GOOD_LINK_QUALITY_GROUP \ - (ZDO_WWAH_MIN_RSSI_FOR_RECEIVING_PACKETS \ - + ZDO_WWAH_RSSI_FOR_RECEIVING_PACKETS_ADDING) - -/** - * @brief Return ZB_TRUE if RSSI value is valid for Good Link Quality group - */ -#define ZDO_WWAH_GET_LINK_QUALITY_GROUP_BY_RSSI(rssi) \ - (zb_bool_t)((rssi) >= ZDO_WWAH_RSSI_FOR_GOOD_LINK_QUALITY_GROUP) - -#endif /* #ifdef ZB_PARENT_CLASSIFICATION */ - -/* Let's compile that macro always */ - -/* low bit for TC Connectivity; high bit for Long Uptime */ -#define ZB_ZDO_TC_CONNECTIVITY_BIT_POS 0U -#define ZB_ZDO_LONG_UPTIME_BIT_POS 1U - -#define ZB_ZDO_SET_TC_CONNECTIVITY_BIT_VALUE(mask, val) \ - if (ZB_U2B(val)) \ - { \ - ZB_SET_BIT_IN_BIT_VECTOR((mask), ZB_ZDO_TC_CONNECTIVITY_BIT_POS); \ - } \ - else \ - { \ - ZB_CLR_BIT_IN_BIT_VECTOR((mask), ZB_ZDO_TC_CONNECTIVITY_BIT_POS); \ - } - -#define ZB_ZDO_SET_LONG_UPTIME_BIT_VALUE(mask, val) \ - if (ZB_U2B(val)) \ - { \ - ZB_SET_BIT_IN_BIT_VECTOR((mask), ZB_ZDO_LONG_UPTIME_BIT_POS); \ - } \ - else \ - { \ - ZB_CLR_BIT_IN_BIT_VECTOR((mask), ZB_ZDO_LONG_UPTIME_BIT_POS); \ - } - -#ifdef ZB_PARENT_CLASSIFICATION - - -/* 0b00 */ -#define ZB_ZCL_WWAH_NO_TC_CONNECTIVITY_AND_SHORT_UPTIME_MASK \ - (zb_uint8_t)(0) - -/* 0b10 */ -#define ZB_ZCL_WWAH_NO_TC_CONNECTIVITY_AND_LONG_UPTIME_MASK \ - (zb_uint8_t)(1 << ZB_ZDO_LONG_UPTIME_BIT_POS) - -/* 0b01 */ -#define ZB_ZCL_WWAH_TC_CONNECTIVITY_AND_SHORT_UPTIME_MASK \ - (zb_uint8_t)(1 << ZB_ZDO_TC_CONNECTIVITY_BIT_POS) - -/* 0b11 */ -#define ZB_ZCL_WWAH_TC_CONNECTIVITY_AND_LONG_UPTIME_MASK \ - (zb_uint8_t)(1 << ZB_ZDO_TC_CONNECTIVITY_BIT_POS | 1 << ZB_ZDO_LONG_UPTIME_BIT_POS) - -/** After this interval ZB_NIB().nwk_long_uptime bit will be set to 1 */ -#define ZDO_WWAH_LONG_UPTIME_INTERVAL (24*60*60*ZB_TIME_ONE_SECOND) - -/** - * @param Set 'WWAH Parent Classification is enabled' in ZDO ctx - * - * @param enable ZB_TRUE if WWAH Parent Classification is enabled; ZB_FALSE otherwise - */ -void zdo_wwah_parent_classification_set(zb_bool_t enable); - -/** - * @brief Get @zb_zcl_wwah_parent_priority_t by @zb_zcl_wwah_classification_mask_t - * - * @param mask - one byte which contain TC Connectivity and Long Uptime bits values - * - * @return @ZB_ZCL_WWAH_PARENT_PRIORITY_INVALID if invalid parameter uses; - * @zb_zcl_wwah_parent_priority_t value otherwise - */ -zb_zcl_wwah_parent_priority_t zdo_wwah_get_parent_priority_by_classification_mask( - zb_uint8_t mask); - - -/** - * @brief Compare neighbors by RSSI and WWAH Parent Priorities - * (see @zb_zcl_wwah_parent_priority_t) if WWAH Parent - * Classification is enabled; otherwise will be used only LQI value - * - * @param nbte_first - pointer to the first neighbor table entry - * @param nbte_second - pointer to the second neighbor table entry - */ -zb_bool_t zdo_wwah_compare_neighbors( - zb_ext_neighbor_tbl_ent_t *nbte_first, zb_ext_neighbor_tbl_ent_t *nbte_second); - -/** @} */ /* @addtogroup ZDO_WWAH_PARENT_CLASSIFICATION */ - -/** @} */ /* @addtogroup ZB_ZCL_WWAH */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#endif /* ZB_PARENT_CLASSIFICATION */ - -#endif /* ZDO_WWAH_PARENT_CLASSIFICATION_H */ diff --git a/zboss/development/src/include/zdo_wwah_stubs.h b/zboss/development/src/include/zdo_wwah_stubs.h deleted file mode 100644 index 2516f78b83..0000000000 --- a/zboss/development/src/include/zdo_wwah_stubs.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: WWAH ZDO Level selector for ZCL WWAH Stubs for all func. -*/ - -#ifndef ZDO_WWAH_STUBS_H -#define ZDO_WWAH_STUBS_H 1 - -#include "zdo_hubs.h" - -#if (defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && defined ZB_ZCL_ENABLE_WWAH_SERVER) -#include "zcl/zb_zcl_wwah.h" - -#define ZB_ZDO_CHECK_IF_WWAH_SERVER_BEHAVIOR() zb_is_wwah_server() /* used in zcl */ -#define ZB_ZDO_CHECK_NEW_CHANNEL(new_channel_mask) zb_zcl_wwah_check_new_channel(new_channel_mask) -#define ZB_ZDO_CHECK_NEW_PANID(new_panid) zb_zcl_wwah_check_new_panid(new_panid) -#define ZB_ZDO_GET_MAX_PARENT_THRESHOLD_RETRY() ZDO_CTX().max_parent_threshold_retry * (1U + zb_zcl_wwah_mac_poll_cca_retry_count()) - - /* Common logic when we have problems with parent polling: - * 1) Data Request + 3 MAC Retries - * 2) Wait MACPollFailureWaitTime - * 3) Repeat steps 1-2 wwah_retry_cnt times - * 4) Wait work_poll_interval - * 5) Repeat steps 1-4 ZDO_CTX().max_parent_threshold_retry times - */ - - /* Note: - * 1) if current retry count(crc) equals zero it means that last poll was success - * 2) crc >= maximum_retry_count leads to polling stop - * 3) crc % (wwah_retry_cnt + 1) shows current iteration of additional polling, - * i.e. loop steps 1-2 above. If remainder is zero - wait for standard timeout, - * or additional timeout otherwise. - */ - -#define ZB_ZDO_GET_CURENT_POLL_ITERATION_INTERVAL(wait_time) \ - if (zb_zcl_wwah_mac_poll_cca_retry_count() && \ - ZDO_CTX().parent_threshold_retry % (1 + zb_zcl_wwah_mac_poll_cca_retry_count())) \ - { \ - (wait_time) = zb_zcl_wwah_mac_poll_failure_wait_time(); \ - } \ - else \ - { \ - (wait_time) = ZDO_CTX().pim.work_poll_interval; \ - } - -void zb_zcl_wwah_update_tc_connection(zb_uint16_t short_addr); - -#define ZB_ZDO_CHECK_NWK_KEY_COMMANDS_BROADCAST_ALLOWED() zb_wwah_check_nwk_key_commands_broadcast_allowed() /* moved */ -#define ZB_ZDO_CHECK_ZDO_COMMAND(di) zb_wwah_check_zdo_command(di) /* moved */ -#define ZB_ZDO_CHECK_IF_APS_ACK_NEEDED(cluster_id) zb_zcl_wwah_check_if_aps_ack_needed(cluster_id) /* used in zcl */ -#define ZB_ZDO_CHECK_IF_APS_LINK_KEY_AUTHORIZATION_NEEDED(cluster_id) zb_zcl_wwah_check_if_aps_link_key_authorization_needed(cluster_id) /* used in zcl */ -#define ZB_ZDO_CHECK_IF_FORCED_TO_USE_TC(cluster_id) zb_zcl_wwah_check_if_forced_to_use_tc(cluster_id) /* used in zcl */ -#define ZB_ZDO_CHECK_CLUSTER_PERMISSION(nwk_addr, cluster_id) zb_zcl_wwah_check_cluster_permission(nwk_addr, cluster_id) /* used in zcl */ -#define ZB_ZDO_CHECK_IF_LEAVE_WITHOUT_REJOIN_ALLOWED() zb_wwah_check_if_leave_without_rejoin_allowed() /* moved */ -#define ZB_ZDO_CHECK_IF_WWAH_REJOIN_ENABLED() zb_zcl_wwah_check_if_wwah_rejoin_enabled() /* not used */ -#define ZB_ZDO_SEND_POWER_DESCRIPTOR_CHANGE() zb_zcl_wwah_schedule_send_power_descriptor_change() /* AF to ZCL signal - keep */ -#define ZB_ZDO_CHECK_IF_INTERPAN_SUPPORTED() zb_zcl_wwah_check_if_interpan_supported() /* moved */ -#define ZB_ZDO_CHECK_IF_WWAH_POOLING_MECHANISM() zb_zcl_wwah_check_if_periodic_router_check_ins_enabled() /* not used */ -#define ZB_ZDO_UPDATE_TC_CONNECTION(short_addr) zb_zcl_wwah_update_tc_connection(short_addr) /* call from nwk to zcl */ -#define ZB_ZDO_CHECK_SRC_ADDRESS_FOR_CLUSTER(short_addr, cluster_id) zb_zcl_wwah_check_src_addr_for_cluster(short_addr, cluster_id) /* used in zcl */ -#else -#define ZB_ZDO_CHECK_IF_WWAH_SERVER_BEHAVIOR() ZB_FALSE -#define ZB_ZDO_CHECK_NEW_CHANNEL(new_channel_mask) ZB_TRUE -#define ZB_ZDO_CHECK_NEW_PANID(new_panid) ZB_TRUE -#define ZB_ZDO_GET_MAX_PARENT_THRESHOLD_RETRY() ZDO_CTX().max_parent_threshold_retry -#define ZB_ZDO_GET_CURENT_POLL_ITERATION_INTERVAL(wait_time) (wait_time) = ZDO_CTX().pim.work_poll_interval -#define ZB_ZDO_CHECK_NWK_KEY_COMMANDS_BROADCAST_ALLOWED() ZB_TRUE -#define ZB_ZDO_CHECK_ZDO_COMMAND(di) ZB_TRUE -#define ZB_ZDO_CHECK_IF_APS_ACK_NEEDED(cluster_id) ZB_TRUE -#define ZB_ZDO_CHECK_IF_APS_LINK_KEY_AUTHORIZATION_NEEDED(cluster_id) ZB_FALSE -#define ZB_ZDO_CHECK_IF_FORCED_TO_USE_TC(cluster_id) ZB_FALSE -#define ZB_ZDO_CHECK_CLUSTER_PERMISSION(nwk_addr, cluster_id) ZB_TRUE -#ifdef ZB_ZDO_DENY_LEAVE_CONFIG -#define ZB_ZDO_CHECK_IF_LEAVE_WITHOUT_REJOIN_ALLOWED() ZG->zdo.leave_req_allowed -#else -#define ZB_ZDO_CHECK_IF_LEAVE_WITHOUT_REJOIN_ALLOWED() ZB_TRUE -#endif -#define ZB_ZDO_CHECK_IF_WWAH_REJOIN_ENABLED() ZB_FALSE -#define ZB_ZDO_SEND_POWER_DESCRIPTOR_CHANGE() -#define ZB_ZDO_CHECK_IF_INTERPAN_SUPPORTED() ZB_TRUE -#define ZB_ZDO_CHECK_IF_WWAH_POOLING_MECHANISM() ZB_FALSE -#define ZB_ZDO_UPDATE_TC_CONNECTION(short_addr) -#define ZB_ZDO_CHECK_SRC_ADDRESS_FOR_CLUSTER(short_addr, cluster_id) ZB_TRUE -#endif /* (defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && defined ZB_ZCL_ENABLE_WWAH_SERVER) */ - -#if defined ZB_PARENT_CLASSIFICATION && defined ZB_ROUTER_ROLE -void zdo_schedule_set_long_uptime(zb_uint8_t param); -void zdo_schedule_cancel_long_uptime(zb_uint8_t param); - -#define ZB_ZDO_SCHEDULE_UPDATE_LONG_UPTIME() zdo_schedule_set_long_uptime(0) -#define ZB_ZDO_CANCEL_UPDATE_LONG_UPTIME() zdo_schedule_cancel_long_uptime(0) - -#else /* ZB_PARENT_CLASSIFICATION */ -#define ZB_ZDO_SCHEDULE_UPDATE_LONG_UPTIME() -#define ZB_ZDO_CANCEL_UPDATE_LONG_UPTIME() - -#endif /* ZB_PARENT_CLASSIFICATION */ - -#endif /* ZDO_WWAH_STUBS_H */ diff --git a/zboss/development/src/include/zdo_wwah_survey_beacons.h b/zboss/development/src/include/zdo_wwah_survey_beacons.h deleted file mode 100644 index 39f3a099c2..0000000000 --- a/zboss/development/src/include/zdo_wwah_survey_beacons.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#ifndef ZDO_WWAH_SURVEY_BEACONS_H -#define ZDO_WWAH_SURVEY_BEACONS_H 1 - -#include "zb_config.h" -#include "zb_common.h" - -/* 2019-02-26: CR:MINOR TODO:Split WWAH-specific and non-WWAH-specific parts of Survey Beacons. */ -#if defined ZB_BEACON_SURVEY && defined ZB_ZCL_ENABLE_WWAH_SERVER - -/** @cond DOXYGEN_ZCL_SECTION */ - -/** - * @addtogroup ZB_ZCL_WWAH - * @{ - */ - -/** - * @addtogroup ZDO_WWAH_SURVEY_BEACONS - * @{ - */ - -typedef zb_zcl_wwah_beacon_survey_t zb_zdo_beacon_survey_parent_info_t; - -/** - * @brief R23, I.3.3 Beacon Survey Configuration TLV - * - * This TLV is 5-bytes in length and contains information - * about the channels and scan configuration that is used - * when performing a beacon survey. - */ -typedef ZB_PACKED_PRE struct zb_zdo_beacon_survey_configuration_t -{ - zb_nlme_beacon_survey_scan_request_t params; -} -ZB_PACKED_STRUCT zb_zdo_beacon_survey_configuration_t; - -/** - * @brief R23, I.3.4 Beacon Survey Results TLV - * - * This TLV is 4-bytes in length and contains information about the - * channels, scan configuration, and counted devices or beacons. - */ -typedef ZB_PACKED_PRE struct zb_zdo_beacon_survey_results_t -{ - /*!< Number of potential parents from the current Zigbee Network */ - zb_uint8_t num_potential_parents_current_zbn; - - /*!< Number of detected non-Zigbee networks */ - zb_uint8_t num_non_zbn; - - /*!< Number of detected ZigBee networks */ - zb_uint8_t num_zbn; - - /*!< Total Beacons Surveyed */ - zb_uint8_t total_beacons_surveyed; -} -ZB_PACKED_STRUCT zb_zdo_beacon_survey_results_t; - -/** - * @brief R23, I.3.5 Potential Parents TLV - * - * This TLV is 3 to 13 bytes in length and indicates the number - * of available parents in radio range. A maximum number of 5 - * parents is supported for this TLV. The list of potential - * parents SHALL be ordered as described in 3.6.1.3.2. - */ -typedef ZB_PACKED_PRE struct zb_zdo_beacon_survey_potential_parents_t -{ - /*!< Pointer to the @zb_zdo_beacon_survey_parent_info_t list */ - zb_uint8_t *parents_info_ptr; - /*!< Short address of the our parent (0xffff for Routers) */ - zb_uint16_t current_parent; - /*!< Count of potential parents (valid range [0;5]) */ - zb_uint8_t count_potential_parents; -} -ZB_PACKED_STRUCT zb_zdo_beacon_survey_potential_parents_t; - -/** - * @brief Structure to store information when 'Beacon Survey' procedure is executing - * - * We reuse a buffer which contain 'Beacon Survey Request' command - * and store all necessary information into it. Format of the - * 'Beacon Survey Response' command is different between ZCL WWAH - * and r23, so we need to use two functions to parse results and - * send response - */ -typedef ZB_PACKED_PRE struct zb_zdo_beacon_survey_resp_params_s -{ - /*!< R23, I.3.5 Potential Parents TLV */ - zb_zdo_beacon_survey_potential_parents_t parents; - /*!< I.3.3 Beacon Survey Configuration TLV */ - zb_zdo_beacon_survey_configuration_t configuration; - /*!< R23, I.3.4 Beacon Survey Results TLV */ - zb_zdo_beacon_survey_results_t results; -} -ZB_PACKED_STRUCT zb_zdo_beacon_survey_resp_params_t; - -/** - * @brief Start Survey Beacons procedure - * - * @param param - reference to a buffer which contain - * @zb_zdo_survey_beacons_params_t - * - * @return @RET_ERROR if failed; - * @RET_BUSY otherwise - in this case stack doesn't free - * the buffer with Survey Beacons command, because this buffer - * will be reused to send Survey Beacons Response command. - */ -zb_ret_t zdo_wwah_start_survey_beacons(zb_uint8_t param); - -/** - * @brief Process a received beacons and put information from it - * into the 'Survey Beacons Response' buffer - * - * @param beacon_noti_ind_ptr - pointer to the @zb_mac_beacon_notify_indication_t - * @param beacon_payload_ptr - pointer to the @zb_mac_beacon_payload_t - */ -void zdo_wwah_process_beacon_info( - zb_mac_beacon_notify_indication_t *beacon_noti_ind_ptr, - zb_mac_beacon_payload_t *beacon_payload_ptr); - -/** - * @brief Send 'Survey Beacons Response' command - * - * @todo need to implement in r23 - */ -void zdo_send_survey_beacons_response(void); - -#if (defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && defined ZB_ZCL_ENABLE_WWAH_SERVER) - -/* 4 bytes for: fcf, seq_num, command_type and beacons_number */ -#define ZDO_WWAH_MAX_BEACON_SURVEY() \ - ((ZB_ZCL_HI_WO_IEEE_MAX_PAYLOAD_SIZE - 4) \ - / sizeof(zb_zdo_beacon_survey_parent_info_t)) - -#define ZDO_WWAH_MAX_BEACON_SURVEY_BYTES() \ - (sizeof(zb_zdo_beacon_survey_parent_info_t) \ - * (ZDO_WWAH_MAX_BEACON_SURVEY())) \ - -void zb_zcl_wwah_send_survey_beacons_response(zb_bufid_t buf, zb_uint16_t zcl_buf); - -#define ZDO_SEND_SURVEY_BEACONS_RESPONSE_FUNC(buf) \ - zb_zcl_wwah_send_survey_beacons_response(0, buf) - -#else /* ZB_ZCL_SUPPORT_CLUSTER_WWAH */ - -/* see R23, I.3.5 Potential Parents TLV, 'Count of Potential Parents' field */ -#define ZDO_WWAH_MAX_BEACON_SURVEY() 5U - -#define ZDO_WWAH_MAX_BEACON_SURVEY_BYTES() \ - (ZDO_WWAH_MAX_BEACON_SURVEY() * sizeof(zb_uint16_t)) - -#define ZDO_SEND_SURVEY_BEACONS_RESPONSE_FUNC() \ - zdo_send_survey_beacons_response(buf) - -#endif /* (defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && defined ZB_ZCL_ENABLE_WWAH_SERVER) */ - -#endif /* defined ZB_BEACON_SURVEY && defined ZB_ZCL_ENABLE_WWAH_SERVER */ - -/** @} */ /* @addtogroup ZDO_WWAH_SURVEY_BEACONS */ - -/** @} */ /* @addtogroup ZB_ZCL_WWAH */ - -/** @endcond */ /* DOXYGEN_ZCL_SECTION */ - -#endif /* ZDO_WWAH_SURVEY_BEACONS_H */ diff --git a/zboss/development/src/zb_error/zb_error_to_string.c b/zboss/development/src/zb_error/zb_error_to_string.c deleted file mode 100644 index 8751a76c28..0000000000 --- a/zboss/development/src/zb_error/zb_error_to_string.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/** - * @addtogroup zb_error - * - * @brief Module for converting ZBOSS error code into a printable string. - * @{ - */ -#ifdef CONFIG_ZIGBEE_ERROR_TO_STRING_ENABLED -#include "zb_error_to_string.h" - -/** Counts number of elements inside the array - */ -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) -#endif - -/** - * @brief Macro for adding an entity to the description array. - * - * Macro that helps to create a single entity in the description array. - */ -#define ZB_ERROR_STRING(mnemonic) {.code = -mnemonic, .name = #mnemonic} - -/** - * @brief Array entity element that describes an error. - */ -typedef struct -{ - zb_ret_t code; /**< Error code. */ - char const * name; /**< Descriptive name (the same as the internal error mnemonic). */ -} zb_strerror_desc_t; - -/** - * @brief Unknown error code. - * - * The constant string used by @ref zb_strerror_get when the error description was not found. - */ -static char const m_unknown_str[] = "Unknown error code"; - -/** - * @brief Array with error codes. - * - * Array that describes error codes. - * - * @note It is required for this array to have error codes placed in ascending order. - * This condition is checked in automatic unit test before the release. - */ -static zb_strerror_desc_t const zb_strerror_array[] = -{ - ZB_ERROR_STRING(RET_OK), - ZB_ERROR_STRING(RET_ERROR), - ZB_ERROR_STRING(RET_BLOCKED), - ZB_ERROR_STRING(RET_EXIT), - ZB_ERROR_STRING(RET_BUSY), - ZB_ERROR_STRING(RET_EOF), - ZB_ERROR_STRING(RET_OUT_OF_RANGE), - ZB_ERROR_STRING(RET_EMPTY), - ZB_ERROR_STRING(RET_CANCELLED), - - ZB_ERROR_STRING(RET_INVALID_PARAMETER_1), - ZB_ERROR_STRING(RET_INVALID_PARAMETER_2), - ZB_ERROR_STRING(RET_INVALID_PARAMETER_3), - ZB_ERROR_STRING(RET_INVALID_PARAMETER_4), - ZB_ERROR_STRING(RET_INVALID_PARAMETER_6), - ZB_ERROR_STRING(RET_PENDING), - ZB_ERROR_STRING(RET_NO_MEMORY), - ZB_ERROR_STRING(RET_INVALID_PARAMETER), - ZB_ERROR_STRING(RET_OPERATION_FAILED), - ZB_ERROR_STRING(RET_BUFFER_TOO_SMALL), - ZB_ERROR_STRING(RET_END_OF_LIST), - ZB_ERROR_STRING(RET_ALREADY_EXISTS), - ZB_ERROR_STRING(RET_NOT_FOUND), - ZB_ERROR_STRING(RET_OVERFLOW), - ZB_ERROR_STRING(RET_TIMEOUT), - ZB_ERROR_STRING(RET_NOT_IMPLEMENTED), - ZB_ERROR_STRING(RET_NO_RESOURCES), - ZB_ERROR_STRING(RET_UNINITIALIZED), - ZB_ERROR_STRING(RET_INVALID_STATE), - ZB_ERROR_STRING(RET_CONNECTION_FAILED), - ZB_ERROR_STRING(RET_CONNECTION_LOST), - ZB_ERROR_STRING(RET_UNAUTHORIZED), - ZB_ERROR_STRING(RET_CONFLICT), - ZB_ERROR_STRING(RET_INVALID_FORMAT), - ZB_ERROR_STRING(RET_NO_MATCH), - ZB_ERROR_STRING(RET_PROTOCOL_ERROR), - ZB_ERROR_STRING(RET_VERSION), - ZB_ERROR_STRING(RET_FILE_NOT_FOUND), - ZB_ERROR_STRING(RET_CONVERSION_ERROR), - ZB_ERROR_STRING(RET_FILE_CORRUPTED), - ZB_ERROR_STRING(RET_PAGE_NOT_FOUND), - ZB_ERROR_STRING(RET_ILLEGAL_REQUEST), - ZB_ERROR_STRING(RET_INVALID_GROUP), - ZB_ERROR_STRING(RET_TABLE_FULL), - ZB_ERROR_STRING(RET_IGNORE), - ZB_ERROR_STRING(RET_AGAIN), - ZB_ERROR_STRING(RET_DEVICE_NOT_FOUND), - ZB_ERROR_STRING(RET_OBSOLETE) -}; - -char const * zb_error_to_string_get(zb_ret_t code) -{ - char const * p_ret = zb_error_to_string_find(code); - return (p_ret == NULL) ? m_unknown_str : p_ret; -} - -char const * zb_error_to_string_find(zb_ret_t code) -{ - zb_strerror_desc_t const * p_start; - zb_strerror_desc_t const * p_end; - p_start = zb_strerror_array; - p_end = zb_strerror_array + ARRAY_SIZE(zb_strerror_array); - - while (p_start < p_end) { - zb_strerror_desc_t const * p_mid = p_start + ((p_end - p_start) / 2); - zb_ret_t mid_c = p_mid->code; - if (mid_c > code) { - p_end = p_mid; - } else if (mid_c < code) { - p_start = p_mid + 1; - } else { - return p_mid->name; - } - } - return NULL; -} - -#endif /* CONFIG_ZIGBEE_ERROR_TO_STRING_ENABLED */ - -/** @} */ diff --git a/zboss/development/src/zb_error/zb_error_to_string.h b/zboss/development/src/zb_error/zb_error_to_string.h deleted file mode 100644 index c4ec76be86..0000000000 --- a/zboss/development/src/zb_error/zb_error_to_string.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/** - * @addtogroup zb_error - * - * @brief Module for converting ZBOSS error code into a printable string. - * @{ - */ -#ifndef ZB_ERRPR_TO_STRING_H__ -#define ZB_ERRPR_TO_STRING_H__ - -#include "zboss_api.h" -#include "zb_errors.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Function for getting a printable error string. - * - * @param code Error code to convert. - * - * @note This function cannot fail. - * For the function that may fail with error translation, - * see @ref zb_error_to_string_find. - * - * @return Pointer to the printable string. - * If the string is not found, - * it returns a simple string that says that the error is unknown. - */ -char const * zb_error_to_string_get(zb_ret_t code); - -/** - * @brief Function for finding a printable error string. - * - * This function gets the error string in the same way as @ref zb_error_to_string_get, - * but if the string is not found, it returns NULL. - * - * @param code Error code to convert. - * @return Pointer to the printable string. - * If the string is not found, NULL is returned. - */ -char const * zb_error_to_string_find(zb_ret_t code); - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZB_STRERROR_H__ */ diff --git a/zboss/development/src/zcl/ha_sas.c b/zboss/development/src/zcl/ha_sas.c deleted file mode 100644 index 053460e619..0000000000 --- a/zboss/development/src/zcl/ha_sas.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Zigbee cluster library, Startup Attribute Sets -*/ - -#define ZB_TRACE_FILE_ID 2058 - -#include "zb_common.h" - -#if defined ZB_ENABLE_ZCL - -#if defined ZB_ENABLE_HA_SAS - -#include "zb_zcl.h" -#include "ha/zb_ha_sas.h" - -static zb_ieee_addr_t g_zb_ha_sas_default_ext_pan_id = ZB_HA_SAS_EXT_PAN_ID; - -void zb_ha_process_sas(void) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_ha_process_sas", (FMT__0)); - - /* Our stack had already set protocol version as appropriate (see - ZB_PROTOCOL_VERSION) */ - /* Our stack had already set stack profile version, see ZB_STACK_PROFILE */ - /* Startup control parameter is an indicator one, not implemented */ - /* Config_Rejoin_Interval and Config_Max_Rejoin_Interval attributes are - optional, so not supported */ - /* Master, network, and default trust center link keys are not set because - they are same as stack defaults. Also this point should be controlled for - possible changes in the future. */ - if (!ZB_JOINED()) - { - ZB_PIBCACHE_NETWORK_ADDRESS() = ZB_HA_SAS_SHORT_ADDRESS; - ZB_PIBCACHE_PAN_ID() = ZB_HA_SAS_PAN_ID; - ZB_EXTPANID_COPY(ZB_NIB_EXT_PAN_ID(), g_zb_ha_sas_default_ext_pan_id); -#ifndef DEBUG - zb_aib_channel_page_list_set_2_4GHz_mask(ZB_HA_SAS_CHANNEL_MASK); /* MMDEVSTUBS */ -#endif - ZB_IEEE_ADDR_ZERO(ZB_AIB().trust_center_address); - } - COMM_CTX().discovery_ctx.nwk_scan_attempts = ZB_HA_SAS_SCAN_ATTEMPTS; - COMM_CTX().discovery_ctx.nwk_time_btwn_scans = ZB_HA_SAS_TIME_BTWN_SCANS; - - TRACE_MSG(TRACE_ZCL1, "< zb_ha_process_sas", (FMT__0)); -} - -#endif /* defined ZB_ENABLE_HA_SAS */ - -#endif /* defined ZB_ENABLE_ZCL */ diff --git a/zboss/development/src/zcl/zb_zcl_s_metering.c b/zboss/development/src/zcl/zb_zcl_s_metering.c deleted file mode 100644 index 5a13ae56d3..0000000000 --- a/zboss/development/src/zcl/zb_zcl_s_metering.c +++ /dev/null @@ -1,908 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: SERVER: Metering Cluster -*/ - -#define ZB_TRACE_FILE_ID 4001 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_METERING) || defined DOXYGEN - -#include "zcl/zb_zcl_metering.h" - -zb_bool_t zb_zcl_process_s_metering_specific_commands(zb_uint8_t param); - -void zb_zcl_metering_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_s_metering_specific_commands); -} - -/* TODO: Turn off correctly */ -#ifdef ZB_ZCL_SUPPORT_CLUSTER_METERING_OPTIONAL -#define ZB_ZCL_METERING_SEND_CMD_HELPER(_fn, _param, _cmd_info, _payload, _payload_size, _cb) \ - _fn((_param), \ - (zb_addr_u *) &ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).source.u.short_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).src_endpoint, \ - ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).dst_endpoint, \ - (_payload), (_payload_size), (_cb)) - - -static zb_uint8_t *zb_zcl_metering_put_get_profile_response(zb_uint8_t *data, const void *pl_arg) -{ - - const zb_zcl_metering_get_profile_response_payload_t *pl = pl_arg; - - ZB_ASSERT(pl_arg); - ZB_ASSERT(data); - - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->end_time); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->status); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->profile_interval_period); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->number_of_periods_delivered); - - for (zb_int_t i = 0; i <= pl->number_of_periods_delivered - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA24(data, (pl->intervals + i)); - } - - return data; -} - - -static zb_uint8_t *zb_zcl_metering_put_get_sampled_data_response(zb_uint8_t *data, const void *pl_arg) -{ - - const zb_zcl_metering_get_sampled_data_response_payload_t *pl = pl_arg; - - ZB_ASSERT(pl_arg); - ZB_ASSERT(data); - - ZB_ZCL_PACKET_PUT_DATA16(data, &pl->sample_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->sample_start_time); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->sample_type); - ZB_ZCL_PACKET_PUT_DATA16(data, &pl->sample_request_interval); - ZB_ZCL_PACKET_PUT_DATA16(data, &pl->number_of_samples); - - for (zb_uint8_t i = 0; i <= pl->number_of_samples - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA24(data, (pl->samples + i)); - } - - return data; -} - - -static zb_uint8_t *zb_zcl_metering_put_publish_snapshot(zb_uint8_t *data, const void *pl_arg) -{ - - const zb_zcl_metering_publish_snapshot_payload_t *pl = pl_arg; - - ZB_ASSERT(pl_arg); - ZB_ASSERT(data); - - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->snapshot_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->snapshot_time); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->total_snapshots_found); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->command_index); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->total_number_of_commands); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->snapshot_cause); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->snapshot_payload_type); - - switch (pl->snapshot_payload_type) - { - case ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS: - { - const zb_zcl_metering_tou_delivered_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_delivered); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_time_stamp_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_time_stamp_delivered); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->bill_delivered_trailing_digit); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - } - break; - case ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS: - { - const zb_zcl_metering_tou_received_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_received); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS", (FMT__0)); - - - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_time_stamp_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_time_stamp_received); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->bill_received_trailing_digit); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_DELIVERED: - { - const zb_zcl_metering_block_delivered_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_delivered); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_DELIVERED", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_time_stamp_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_time_stamp_delivered); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->bill_delivered_trailing_digit); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_and_block_thresholds_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_and_block_thresholds_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_block_summation + i)); - } - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_RECEIVED: - { - const zb_zcl_metering_block_received_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_received); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_RECEIVED", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_time_stamp_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_time_stamp_received); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->bill_received_trailing_digit); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_and_block_thresholds_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_and_block_thresholds_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_block_summation + i)); - } - } - break; - case ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING: - { - const zb_zcl_metering_tou_delivered_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_delivered_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_delivered); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - } - break; - case ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING: - { - const zb_zcl_metering_tou_received_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_received_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_received); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING: - { - const zb_zcl_metering_block_tier_delivered_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_tier_delivered_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_delivered); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_and_block_thresholds_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_and_block_thresholds_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_block_summation + i)); - } - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING: - { - const zb_zcl_metering_block_tier_received_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_tier_received_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_received); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_and_block_thresholds_in_use); - - for (zb_uint8_t i = 0; i <= sub_payload->number_of_tiers_and_block_thresholds_in_use - 1; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_block_summation + i)); - } - } - break; - case ZB_ZCL_METERING_DATA_UNAVAILABLE: - /*NOTE: from SE spec: The data for this snapshot is currently unavailable; - * if used, there is currently no subsequent snapshot data. - */ - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_DATA_UNAVAILABLE", (FMT__0)); - break; - default: - TRACE_MSG(TRACE_ZCL1, "Malformed packet: unsupported snapshot payload type", (FMT__0)); - break; - } - - return data; -} - - -static zb_int16_t zb_zcl_metering_calculate_publish_snapshot_payload_size(const zb_zcl_metering_publish_snapshot_payload_t *pl) -{ - - zb_int16_t pl_size = 0; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_calculate_publish_snapshot_payload_size", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_publish_snapshot_payload_t, snapshot_sub_payload); - - switch (pl->snapshot_payload_type) - { - case ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS: - { - const zb_zcl_metering_tou_delivered_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_delivered); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_tou_delivered_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS: - { - const zb_zcl_metering_tou_received_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_received); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_tou_received_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_DELIVERED: - { - const zb_zcl_metering_block_delivered_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_delivered); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_DELIVERED", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_block_delivered_payload_t, tier_summation); - pl_size += (sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE); - pl_size += 1; /* 1 byte for number_of_tiers_and_block_thresholds_in_use */ - pl_size += sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_RECEIVED: - { - const zb_zcl_metering_block_received_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_received); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_RECEIVED", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_block_received_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - pl_size += 1; /* 1 byte for number_of_tiers_and_block_thresholds_in_use */ - pl_size += sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING: - { - const zb_zcl_metering_tou_delivered_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_delivered_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_tou_delivered_no_billing_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING: - { - const zb_zcl_metering_tou_received_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_received_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_tou_received_no_billing_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING: - { - const zb_zcl_metering_block_tier_delivered_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_tier_delivered_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_block_tier_delivered_no_billing_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - pl_size += 1; /*1 byte for number_of_tiers_and_block_thresholds_in_use*/ - pl_size += sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING: - { - const zb_zcl_metering_block_tier_received_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_tier_received_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_block_tier_received_no_billing_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - pl_size += 1; /*1 byte for number_of_tiers_and_block_thresholds_in_use*/ - pl_size += sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_DATA_UNAVAILABLE: - /*NOTE: from SE spec: The data for this snapshot is currently unavailable; - * if used, there is currently no subsequent snapshot data. - */ - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_DATA_UNAVAILABLE", (FMT__0)); - break; - default: - TRACE_MSG(TRACE_ZCL1, "Malformed packet: unsupported snapshot payload type", (FMT__0)); - pl_size = -1; - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_calculate_publish_snapshot_payload_size", (FMT__0)); - - return pl_size; -} - - -void zb_zcl_metering_send_cmd_publish_snapshot(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_metering_publish_snapshot_payload_t *pl, - zb_callback_t cb) -{ - - zb_int16_t pl_size; - - pl_size = zb_zcl_metering_calculate_publish_snapshot_payload_size(pl); - - if ((pl_size <= 255)&& (pl_size > 0)) - { - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, pl, - (zb_uint8_t)pl_size, - zb_zcl_metering_put_publish_snapshot, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_SRV_CMD_PUBLISH_SNAPSHOT, - cb); - } - else - { - TRACE_MSG(TRACE_ERROR, "zb_zcl_metering_send_cmd_publish_snapshot: invalid payload", (FMT__0)); - ZB_ZCL_SCHEDULE_STATUS_ABORT(param, (zb_addr_u *)dst_addr, dst_addr_mode, dst_ep, src_ep, cb); - } -} - - -void zb_zcl_metering_send_cmd_request_fast_poll_mode_response(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_metering_request_fast_poll_mode_response_payload_t *pl, - zb_uint8_t pl_size, - zb_callback_t cb) -{ - - zb_zcl_metering_request_fast_poll_mode_response_payload_t payload; - zb_uint8_t *data = (zb_uint8_t *) &payload; - - ZB_BZERO(&payload, sizeof(payload)); - - ZB_ZCL_PACKET_PUT_DATA8(data, pl->applied_update_period_in_seconds); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->fast_poll_mode_end_time); - - if (0 == pl_size) - { - pl_size = sizeof(payload); - } - - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, &payload, pl_size, - NULL, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_SRV_CMD_REQUEST_FAST_POLL_MODE_RESPONSE, - cb); - -} - - -void zb_zcl_metering_send_cmd_get_profile_response(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, const zb_zcl_metering_get_profile_response_payload_t *pl, - zb_uint8_t pl_size, zb_callback_t cb) -{ - if (0 == pl_size) - { - pl_size = sizeof(zb_zcl_metering_get_profile_response_payload_t) - sizeof(void *) + ZB_24BIT_SIZE * pl->number_of_periods_delivered; - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_send_cmd_get_profile_response: " - "passed 0, calculated size = %d", (FMT__D, pl_size)); - } - - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, pl, pl_size, - zb_zcl_metering_put_get_profile_response, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_SRV_CMD_GET_PROFILE_RESPONSE, - cb); - -} - - -void zb_zcl_metering_send_cmd_get_sampled_data_response(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_metering_get_sampled_data_response_payload_t *pl, - zb_uint8_t pl_size, zb_callback_t cb) -{ - if (0 == pl_size) - { - pl_size = sizeof(zb_zcl_metering_get_sampled_data_response_payload_t) - sizeof(void *) + ZB_24BIT_SIZE * pl->number_of_samples; - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_send_cmd_get_sampled_data_response: " - "passed 0, calculated size = %d", (FMT__D, pl_size)); - } - - - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, pl, pl_size, - zb_zcl_metering_put_get_sampled_data_response, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_SRV_CMD_GET_PROFILE_RESPONSE, - cb); - -} - - -static const zb_uint8_t *zb_zcl_metering_get_snapshot_data_parse_payload(zb_zcl_metering_get_snapshot_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_get_snapshot_data_parse_payload", (FMT__0)); - - if (data_size != sizeof(zb_zcl_metering_get_snapshot_payload_t)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl->earliest_start_time, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->latest_end_time, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->snapshot_offset, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->snapshot_cause, data); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_get_snapshot_data_parse_payload", (FMT__0)); - - return data; -} - - -static const zb_uint8_t *zb_zcl_metering_request_fast_poll_mode_parse_payload( - zb_zcl_metering_request_fast_poll_mode_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_request_fast_poll_mode_parse_payload", (FMT__0)); - - if (data_size != sizeof(zb_zcl_metering_request_fast_poll_mode_payload_t)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA8(&pl->fast_poll_update_period, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->duration_in_minutes, data); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_request_fast_poll_mode_parse_payload", (FMT__0)); - - return data; -} - - -static const zb_uint8_t *zb_zcl_metering_get_sampled_data_parse_payload(zb_zcl_metering_get_sampled_data_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_get_sampled_data_parse_payload", (FMT__0)); - - if (data_size != sizeof(zb_zcl_metering_get_sampled_data_payload_t)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA16(&pl->sample_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->earliest_sample_time, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->sample_type, data); - ZB_ZCL_PACKET_GET_DATA16(&pl->number_of_samples, data); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_get_sampled_data_parse_payload", (FMT__0)); - - return data; -} - - -static const zb_uint8_t *zb_zcl_metering_get_profile_parse_payload(zb_zcl_metering_get_profile_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_metering_get_profile_parse_payload", (FMT__0)); - - /* NOTE: User must check whether the number_of_periods is greater than MaxNumberOfPeriodsDelivered. */ - if (!ZB_ZCL_METERING_GET_PROFILE_PAYLOAD_SIZE_IS_VALID(data_size)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA8(&pl->interval_channel, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->end_time, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->number_of_periods, data); - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_metering_process_request_fast_poll_mode", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_REQUEST_FAST_POLL_MODE_CB_ID, - RET_ERROR, cmd_info, &pl_in, &pl_out); - - if (!zb_zcl_metering_request_fast_poll_mode_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid request_fast_poll_mode", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - ZB_ZCL_METERING_SEND_CMD_HELPER(zb_zcl_metering_send_cmd_request_fast_poll_mode_response, - param, cmd_info, &pl_out, 0, NULL); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_request_fast_poll_mode", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_metering_process_get_snapshot(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_metering_get_snapshot_payload_t pl_in ; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_process_get_snapshot", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_GET_SNAPSHOT_CB_ID, - RET_NOT_FOUND, cmd_info, &pl_in, NULL); - - if (!zb_zcl_metering_get_snapshot_data_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid get_profile", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - /*We don't send a PublishSnapshot command. Application must send reply - * for this command and free buffer. - */ - break; - case RET_NOT_FOUND: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_get_snapshot", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_metering_process_get_sampled_data(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_metering_get_sampled_data_payload_t pl_in ; - zb_zcl_metering_get_sampled_data_response_payload_t pl_out; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_process_get_sampled_data", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_GET_SAMPLED_DATA_CB_ID, - RET_NOT_FOUND, cmd_info, &pl_in, &pl_out); - - if (!zb_zcl_metering_get_sampled_data_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid get_profile", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - ZB_ZCL_METERING_SEND_CMD_HELPER(zb_zcl_metering_send_cmd_get_sampled_data_response, - param, cmd_info, &pl_out, 0, NULL); - break; - case RET_NOT_FOUND: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_get_sampled_data", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_metering_process_get_profile(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_metering_get_profile_payload_t pl_in ; - zb_zcl_metering_get_profile_response_payload_t pl_out; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_process_get_profile", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_GET_PROFILE_CB_ID, - RET_ERROR, cmd_info, &pl_in, &pl_out); - - if (!zb_zcl_metering_get_profile_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid get_profile", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - ZB_ZCL_METERING_SEND_CMD_HELPER(zb_zcl_metering_send_cmd_get_profile_response, - param, cmd_info, &pl_out, 0, NULL); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_get_profile", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_process_metering_server_commands(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_bool_t processed = ZB_FALSE; - - switch ((zb_zcl_metering_cli_cmd_t)cmd_info->cmd_id) - { - case ZB_ZCL_METERING_CLI_CMD_GET_PROFILE: - processed = zb_zcl_metering_process_get_profile(param, cmd_info); - break; - case ZB_ZCL_METERING_CLI_CMD_REQUEST_FAST_POLL_MODE: - processed = zb_zcl_metering_process_request_fast_poll_mode(param, cmd_info); - break; - case ZB_ZCL_METERING_CLI_CMD_GET_SNAPSHOT: - processed = zb_zcl_metering_process_get_snapshot(param, cmd_info); - break; - case ZB_ZCL_METERING_CLI_CMD_GET_SAMPLED_DATA: - processed = zb_zcl_metering_process_get_sampled_data(param, cmd_info); - break; - default: - break; - } - - return processed; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_METERING_OPTIONAL */ - - -zb_bool_t zb_zcl_process_s_metering_specific_commands(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t processed = ZB_FALSE; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_s_metering_specific_commands, " - "param=%hd, cmd_id=%hd", (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_METERING); - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_METERING_OPTIONAL - if (ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction) - { - processed = zb_zcl_process_metering_server_commands(param, &cmd_info); - } -#endif - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_s_metering_specific_commands (ret=%hd)", - (FMT__H, processed)); - - return processed; -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_METERING || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_alarms_commands.c b/zboss/development/src/zcl/zcl_alarms_commands.c deleted file mode 100644 index b4a8c2e1fa..0000000000 --- a/zboss/development/src/zcl/zcl_alarms_commands.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Alarms cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2059 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_ALARMS) - -#include "zb_zcl.h" -#include "zcl/zb_zcl_alarms.h" - -static zb_uint8_t gs_alarms_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_ALARMS_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -static zb_uint8_t gs_alarms_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_ALARMS_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -static zb_discover_cmd_list_t gs_alarms_client_cmd_list = -{ - sizeof(gs_alarms_client_received_commands), gs_alarms_client_received_commands, - sizeof(gs_alarms_server_received_commands), gs_alarms_server_received_commands -}; - -static zb_discover_cmd_list_t gs_alarms_server_cmd_list = -{ - sizeof(gs_alarms_server_received_commands), gs_alarms_server_received_commands, - sizeof(gs_alarms_client_received_commands), gs_alarms_client_received_commands -}; - -zb_bool_t zb_zcl_process_alarms_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_alarms_specific_commands_cli(zb_uint8_t param); - -void zb_zcl_alarms_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ALARMS, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_alarms_specific_commands_srv); -} - -void zb_zcl_alarms_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ALARMS, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_alarms_specific_commands_cli); -} - -static zb_zcl_status_t zb_zcl_alarms_map_ret_code_to_zcl_status(zb_ret_t ret_code) -{ - zb_zcl_status_t status; - - ZB_ASSERT(ret_code != RET_BUSY); - - switch (ret_code) - { - case RET_OK: - status = ZB_ZCL_STATUS_SUCCESS; - break; - case RET_INVALID_PARAMETER_1: - status = ZB_ZCL_STATUS_INVALID_FIELD; - break; - case RET_INVALID_PARAMETER: - status = ZB_ZCL_STATUS_INVALID_VALUE; - break; - case RET_ERROR: - status = (zb_zcl_get_backward_compatible_statuses_mode() == ZB_ZCL_STATUSES_ZCL8_MODE) ? - ZB_ZCL_STATUS_FAIL : ZB_ZCL_STATUS_HW_FAIL; - break; - default: - status = ZB_ZCL_STATUS_FAIL; - break; - } - - return status; -} - -static zb_ret_t zb_zcl_alarms_reset_alarm_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_alarms_reset_alarm_req_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_alarms_reset_alarm_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_ALARMS_GET_RESET_ALARM_REQ(param, pl_in, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_ALARMS_GET_RESET_ALARM_REQ", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_ALARMS_RESET_ALARM_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_alarms_reset_alarm_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -static zb_ret_t zb_zcl_alarms_reset_all_alarms_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_alarms_reset_all_alarms_handler %hx", (FMT__H, param)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_ALARMS_RESET_ALL_ALARMS_CB_ID, RET_OK, cmd_info, NULL, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_alarms_reset_all_alarms_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -static zb_ret_t zb_zcl_alarms_alarm_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_alarms_alarm_res_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_alarms_alarm_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_ALARMS_GET_ALARM_RES(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_ALARMS_GET_ALARM_RES", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_ALARMS_ALARM_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_alarms_alarm_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -zb_bool_t zb_zcl_process_alarms_specific_commands_srv(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_alarms_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_alarms_specific_commands_srv: param %hd, cmd %hd", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_ALARMS == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_ALARMS_RESET_ALARM_ID: - ret = zb_zcl_alarms_reset_alarm_handler(param, &cmd_info); - TRACE_MSG(TRACE_ZCL3, "Processed RESET_ALARM command", (FMT__0)); - break; - - case ZB_ZCL_CMD_ALARMS_RESET_ALL_ALARMS_ID: - ret = zb_zcl_alarms_reset_all_alarms_handler(param, &cmd_info); - TRACE_MSG(TRACE_ZCL3, "Processed RESET_ALL_ALARMS command", (FMT__0)); - break; - - default: - processed = ZB_FALSE; - break; - } - - if (processed && ret != RET_BUSY) - { - zb_zcl_send_default_handler(param, &cmd_info, - zb_zcl_alarms_map_ret_code_to_zcl_status(ret)); - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_alarms_specific_commands_srv: processed %d", - (FMT__D, processed)); - - return processed; -} - -zb_bool_t zb_zcl_process_alarms_specific_commands_cli(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_alarms_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_alarms_specific_commands_cli: param %hd, cmd %hd", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_ALARMS == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction); - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_ALARMS_ALARM_ID: - ret = zb_zcl_alarms_alarm_handler(param, &cmd_info); - TRACE_MSG(TRACE_ZCL3, "Processed ALARM command", (FMT__0)); - break; - - default: - processed = ZB_FALSE; - break; - } - - if (processed && ret != RET_BUSY) - { - zb_zcl_send_default_handler(param, &cmd_info, - zb_zcl_alarms_map_ret_code_to_zcl_status(ret)); - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_alarms_specific_commands_cli: processed %d", - (FMT__D, processed)); - - return processed; -} -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_ALARMS*/ diff --git a/zboss/development/src/zcl/zcl_attr_value.c b/zboss/development/src/zcl/zcl_attr_value.c deleted file mode 100644 index 2f8edb7ea2..0000000000 --- a/zboss/development/src/zcl/zcl_attr_value.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL: implements attribute values check -*/ - -#define ZB_TRACE_FILE_ID 2060 - -#include "zb_common.h" - -#if defined ZB_ENABLE_ZCL - -#include "zb_zcl.h" -#include "zb_aps.h" -#include "zcl/zb_zcl_common.h" -#include "zb_zdo.h" - -/*! - Check if attribute value is valid or not - @param cluster_id - cluster ID - @param cluster_role - cluster role (@ref zcl_cluster_role) - @param endpoint - endpoint - @param attr_id - attribute ID - @param value - pointer to attribute data - @return ZB_TRUE if data value is valid, ZB_FALSE otherwise -*/ -#if 0 -zb_bool_t zb_zcl_check_attr_value(zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *value) -{ - zb_bool_t ret = ZB_TRUE; - zb_ret_t cb_ret = RET_IGNORE; - - zb_zcl_cluster_check_value_t cluster_check_value; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_check_attr_value cluster_id %d, endpoint %hd, attr_id %d, value %p", - (FMT__D_H_D_P, cluster_id, endpoint, attr_id, value)); - - ZB_ASSERT(value); - - - if (ZCL_CTX().app_check_attr_value_cb) - { - cb_ret = ZCL_CTX().app_check_attr_value_cb(cluster_id, cluster_role, endpoint, attr_id, value); - } - - cluster_check_value = zb_zcl_get_cluster_check_value(cluster_id, - cluster_role); - - if (cb_ret != RET_IGNORE) - { - ret = (cb_ret == RET_OK) ? ZB_TRUE : ZB_FALSE; - } - else if (cluster_check_value) - { - ret = (cluster_check_value(attr_id, endpoint, value) == RET_ERROR) ? - ZB_FALSE : ZB_TRUE; - /*ret = cluster_check_value(attr_id, endpoint, value);*/ - } - else - { - if (zb_zcl_get_cluster_handler(cluster_id, ZB_ZCL_CLUSTER_SERVER_ROLE)) - { - TRACE_MSG(TRACE_ZCL3, "Cluster presents (0x%x), all attribute values allowed", (FMT__D, cluster_id)); - ret = ZB_TRUE; - } - else - { - TRACE_MSG(TRACE_ZCL1, "Error, cluster is not supported %x", (FMT__D, cluster_id)); - return ZB_FALSE; - } - } -/* CR: AEV: Where is call to ZCL_CTX().zb_zcl_check_attr_value_cb? Why it is removed? */ -/* Code Fix:DD: This callback was renamed to app_check_attr_value_cb. This callback is invoked -before cluster's check attribute value callback. */ - return ret; -} -#endif - -zb_ret_t zb_zcl_check_attr_value(zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *value) -{ - zb_ret_t ret; - zb_ret_t cb_ret = RET_IGNORE; - - zb_zcl_cluster_check_value_t cluster_check_value; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_check_attr_value cluster_id %d, endpoint %hd, attr_id %d, value %p", - (FMT__D_H_D_P, cluster_id, endpoint, attr_id, value)); - - ZB_ASSERT(value); - - - if (ZCL_CTX().app_check_attr_value_cb != NULL) - { - cb_ret = ZCL_CTX().app_check_attr_value_cb(cluster_id, cluster_role, endpoint, attr_id, value); - } - - cluster_check_value = zb_zcl_internal_get_cluster_check_value(endpoint, - cluster_id, - cluster_role); - - if (cb_ret != RET_IGNORE) - { - ret = cb_ret; - } - else if (cluster_check_value != NULL) - { - ret = cluster_check_value(attr_id, endpoint, value); - } - else - { - TRACE_MSG(TRACE_ZCL3, "Cluster (0x%x) has not check_value function, all attribute values allowed", (FMT__D, cluster_id)); - ret = RET_OK; - } -/* DD: Callback ZCL_CTX().zb_zcl_check_attr_value_cb was renamed to app_check_attr_value_cb. - This callback is invoked before cluster's check attribute value callback. */ - return ret; -} -/*! - Hook on Write Attribute command - @param endpoint - endpoint - @param cluster_id - cluster ID - @param cluster_id - cluster role (@ref zcl_cluster_role) - @param attr_id - attribute ID - @param new_value - new value of attribute -*/ -void zb_zcl_write_attr_hook( - zb_uint8_t endpoint, zb_uint16_t cluster_id, zb_uint8_t cluster_role, - zb_uint16_t attr_id, zb_uint8_t *new_value) -{ - zb_zcl_cluster_write_attr_hook_t cluster_write_attr_hook; - ZVUNUSED(endpoint); - ZVUNUSED(cluster_id); - ZVUNUSED(attr_id); - ZVUNUSED(new_value); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_write_attr_hook cluster_id %d, endpoint %hd, attr_id %d", - (FMT__D_H_D, cluster_id, endpoint, attr_id)); - - cluster_write_attr_hook = zb_zcl_internal_get_cluster_write_attr_hook(endpoint, - cluster_id, - cluster_role); - if (cluster_write_attr_hook != NULL) - { - cluster_write_attr_hook(endpoint, attr_id, new_value); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_write_attr_hook", (FMT__0)); -} - -/*! - Set attribute value cluster specific postprocessing - @param cmd_info - cluster role (@ref zcl_cluster_role) - @param attr_id - attribute ID - @param new_value - new value of attribute -*/ -void zb_zcl_set_attr_val_post_process_cluster_specific(zb_zcl_parsed_hdr_t *cmd_info, - zb_uint16_t attr_id, - zb_uint8_t *value) -{ - ZVUNUSED(cmd_info); - ZVUNUSED(attr_id); - ZVUNUSED(value); - - /* Supposedly the bette solution is to add - * one more type of the cluster handler */ - switch (cmd_info->cluster_id) - { - case ZB_ZCL_CLUSTER_ID_IAS_ZONE: -#ifdef ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE - zb_zcl_ias_set_attr_val_post_process(cmd_info, attr_id, value); -#endif - break; - default: - break; - } -} - -#endif /* ZB_ENABLE_ZCL */ diff --git a/zboss/development/src/zcl/zcl_basic_commands.c b/zboss/development/src/zcl/zcl_basic_commands.c deleted file mode 100644 index 90b8d76f57..0000000000 --- a/zboss/development/src/zcl/zcl_basic_commands.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Basic cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2061 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_BASIC) - -#include "zb_aps.h" -#include "zb_zcl.h" -#include "zb_zdo.h" -#include "zcl/zb_zcl_basic.h" - -static zb_uint8_t gs_basic_commands[] = { ZB_ZCL_CLUSTER_ID_BASIC_SERVER_ROLE_RECEIVED_CMD_LIST }; - -static zb_discover_cmd_list_t gs_basic_server_cmd_list = -{ - sizeof(gs_basic_commands), gs_basic_commands, - 0, NULL -}; - -static zb_discover_cmd_list_t gs_basic_client_cmd_list = -{ - 0, NULL, - sizeof(gs_basic_commands), gs_basic_commands -}; - -zb_ret_t check_value_basic_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -zb_bool_t zb_zcl_process_basic_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_basic_specific_commands_cli(zb_uint8_t param); - -void zb_zcl_basic_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_BASIC, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_basic_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_basic_specific_commands_srv); -} - -void zb_zcl_basic_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_BASIC, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_basic_specific_commands_cli); -} - -zb_ret_t check_value_basic_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} -/* Invoke User App for "Reset to Factory Defaults" command - */ -static void zb_zcl_basic_reset_invoke_user_app(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t result = RET_NOT_IMPLEMENTED; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_basic_reset_invoke_user_app param %hd", (FMT__H, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - if ( ZCL_CTX().set_default_attr_cb != NULL ) - { - (ZCL_CTX().set_default_attr_cb)(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint); - } - else - { - ZB_ZCL_RESET_TO_FACTORY_DEFAULTS_USER_APP(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, result); - } - - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, zb_zcl_get_zcl_status_from_ret(result)); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_basic_reset_invoke_user_app", (FMT__0)); -} - -zb_bool_t zb_zcl_check_is_device_enabled(zb_uint8_t ep_id, zb_uint8_t cmd_id, zb_uint16_t cluster_id, zb_bool_t is_common_command) -{ - zb_ret_t ret = ZB_TRUE; - zb_zcl_cluster_desc_t *cluster_desc = get_cluster_desc(zb_af_get_endpoint_desc(ep_id), ZB_ZCL_CLUSTER_ID_BASIC, ZB_ZCL_CLUSTER_SERVER_ROLE); - - if (cluster_desc) - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(ep_id, ZB_ZCL_CLUSTER_ID_BASIC, - ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_BASIC_DEVICE_ENABLED_ID); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_check_is_device_enabled ep_id %hd, cmd_id %hd, cluster_id %d, is_common_command %hd", (FMT__H_H_D_H, ep_id, cmd_id, cluster_id, ZB_B2U(is_common_command))); - if (attr_desc) - { - /* See ZCL spec 3.2.2.2.18 DeviceEnabled Attribute */ - if (!ZB_U2B(ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc))) - { - ret = ZB_FALSE; - if ((is_common_command && (cmd_id == ZB_ZCL_CMD_READ_ATTRIB || - cmd_id == ZB_ZCL_CMD_READ_ATTRIB_RESP || - cmd_id == ZB_ZCL_CMD_WRITE_ATTRIB || - cmd_id == ZB_ZCL_CMD_WRITE_ATTRIB_UNDIV || - cmd_id == ZB_ZCL_CMD_WRITE_ATTRIB_RESP || - cmd_id == ZB_ZCL_CMD_WRITE_ATTRIB_NO_RESP)) || - (!is_common_command && cluster_id == ZB_ZCL_CLUSTER_ID_IDENTIFY) || - (is_common_command && cmd_id == ZB_ZCL_CMD_DEFAULT_RESP && cluster_id == ZB_ZCL_CLUSTER_ID_IDENTIFY)) - { - ret = ZB_TRUE; - } - } - } - if (!ret) - { - TRACE_MSG(TRACE_ZCL1, "Device is disabled. The command should be dropped", (FMT__0)); - } - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_check_is_device_enabled ret %hd", (FMT__H, ZB_B2U(ret))); - return ret; -} - -zb_bool_t zb_zcl_process_basic_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_basic_client_cmd_list; - return ZB_TRUE; - } - return ZB_FALSE; -} - -zb_bool_t zb_zcl_process_basic_specific_commands_srv(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t status = RET_OK; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_basic_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_basic_specific_commands_srv: param %hd, cmd %hd", - (FMT__H_H, param, cmd_info.cmd_id)); - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_BASIC_RESET_ID: - TRACE_MSG(TRACE_ZCL3, "Processed RESET command", (FMT__0)); - ZB_SCHEDULE_CALLBACK(zb_zcl_basic_reset_invoke_user_app, param); - status = RET_BUSY; - break; - - default: - processed = ZB_FALSE; - break; - } - - if( processed ) - { - if( cmd_info.disable_default_response && status == RET_OK) - { - TRACE_MSG( TRACE_ZCL3, - "Default response disabled", - (FMT__0)); - zb_buf_free(param); - } - else if (status != RET_BUSY) - { - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - ZB_ZCL_SEND_DEFAULT_RESP( param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_BASIC, - cmd_info.seq_number, - cmd_info.cmd_id, - status==RET_OK ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_INVALID_FIELD); - } - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_basic_specific_commands|_srv: processed %d", - (FMT__D, processed)); - - return processed; -} -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_BASIC*/ diff --git a/zboss/development/src/zcl/zcl_binary_input.c b/zboss/development/src/zcl/zcl_binary_input.c deleted file mode 100644 index 3cc8cc9cc3..0000000000 --- a/zboss/development/src/zcl/zcl_binary_input.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Binary input cluster implementation. -*/ - - - -#define ZB_TRACE_FILE_ID 85 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_BINARY_INPUT) - -#include "zboss_api.h" -#include "zcl/zb_zcl_binary_input.h" - -static zb_ret_t check_value_binary_input_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_binary_input_init_server(void) -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_BINARY_INPUT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_binary_input_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - - -void zb_zcl_binary_input_init_client(void) -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_BINARY_INPUT, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -static zb_ret_t check_value_binary_input_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - ZVUNUSED(endpoint); - - switch (attr_id) - { - case ZB_ZCL_ATTR_BINARY_INPUT_OUT_OF_SERVICE_ID: - case ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID: - ret = ZB_ZCL_CHECK_BOOL_VALUE(*value) ? RET_OK : RET_ERROR; - break; - - case ZB_ZCL_ATTR_BINARY_INPUT_STATUS_FLAG_ID: - if (*value > ZB_ZCL_BINARY_INPUT_STATUS_FLAG_MAX_VALUE) - { - ret = RET_ERROR; - } - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_binary_input ret %hd", (FMT__H, ret)); - return ret; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_BINARY_INPUT */ diff --git a/zboss/development/src/zcl/zcl_c_daily_schedule.c b/zboss/development/src/zcl/zcl_c_daily_schedule.c deleted file mode 100644 index 4c6251d337..0000000000 --- a/zboss/development/src/zcl/zcl_c_daily_schedule.c +++ /dev/null @@ -1,456 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: CLIENT: Daily Schedule Cluster -*/ - -#define ZB_TRACE_FILE_ID 12 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_DAILY_SCHEDULE) || defined DOXYGEN - -#include "zcl/zb_zcl_daily_schedule.h" - -/******************************************************************************/ -/* Common definitions */ - -zb_uint8_t gs_daily_schedule_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_daily_schedule_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_daily_schedule_client_cmd_list = -{ - sizeof(gs_daily_schedule_client_received_commands), gs_daily_schedule_client_received_commands, - sizeof(gs_daily_schedule_client_generated_commands), gs_daily_schedule_client_generated_commands -}; - - -zb_bool_t zb_zcl_process_c_daily_schedule_specific_commands(zb_uint8_t param); - -static zb_ret_t check_value_daily_schedule(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_daily_schedule_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)check_value_daily_schedule, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_c_daily_schedule_specific_commands); -} - - -static zb_ret_t check_value_daily_schedule(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} - -#define PUT_PL_FUN(type) type ## _put_payload -#define PUT_PL_START(type, pl_var) \ -static zb_uint8_t *PUT_PL_FUN(type)(zb_uint8_t *data, const void *pl_arg) \ -{ \ - const type *pl_var = pl_arg; \ - ZB_ASSERT(pl_arg); \ - ZB_ASSERT(data); - -#define PUT_PL_END() return data; } - -PUT_PL_START(zb_zcl_daily_schedule_get_schedule_payload_t, pl) - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->provider_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->earliest_start_time); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->min_issuer_event_id); - ZB_ZCL_PACKET_PUT_DATA8 (data, pl->number_of_schedules); - ZB_ZCL_PACKET_PUT_DATA8 (data, pl->schedule_type); - -PUT_PL_END() - -PUT_PL_START(zb_zcl_daily_schedule_get_day_profile_payload_t, pl) - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->provider_id); - ZB_ZCL_PACKET_PUT_DATA16(data, &pl->day_id); -PUT_PL_END() - -#undef PUT_PL_START -#undef PUT_PL_END - -void zb_zcl_daily_schedule_send_cmd_get_schedule(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_daily_schedule_get_schedule_payload_t *pl, - zb_callback_t cb -) -{ - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, pl, sizeof(*pl), - PUT_PL_FUN(zb_zcl_daily_schedule_get_schedule_payload_t), - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE, - cb); -} - - -void zb_zcl_daily_schedule_send_cmd_get_day_profile(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_daily_schedule_get_day_profile_payload_t *pl, - zb_callback_t cb -) -{ - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, pl, sizeof(*pl), - PUT_PL_FUN(zb_zcl_daily_schedule_get_day_profile_payload_t), - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_DAY_PROFILE, - cb); -} - - -void zb_zcl_daily_schedule_send_cmd_get_schedule_cancellation(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - zb_callback_t cb -) -{ - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, NULL, 0, NULL, - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE_CANCELLATION, - cb); -} - - -/******************************************************************************/ -/* Client definitions */ - -//+ -static const zb_uint8_t *zb_zcl_daily_schedule_publish_schedule_parse_payload( - zb_zcl_daily_schedule_publish_schedule_payload_t *pl, zb_uint8_t bufid) -{ - zb_uint8_t *data = zb_buf_begin(bufid); - zb_uint8_t data_size = zb_buf_len(bufid); - - if (!ZB_ZCL_DAILY_SCHEDULE_PUBLISH_SCHEDULE_PL_SIZE_IS_VALID(data, data_size)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd, expected: %hd", (FMT__H_H, - data_size, ZB_ZCL_DAILY_SCHEDULE_PUBLISH_SCHEDULE_PL_EXPECTED_SIZE(pl))); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl->provider_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->issuer_event_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->schedule_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->start_time, data); - ZB_ZCL_PACKET_GET_DATA8 (&pl->schedule_type, data); - ZB_ZCL_PACKET_GET_DATA8 (&pl->schedule_time_reference, data); - - ZB_ZCL_PACKET_GET_STATIC_STRING(pl->schedule_name, data); - - if (!data) - { - TRACE_MSG(TRACE_ZCL1, "Invalid string len = %hd", - (FMT__H, ZB_ZCL_GET_STRING_LENGTH(pl->schedule_name))); - return NULL; - } - - return data; -} - - -static const zb_uint8_t *zb_zcl_daily_schedule_publish_day_profile_parse_payload( - zb_zcl_daily_schedule_publish_day_profile_payload_t *pl, - zb_uint8_t bufid) -{ - zb_uint8_t *data = zb_buf_begin(bufid); - zb_uint8_t data_size = zb_buf_len(bufid); - zb_uint8_t data_len = 0; - zb_uint8_t entry_count = 0, i; - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_daily_schedule_publish_day_profile_parse_payload", (FMT__0)); - - if (!ZB_ZCL_DAILY_SCHEDULE_PUBLISH_DAY_PROFILE_PL_SIZE_IS_VALID(data_size)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl->provider_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->issuer_event_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->schedule_id, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->total_number_of_schedule_entries, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->command_index, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->total_number_of_commands, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->schedule_type, data); - pl->day_schedule_entries = (zb_zcl_daily_schedule_entry_t *)data; - - data_len = data_size - (sizeof(zb_zcl_daily_schedule_publish_day_profile_payload_t) - sizeof(void *) - sizeof(zb_uint8_t)); - - switch (pl->schedule_type) - { - case ZB_ZCL_DAILY_SCHEDULE_TYPE_LINKY_SCHEDULE: - entry_count = data_len / sizeof(zb_zcl_daily_schedule_linky_schedule_entry_t); - - /* Restore byte order */ - for (i = 0; i < entry_count; i++) - { - ZB_LETOH16_ONPLACE(pl->day_schedule_entries[i].linky_schedule_entry.start_time); - } - - break; - } - - pl->number_of_entries_in_this_command = entry_count; - - TRACE_MSG(TRACE_ZCL1, "<>zb_zcl_daily_schedule_cancel_schedule_parse_payload", (FMT__0)); - - if (!ZB_ZCL_DAILY_SCHEDULE_CANCEL_SCHEDULE_PL_SIZE_IS_VALID(data_size)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl->provider_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->schedule_id, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->schedule_type, data); - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_daily_schedule_process_publish_schedule", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_DAILY_SCHEDULE_PUBLISH_SCHEDULE_CB_ID, - RET_ERROR, cmd_info, &pl_in, NULL); - - if (!zb_zcl_daily_schedule_publish_schedule_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - zb_zcl_send_default_handler(param, cmd_info, - (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); - - TRACE_MSG(TRACE_ZCL3, "<< zb_zcl_daily_schedule_process_publish_schedule", (FMT__0)); - - return ZB_TRUE; -} - -static zb_bool_t zb_zcl_daily_schedule_process_publish_day_profile(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_daily_schedule_publish_day_profile_payload_t pl_in = ZB_ZCL_DAILY_SCHEDULE_PUBLISH_DAY_PROFILE_PL_INIT; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_daily_schedule_process_publish_day_profile", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_DAILY_SCHEDULE_PUBLISH_DAY_PROFILE_CB_ID, - RET_ERROR, cmd_info, &pl_in, NULL); - if (!zb_zcl_daily_schedule_publish_day_profile_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid publish day profile payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - zb_zcl_send_default_handler(param, cmd_info, - (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_daily_schedule_process_publish_day_profile", (FMT__0)); - return ZB_TRUE; -} - -static zb_bool_t zb_zcl_daily_schedule_process_cancel_schedule(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_daily_schedule_cancel_schedule_payload_t pl_in = ZB_ZCL_DAILY_SCHEDULE_CANCEL_SCHEDULE_PL_INIT; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_daily_schedule_process_cancel_schedule", (FMT__0)); - - if (!zb_zcl_daily_schedule_cancel_schedule_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid cancel schedule payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_DAILY_SCHEDULE_CANCEL_SCHEDULE_CB_ID, - RET_NOT_FOUND, cmd_info, &pl_in, NULL); - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - zb_zcl_send_default_handler(param, cmd_info, - (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_daily_schedule_process_cancel_schedule", (FMT__0)); - - return ZB_TRUE; -} - -static zb_bool_t zb_zcl_daily_schedule_process_cancel_all_schedules(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_daily_schedule_process_cancel_all_schedules", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_DAILY_SCHEDULE_CANCEL_ALL_SCHEDULES_CB_ID, - RET_NOT_FOUND, cmd_info, NULL, NULL); - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - zb_zcl_send_default_handler(param, cmd_info, - (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_daily_schedule_process_cancel_all_schedules", (FMT__0)); - - return ZB_TRUE; -} - -static zb_bool_t zb_zcl_process_daily_schedule_cli_cmd(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_bool_t processed = ZB_FALSE; - - switch( (zb_zcl_daily_schedule_srv_cmd_t) cmd_info->cmd_id) - { - case ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_SCHEDULE: - processed = zb_zcl_daily_schedule_process_publish_schedule(param, cmd_info); - break; - case ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_DAY_PROFILE: - processed = zb_zcl_daily_schedule_process_publish_day_profile(param, cmd_info); - break; - case ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_SCHEDULE: - processed = zb_zcl_daily_schedule_process_cancel_schedule(param, cmd_info); - break; - case ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_ALL_SCHEDULES: - processed = zb_zcl_daily_schedule_process_cancel_all_schedules(param, cmd_info); - break; - /* FIXME: add default case */ -#ifdef WIP - default: - break; -#endif - } - - return processed; -} - - -/******************************************************************************/ -/* Handler definition */ -zb_bool_t zb_zcl_process_c_daily_schedule_specific_commands(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t processed = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_c_daily_schedule_specific_commands, " - "param=%hd", (FMT__H, param )); - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_daily_schedule_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - /* ZB_ASSERT(cmd_info.profile_id == ZB_AF_SE_PROFILE_ID); */ - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE); - - if (ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction) - { - processed = zb_zcl_process_daily_schedule_cli_cmd(param, &cmd_info); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_c_daily_schedule_specific_commands (ret=%hd, cmd_id=%hd)", - (FMT__H_H, processed, cmd_info.cmd_id)); - - return processed; -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_DAILY_SCHEDULE || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_c_drlc.c b/zboss/development/src/zcl/zcl_c_drlc.c deleted file mode 100644 index c536bcc518..0000000000 --- a/zboss/development/src/zcl/zcl_c_drlc.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: CLIENT: Demand Response and Load Control cluster definitions - -*/ - -#define ZB_TRACE_FILE_ID 24548 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_DRLC) || defined DOXYGEN - -#include "zcl/zb_zcl_drlc.h" - -/* Init 'zb_addr_u' from 'zb_zcl_parsed_hdr_t.src_addr' field */ -#define ZB_ADDR_INIT_FROM_CMD_INFO(_cmd_info) \ - { \ - .addr_short = ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).source.u.short_addr \ - } - -zb_uint8_t gs_drlc_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_DRLC_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_drlc_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_DRLC_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_drlc_client_cmd_list = -{ - sizeof(gs_drlc_client_received_commands), gs_drlc_client_received_commands, - sizeof(gs_drlc_client_generated_commands), gs_drlc_client_generated_commands -}; - -zb_bool_t zb_zcl_process_c_drlc_specific_commands(zb_uint8_t param); - -static zb_ret_t check_value_drlc(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_drlc_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_DRLC, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)check_value_drlc, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_c_drlc_specific_commands); -} - -static zb_ret_t check_value_drlc(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - - ZVUNUSED(endpoint); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID: - if( ZB_ZCL_ATTR_GET16(value) > ZB_ZCL_DRLC_CLUSTER_REVISION_MAX ) - { - ret = RET_ERROR; - } - break; - default: - ret = RET_OK; - break; - } - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return ret; -} -/** - * Client - * - * No Attributes - * - * 2 mandatory commands generated - * 3 mandatory commands handled - * - */ - -void zb_drlc_client_send_report_event_status(zb_uint8_t param, - zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_zcl_drlc_report_event_status_payload_t *payload, - zb_callback_t cb) -{ - zb_zcl_drlc_report_event_status_payload_t pl = ZB_ZCL_DRLC_REPORT_EVENT_STATUS_PAYLOAD_INIT; - zb_uint8_t *data = (zb_uint8_t *)&pl; - - TRACE_MSG(TRACE_ZCL1, ">> zb_drlc_client_send_report_event_status", (FMT__0)); - - ZB_BZERO(&pl, sizeof(pl)); - - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->issuer_event_id); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->event_status); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->event_status_time); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->criticality_level_applied); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->cooling_temperature_set_point_applied); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->heating_temperature_set_point_applied); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->average_load_adjustment_percentage_applied); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->duty_cycle_applied); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->event_control); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->signature_type); - ZB_ZCL_PACKET_PUT_DATA_N(data, &payload->signature, sizeof(pl.signature)); - - zb_zcl_send_cmd( - param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, - &pl, sizeof(pl), NULL, - ZB_ZCL_CLUSTER_ID_DRLC, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS, - cb - ); - - TRACE_MSG(TRACE_ZCL1, "<< zb_drlc_client_send_report_event_status", (FMT__0)); -} - -void zb_drlc_client_send_get_scheduled_events(zb_uint8_t param, - zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_zcl_drlc_get_scheduled_events_payload_t *payload, - zb_callback_t cb) -{ - zb_zcl_drlc_get_scheduled_events_payload_t pl = ZB_ZCL_DRLC_CMD_GET_SCHEDULED_EVENTS_PAYLOAD_INIT; - zb_uint8_t *data = (zb_uint8_t *)&pl; - - TRACE_MSG(TRACE_ZCL1, ">> zb_drlc_client_send_get_scheduled_events", (FMT__0)); - - ZB_BZERO(&pl, sizeof(pl)); - - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->start_time); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->number_of_events); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->issuer_event_id); - - zb_zcl_send_cmd( - param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, - &pl, sizeof(pl), NULL, - ZB_ZCL_CLUSTER_ID_DRLC, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DRLC_CLI_CMD_GET_SCHEDULED_EVENTS, - cb - ); - - TRACE_MSG(TRACE_ZCL1, "<< zb_drlc_client_send_get_scheduled_events", (FMT__0)); -} - -zb_ret_t zb_drlc_client_handle_load_control_event(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_drlc_lce_payload_t pl_in = ZB_ZCL_DRLC_LCE_PAYLOAD_INIT; - zb_zcl_drlc_report_event_status_payload_t pl_out = ZB_ZCL_DRLC_REPORT_EVENT_STATUS_PAYLOAD_INIT; - zb_addr_u dst_addr = ZB_ADDR_INIT_FROM_CMD_INFO(cmd_info); - zb_uint8_t *data = zb_buf_begin(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_drlc_client_handle_load_control_event", (FMT__0)); - - if (!ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT_IS_VALID(zb_buf_len(param))) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet len (%hd).", (FMT__H, zb_buf_len(param))); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return RET_INVALID_FORMAT; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl_in.issuer_event_id, data); - ZB_ZCL_PACKET_GET_DATA16(&pl_in.device_class, data); - ZB_ZCL_PACKET_GET_DATA8(&pl_in.utility_enrollment_group, data); - ZB_ZCL_PACKET_GET_DATA32(&pl_in.start_time, data); - ZB_ZCL_PACKET_GET_DATA16(&pl_in.duration_in_minutes, data); - ZB_ZCL_PACKET_GET_DATA8(&pl_in.criticality_level, data); - ZB_ZCL_PACKET_GET_DATA8(&pl_in.cooling_temperature_offset, data); - ZB_ZCL_PACKET_GET_DATA8(&pl_in.heating_temperature_offset, data); - ZB_ZCL_PACKET_GET_DATA16(&pl_in.cooling_temperature_set_point, data); - ZB_ZCL_PACKET_GET_DATA16(&pl_in.heating_temperature_set_point, data); - ZB_ZCL_PACKET_GET_DATA8(&pl_in.average_load_adjustment_percentage, data); - ZB_ZCL_PACKET_GET_DATA8(&pl_in.duty_cycle, data); - ZB_ZCL_PACKET_GET_DATA8(&pl_in.event_control, data); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DRLC_LOAD_CONTROL_EVENT_CB_ID, RET_OK, cmd_info, &pl_in, &pl_out); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - zb_drlc_client_send_report_event_status(param, - &dst_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - &pl_out, NULL); - } - else - { - TRACE_MSG(TRACE_ZCL1, "<< error in user cb call:%d", (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - zb_buf_free(param); - return RET_ERROR; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_drlc_client_handle_load_control_event", (FMT__0)); - - return RET_OK; -} - -zb_ret_t zb_drlc_client_handle_cancel_load_control_event(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_drlc_cancel_lce_payload_t pl_in = ZB_ZCL_DRLC_CANCEL_LCE_PAYLOAD_INIT; - zb_zcl_drlc_report_event_status_payload_t pl_out = ZB_ZCL_DRLC_REPORT_EVENT_STATUS_PAYLOAD_INIT; - zb_addr_u dst_addr = ZB_ADDR_INIT_FROM_CMD_INFO(cmd_info); - zb_uint8_t *data = zb_buf_begin(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_drlc_client_handle_cancel_load_control_event", (FMT__0)); - - if (!ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT_IS_VALID(zb_buf_len(param))) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet len (%hd).", (FMT__H, zb_buf_len(param))); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return RET_INVALID_FORMAT; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl_in.issuer_event_id, data); - ZB_ZCL_PACKET_GET_DATA16(&pl_in.device_class, data); - ZB_ZCL_PACKET_GET_DATA8(&pl_in.utility_enrollment_group, data); - ZB_ZCL_PACKET_GET_DATA8(&pl_in.cancel_control, data); - ZB_ZCL_PACKET_GET_DATA32(&pl_in.effective_time, data); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DRLC_CANCEL_LOAD_CONTROL_EVENT_CB_ID, RET_ERROR, cmd_info, &pl_in, &pl_out); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_drlc_client_handle_cancel_load_control_event", (FMT__0)); - -/*Note: If the Cancel Load Control Event command is received after the event has ended, the -device shall reply using the "Report Event Status Command" with an Event Status of "Rejected -- Invalid Cancel Command (Undefined Event)"*/ -/** - * We do not send replies, this is application's task since it is responsible - * for calling send_report_event for each registered cancelled event - */ - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - zb_drlc_client_send_report_event_status(param, - &dst_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - &pl_out, - NULL); - } - else - { - TRACE_MSG(TRACE_ZCL1, "<< error in user cb call:%d", (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - zb_buf_free(param); - return RET_ERROR; - } - - return RET_OK; -} - -zb_ret_t zb_drlc_client_handle_cancel_all_load_control_events(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_drlc_cancel_alce_payload_t pl_in = ZB_ZCL_DRLC_CANCEL_ALCE_PAYLOAD_INIT; - zb_uint8_t *data = zb_buf_begin(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_drlc_client_handle_cancel_all_load_control_events", (FMT__0)); - - if (!ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS_IS_VALID(zb_buf_len(param))) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet len (%hd).", (FMT__H, zb_buf_len(param))); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return RET_INVALID_FORMAT; - } - - ZB_ZCL_PACKET_GET_DATA8(&pl_in.cancel_control, data); - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DRLC_CANCEL_ALL_LOAD_CONTROL_EVENTS_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_drlc_client_handle_cancel_all_load_control_events", (FMT__0)); - - /* SE spec: - * The Cancel All Load Control Events command is processed by the device as if individual - * Cancel Load Control Event commands were received for all of the currently stored events in the device. - * The device will respond with a "Report Event Status Command" for each individual load control event canceled.*/ - - /* NOTE: We do not send replies, this is application's task since it is responsible - * for calling send_report_event for each registered cancelled event - */ - - zb_buf_free(param); - - return RET_OK; -} - -static zb_bool_t zb_zcl_process_drlc_client_commands(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_uint8_t processed = ZB_FALSE; - zb_ret_t result = RET_ERROR; - /* ZCL8: CCB 2477: use UNSUP_COMMAND instead of Unsupported cluster command status */ - zb_uint8_t status = ZB_ZCL_STATUS_UNSUP_CMD; - - switch ((zb_zcl_drlc_srv_cmd_t) cmd_info->cmd_id) - { - case ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT: - result = zb_drlc_client_handle_load_control_event(param, cmd_info); - status = (RET_OK == result) ? ZB_ZCL_STATUS_SUCCESS: - ((RET_INVALID_FORMAT == result) ? ZB_ZCL_STATUS_INVALID_FIELD : ZB_ZCL_STATUS_FAIL); - processed = ZB_TRUE; - break; - case ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT: - result = zb_drlc_client_handle_cancel_load_control_event(param, cmd_info); - status = (RET_OK == result) ? ZB_ZCL_STATUS_SUCCESS: - ((RET_INVALID_FORMAT == result) ? ZB_ZCL_STATUS_INVALID_FIELD : ZB_ZCL_STATUS_FAIL); - processed = ZB_TRUE; - break; - case ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS: - result = zb_drlc_client_handle_cancel_all_load_control_events(param, cmd_info); - status = (RET_OK == result) ? ZB_ZCL_STATUS_SUCCESS: - ((RET_INVALID_FORMAT == result) ? ZB_ZCL_STATUS_INVALID_FIELD : ZB_ZCL_STATUS_FAIL); - processed = ZB_TRUE; - break; - default: - break; - } - - if (!processed) - { - if (!cmd_info->disable_default_response) - { - ZB_ZCL_SEND_DEFAULT_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - cmd_info->seq_number, - cmd_info->cmd_id, - status); - } - else - { - zb_buf_free(param); - } - } - return ZB_TRUE; -} - - -/** - * - */ - -zb_bool_t zb_zcl_process_c_drlc_specific_commands(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_drlc_specific_commands", (FMT__0)); - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_drlc_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - /* ZB_ASSERT(cmd_info.profile_id == ZB_AF_SE_PROFILE_ID); */ - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_DRLC); - - if(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction) - { - return zb_zcl_process_drlc_client_commands(param, &cmd_info); - } - - return ZB_FALSE; -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_DRLC || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_c_messaging.c b/zboss/development/src/zcl/zcl_c_messaging.c deleted file mode 100644 index 594b14035f..0000000000 --- a/zboss/development/src/zcl/zcl_c_messaging.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: CLIENT: Messaging cluster handlers -*/ - -#define ZB_TRACE_FILE_ID 92 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_MESSAGING) || defined DOXYGEN - -#include "zboss_api.h" -#include "zcl/zb_zcl_messaging.h" - -zb_uint8_t gs_messaging_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_MESSAGING_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_messaging_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_MESSAGING_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_messaging_client_cmd_list = -{ - sizeof(gs_messaging_client_received_commands), gs_messaging_client_received_commands, - sizeof(gs_messaging_client_generated_commands), gs_messaging_client_generated_commands -}; - - - -typedef zb_uint8_t *(zb_zcl_messaging_put_payload_cb_t)(zb_uint8_t *, const void *); - - -static zb_uint8_t *zb_zcl_messaging_msg_confirmation_put_payload( - zb_uint8_t *data, const void *_payload) -{ - const zb_zcl_messaging_message_confirm_payload_t *payload = _payload; - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->message_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->confirmation_time); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->message_confirmation_control); - ZB_ZCL_PACKET_PUT_STRING(data, payload->message_confirmation_response); - return data; -} - -void zb_zcl_messaging_send_get_last_msg(zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_callback_t cb) -{ - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_messaging_send_get_last_msg", (FMT__0)); - - zb_zcl_send_cmd(param, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, - NULL, 0, NULL, - ZB_ZCL_CLUSTER_ID_MESSAGING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_MESSAGING_CLI_CMD_GET_LAST_MESSAGE, - cb - ); - - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_messaging_send_get_last_msg", (FMT__0)); -} - -void zb_zcl_messaging_send_msg_confirmation(zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_messaging_message_confirm_payload_t *payload, - zb_callback_t cb) -{ - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_messaging_send_msg_confirmation", (FMT__0)); - - zb_zcl_send_cmd(param, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, - payload, sizeof(*payload), zb_zcl_messaging_msg_confirmation_put_payload, - ZB_ZCL_CLUSTER_ID_MESSAGING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_MESSAGING_CLI_CMD_MESSAGE_CONFIRMATION, - cb - ); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_messaging_send_msg_confirmation", (FMT__0)); -} - - -static void zb_zcl_messaging_client_handle_cancel_message(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_messaging_cancel_message_payload_t pl = ZB_ZCL_MESSAGING_CANCEL_MSG_PAYLOAD_INIT; - zb_uint8_t *data = zb_buf_begin(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_messaging_client_handle_cancel_message", (FMT__0)); - - if (!ZB_ZCL_MESSAGING_MSG_CANCEL_MESSAGE_SIZE_IS_VALID(zb_buf_len(param))) - { - TRACE_MSG(TRACE_ZCL1, "malformed packet (small), prevented buffer overflow (%hd)", - (FMT__H, zb_buf_len(param))); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl.message_id, data); - ZB_ZCL_PACKET_GET_DATA8(&pl.message_control, data); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_MESSAGING_CANCEL_MSG_CB_ID, RET_OK, cmd_info, &pl, NULL); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_messaging_client_handle_cancel_message", (FMT__0)); - - zb_zcl_send_default_handler(param, cmd_info, - (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); -} - - -static void zb_zcl_messaging_client_handle_display_message(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_messaging_display_message_payload_t pl = ZB_ZCL_MESSAGING_DISPLAY_MSG_PAYLOAD_INIT; - zb_uint8_t *data = zb_buf_begin(param); - zb_int16_t pkt_len = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_messaging_client_handle_display_message", (FMT__0)); - - if (!ZB_ZCL_MESSAGING_DISPLAY_MSG_PAYLOAD_SIZE_IS_VALID(pkt_len)) - { - TRACE_MSG(TRACE_ZCL1, "malformed packet (small), prevented buffer overflow (%hd)", - (FMT__H, pkt_len)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl.message_id, data); - ZB_ZCL_PACKET_GET_DATA8(&pl.message_control, data); - ZB_ZCL_PACKET_GET_DATA32(&pl.start_time, data); - ZB_ZCL_PACKET_GET_DATA16(&pl.duration_in_minutes, data); - ZB_ZCL_PACKET_GET_DATA8(&pl.message_len, data); - data+=pl.message_len; - pkt_len-=pl.message_len+12; - - if (ZB_ZCL_MESSAGING_INTER_PAN_TRANSMISSION_ONLY == ZB_ZCL_MESSAGING_MESSAGE_CONTROL_GET_TRANSMISSION_MECHANISM(pl.message_control)) - { - TRACE_MSG(TRACE_ZCL1, "Use of the Inter-PAN transmission mechanism within the Messaging cluster is now deprecated.", - (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - if (pkt_len>0) - { - ZB_ZCL_PACKET_GET_DATA8(&pl.extended_message_control, data); - TRACE_MSG(TRACE_ZCL3, "Extended message control field present: %hd.",(FMT__H,pl.extended_message_control)); - } - else - { - pl.extended_message_control = 1; - } - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_MESSAGING_DISPLAY_MSG_CB_ID, RET_OK, cmd_info, &pl, NULL); - -/*NOTE: AEV: this done after ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH, because of this function can move buffer*/ - pl.message = (zb_uint8_t*)zb_buf_begin(param)+ZB_OFFSETOF(zb_zcl_messaging_display_message_payload_t, message); - - DUMP_TRAF("msg:", (zb_uint8_t *)pl.message, pl.message_len, 0); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - zb_zcl_send_default_handler(param, cmd_info, - (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_messaging_client_handle_display_message", (FMT__0)); -} - -static zb_bool_t zb_zcl_messaging_client_side_process_commands(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_bool_t processed = ZB_FALSE; - - switch ((zb_zcl_messaging_srv_cmd_t) cmd_info->cmd_id) - { - case ZB_ZCL_MESSAGING_SRV_CMD_CANCEL_MESSAGE: - zb_zcl_messaging_client_handle_cancel_message(param, cmd_info); - processed = ZB_TRUE; - break; - case ZB_ZCL_MESSAGING_SRV_CMD_DISPLAY_MESSAGE: - zb_zcl_messaging_client_handle_display_message(param, cmd_info); - processed = ZB_TRUE; - break; - default: - break; - } - - return processed; -} - - -zb_bool_t zb_zcl_process_c_messaging_specific_command(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t res = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_c_messaging_specific_command param %hd", (FMT__H, param)); - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_messaging_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - /* ZB_ASSERT(cmd_info.profile_id == ZB_AF_SE_PROFILE_ID); */ - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_MESSAGING); - - if (ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction) - { - /* process commands sent by servers */ - res = zb_zcl_messaging_client_side_process_commands(param, &cmd_info); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_c_messaging_specific_command", (FMT__0)); - return res; -} - -void zb_zcl_messaging_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_MESSAGING, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_c_messaging_specific_command); -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_MESSAGING || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_c_metering.c b/zboss/development/src/zcl/zcl_c_metering.c deleted file mode 100644 index a7d5730410..0000000000 --- a/zboss/development/src/zcl/zcl_c_metering.c +++ /dev/null @@ -1,918 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: CLIENT: Metering Cluster -*/ - -#define ZB_TRACE_FILE_ID 4000 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_METERING) || defined DOXYGEN - -#include "zcl/zb_zcl_metering.h" - -zb_uint8_t gs_metering_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_METERING_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_metering_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_METERING_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_metering_client_cmd_list = -{ - sizeof(gs_metering_client_received_commands), gs_metering_client_received_commands, - sizeof(gs_metering_client_generated_commands), gs_metering_client_generated_commands -}; - -zb_bool_t zb_zcl_process_c_metering_specific_commands(zb_uint8_t param); - -void zb_zcl_metering_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)zb_zcl_process_c_metering_specific_commands); -} - -void zb_zcl_metering_send_cmd_get_snapshot(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_zcl_metering_get_snapshot_payload_t *payload, - zb_callback_t cb) -{ - zb_zcl_metering_get_snapshot_payload_t pl; - zb_uint8_t *data = (zb_uint8_t *) &pl; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_server_send_get_snapshot", (FMT__0)); - - ZB_BZERO(&pl, sizeof(pl)); - - - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->earliest_start_time); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->latest_end_time); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->snapshot_offset); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->snapshot_cause); - - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, &pl, sizeof(pl), NULL, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_CLI_CMD_GET_SNAPSHOT, - cb); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_server_send_get_snapshot", (FMT__0)); -} - - -void zb_zcl_metering_send_cmd_get_sampled_data(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_zcl_metering_get_sampled_data_payload_t *payload, - zb_callback_t cb) -{ - zb_zcl_metering_get_sampled_data_payload_t pl; - zb_uint8_t *data = (zb_uint8_t *) &pl; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_server_send_get_sampled_data", (FMT__0)); - - ZB_BZERO(&pl, sizeof(pl)); - - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->sample_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->earliest_sample_time); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->sample_type); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->number_of_samples); - - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, &pl, sizeof(pl), NULL, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_CLI_CMD_GET_SAMPLED_DATA, - cb); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_server_send_get_sampled_data", (FMT__0)); -} - - -void zb_zcl_metering_send_cmd_request_fast_poll_mode(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_zcl_metering_request_fast_poll_mode_payload_t *payload, - zb_callback_t cb) -{ - zb_zcl_metering_request_fast_poll_mode_payload_t pl; - zb_uint8_t *data = (zb_uint8_t *) &pl; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_server_send_request_fast_poll_mode", (FMT__0)); - - ZB_BZERO(&pl, sizeof(pl)); - - ZB_ZCL_PACKET_PUT_DATA8(data, payload->fast_poll_update_period); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->duration_in_minutes); - - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, &pl, sizeof(pl), NULL, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_CLI_CMD_REQUEST_FAST_POLL_MODE, - cb); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_server_send_request_fast_poll_mode", (FMT__0)); -} - - -void zb_zcl_metering_send_cmd_get_profile(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_zcl_metering_get_profile_payload_t *payload, - zb_callback_t cb) -{ - zb_zcl_metering_get_profile_payload_t pl; - zb_uint8_t *data = (zb_uint8_t *) &pl; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_server_send_get_profile", (FMT__0)); - - ZB_BZERO(&pl, sizeof(pl)); - - ZB_ZCL_PACKET_PUT_DATA8(data, payload->interval_channel); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->end_time); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->number_of_periods); - - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, &pl, sizeof(pl), NULL, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_CLI_CMD_GET_PROFILE, - cb); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_server_send_get_profile", (FMT__0)); -} - - -static const zb_uint8_t *zb_zcl_metering_request_fast_poll_mode_response_parse_payload( - zb_zcl_metering_request_fast_poll_mode_response_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_metering_request_fast_poll_mode_response_parse_payload", (FMT__0)); - - if (data_size < sizeof(zb_zcl_metering_request_fast_poll_mode_response_payload_t)) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA8(&pl->applied_update_period_in_seconds, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->fast_poll_mode_end_time, data); - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_metering_get_sampled_data_response_parse_payload", (FMT__0)); - - if (data_size >= (ZB_OFFSETOF(zb_zcl_metering_get_sampled_data_response_payload_t, samples))) - { - ZB_ZCL_PACKET_GET_DATA16(&pl->sample_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->sample_start_time, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->sample_type, data); - ZB_ZCL_PACKET_GET_DATA16(&pl->sample_request_interval, data); - ZB_ZCL_PACKET_GET_DATA16(&pl->number_of_samples, data); - - data_size -= ZB_OFFSETOF(zb_zcl_metering_get_sampled_data_response_payload_t, samples); - - if (data_size == ZB_24BIT_SIZE * pl->number_of_samples) - { - pl->samples = (zb_uint24_t *)data; - } - else - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet, remaining size:%d, expected remaining size:%d", - (FMT__D_D, data_size, ZB_24BIT_SIZE * pl->number_of_samples)); - data = NULL; - } - - } - else - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - data = NULL; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_get_sampled_data_response_parse_payload", (FMT__0)); - - return data; -} - - -static const zb_uint8_t *zb_zcl_metering_publish_snapshot_parse_payload(zb_zcl_metering_publish_snapshot_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_publish_snapshot_parse_payload", (FMT__0)); - - if (data_size < ZB_OFFSETOF(zb_zcl_metering_publish_snapshot_payload_t, snapshot_sub_payload)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size", (FMT__0)); - return NULL; - } - - data_size -= ZB_OFFSETOF(zb_zcl_metering_publish_snapshot_payload_t, snapshot_sub_payload); - - ZB_ZCL_PACKET_GET_DATA32(&pl->snapshot_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->snapshot_time, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->total_snapshots_found, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->command_index, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->total_number_of_commands, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->snapshot_cause, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->snapshot_payload_type, data); - - switch (pl->snapshot_payload_type) - { - case ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS: - { - zb_zcl_metering_tou_delivered_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_delivered); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS", (FMT__0)); - - if (data_size < ZB_OFFSETOF(zb_zcl_metering_tou_delivered_payload_t, tier_summation)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid sub-payload size", (FMT__0)); - return NULL; - } - - data_size -= ZB_OFFSETOF(zb_zcl_metering_tou_delivered_payload_t, tier_summation); - - ZB_ZCL_PACKET_GET_DATA48(&sub_payload->current_summation_delivered, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->bill_to_date_delivered, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->bill_to_date_time_stamp_delivered, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->projected_bill_delivered, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->projected_bill_time_stamp_delivered, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->bill_delivered_trailing_digit, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_in_use, data); - - if (data_size != (sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE)) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - return NULL; - } - - sub_payload->tier_summation = (zb_uint48_t *)data; - } - break; - case ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS: - { - zb_zcl_metering_tou_received_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_received); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS", (FMT__0)); - - if (data_size < ZB_OFFSETOF(zb_zcl_metering_tou_received_payload_t, tier_summation)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid sub-payload size", (FMT__0)); - return NULL; - } - - data_size -= ZB_OFFSETOF(zb_zcl_metering_tou_received_payload_t, tier_summation); - - ZB_ZCL_PACKET_GET_DATA48(&sub_payload->current_summation_received, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->bill_to_date_received, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->bill_to_date_time_stamp_received, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->projected_bill_received, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->projected_bill_time_stamp_received, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->bill_received_trailing_digit, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_in_use, data); - - if (data_size != (sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE)) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - return NULL; - } - - sub_payload->tier_summation = (zb_uint48_t *)data; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_DELIVERED: - { - zb_zcl_metering_block_delivered_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_delivered); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_DELIVERED", (FMT__0)); - - if (data_size < ZB_OFFSETOF(zb_zcl_metering_block_delivered_payload_t, tier_summation)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid sub-payload size", (FMT__0)); - return NULL; - } - - data_size -= ZB_OFFSETOF(zb_zcl_metering_block_delivered_payload_t, tier_summation); - - ZB_ZCL_PACKET_GET_DATA48(&sub_payload->current_summation_delivered, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->bill_to_date_delivered, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->bill_to_date_time_stamp_delivered, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->projected_bill_delivered, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->projected_bill_time_stamp_delivered, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->bill_delivered_trailing_digit, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_in_use, data); - - if (data_size < (sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE)) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - return NULL; - } - - sub_payload->tier_summation = (zb_uint48_t *)data; - - /*subtract tier_summation size*/ - data_size -= sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - - data += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; /* move pointer to number_of_tiers_and_block_thresholds_in_use */ - - if (0 == data_size) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet: can't parse after tier_summation", (FMT__0)); - return NULL; - } - - /*subtract 1 byte for number_of_tiers_and_block_thresholds_in_use*/ - data_size -= 1; - - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_and_block_thresholds_in_use, data); - - if (data_size != sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet: can't parse tier_block_summation", (FMT__0)); - return NULL; - } - - sub_payload->tier_block_summation = (zb_uint48_t *)data; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_RECEIVED: - { - zb_zcl_metering_block_received_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_received); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_RECEIVED", (FMT__0)); - - if (data_size < ZB_OFFSETOF(zb_zcl_metering_block_received_payload_t, tier_summation)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid sub-payload size", (FMT__0)); - return NULL; - } - - data_size -= ZB_OFFSETOF(zb_zcl_metering_block_received_payload_t, tier_summation); - - ZB_ZCL_PACKET_GET_DATA48(&sub_payload->current_summation_received, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->bill_to_date_received, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->bill_to_date_time_stamp_received, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->projected_bill_received, data); - ZB_ZCL_PACKET_GET_DATA32(&sub_payload->projected_bill_time_stamp_received, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->bill_received_trailing_digit, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_in_use, data); - - if (data_size < (sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE)) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - return NULL; - } - - sub_payload->tier_summation = (zb_uint48_t *)data; - - /*subtract tier_summation size*/ - data_size -= sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - - data += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; /* move pointer to number_of_tiers_and_block_thresholds_in_use */ - - if (0 == data_size) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet: can't parse after tier_summation", (FMT__0)); - return NULL; - } - - /*subtract 1 byte for number_of_tiers_and_block_thresholds_in_use*/ - data_size -= 1; - - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_and_block_thresholds_in_use, data); - - if (data_size != sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet: can't parse tier_block_summation", (FMT__0)); - return NULL; - } - - sub_payload->tier_block_summation = (zb_uint48_t *)data; - } - break; - case ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING: - { - zb_zcl_metering_tou_delivered_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_delivered_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING", (FMT__0)); - - if (data_size < ZB_OFFSETOF(zb_zcl_metering_tou_delivered_no_billing_payload_t, tier_summation)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid sub-payload size", (FMT__0)); - return NULL; - } - - data_size -= ZB_OFFSETOF(zb_zcl_metering_tou_delivered_no_billing_payload_t, tier_summation); - - ZB_ZCL_PACKET_GET_DATA48(&sub_payload->current_summation_delivered, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_in_use, data); - - if (data_size < (sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE)) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - return NULL; - } - - sub_payload->tier_summation = (zb_uint48_t *)data; - } - break; - case ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING: - { - zb_zcl_metering_tou_received_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_received_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING", (FMT__0)); - - if (data_size < ZB_OFFSETOF(zb_zcl_metering_tou_received_no_billing_payload_t, tier_summation)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid sub-payload size", (FMT__0)); - return NULL; - } - - data_size -= ZB_OFFSETOF(zb_zcl_metering_tou_received_no_billing_payload_t, tier_summation); - - ZB_ZCL_PACKET_GET_DATA48(&sub_payload->current_summation_received, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_in_use, data); - - if (data_size < (sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE)) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - return NULL; - } - - sub_payload->tier_summation = (zb_uint48_t *)data; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING: - { - zb_zcl_metering_block_tier_delivered_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_tier_delivered_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING", (FMT__0)); - - if (data_size < ZB_OFFSETOF(zb_zcl_metering_block_tier_delivered_no_billing_payload_t, tier_summation)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid sub-payload size", (FMT__0)); - return NULL; - } - - data_size -= ZB_OFFSETOF(zb_zcl_metering_block_tier_delivered_no_billing_payload_t, tier_summation); - - ZB_ZCL_PACKET_GET_DATA48(&sub_payload->current_summation_delivered, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_in_use, data); - - if (data_size < (sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE)) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - return NULL; - } - - sub_payload->tier_summation = (zb_uint48_t *)data; - - /*subtract tier_summation size*/ - data_size -= sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - - data += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; /* move pointer to number_of_tiers_and_block_thresholds_in_use */ - - if (0 == data_size) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet: can't parse after tier_summation", (FMT__0)); - return NULL; - } - - /*subtract 1 byte for number_of_tiers_and_block_thresholds_in_use*/ - data_size -= 1; - - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_and_block_thresholds_in_use, data); - - if (data_size != sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet: can't parse tier_block_summation", (FMT__0)); - return NULL; - } - - sub_payload->tier_block_summation = (zb_uint48_t *)data; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING: - { - zb_zcl_metering_block_tier_received_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_tier_received_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING", (FMT__0)); - - if (data_size < ZB_OFFSETOF(zb_zcl_metering_block_tier_received_no_billing_payload_t, tier_summation)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid sub-payload size", (FMT__0)); - return NULL; - } - - data_size -= ZB_OFFSETOF(zb_zcl_metering_block_tier_received_no_billing_payload_t, tier_summation); - - ZB_ZCL_PACKET_GET_DATA48(&sub_payload->current_summation_received, data); - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_in_use, data); - - if (data_size < (sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE)) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - return NULL; - } - - sub_payload->tier_summation = (zb_uint48_t *)data; - - /*subtract tier_summation size*/ - data_size -= sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - - data += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; /* move pointer to number_of_tiers_and_block_thresholds_in_use */ - - if (0 == data_size) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet: can't parse after tier_summation", (FMT__0)); - return NULL; - } - - /*subtract 1 byte for number_of_tiers_and_block_thresholds_in_use*/ - data_size -= 1; - - ZB_ZCL_PACKET_GET_DATA8(&sub_payload->number_of_tiers_and_block_thresholds_in_use, data); - - if (data_size != sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet: can't parse tier_block_summation", (FMT__0)); - return NULL; - } - - sub_payload->tier_block_summation = (zb_uint48_t *)data; - } - break; - case ZB_ZCL_METERING_DATA_UNAVAILABLE: - /*NOTE: from SE spec: The data for this snapshot is currently unavailable; - * if used, there is currently no subsequent snapshot data. - */ - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_DATA_UNAVAILABLE", (FMT__0)); - if (data_size != 0) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - return NULL; - } - break; - default: - TRACE_MSG(TRACE_ZCL1, "Malformed packet: unsupported snapshot payload type", (FMT__0)); - return NULL; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_publish_snapshot_parse_payload", (FMT__0)); - - return data; -} - -static const zb_uint8_t *zb_zcl_metering_get_profile_response_parse_payload(zb_zcl_metering_get_profile_response_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_metering_get_profile_response_parse_payload", (FMT__0)); - - if (data_size >= (ZB_OFFSETOF(zb_zcl_metering_get_profile_response_payload_t, intervals))) - { - ZB_ZCL_PACKET_GET_DATA32(&pl->end_time, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->status, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->profile_interval_period, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->number_of_periods_delivered, data); - - data_size -= ZB_OFFSETOF(zb_zcl_metering_get_profile_response_payload_t, intervals); - - if (data_size == ZB_24BIT_SIZE * pl->number_of_periods_delivered) - { - pl->intervals = (zb_uint24_t *)data; - } - else - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet, remaining size:%d, expected remaining size:%d", - (FMT__D_D, data_size, ZB_24BIT_SIZE * pl->number_of_periods_delivered)); - data = NULL; - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet, data_size:%d", (FMT__D, data_size)); - data = NULL; - } - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_metering_process_request_fast_poll_mode_response", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_REQUEST_FAST_POLL_MODE_RESPONSE_CB_ID, - RET_ERROR, cmd_info, &pl_in, NULL); - - if (!zb_zcl_metering_request_fast_poll_mode_response_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid request_fast_poll_mode_response command payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_SUCCESS); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_request_fast_poll_mode_response", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_metering_process_publish_snapshot(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_metering_publish_snapshot_payload_t pl_in ; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_process_publish_snapshot", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_PUBLISH_SNAPSHOT_CB_ID, - RET_ERROR, cmd_info, &pl_in, NULL); - - if (!zb_zcl_metering_publish_snapshot_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid publish_snapshot command payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_SUCCESS); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_publish_snapshot", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_metering_process_get_sampled_data_response(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_metering_get_sampled_data_response_payload_t pl_in ; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_process_get_sampled_data_response", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_GET_SAMPLED_DATA_RESPONSE_CB_ID, - RET_ERROR, cmd_info, &pl_in, NULL); - - if (!zb_zcl_metering_get_sampled_data_response_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid get_sampled_data_response command payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_SUCCESS); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_get_sampled_data_response", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_metering_process_get_profile_response(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_metering_get_profile_response_payload_t pl_in ; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_process_get_profile_response", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_GET_PROFILE_RESPONSE_CB_ID, - RET_ERROR, cmd_info, &pl_in, NULL); - - if (!zb_zcl_metering_get_profile_response_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid get_profile_response command payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_SUCCESS); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_get_profile_response", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_process_metering_client_commands(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_bool_t processed = ZB_FALSE; - - switch ((zb_zcl_metering_cli_cmd_t)cmd_info->cmd_id) - { - case ZB_ZCL_METERING_SRV_CMD_GET_PROFILE_RESPONSE: - processed = zb_zcl_metering_process_get_profile_response(param, cmd_info); - break; - case ZB_ZCL_METERING_SRV_CMD_REQUEST_FAST_POLL_MODE_RESPONSE: - processed = zb_zcl_metering_process_request_fast_poll_mode_response(param, cmd_info); - break; - case ZB_ZCL_METERING_SRV_CMD_PUBLISH_SNAPSHOT: - processed = zb_zcl_metering_process_publish_snapshot(param, cmd_info); - break; - case ZB_ZCL_METERING_SRV_CMD_GET_SAMPLED_DATA_RESPONSE: - processed = zb_zcl_metering_process_get_sampled_data_response(param, cmd_info); - break; - default: - break; - } - - return processed; -} - - -zb_bool_t zb_zcl_process_c_metering_specific_commands(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t processed = ZB_FALSE; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_metering_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_c_metering_specific_commands, " - "param=%hd, cmd_id=%hd", (FMT__H_H, param, cmd_info.cmd_id)); - - /* ZB_ASSERT(cmd_info.profile_id == ZB_AF_SE_PROFILE_ID); */ - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_METERING); - - if (ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction) - { - processed = zb_zcl_process_metering_client_commands(param, &cmd_info); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_c_metering_specific_commands (ret=%hd)", - (FMT__H, processed)); - - return processed; -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_METERING || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_c_price.c b/zboss/development/src/zcl/zcl_c_price.c deleted file mode 100644 index a758e033eb..0000000000 --- a/zboss/development/src/zcl/zcl_c_price.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: CLIENT: Smart Energy Price Cluster -*/ - -#define ZB_TRACE_FILE_ID 3998 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_PRICE) || defined DOXYGEN - -zb_uint8_t gs_price_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_PRICE_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_price_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_PRICE_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_price_client_cmd_list = -{ - sizeof(gs_price_client_received_commands), gs_price_client_received_commands, - sizeof(gs_price_client_generated_commands), gs_price_client_generated_commands -}; - -typedef zb_uint8_t *(*zb_price_put_payload_cb_t)(zb_uint8_t *, const void *); - -zb_bool_t zb_zcl_process_c_price_specific_commands(zb_uint8_t param); - - -static zb_ret_t check_value_price(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_price_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_PRICE, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)check_value_price, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_c_price_specific_commands); -} - - -static zb_ret_t check_value_price(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} - - -/* convert raw data into payload */ -static ZB_INLINE const zb_uint8_t *zb_zcl_price_publish_price_get_payload_from_data( - zb_zcl_price_publish_price_payload_t *payload, const zb_uint8_t param) -{ - zb_uint8_t nibble_buf = 0; - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - zb_uint8_t exp_p_size = 0; - - if (!ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_SIZE_IS_VALID(data_size)) - { - TRACE_MSG(TRACE_ZCL1, "Received invalid PublishPrice command, " - "payload_len = %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA32(&payload->provider_id, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->rate_label[0], data); - - if (payload->rate_label[0] >= sizeof(payload->rate_label)) - { - TRACE_MSG(TRACE_ZCL1, "Received invalid Price Cluster command, " - "rate_label[0]=%d", (FMT__D, payload->rate_label[0])); - return NULL; - } - - exp_p_size = ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_EXPECTED_SIZE(payload); - - if (exp_p_size != data_size) - { - TRACE_MSG(TRACE_ZCL1, "Received invalid PublishPrice command, " - "expected size = %hd, actual size = %hd", (FMT__H_H, exp_p_size, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA_N(&payload->rate_label[1], data, - payload->rate_label[0]); - ZB_ZCL_PACKET_GET_DATA32(&payload->issuer_event_id, data); - ZB_ZCL_PACKET_GET_DATA32(&payload->current_time, data); - ZB_ZCL_PACKET_GET_DATA8(&payload->unit_of_measure, data); - ZB_ZCL_PACKET_GET_DATA16(&payload->currency, data); - ZB_ZCL_PACKET_GET_DATA8(&nibble_buf, data); - payload->price_trailing_digit = ZB_UINT8_MSB_NIBBLE(nibble_buf); - payload->price_tier = ZB_UINT8_LSB_NIBBLE(nibble_buf); - ZB_ZCL_PACKET_GET_DATA8(&nibble_buf, data); - payload->number_of_price_tiers = ZB_UINT8_MSB_NIBBLE(nibble_buf); - payload->register_tier = ZB_UINT8_LSB_NIBBLE(nibble_buf); - ZB_ZCL_PACKET_GET_DATA32(&payload->start_time, data); - ZB_ZCL_PACKET_GET_DATA16(&payload->duration_in_minutes, data); - ZB_ZCL_PACKET_GET_DATA32(&payload->price, data); - - ZB_ZCL_PACKET_GET_DATA8 (&payload->price_ratio, data); - ZB_ZCL_PACKET_GET_DATA32(&payload->generation_price, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->generation_price_ratio, data); - ZB_ZCL_PACKET_GET_DATA32(&payload->alternate_cost_delivered, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->alternate_cost_unit, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->alternate_cost_trailing_digit, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->number_of_block_thresholds, data); - - ZB_ZCL_PACKET_GET_DATA8(&payload->price_control, data); - - ZB_ZCL_PACKET_GET_DATA8 (&payload->number_of_generation_tiers, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->generation_tier, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->extended_number_of_price_tiers, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->extended_price_tier, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->extended_register_tier, data); - - return data; -} - -void zb_zcl_price_send_cmd_get_tier_labels(zb_uint8_t param, zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_zcl_price_get_tier_labels_payload_t *payload, - zb_callback_t cb) -{ - zb_zcl_price_get_tier_labels_payload_t pl; - zb_uint8_t *data = (zb_uint8_t *) &pl; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_price_server_send_get_tier_labels", (FMT__0)); - - ZB_BZERO(&pl, sizeof(pl)); - - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->issuer_tariff_id); - - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, &pl, sizeof(pl), NULL, - ZB_ZCL_CLUSTER_ID_PRICE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_PRICE_CLI_CMD_GET_TIER_LABELS, - cb); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_price_server_send_get_tier_labels", (FMT__0)); -} - - -static void zb_zcl_price_process_publish_price(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_price_publish_price_payload_t pl_in = ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_INIT; - zb_zcl_price_ack_payload_t pl_out = ZB_ZCL_PRICE_ACK_PAYLOAD_INIT; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_price_process_publish_price", (FMT__0)); - - if (!ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_SIZE_IS_VALID(zb_buf_len(param))) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet len (%hd).", (FMT__H, zb_buf_len(param))); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - if (!zb_zcl_price_publish_price_get_payload_from_data(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet payload.", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - pl_out = ZB_ZCL_PRICE_ACK_PAYLOAD_INIT_FROM_PUBLISH_PRICE_PAYLOAD(&pl_in); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_PRICE_PUBLISH_PRICE_CB_ID, RET_OK, cmd_info, &pl_in, &pl_out); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - if (pl_in.price_control & ZB_ZCL_PRICE_CONTROL_PRICE_ACKNOWLEDGEMENT_REQUIRED) - { - ZB_ZCL_PRICE_SEND_CMD_PRICE_ACK(param, - (zb_addr_u *) &ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - &pl_out); - } - else - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_SUCCESS); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_price_process_publish_price", (FMT__0)); -} - - -static const zb_uint8_t *zb_zcl_price_publish_tier_labels_parse_payload( - zb_zcl_price_publish_tier_labels_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - zb_int16_t remaining_len = 0; - zb_uint8_t number_of_entries_in_this_command = 0; - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_price_publish_tier_labels_parse_payload, data_size = %d", (FMT__D, data_size)); - - ZB_ZCL_PACKET_GET_DATA32(&pl->provider_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->issuer_event_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->issuer_tariff_id, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->command_index, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->total_number_of_commands, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->number_of_labels, data); - - remaining_len = data_size - ZB_OFFSETOF(zb_zcl_price_publish_tier_labels_payload_t, tier_labels); - pl->tier_labels = (zb_zcl_price_publish_tier_labels_sub_payload_t *)data; - while (remaining_len > 0) - { - remaining_len--; /* size of Tier ID field */ - data++; - - if ((remaining_len < *(data)) && (*(data) < sizeof(((zb_zcl_price_publish_tier_labels_sub_payload_t *)0)->tier_label))) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); /* Can't parse tier labels entries */ - return NULL; - } - - remaining_len -= *(data) + 1; /* subtract the length of octet string */ - data += *(data) + 1; /* move to next entry */ - number_of_entries_in_this_command++; - } - - if (number_of_entries_in_this_command != pl->number_of_labels) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet: number_of_entries_in_this_command != number_of_labels", (FMT__0)); - TRACE_MSG(TRACE_ZCL1, "Malformed packet: number_of_entries_in_this_command = %d", (FMT__D, number_of_entries_in_this_command)); - TRACE_MSG(TRACE_ZCL1, "Malformed packet: number_of_labels = %d", (FMT__D, pl->number_of_labels)); - return NULL; - } - - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_price_process_publish_tier_labels", (FMT__0)); - - /* NOTE: this command can move memory and we must invoke it before payload parsing */ - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_PRICE_PUBLISH_TIER_LABELS_CB_ID, - RET_ERROR, cmd_info, &pl_in, NULL); - - if ((!ZB_ZCL_PRICE_PUBLISH_TIER_LABELS_PAYLOAD_SIZE_IS_VALID(zb_buf_len(param))) - || (!zb_zcl_price_publish_tier_labels_parse_payload(&pl_in, param))) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet payload.", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - zb_zcl_send_default_handler(param, cmd_info, - (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_price_process_publish_tier_labels", (FMT__0)); -} - - -static zb_bool_t zb_zcl_process_price_client_commands(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_bool_t processed = ZB_FALSE; - - switch ((zb_zcl_price_server_cmd_t) cmd_info->cmd_id) - { - case ZB_ZCL_PRICE_SRV_CMD_PUBLISH_PRICE: -/* #ifdef ZB_ENABLE_SE */ -#if defined(ZB_SE_ENABLE_STEADY_STATE_PROCESSING) - if (zb_se_steady_state_block_zcl_cmd(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, cmd_info->seq_number)) - { - (void) zb_se_steady_publish_price_handle(param); - } - else -#endif - { - zb_zcl_price_process_publish_price(param, cmd_info); - } - processed = ZB_TRUE; - break; - case ZB_ZCL_PRICE_SRV_CMD_PUBLISH_TIER_LABELS: - zb_zcl_price_process_publish_tier_labels(param, cmd_info); - processed = ZB_TRUE; - break; - default: - break; - } - - return processed; -} - -zb_bool_t zb_zcl_process_c_price_specific_commands(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t processed = ZB_FALSE; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_price_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_c_price_specific_commands, " - "param=%hd, cmd_id=%hd", (FMT__H_H, param, cmd_info.cmd_id)); - - /* ZB_ASSERT(cmd_info.profile_id == ZB_AF_SE_PROFILE_ID); */ - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_PRICE); - - if (ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction) - { - processed = zb_zcl_process_price_client_commands(param, &cmd_info); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_c_price_specific_commands (ret=%hd)", - (FMT__H, processed)); - - return processed; -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_PRICE || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_c_wwah.c b/zboss/development/src/zcl/zcl_c_wwah.c deleted file mode 100644 index 5f207dddef..0000000000 --- a/zboss/development/src/zcl/zcl_c_wwah.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL WWAH cluster specific commands handling - Client role -*/ - -#define ZB_TRACE_FILE_ID 12083 - -#include "zb_common.h" - -#if defined ZB_ZCL_SUPPORT_CLUSTER_WWAH - -#ifdef ZB_ZCL_ENABLE_WWAH_CLIENT - -static const zb_uint8_t gs_wwah_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_WWAH_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -static const zb_uint8_t gs_wwah_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_WWAH_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_wwah_client_cmd_list = -{ - sizeof(gs_wwah_client_received_commands), (zb_uint8_t *)gs_wwah_client_received_commands, - sizeof(gs_wwah_client_generated_commands), (zb_uint8_t *)gs_wwah_client_generated_commands -}; - -zb_bool_t zb_zcl_process_wwah_specific_commands_cli(zb_uint8_t param); - -void zb_zcl_wwah_init_client() -{ - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_init_client", (FMT__0)); - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_wwah_specific_commands_cli); -} - -zb_bool_t zb_zcl_process_wwah_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_wwah_client_cmd_list; - return ZB_TRUE; - } - return ZB_FALSE; -} - -#endif /* ZB_ZCL_ENABLE_WWAH_CLIENT */ - -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_WWAH */ diff --git a/zboss/development/src/zcl/zcl_color_control_commands.c b/zboss/development/src/zcl/zcl_color_control_commands.c deleted file mode 100644 index 43dd47c5d3..0000000000 --- a/zboss/development/src/zcl/zcl_color_control_commands.c +++ /dev/null @@ -1,5498 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Color Control cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2062 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_COLOR_CONTROL) - -#include "zb_time.h" -#include "zb_zcl.h" -#include "zb_aps.h" - -static void zb_zcl_color_control_update_color_attrbute(zb_uint8_t endpoint); - -/** @internal - @{ -*/ - -static zb_uint8_t gs_color_control_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -static zb_discover_cmd_list_t gs_color_control_client_cmd_list = -{ - 0, NULL, - sizeof(gs_color_control_client_generated_commands), gs_color_control_client_generated_commands -}; - -static zb_discover_cmd_list_t gs_color_control_server_cmd_list = -{ - sizeof(gs_color_control_client_generated_commands), gs_color_control_client_generated_commands, - 0, NULL -}; - -zb_ret_t check_value_color_control_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -zb_ret_t check_value_color_control_client(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -zb_bool_t zb_zcl_process_color_control_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_color_control_specific_commands_cli(zb_uint8_t param); -void zb_zcl_process_color_control_specific_commands_srv_2param(zb_uint8_t buf2_param, zb_uint16_t cmd_param); - -void zb_zcl_color_control_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_color_control_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_color_control_specific_commands_srv); -} - -void zb_zcl_color_control_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - check_value_color_control_client, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_color_control_specific_commands_cli); -} - -zb_ret_t check_value_color_control_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - ZVUNUSED(endpoint); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID: - ret = (*value <= ZB_ZCL_COLOR_CONTROL_CURRENT_HUE_MAX_VALUE) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID: - ret = (*value <= ZB_ZCL_COLOR_CONTROL_CURRENT_SATURATION_MAX_VALUE) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID: - ret = (ZB_ZCL_ATTR_GET16(value) <= ZB_ZCL_COLOR_CONTROL_CURRENT_X_MAX_VALUE) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID: - ret = (ZB_ZCL_ATTR_GET16(value) <= ZB_ZCL_COLOR_CONTROL_CURRENT_Y_MAX_VALUE) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID: - case ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_ID: - case ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_ID: - ret = (ZB_ZCL_ATTR_GET16(value) <= ZB_ZCL_COLOR_CONTROL_COLOR_TEMPERATURE_MAX_VALUE) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_ACTIVE_ID: - ret = (*value <= ZB_ZCL_CMD_COLOR_CONTROL_LOOP_ACTION_CURRENT_HUE) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_DIRECTION_ID: - ret = (*value <= ZB_ZCL_CMD_COLOR_CONTROL_LOOP_DIRECTION_INCREMENT) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_CAPABILITIES_ID: - ret = (ZB_ZCL_ATTR_GET16(value) <= ZB_ZCL_COLOR_CONTROL_COLOR_CAPABILITIES_MAX_VALUE) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID: - if( ZB_ZCL_ATTR_GET16(value) > ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX ) - { - ret = RET_ERROR; - } - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_color_control ret %hd", (FMT__H, ret)); - return ret; -} - -zb_ret_t check_value_color_control_client(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - - ZVUNUSED(endpoint); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID: - if( ZB_ZCL_ATTR_GET16(value) > ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX ) - { - ret = RET_ERROR; - } - break; - default: - break; - } - - return ret; -} -/** @addtogroup ZB_ZCL_COLOR_CONTROL - ZCL Color Control cluster Helper functions - @{ -*/ - -/** @brief Get 8bit attribute value from Color Control cluster - @param endpoint - endpoint - @param attr_id - attribute ID - @return attribute value -*/ -static zb_uint8_t zb_zcl_color_control_get8(zb_uint8_t endpoint, zb_uint16_t attr_id) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id); - ZB_ASSERT(attr_desc); - return ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); -} - -/** @brief Get 16bit attribute value from Color Control cluster - @param endpoint - endpoint - @param attr_id - attribute ID - @return attribute value -*/ -static zb_uint16_t zb_zcl_color_control_get16(zb_uint8_t endpoint, zb_uint16_t attr_id) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id); - ZB_ASSERT(attr_desc); - return ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); -} - -/** @brief Set 8bit attribute value from Color Control cluster - @param endpoint - endpoint - @param attr_id - attribute ID - @param value - new attribute value -*/ -static void zb_zcl_color_control_set8(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t value) -{ - /* Use SET_ATTRIBUTE to report attribute change if needed. */ - ZB_ZCL_SET_ATTRIBUTE(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - attr_id, - &value, - ZB_FALSE); -} - -/** @brief Set 16bit attribute value from Color Control cluster - @param endpoint - endpoint - @param attr_id - attribute ID - @param value - new attribute value -*/ -static void zb_zcl_color_control_set16(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint16_t value) -{ - /* Use SET_ATTRIBUTE to report attribute change if needed. */ - ZB_ZCL_SET_ATTRIBUTE(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - attr_id, - (zb_uint8_t*)&value, - ZB_FALSE); -} - -/** @brief Set color mode attribute and call change attribute color - see ZCL spec 5.2.2.3.1 - @param endpoint - endpoint - @param mode - new color mode -*/ -static void zb_zcl_color_control_set_color_mode(zb_uint8_t endpoint, zb_uint8_t mode) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_MODE_ID); - ZB_ASSERT(attr_desc); - - if(ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc)!=mode) - { - // TODO convert color attribute - zb_zcl_color_control_update_color_attrbute(endpoint); - } - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, mode); - - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID, mode); -} - -/** @brief Invoke User App and set new value of attribute - @param param - buffer with @see zb_zcl_color_control_invoke_user_t. Also use User App - @return result invoke User App. -*/ -static zb_ret_t zb_zcl_color_control_invoke_user_and_set_attribute(zb_uint8_t param) -{ - zb_ret_t status = RET_OK; - zb_zcl_attr_t * attr_desc; - zb_zcl_color_control_invoke_user_t user_data; - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_color_control_invoke_user_and_set_attribute %hd", (FMT__H, param)); - ZB_MEMCPY(&user_data, ZB_BUF_GET_PARAM(param, zb_zcl_color_control_invoke_user_t), - sizeof(zb_zcl_color_control_invoke_user_t)); - - attr_desc = zb_zcl_get_attr_desc_a(user_data.endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, user_data.attr_id); - - ZB_ASSERT(attr_desc); - - if(attr_desc->type == ZB_ZCL_ATTR_TYPE_U16) - { - if( ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) != user_data.new_value) - { - ZB_ZCL_INVOKE_USER_APP_SET_ATTR_WITH_RESULT(param, user_data.endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, attr_desc, &(user_data.new_value), status); - TRACE_MSG(TRACE_ZCL2, "attr_desc %p new value %d", (FMT__P_D, attr_desc, user_data.new_value)); - - /* ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(user_data.attr_desc, user_data.new_value); */ - /* Yes, it is not the best way to set attribute - SET_ATTRIBUTE will search again for - * attr_desc by ep/cluster/attr_id when we already have it. - * TODO: Modify ZCL api to bypass these getters if attr_desc is given. - */ - ZB_ZCL_SET_ATTRIBUTE(user_data.endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - user_data.attr_id, - (zb_uint8_t*)&user_data.new_value, - ZB_FALSE); - } - } - else - { - zb_uint8_t val8 = (zb_uint8_t)(user_data.new_value); - if( ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) != val8) - { - ZB_ZCL_INVOKE_USER_APP_SET_ATTR_WITH_RESULT(param, user_data.endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, attr_desc, &val8, status); - TRACE_MSG(TRACE_ZCL2, "attr_desc %p new value %hd", (FMT__P_H, attr_desc, val8)); - /* ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(user_data.attr_desc, val8); */ - ZB_ZCL_SET_ATTRIBUTE(user_data.endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - user_data.attr_id, - (zb_uint8_t*)&val8, - ZB_FALSE); - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_color_control_invoke_user_and_set_attribute %hd", (FMT__D, status)); - return status; -} - -/** - * @} -*/ - -/** @addtogroup ZB_ZCL_COLOR_CONTROL - ZCL Color Control cluster Convert color between "Hue,Saturation" - "ColorXY" - "Color Temperature" - @{ - Use convert in/out RGB - Need to recode without use float type. -*/ - -#define ABS(a) ((a)>0 ? (a) : -(a)) - -typedef struct zb_zcl_color_control_color_convert_s -{ - zb_uint8_t hue; /** Hue */ - zb_uint8_t saturation; /** Saturation */ - zb_uint8_t color_x; /** Color X, high byte */ - zb_uint8_t color_y; /** Color Y, high byte */ - zb_uint16_t color_temp; /** Color Temperature, high byte */ -} zb_zcl_color_control_color_convert_t; - -#define ZB_ZCL_COLOR_CONTROL_CONVERT_COLOR_COUNT 8 - -static zb_zcl_color_control_color_convert_t zb_zcl_color_control_convert_table[ZB_ZCL_COLOR_CONTROL_CONVERT_COLOR_COUNT] = -{ - { 0x00, 0x00, 0, 0, 0}, // black - { 0x00, 0xff, 242, 255, 5000}, // white - { 0x00, 0xff, 106, 54, 4013}, // red - { 0x2a, 0xff, 196, 237, 4000}, // red+green - { 0x55, 0xff, 91, 182, 5713}, // green - { 0x80, 0xff, 137, 201, 9406}, // green+blue - { 0xaa, 0xff, 46, 18, 25000}, // blue - { 0xd5, 0xff, 151, 73, 4020}, // blue+red -}; - -static zb_uint8_t zb_zcl_color_control_hue_sat_to_index(zb_uint8_t hue, zb_uint8_t sat) -{ - zb_uint8_t index=0; - zb_uint16_t offset = ABS(hue-zb_zcl_color_control_convert_table[0].hue)+ - ABS(sat-zb_zcl_color_control_convert_table[0].saturation); - zb_uint8_t i; - zb_uint16_t tmp; - - for(i=1; i> 8; - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, hue); - // next - run ordinary hue and saturation mode - /* FALLTHROUGH */ - case ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION: - hue = zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID); - sat = zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID); - index = zb_zcl_color_control_hue_sat_to_index(hue, sat); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, - zb_zcl_color_control_convert_table[index].color_x << 8); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID, - zb_zcl_color_control_convert_table[index].color_y << 8); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, - zb_zcl_color_control_convert_table[index].color_temp); - break; - case ZB_ZCL_COLOR_CONTROL_COLOR_MODE_CURRENT_X_Y: - x = zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID); - y = zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID); - index = zb_zcl_color_control_color_xy_to_index(x, y); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, - zb_zcl_color_control_convert_table[index].hue); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, - zb_zcl_color_control_convert_table[index].saturation); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, - zb_zcl_color_control_convert_table[index].color_temp); - hue = zb_zcl_color_control_convert_table[index].hue; - break; - case ZB_ZCL_COLOR_CONTROL_COLOR_MODE_TEMPERATURE: - temp = zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID); - index = zb_zcl_color_control_color_temp_to_index(temp); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, - zb_zcl_color_control_convert_table[index].color_x << 8); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID, - zb_zcl_color_control_convert_table[index].color_y << 8); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, - zb_zcl_color_control_convert_table[index].hue); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, - zb_zcl_color_control_convert_table[index].saturation); - hue = zb_zcl_color_control_convert_table[index].hue; - break; - } - - if(old_mode!=ZB_ZCL_COLOR_CONTROL_COLOR_EX_MODE_HUE_SATURATION_EX) - { - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID, hue << 8); - } -} - -#if 0 - -#define MIN(a, b) ((a)<(b) ? (a) : (b)) -#define MAX(a, b) ((a)>(b) ? (a) : (b)) - -/** Convert RGB to Hue,Saturation - * RGB - [0..0xffff] - * Hue,Sat - [0..0xff] -*/ -#define RGB_to_HS(r, g, b, h, s) \ -{ \ - zb_uint16_t min, max, delta; \ - min = MIN( (r), (g) ); \ - min = MIN( min, (b) ); \ - max = MAX( (r), (g) ); \ - max = MAX( max, (b) ); \ - delta = max - min; \ - if( max == 0 ) \ - { \ - (s) = (h) = 0; \ - } \ - else \ - { \ - s = (zb_uint8_t)(ZB_UINT8_MAX * delta / max); /* s */ \ - \ - if( (r) == max ) /* between yellow & magenta*/ \ - h = (zb_uint8_t)(ZB_UINT8_MAX/6 * ( (g) - (b) ) / delta); \ - else if( (g) == max ) /* between cyan & yellow*/ \ - h = (zb_uint8_t)(ZB_UINT8_MAX/6 * (2 + ( (b) - (r) ) / delta)); \ - else /* between magenta & cyan*/ \ - h = (zb_uint8_t)(ZB_UINT8_MAX/6 * (4 + ( (r) - (g) ) / delta)); \ - } \ -} - -/** Convert Hue,Saturation,V to RGB - * RGB - [0..0xffff] - * Hue,Sat - [0..0xff] - * V always = (ZB_UINT16_MAX-1) -*/ -#define HSV_to_RGB(h, s, v, r, g, b ) \ -{ \ - zb_uint8_t i; \ - zb_uint8_t sector = ZB_UINT8_MAX/6; \ - zb_uint16_t f, p, q, t; \ - if( s == 0 ) { /* achromatic (grey)*/ \ - r = g = b = (v); \ - } \ - else \ - { \ - i = h / sector; /* sector 0 to 5 */ \ - f = h % sector; /* factorial part of h*/ \ - p = (zb_uint16_t)(v * ( 1.0 - s/ZB_UINT8_MAX )); \ - q = (zb_uint16_t)(v * ( 1.0 - s/ZB_UINT8_MAX * f/(float)sector )); \ - t = (zb_uint16_t)(v * ( 1.0 - s/ZB_UINT8_MAX * ( 1 - f/(float)sector ) )); \ - switch( i ) { \ - case 0: r = (v); g = t; b = p; break; \ - case 1: r = q; g = (v); b = p; break; \ - case 2: r = p; g = (v); b = t; break; \ - case 3: r = p; g = q; b = (v); break; \ - case 4: r = t; g = p; b = (v); break; \ - case 5: \ - default: r = (v); g = p; b = q; break; \ - } \ - } \ -} - -/** Convert ColorXY to RGB - * r, g, b - [0, 0xffff] - * x, y- [0, 0xffff] - * */ -#define XY_to_RGB(x, y, r, g, b) \ -{ \ - zb_uint16_t z = ZB_UINT16_MAX - (x) - (y); \ - r = (zb_uint16_t)( 3.240479*(x) -1.537150*(y) -0.498535*(z)); \ - g = (zb_uint16_t)(-0.969256*(x) +1.875992*(y) +0.041556*(z)); \ - b = (zb_uint16_t)( 0.055648*(x) -0.204043*(y) +1.057311*(z)); \ -} - -/** Convert RGB to ColorXY - * r, g, b - [0, 0xffff] - * x, y - [0, 0xffff] - * */ -#define RGB_to_XY(r, g, b, x, y) \ -{ \ - x = (zb_uint16_t)( 0.412453*(r) +0.357580*(g) +0.180423*(b)); \ - y = (zb_uint16_t)( 0.212671*(r) +0.715160*(g) +0.072169*(b)); \ -/*z = (zb_uint16_t)( 0.019334*(r) +0.119193*(g) +0.950227*(b)); */\ -} - -/** Convert Color temperature to ColorXY - * T - Color temperature, t_kelvin=1000000/T, see spec 5.2.2.2.1.8 - * t form define = 1000/t_kelvin = T/1000 - * */ -#define KELVIN_to_XY(T, x, y) \ -{ \ - /*float t = 1000.0/t_kelvin;*/ \ - float t = T/1000.0; \ - float X, Y; \ - if(T>1000/4 /*t_kelvin < 4000.0f*/) \ - { \ - X = ((-0.2661239f*t - 0.2343580f)*t + 0.8776956f)*t + 0.17991f; \ - if(T>1000000/2222 /*t_kelvin < 2222.0f*/) \ - Y = ((-1.1063814f*X - 1.34811020f)*X + 2.18555832f)*X - 0.20219683f; \ - else \ - Y = ((-0.9549476f*X - 1.37418593f)*X + 2.09137015f)*X - 0.16748867f; \ - } \ - else \ - { \ - X = ((-3.0258469f*t + 2.1070379f)*t + 0.2226347f)*t + 0.24039f; \ - Y = ((3.0817580f*X - 5.8733867f)*X + 3.75112997f)*X - 0.37001483f; \ - } \ - x = (zb_uint16_t)(ZB_UINT16_MAX*X); \ - y = (zb_uint16_t)(ZB_UINT16_MAX*Y); \ -} - -/** Convert ColorXY to Color temperature - * T - Color temperature, t_kelvin=1000000/T, see spec 5.2.2.2.1.8 - * T = 1000000/t_kelvin - * */ -#define XY_to_KELVIN(x, y, T) \ -{ \ - float n = (x - 0.3320*ZB_UINT16_MAX)/(y - 0.1858*ZB_UINT16_MAX); \ - T = (zb_uint16_t)1000000/(((-449*n + 3525)*n - 6823.3)*n + 5520.33); \ -} - -/** @brief Update Color attributes when change Color Mode attribute - @param endpoint - endpoint -*/ -static void zb_zcl_color_control_update_color_attrbute(zb_uint8_t endpoint) -{ - zb_uint16_t r, g, b; - zb_uint8_t hue; - zb_uint8_t sat; - zb_uint16_t x; - zb_uint16_t y; - zb_uint16_t temp; - zb_uint8_t old_mode = zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_MODE_ID); - - switch(old_mode) - { - case ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION: - hue = zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID); - sat = zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID); - HSV_to_RGB(hue, sat, (ZB_UINT16_MAX-1), r, g, b); - RGB_to_XY(r, g, b, x, y); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, x); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID, y); - XY_to_KELVIN(x, y, temp); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, temp); - break; - case ZB_ZCL_COLOR_CONTROL_COLOR_MODE_CURRENT_X_Y: - x = zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID); - y = zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID); - XY_to_RGB(x, y, r, g, b); - RGB_to_HS(r, g, b, hue, sat); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, hue); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, sat); - XY_to_KELVIN(x, y, temp); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, temp); - break; - case ZB_ZCL_COLOR_CONTROL_COLOR_MODE_TEMPERATURE: - temp = zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID); - KELVIN_to_XY(temp, x, y); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, x); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID, y); - XY_to_RGB(x, y, r, g, b); - RGB_to_HS(r, g, b, hue, sat); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, hue); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, sat); - break; - } - -} - -#endif -/** - * @} -*/ - -/** - * @brief Define for Invoke User App and set attribute value - * see @ref zb_zcl_color_control_invoke_user_s - * - * @param buf - buffer with struct @ref zb_zcl_color_control_invoke_user_s 'zb_zcl_color_control_invoke_user_t' - * @param attr_desc_ - attribute descriptor - * @param val - new attribute value - * @param status - invoke User App result - */ -static zb_bool_t zb_zcl_color_control_invoke_user_app(zb_bufid_t buf, zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint16_t val) -{ - zb_zcl_color_control_invoke_user_t *user_data = - ZB_BUF_GET_PARAM((buf), zb_zcl_color_control_invoke_user_t); - user_data->endpoint = endpoint; - user_data->attr_id = attr_id; - user_data->new_value = val; - return ((zb_bool_t) zb_zcl_color_control_invoke_user_and_set_attribute(buf)); -} - -/** @brief Process one interaction of move or step command for one attribute - * @param el_data - pointer on data, @see zb_zcl_color_control_loop_element_t - * @return result invoke User App */ -static zb_bool_t zb_zcl_process_color_control_element_loop(zb_zcl_color_control_loop_element_t *el_data) -{ - zb_zcl_attr_t * attr_desc; - zb_int32_t val; - zb_ret_t status; - zb_bool_t is_16bit; - zb_bool_t is_finish = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_element_loop", (FMT__0)); - - attr_desc = zb_zcl_get_attr_desc_a(el_data->endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, el_data->attr_id); - ZB_ASSERT(attr_desc); - - // calcutate new value - is_16bit = (attr_desc->type == ZB_ZCL_ATTR_TYPE_U16) ? ZB_TRUE : ZB_FALSE; - val = (is_16bit) ? ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) : - ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - TRACE_MSG(TRACE_ZCL2, "val_old %d delta %d", (FMT__D_D, val, el_data->value)); - val += el_data->value; - - if(el_data->value> 0 && val > el_data->limit) - { - if (el_data->is_continue) - { - val -= (is_16bit ? ZB_UINT16_MAX : ZB_UINT8_MAX); - } - else - { - val = el_data->limit; is_finish = ZB_TRUE; - } - } - else if(el_data->value< 0 && val < el_data->limit) - { - if (el_data->is_continue) - { - val += (is_16bit ? ZB_UINT16_MAX : ZB_UINT8_MAX); - } - else - { - val = el_data->limit; is_finish = ZB_TRUE; - } - } - - TRACE_MSG(TRACE_ZCL2, "val_new %d", (FMT__D, val)); - - status = zb_zcl_color_control_invoke_user_app(el_data->buffer_id, el_data->endpoint, el_data->attr_id, val); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_element_loop %hd", (FMT__D, status)); - - return (status==RET_OK && !is_finish) ? ZB_TRUE : ZB_FALSE; -} - -static zb_bool_t color_control_check_req_options(zb_uint8_t param, zb_uint8_t endpoint) -{ - zb_zcl_color_control_req_options_t req_options; - zb_bool_t res = ZB_TRUE; - zb_zcl_attr_t *attr_desc; - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_ON_OFF - zb_af_endpoint_desc_t *ep_desc; - zb_zcl_cluster_desc_t *cluster_desc; -#endif - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_COLOR_CONTROL_OPTIONS_ID); - - if (attr_desc != NULL) - { - zb_uint8_t options = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - ZB_ZCL_COLOR_CONTROL_GET_CMD_OPTIONS(param, req_options); - - /* Check and override bits if needed */ - if (ZB_CHECK_BIT_IN_BIT_VECTOR(&req_options.options_mask, - ZB_ZCL_COLOR_CONTROL_OPTIONS_EXECUTE_IF_OFF)) - { - if (ZB_CHECK_BIT_IN_BIT_VECTOR(&req_options.options_override, - ZB_ZCL_COLOR_CONTROL_OPTIONS_EXECUTE_IF_OFF)) - { - ZB_SET_BIT_IN_BIT_VECTOR(&options, - ZB_ZCL_COLOR_CONTROL_OPTIONS_EXECUTE_IF_OFF); - } - else - { - ZB_CLR_BIT_IN_BIT_VECTOR(&options, - ZB_ZCL_COLOR_CONTROL_OPTIONS_EXECUTE_IF_OFF); - } - } - - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_ON_OFF - /* ZCL7, 5.2.2.2.1.30 ExecuteIfOff Options Bit - Command execution SHALL NOT continue beyond the Options proceeding if all of thee criteria - are true: - - The On/Off cluster exists on the same endpoint as this cluster - - The OnOff attribute of the On/Off cluster, on this endpoint, is 0x00 (FALSE) - - The value of the ExecuteIfOff bit is 0 - */ - ep_desc = zb_af_get_endpoint_desc(endpoint); - cluster_desc = get_cluster_desc(ep_desc, ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE); - /* On/Off cluster may not be on the endpoint. - * In this case return true and continue command execution .*/ - if (cluster_desc) - { - attr_desc = zb_zcl_get_attr_desc(cluster_desc, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID); - - if (attr_desc && - !ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) && /* On/Off attrbute is Off */ - !ZB_CHECK_BIT_IN_BIT_VECTOR(&options, ZB_ZCL_LEVEL_CONTROL_OPTIONS_EXECUTE_IF_OFF)) /* ExecuteIfOff - * is False */ - { - /* ExecuteIfOff policy, deny */ - res = ZB_FALSE; - } - } -#endif - } - - TRACE_MSG(TRACE_ZCL1, "color_control_check_req_options: enabled %hd", (FMT__H, res)); - return res; -} - -static zb_bool_t color_control_check_color_capabilities(zb_uint8_t endpoint, zb_uint8_t cmd_id) -{ - zb_bool_t res = ZB_FALSE; - zb_zcl_attr_t *attr_desc; - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_CAPABILITIES_ID); - - if (attr_desc != NULL) - { - zb_uint16_t color_capabilites = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - switch (cmd_id) - { - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE: - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_HUE: - case ZB_ZCL_CMD_COLOR_CONTROL_STEP_HUE: - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_SATURATION: - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_SATURATION: - case ZB_ZCL_CMD_COLOR_CONTROL_STEP_SATURATION: - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SATURATION: - res = (zb_bool_t)(color_capabilites & ZB_ZCL_COLOR_CONTROL_CAPABILITIES_HUE_SATURATION); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR: - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR: - case ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR: - res = (zb_bool_t)(color_capabilites & ZB_ZCL_COLOR_CONTROL_CAPABILITIES_X_Y); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE: - case ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_HUE: - case ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_STEP_HUE: - case ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_SATURATION: - res = (zb_bool_t)(color_capabilites & ZB_ZCL_COLOR_CONTROL_CAPABILITIES_EX_HUE); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_COLOR_LOOP_SET: - res = (zb_bool_t)(color_capabilites & ZB_ZCL_COLOR_CONTROL_CAPABILITIES_COLOR_LOOP); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_STOP_MOVE_STEP: - res = (zb_bool_t)((color_capabilites & ZB_ZCL_COLOR_CONTROL_CAPABILITIES_HUE_SATURATION) - || (color_capabilites & ZB_ZCL_COLOR_CONTROL_CAPABILITIES_EX_HUE) - || (color_capabilites & ZB_ZCL_COLOR_CONTROL_CAPABILITIES_X_Y) - || (color_capabilites & ZB_ZCL_COLOR_CONTROL_CAPABILITIES_COLOR_TEMP)); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR_TEMPERATURE: - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR_TEMPERATURE: - case ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR_TEMPERATURE: - res = (zb_bool_t)(color_capabilites & ZB_ZCL_COLOR_CONTROL_CAPABILITIES_COLOR_TEMP); - break; - - default: - res = ZB_FALSE; - } - } - - TRACE_MSG(TRACE_ZCL1, "color_control_check_color_capabilities: supported %hd", (FMT__H, res)); - - return res; -} - -/** @brief Process one interation of move command - * @param param - buffer with move loop data, @see zb_zcl_color_control_move_loop_t - * - * Function convert from time offset between current time and last processed time plus - * non-used msec (saved in loop data as time_mod fields) to delta value. - * New non-used msec save in loop data as time_mod fields. - * - * Its make separate for first and second (if need) attribute. - * */ -static void zb_zcl_process_color_control_move_loop(zb_uint8_t param) -{ - zb_time_t current_time = ZB_TIMER_GET(); - zb_zcl_color_control_move_loop_t loop_data; - zb_zcl_color_control_loop_element_t element; - zb_bool_t is_continue = ZB_FALSE; - zb_uint16_t time_offset; - zb_int16_t delta; - zb_bool_t is_non_stop_attr; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_loop %hd", (FMT__H, param)); - - // save loop data - param buffer may change for invoke User App - ZB_MEMCPY(&loop_data, ZB_BUF_GET_PARAM(param, zb_zcl_color_control_move_loop_t), - sizeof(zb_zcl_color_control_move_loop_t)); - - // calc time offset - time_offset = ZB_TIME_BEACON_INTERVAL_TO_MSEC(ZB_TIME_SUBTRACT(current_time, loop_data.time_last)); - TRACE_MSG(TRACE_ZCL1, "time offset %hd msec time_mod1 %d time_mod2 %d", (FMT__D_D_D, - time_offset, loop_data.time_mod, loop_data.time_mod2)); - - // prepare struct for process each move command - is_non_stop_attr = ((loop_data.attr_id == ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID) - ) ? ZB_TRUE : ZB_FALSE; - - // calc delta attribute value and update non-used msec for first attribute - delta = loop_data.rate * (time_offset + loop_data.time_mod) / ZB_ZCL_COLOR_CONTROL_SEC_TO_MSEC; - loop_data.time_mod = (time_offset + loop_data.time_mod) - (delta * ZB_ZCL_COLOR_CONTROL_SEC_TO_MSEC / loop_data.rate); - - // update first attribute - ZB_ZCL_COLOR_CONTROL_FILL_LOOP_ELEMENT(element, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint, param, - loop_data.attr_id, delta, is_non_stop_attr, loop_data.limit); - - if (zb_zcl_process_color_control_element_loop( &element )) - { - if(loop_data.attr_id == ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID) - { - if(zb_zcl_color_control_get16(element.endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID) - != loop_data.limit) - { - is_continue = ZB_TRUE; - } - } - else - { - is_continue = ZB_TRUE; - } - } - - // if second attribute is exist - if(loop_data.attr_id2!=0) - { - // calc delta attribute value and update non-used msec for second attribute - delta = loop_data.rate2 * (time_offset + loop_data.time_mod2) / ZB_ZCL_COLOR_CONTROL_SEC_TO_MSEC; - loop_data.time_mod2 = (time_offset + loop_data.time_mod2) - (delta * ZB_ZCL_COLOR_CONTROL_SEC_TO_MSEC / loop_data.rate2); - - // update second attribute - ZB_ZCL_COLOR_CONTROL_FILL_LOOP_ELEMENT(element, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint, param, - loop_data.attr_id2, delta, ZB_FALSE, loop_data.limit2); - if (zb_zcl_process_color_control_element_loop( &element )) - { - is_continue = ZB_TRUE; - } - } - - // - if (is_continue) - { - TRACE_MSG(TRACE_ZCL2, "Schedule next", (FMT__0)); - loop_data.time_last = current_time; - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_color_control_move_loop_t), &loop_data, sizeof(loop_data)); - ZB_SCHEDULE_ALARM(zb_zcl_process_color_control_move_loop, param, 5); - } - else // send response command - { - TRACE_MSG(TRACE_ZCL2, "Finish", (FMT__0)); - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_loop", (FMT__0)); -} - -/** @brief Process one iteration of "move to" command - * @param param - buffer with move to loop data, @see zb_zcl_color_control_move_to_loop_t - * - * Function convert from time offset between current time and last processed time plus - * non-used msec (saved in loop data as time_mod fields) to delta value. - * New non-used msec save in loop data as time_mod fields. - * - * Its make separate for first and second (if need) attribute. - * */ -static void zb_zcl_process_color_control_move_to_loop(zb_uint8_t param) -{ - zb_zcl_color_control_move_to_loop_t loop_data; - zb_time_t current_time = ZB_TIMER_GET(); - zb_uint16_t delta_time; - zb_int32_t rm_time_unit; - zb_int32_t val; - zb_zcl_attr_t * attr_desc; - zb_ret_t status; - zb_bool_t is_16bit; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_to_loop %hd curr_time %d", (FMT__H_D, param, current_time)); - - ZB_MEMCPY(&loop_data, ZB_BUF_GET_PARAM(param, zb_zcl_color_control_move_to_loop_t), - sizeof(zb_zcl_color_control_move_to_loop_t)); - - delta_time = ZB_BEACON_INTERVAL_TO_TIME_UNITS(ZB_TIME_SUBTRACT(current_time, loop_data.start_time)); - rm_time_unit = (zb_int32_t)loop_data.transition_time - delta_time; - - attr_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, loop_data.attr_id); - ZB_ASSERT(attr_desc); - - TRACE_MSG(TRACE_ZCL2, "start time %d curr time %d all time %d delta time %d remaining time %d", (FMT__D_D_D_D_D, - loop_data.start_time, current_time, loop_data.transition_time, delta_time, rm_time_unit)); - - // process first attribute - is_16bit = (attr_desc->type == ZB_ZCL_ATTR_TYPE_U16) ? ZB_TRUE : ZB_FALSE; - if (rm_time_unit!=0) - { - zb_int32_t unit_max = is_16bit ? ZB_UINT16_MAX : ZB_UINT8_MAX; - zb_int32_t all_delta = (loop_data.finish_value - loop_data.start_value); - - if((loop_data.attr_id == ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID) - || (loop_data.attr_id == ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID) - ) - { - if (loop_data.incr_direction && loop_data.finish_value < loop_data.start_value) - { - all_delta += unit_max; - } - if (!loop_data.incr_direction && loop_data.finish_value > loop_data.start_value) - { - all_delta -= unit_max; - } - } - - val = (zb_int32_t)(all_delta * delta_time / loop_data.transition_time + loop_data.start_value); - if(val > unit_max) - { - val -= unit_max; - } - } - else - { - val = loop_data.finish_value; - } - - // - TRACE_MSG(TRACE_ZCL2, "attr_id 0x%x val_st %d val_end %u val %d", (FMT__D_D_D_D, - loop_data.attr_id, loop_data.start_value, loop_data.finish_value, val)); - status = zb_zcl_color_control_invoke_user_app(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint, loop_data.attr_id, val); - - // process second attribute - if(loop_data.attr_id2!=0) - { - attr_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, loop_data.attr_id2); - ZB_ASSERT(attr_desc); - - if (rm_time_unit!=0) - { - zb_int32_t all_delta = (loop_data.finish_value2 - loop_data.start_value2); - val = (zb_int32_t)(all_delta * delta_time / loop_data.transition_time + loop_data.start_value2); - } - else - { - val = loop_data.finish_value2; - } - - TRACE_MSG(TRACE_ZCL2, "attr_id2 0x%x val_st2 %d val_end2 %d val %d", (FMT__D_D_D_D, - loop_data.attr_id2, loop_data.start_value2, loop_data.finish_value2, val)); - status = zb_zcl_color_control_invoke_user_app(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint, loop_data.attr_id2, val); - } - - // set Remaining Time attr, if exist - TRACE_MSG(TRACE_ZCL2, "Remaining Time units %d", (FMT__D, rm_time_unit)); - zb_zcl_color_control_set16(ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint, - ZB_ZCL_ATTR_COLOR_CONTROL_REMAINING_TIME_ID, - rm_time_unit>0 ? rm_time_unit : 0); - - // - if (rm_time_unit>0) - { - TRACE_MSG(TRACE_ZCL2, "Schedule next", (FMT__0)); - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_color_control_move_to_loop_t), &loop_data, sizeof(loop_data)); - ZB_SCHEDULE_ALARM(zb_zcl_process_color_control_move_to_loop, param, 5); - } - else // finish - { - TRACE_MSG(TRACE_ZCL2, "Finish. Status = %d", (FMT__D, status)); - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_to_loop", (FMT__0)); -} - -/** @brief Process one iteration of step command - * @param param - buffer with step loop data, @see zb_zcl_color_control_step_loop_t - * - * Function calculate number steps between between current time and last processed time. - * If steps >0 then correct attributes value and update last processed time. - * Last process time = previous last process time plus time for steps (sharp). - * New last process time <= Current lime. - * */ -static void zb_zcl_process_color_control_step_loop(zb_uint8_t param) -{ - zb_zcl_color_control_step_loop_t loop_data; - zb_zcl_color_control_loop_element_t element; - zb_bool_t is_continue = ZB_FALSE; - zb_time_t current_time = ZB_TIMER_GET(); - zb_uint8_t steps; - zb_bool_t is_non_stop_attr; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_step_loop %hd", (FMT__H, param)); - - ZB_MEMCPY(&loop_data, ZB_BUF_GET_PARAM(param, zb_zcl_color_control_step_loop_t), - sizeof(zb_zcl_color_control_step_loop_t)); - - TRACE_MSG(TRACE_ZCL2, "endpoint %hd", (FMT__H, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint)); - - // calc steps - steps = ZB_TIME_SUBTRACT(current_time, loop_data.last_time) / loop_data.step_time; - if(steps!=0) - { - is_non_stop_attr = ((loop_data.attr_id == ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID) - || (loop_data.attr_id == ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID) - ) ? ZB_TRUE : ZB_FALSE; - - ZB_ZCL_COLOR_CONTROL_FILL_LOOP_ELEMENT(element, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint, param, - loop_data.attr_id, steps*loop_data.rate, is_non_stop_attr, loop_data.limit); - is_continue = zb_zcl_process_color_control_element_loop( &element ); - - if (loop_data.attr_id2!=0) - { - ZB_ZCL_COLOR_CONTROL_FILL_LOOP_ELEMENT(element, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint, - param, loop_data.attr_id2, steps*loop_data.rate2, - ZB_FALSE, loop_data.limit2); - is_continue |= zb_zcl_process_color_control_element_loop( &element ); - } - } - else - { - is_continue = ZB_TRUE; - } - - if ( is_continue ) - { - zb_time_t alarm_time = ZB_TIME_SUBTRACT( - loop_data.last_time + (steps+1)*loop_data.step_time, current_time); - if(alarm_time>ZB_HALF_MAX_TIME_VAL) - { - alarm_time = 0; - } - loop_data.last_time += steps*loop_data.step_time; - - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_color_control_step_loop_t), &loop_data, sizeof(loop_data)); - ZB_SCHEDULE_ALARM(zb_zcl_process_color_control_step_loop, param, alarm_time); - } - else // finish - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_step_loop", (FMT__0)); -} - -/** @brief Stop any loop command - * @param func - address loop function - * @param size_loop_data - sizeof of loop data structure - * - * All struct data for loop command (@see zb_zcl_color_control_move_to_loop_t, - * @see zb_zcl_color_control_move_loop_t, @see zb_zcl_color_control_step_loop_t) - * contain @see zb_zcl_parsed_hdr_t as first field. - * - * Function find and remove schedule alarm by 'func' parameters, - * get association buffer, copy @see zb_zcl_parsed_hdr_t struct by size_loop_data - * parameter and invoke ZB_ZCL_PROCESS_COMMAND_FINISH. - * */ -static void zb_zcl_process_color_control_stop(zb_callback_t func, zb_uint8_t size_loop_data) -{ - zb_uint8_t param; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_stop %p %hd", (FMT__P_H, func, size_loop_data)); - - ZB_SCHEDULE_ALARM_CANCEL_AND_GET_BUF(func, ZB_ALARM_ALL_CB, ¶m); - if(param!=0) - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_stop", (FMT__0)); -} - -/** @brief Stop all loop commands from Color Control cluster - * @param endpoint - endpoint. Not used. Function stop All loop command without - * current endpoint - * */ -static void zb_zcl_process_color_control_stop_all_commands(zb_uint8_t endpoint) -{ - (void)endpoint; - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_stop_all_commands", (FMT__0)); - zb_zcl_process_color_control_stop(zb_zcl_process_color_control_move_to_loop, - sizeof(zb_zcl_color_control_move_to_loop_t)); - zb_zcl_process_color_control_stop(zb_zcl_process_color_control_move_loop, - sizeof(zb_zcl_color_control_move_loop_t)); - zb_zcl_process_color_control_stop(zb_zcl_process_color_control_step_loop, - sizeof(zb_zcl_color_control_step_loop_t)); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_stop_all_commands", (FMT__0)); -} - -/////////////////// -/** @brief Move To Hue command - @see ZCL spec, subclause 5.2.2.3.2 */ -static zb_ret_t zb_zcl_process_color_control_move_to_hue_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_move_to_hue_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_to_hue_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_HUE_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_HUE_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (payload.hue > ZB_ZCL_COLOR_CONTROL_CURRENT_HUE_MAX_VALUE) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_bool_t direction = ZB_FALSE; - zb_uint32_t val_end; - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_uint8_t curr_val = zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID); - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - - switch(payload.direction) - { - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SHORTEST: - val_end = payload.hue + (payload.hue <= curr_val ? ZB_UINT8_MAX : 0); - direction = (val_end - curr_val <= ZB_UINT8_MAX/2) ? ZB_TRUE : ZB_FALSE; - break; - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_LONGEST: - val_end = payload.hue + (payload.hue <= curr_val ? ZB_UINT8_MAX : 0) ? ZB_TRUE : ZB_FALSE; - direction = (val_end - curr_val >= ZB_UINT8_MAX/2) ? ZB_TRUE : ZB_FALSE; - break; - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_UP: - direction=ZB_TRUE; - break; - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_DOWN: - direction=ZB_FALSE; - break; - } - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_TO_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, - curr_val, payload.hue, direction, payload.transition_time); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_to_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_to_hue_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Move Hue command - @see ZCL8 spec, subclause 5.2.2.3.5 */ -static zb_ret_t zb_zcl_process_color_control_move_hue_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_move_hue_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_hue_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - ZB_ZCL_COLOR_CONTROL_GET_MOVE_HUE_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_MOVE_HUE_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - if (payload.move_mode == ZB_ZCL_CMD_COLOR_CONTROL_MOVE_STOP) - { - zb_zcl_process_color_control_stop_all_commands(endpoint); - } - /* Condition is fixed according to CCB2501*/ - else if(payload.rate==0 && (payload.move_mode == ZB_ZCL_CMD_COLOR_CONTROL_MOVE_UP || - payload.move_mode == ZB_ZCL_CMD_COLOR_CONTROL_MOVE_DOWN)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, - ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_DATA(param, &cmd_info, - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, - (payload.move_mode==ZB_ZCL_CMD_COLOR_CONTROL_MOVE_UP ? 1 : -1) * - payload.rate, ZB_ZCL_COLOR_CONTROL_CURRENT_HUE_MAX_VALUE); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_hue_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Step Hue command - @see ZCL spec, subclause 5.2.2.3.4 */ -static zb_ret_t zb_zcl_process_color_control_step_hue_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_step_hue_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_step_hue_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_STEP_HUE_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_STEP_HUE_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (payload.step_size == 0) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, - ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - - ZB_ZCL_COLOR_CONTROL_FILL_STEP_DATA(param, &cmd_info, - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, - payload.step_size*(payload.step_mode== ZB_ZCL_CMD_COLOR_CONTROL_STEP_UP ? 1 : -1), - payload.transition_time, - (payload.step_mode== ZB_ZCL_CMD_COLOR_CONTROL_STEP_UP ? ZB_ZCL_COLOR_CONTROL_CURRENT_HUE_MAX_VALUE : 0)); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_step_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_step_hue_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Move To Saturation command - @see ZCL spec, subclause 5.2.2.3.5 */ -static zb_ret_t zb_zcl_process_color_control_move_to_saturation_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_move_to_saturation_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_to_saturation_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_SATURATION_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_SATURATION_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (payload.saturation > ZB_ZCL_COLOR_CONTROL_CURRENT_SATURATION_MAX_VALUE) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_uint8_t sat = zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID); - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_TO_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, - sat, payload.saturation, (sat < payload.saturation), payload.transition_time); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_to_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_to_saturation_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Move Saturation command - @see ZCL spec, subclause 5.2.2.3.6 */ -static zb_ret_t zb_zcl_process_color_control_move_saturation_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_move_saturation_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_saturation_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_MOVE_SATURATION_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_MOVE_SATURATION_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - if(payload.move_mode==ZB_ZCL_CMD_COLOR_CONTROL_MOVE_STOP) - { - zb_zcl_process_color_control_stop_all_commands(endpoint); - } - else if(payload.rate==0) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_DATA(param, &cmd_info, - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, - (payload.move_mode==ZB_ZCL_CMD_COLOR_CONTROL_MOVE_UP ? 1 : -1) * - payload.rate, ZB_ZCL_COLOR_CONTROL_CURRENT_SATURATION_MAX_VALUE); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_saturation_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Step Saturation command - @see ZCL spec, subclause 5.2.2.3.7 */ -static zb_ret_t zb_zcl_process_color_control_step_saturation_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_step_saturation_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_step_saturation_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_STEP_SATURATION_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_STEP_SATURATION_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (payload.step_size == 0) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - - ZB_ZCL_COLOR_CONTROL_FILL_STEP_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, - payload.step_size*(payload.step_mode== ZB_ZCL_CMD_COLOR_CONTROL_STEP_UP ? 1 : -1), - payload.transition_time, - (payload.step_mode== ZB_ZCL_CMD_COLOR_CONTROL_STEP_UP ? ZB_ZCL_COLOR_CONTROL_CURRENT_SATURATION_MAX_VALUE : 0)); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_step_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_step_saturation_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Move To Hue And Saturation command - @see ZCL spec, subclause 5.2.2.3.8 */ -static zb_ret_t zb_zcl_process_color_control_move_to_hue_saturation_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_move_to_hue_saturation_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_to_hue_saturation_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_HUE_SATURATION_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_HUE_SATURATION_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (payload.hue > ZB_ZCL_COLOR_CONTROL_CURRENT_HUE_MAX_VALUE || - payload.saturation > ZB_ZCL_COLOR_CONTROL_CURRENT_SATURATION_MAX_VALUE) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_zcl_color_control_move_to_loop_t *loop_data; - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID); - ZB_ASSERT(attr_desc); - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_TO_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, - ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc), payload.hue, - payload.hue > ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc), payload.transition_time); - - loop_data = ZB_BUF_GET_PARAM(param, zb_zcl_color_control_move_to_loop_t); - loop_data->attr_id2 = ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID; - loop_data->start_value2 = zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID); - loop_data->finish_value2 = payload.saturation; - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_to_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_to_hue_saturation_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Move To Color command - @see ZCL spec, subclause 5.2.2.3.9 */ -static zb_ret_t zb_zcl_process_color_control_move_to_color_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_move_to_color_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_to_color_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_COLOR_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_COLOR_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (payload.color_x > ZB_ZCL_COLOR_CONTROL_CURRENT_X_MAX_VALUE || - payload.color_y > ZB_ZCL_COLOR_CONTROL_CURRENT_Y_MAX_VALUE) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_zcl_color_control_move_to_loop_t *loop_data; - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID); - ZB_ASSERT(attr_desc); - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_CURRENT_X_Y); - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_TO_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, - ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc), payload.color_x, - payload.color_x > ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc), payload.transition_time); - - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID); - ZB_ASSERT(attr_desc); - - loop_data = ZB_BUF_GET_PARAM(param, zb_zcl_color_control_move_to_loop_t); - loop_data->attr_id2 = ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID; - loop_data->start_value2 = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - loop_data->finish_value2 = payload.color_y; - - TRACE_MSG(TRACE_ZCL2, "start time %d val1 start 0x%x val1 end 0x%x val2 start 0x%x val2 end 0x%x", - (FMT__D_D_D_D_D, loop_data->start_time, loop_data->start_value, loop_data->finish_value, - loop_data->start_value2, loop_data->finish_value2)); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_to_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_to_color_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Move Color command - @see ZCL spec, subclause 5.2.2.3.10 */ -static zb_ret_t zb_zcl_process_color_control_move_color_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_move_color_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_color_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_MOVE_COLOR_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_MOVE_COLOR_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - if (payload.rate_x==0 && payload.rate_y==0) - { - zb_zcl_process_color_control_stop_all_commands(endpoint); - } - else - { - zb_zcl_color_control_move_loop_t *loop_data; - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_CURRENT_X_Y); - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_DATA(param, &cmd_info, - ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, payload.rate_x, - ZB_ZCL_COLOR_CONTROL_CURRENT_X_MAX_VALUE); - - loop_data = ZB_BUF_GET_PARAM((param), zb_zcl_color_control_move_loop_t); - loop_data->attr_id2 = ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID; - loop_data->rate2 = payload.rate_y; - loop_data->limit2 = ZB_ZCL_COLOR_CONTROL_CURRENT_Y_MAX_VALUE; - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_loop, param); - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_color_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Step Color command - @see ZCL spec, subclause 5.2.2.3.11 */ -static zb_ret_t zb_zcl_process_color_control_step_color_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_step_color_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_step_color_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_STEP_COLOR_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_STEP_COLOR_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_zcl_color_control_step_loop_t *loop_data; - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_CURRENT_X_Y); - - ZB_ZCL_COLOR_CONTROL_FILL_STEP_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, - payload.step_x, payload.transition_time, - ((zb_int16_t)payload.step_x>0 ? ZB_ZCL_COLOR_CONTROL_CURRENT_X_MAX_VALUE : 0)); - - loop_data = ZB_BUF_GET_PARAM(param, zb_zcl_color_control_step_loop_t); - loop_data->attr_id2 = ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID; - loop_data->rate2 = payload.step_y; - loop_data->limit2 = ((zb_int16_t)payload.step_y>0 ? ZB_ZCL_COLOR_CONTROL_CURRENT_Y_MAX_VALUE : 0); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_step_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_step_color_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Move To Color Temperature command - @see ZCL spec, subclause 5.2.2.3.12 */ -static zb_ret_t zb_zcl_process_color_control_move_to_color_temp_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_move_to_color_temperature_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_to_color_temp_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_COLOR_TEMPERATURE_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_MOVE_TO_COLOR_TEMP_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (payload.color_temperature == ZB_ZCL_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIREDS_INVALID_VALUE) - { - TRACE_MSG(TRACE_ZCL1, "Error payload parameter", (FMT__0)); - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID); - ZB_ASSERT(attr_desc); - - TRACE_MSG(TRACE_ZCL1, "payload.color_temperature %d", (FMT__D, payload.color_temperature)); - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - TRACE_MSG(TRACE_ZCL1, "Prepare loop", (FMT__0)); - - if( payload.color_temperature < zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_ID)) - { - payload.color_temperature = zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_ID); - } - else if (payload.color_temperature > zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_ID)) - { - payload.color_temperature = zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_ID); - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_TEMPERATURE); - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_TO_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, - ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc), payload.color_temperature, - payload.color_temperature > ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc), payload.transition_time); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_to_loop, param); - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH(buf2_param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_to_color_temp_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Enhanced Move To Hue command - @see ZCL spec, subclause 5.2.2.3.14 */ -static zb_ret_t zb_zcl_process_color_control_enhanced_move_to_hue_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_enhanced_move_to_hue_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_enhanced_move_to_hue_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_MOVE_TO_HUE_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_MOVE_TO_HUE_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_bool_t direction = ZB_FALSE; - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_uint16_t curr_val = zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID); - zb_uint32_t val_end; - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID, - ZB_ZCL_COLOR_CONTROL_COLOR_EX_MODE_HUE_SATURATION_EX); - - switch(payload.direction) - { - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SHORTEST: - val_end = payload.enhanced_hue + (payload.enhanced_hue <= curr_val ? ZB_UINT16_MAX : 0); - direction = (val_end - curr_val <= ZB_UINT16_MAX/2) ? ZB_TRUE : ZB_FALSE; - break; - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_LONGEST: - val_end = payload.enhanced_hue + (payload.enhanced_hue <= curr_val ? ZB_UINT8_MAX : 0); - direction = (val_end - curr_val >= ZB_UINT16_MAX/2) ? ZB_TRUE : ZB_FALSE; - break; - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_UP: - direction=ZB_TRUE; - break; - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_DOWN: - direction=ZB_FALSE; - break; - } - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_TO_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID, - curr_val, payload.enhanced_hue, direction, payload.transition_time); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_to_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH((buf2_param), &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_enhanced_move_to_hue_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Enhanced Move Hue command - @see ZCL spec, subclause 5.2.2.3.15 */ -static zb_ret_t zb_zcl_process_color_control_enhanced_move_hue_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_enhanced_move_hue_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_enhanced_move_hue_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_MOVE_HUE_REQ(param, payload, status); - if (!color_control_check_color_capabilities(endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_MOVE_HUE_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (!color_control_check_req_options(param, endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - if(payload.move_mode==ZB_ZCL_CMD_COLOR_CONTROL_MOVE_STOP) - { - zb_zcl_process_color_control_stop_all_commands(endpoint); - } - else if(payload.rate==0) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID - , ZB_ZCL_COLOR_CONTROL_COLOR_EX_MODE_HUE_SATURATION_EX); - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_DATA(param, &cmd_info, - ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID, - (payload.move_mode==ZB_ZCL_CMD_COLOR_CONTROL_MOVE_UP ? 1 : -1) * - payload.rate, ZB_ZCL_COLOR_CONTROL_ENHANCED_HUE_MAX_DEF_VALUE); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH((buf2_param), &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_enhanced_move_hue_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Enhanced Step Hue command - @see ZCL spec, subclause 5.2.2.3.16 */ -static zb_ret_t zb_zcl_process_color_control_enhanced_step_hue_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_enhanced_step_hue_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_enhanced_step_hue_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_STEP_HUE_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_STEP_HUE_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (payload.step_size == 0) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID - , ZB_ZCL_COLOR_CONTROL_COLOR_EX_MODE_HUE_SATURATION_EX); - - ZB_ZCL_COLOR_CONTROL_FILL_STEP_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID, - payload.step_size*(payload.step_mode== ZB_ZCL_CMD_COLOR_CONTROL_STEP_UP ? 1 : -1), - payload.transition_time, ZB_ZCL_COLOR_CONTROL_ENHANCED_HUE_MAX_DEF_VALUE); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_step_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH((buf2_param), &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_enhanced_step_hue_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Enhanced Move To Hue Saturation command - @see ZCL spec, subclause 5.2.2.3.17 */ -static zb_ret_t zb_zcl_process_color_control_enhanced_move_to_hue_saturation_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_enhanced_move_to_hue_saturation_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_enhanced_move_to_hue_saturation_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_MOVE_TO_HUE_SATURATION_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_ENHANCED_MOVE_TO_HUE_SATURATION_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_zcl_color_control_move_to_loop_t *loop_data; - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID); - ZB_ASSERT(attr_desc); - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID - , ZB_ZCL_COLOR_CONTROL_COLOR_EX_MODE_HUE_SATURATION_EX); - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_TO_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID, - ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc), payload.enhanced_hue, - payload.enhanced_hue > ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc), payload.transition_time); - - loop_data = ZB_BUF_GET_PARAM(param, zb_zcl_color_control_move_to_loop_t); - loop_data->attr_id2 = ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID; - loop_data->start_value2 = zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID); - loop_data->finish_value2 = payload.saturation; - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_to_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH((buf2_param), &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_enhanced_move_to_hue_saturation_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Process Color Loop Set command - * - * - * Its continuous loop: - * If the color loop is active, the device shall cycle over the complete range of values of the 1 - * EnhancedCurrentHue attribute in the direction of the ColorLoopDirection attribute over the time 2 - * specified in the ColorLoopTime attribute. - * - * For make one loop only need uncomment all string with 'is_finish' variable - * and 'if (!is_finish) .. else ...' condition - * - * */ -static void zb_zcl_process_color_control_color_loop(zb_uint8_t param) -{ - zb_zcl_color_control_color_loop_set_t loop_data; - zb_zcl_attr_t * attr_desc; - zb_uint8_t endpoint; - zb_time_t current_time = ZB_TIMER_GET(); - zb_uint8_t loop_active; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_color_loop %hd", (FMT__H, param)); - - ZB_MEMCPY(&loop_data, ZB_BUF_GET_PARAM(param, zb_zcl_color_control_color_loop_set_t), - sizeof(zb_zcl_color_control_color_loop_set_t)); - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&(loop_data.cmd_info)).dst_endpoint; - - loop_active = zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_ACTIVE_ID); - - if (loop_active != ZB_ZCL_CMD_COLOR_CONTROL_LOOP_ACTION_DEACTIVATE) - { - zb_int8_t direction; - zb_uint16_t max_time; - zb_int32_t val; - zb_uint16_t val16; - - direction = (zb_zcl_color_control_get8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_DIRECTION_ID) - == ZB_ZCL_CMD_COLOR_CONTROL_LOOP_DIRECTION_INCREMENT) ? 1 : -1; - - max_time = zb_zcl_color_control_get16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_TIME_ID); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID); - ZB_ASSERT(attr_desc); - val = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - TRACE_MSG(TRACE_ZCL1, "val %hd direct %hd max_time %hd max time beacon %d delta time %d", (FMT__D_D_D_D_D, - val, direction, max_time, ZB_MILLISECONDS_TO_BEACON_INTERVAL(1000* max_time), - ZB_TIME_SUBTRACT(current_time, loop_data.last_time))); - - val += direction * (ZB_UINT16_MAX / (ZB_MILLISECONDS_TO_BEACON_INTERVAL(1000* max_time)) * - ZB_TIME_SUBTRACT(current_time, loop_data.last_time)); - if (val >= (zb_int32_t)ZB_UINT16_MAX) - { - val -= ZB_UINT16_MAX; - } - if (val < 0) - { - val += ZB_UINT16_MAX; - } - - val16 = (zb_uint16_t)val; - - TRACE_MSG(TRACE_ZCL1, "new val %hd", (FMT__D, val16)); - - (void)zb_zcl_color_control_invoke_user_app(param, endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID, val16); - } - - { - zb_time_t alarm_time = ZB_TIME_SUBTRACT(loop_data.last_time + ZB_ZCL_COLOR_CONTROL_TIMER_BEACON_INTERVAL, - current_time); - if (alarm_time > ZB_HALF_MAX_TIME_VAL) - { - alarm_time = 0; - } - loop_data.last_time = current_time; - - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_color_control_color_loop_set_t), &loop_data, sizeof(loop_data)); - ZB_SCHEDULE_ALARM(zb_zcl_process_color_control_color_loop, param, alarm_time); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_color_loop", (FMT__0)); -} - -/** @brief Process Color Loop Set command - @see ZCL spec, subclause 5.2.2.3.18 */ -static zb_ret_t zb_zcl_process_color_control_color_loop_set_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_color_loop_set_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_color_loop_set_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - ZB_ZCL_COLOR_CONTROL_GET_COLOR_LOOP_SET_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_COLOR_LOOP_SET_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_HUE_SATURATION); - - TRACE_MSG(TRACE_ZCL3, "payload.update_flags 0x%hx", (FMT__H, payload.update_flags)); - - if((payload.update_flags & ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_DIRECTION) != 0) - { - TRACE_MSG(TRACE_ZCL3, "ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_DIRECTION: 0x%hx", (FMT__H, payload.direction)); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_DIRECTION_ID, payload.direction); - } - - if((payload.update_flags & ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_TIME) != 0) - { - TRACE_MSG(TRACE_ZCL3, "ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_TIME: 0x%x", (FMT__D, payload.time)); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_TIME_ID, payload.time); - } - - if((payload.update_flags & ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_START_HUE) != 0) - { - TRACE_MSG(TRACE_ZCL3, "ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_START_HUE: 0x%x", (FMT__D, payload.start_hue)); - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_START_ENHANCED_HUE_ID, payload.start_hue); - } - - if((payload.update_flags & ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_ACTION) != 0) - { - TRACE_MSG(TRACE_ZCL3, "ZB_ZCL_CMD_COLOR_CONTROL_LOOP_UPDATE_ACTION: 0x%hx", (FMT__H, payload.action)); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_ACTIVE_ID, - payload.action==ZB_ZCL_CMD_COLOR_CONTROL_LOOP_ACTION_DEACTIVATE ? 0 : 1); - - switch(payload.action) - { - case ZB_ZCL_CMD_COLOR_CONTROL_LOOP_ACTION_DEACTIVATE: - zb_zcl_process_color_control_stop(zb_zcl_process_color_control_color_loop, - sizeof(zb_zcl_color_control_color_loop_set_t)); - - ZB_ZCL_COLOR_CONTROL_COPY_ATTRIBUTE_16(endpoint, - ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID, - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_STORED_ENHANCED_HUE_ID); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_LOOP_ACTION_START_HUE: - ZB_ZCL_COLOR_CONTROL_COPY_ATTRIBUTE_16(endpoint, - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_START_ENHANCED_HUE_ID, - ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID); - - ZB_ZCL_COLOR_CONTROL_FILL_COLOR_LOOP_SET_DATA(param, &cmd_info); - ZB_SCHEDULE_ALARM(zb_zcl_process_color_control_color_loop, param, 0); - ret = RET_BUSY; - ZB_ZCL_PROCESS_COMMAND_FINISH((buf2_param), &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_LOOP_ACTION_CURRENT_HUE: - ZB_ZCL_COLOR_CONTROL_COPY_ATTRIBUTE_16(endpoint, - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_LOOP_STORED_ENHANCED_HUE_ID, - ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_CURRENT_HUE_ID); - - ZB_ZCL_COLOR_CONTROL_FILL_COLOR_LOOP_SET_DATA(param, &cmd_info); - ZB_SCHEDULE_ALARM(zb_zcl_process_color_control_color_loop, param, 0); - ret = RET_BUSY; - ZB_ZCL_PROCESS_COMMAND_FINISH((buf2_param), &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - break; - - default: - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - break; - } - } - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_color_loop_set_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Process Color Loop Stop command - @see ZCL spec, subclause 5.2.2.3.19 */ -static zb_ret_t zb_zcl_process_color_control_stop_move_step_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_stop_move_step_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - if (!color_control_check_color_capabilities(endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (color_control_check_req_options(param, endpoint)) - { - zb_zcl_color_control_set16(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_REMAINING_TIME_ID, 0); - - zb_zcl_process_color_control_stop_all_commands(endpoint); - } - - zb_buf_free(buf2_param); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_stop_move_step_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/* Get Temperature Limit by payload max/min field & direction */ -static zb_uint16_t zb_zcl_color_control_get_color_temperature_limit( - zb_uint8_t endpoint, zb_bool_t is_up, zb_uint16_t min, zb_uint16_t max) -{ - zb_uint16_t limit = is_up ? max : min; - if (limit ==0) - { - limit = zb_zcl_color_control_get16(endpoint, - is_up ? ((zb_uint16_t) ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_ID) : - ((zb_uint16_t) ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_ID)); - } - return limit; -} - -/** @brief Process Move Color Temperature command - @see ZCL spec, subclause 5.2.2.3.20 */ -static zb_ret_t zb_zcl_process_color_control_move_color_temp_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_move_color_temp_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_move_color_temp_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - ZB_ZCL_COLOR_CONTROL_GET_MOVE_COLOR_TEMP_REQ(param, payload, status); - if (!color_control_check_color_capabilities(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_MOVE_COLOR_TEMP_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (!color_control_check_req_options(param, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - if(payload.move_mode==ZB_ZCL_CMD_COLOR_CONTROL_MOVE_STOP) - { - zb_zcl_process_color_control_stop_all_commands(endpoint); - } - else if(payload.rate==0) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_uint16_t limit = zb_zcl_color_control_get_color_temperature_limit( - endpoint, (zb_bool_t)(payload.move_mode == ZB_ZCL_CMD_COLOR_CONTROL_MOVE_UP), - payload.color_temp_min, payload.color_temp_max); - - zb_zcl_process_color_control_stop_all_commands(endpoint); - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_TEMPERATURE); - - ZB_ZCL_COLOR_CONTROL_FILL_MOVE_DATA(param, &cmd_info, - ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, - (payload.move_mode== ZB_ZCL_CMD_COLOR_CONTROL_MOVE_UP ? 1 : -1) * payload.rate, limit); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_move_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH((buf2_param), &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_move_color_temp_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/** @brief Process Step Color Temperature command - @see ZCL spec, subclause 5.2.2.3.21 */ -static zb_ret_t zb_zcl_process_color_control_step_color_temp_handler(zb_uint8_t param, zb_uint8_t buf2_param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_color_control_step_color_temp_req_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_color_control_step_color_temp_handler param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - ZB_ZCL_COLOR_CONTROL_GET_STEP_COLOR_TEMP_REQ(param, payload, status); - if (!color_control_check_color_capabilities(endpoint, cmd_info.cmd_id)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_UNSUP_CMD); - ret = RET_BUSY; // not need send answer yet - } - else if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_COLOR_CONTROL_GET_STEP_COLOR_TEMP_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if (!color_control_check_req_options(param, endpoint)) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_SUCCESS); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_uint16_t limit; - - if (payload.transition_time == 0) - { - payload.transition_time++; - } - - zb_zcl_process_color_control_stop_all_commands(endpoint); - limit = zb_zcl_color_control_get_color_temperature_limit( - endpoint, (zb_bool_t)(payload.step_mode == ZB_ZCL_CMD_COLOR_CONTROL_STEP_UP), - payload.color_temp_min, payload.color_temp_max); - - zb_zcl_color_control_set_color_mode(endpoint, ZB_ZCL_COLOR_CONTROL_COLOR_MODE_TEMPERATURE); - zb_zcl_color_control_set8(endpoint, ZB_ZCL_ATTR_COLOR_CONTROL_ENHANCED_COLOR_MODE_ID - , ZB_ZCL_COLOR_CONTROL_COLOR_MODE_TEMPERATURE); - - ZB_ZCL_COLOR_CONTROL_FILL_STEP_DATA(param, &cmd_info, ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, - payload.step_size*(payload.step_mode== ZB_ZCL_CMD_COLOR_CONTROL_STEP_UP ? 1 : -1), - payload.transition_time, limit); - - ZB_SCHEDULE_CALLBACK(zb_zcl_process_color_control_step_loop, param); - - ret = RET_BUSY; - - ZB_ZCL_PROCESS_COMMAND_FINISH((buf2_param), &cmd_info, ZB_ZCL_STATUS_SUCCESS); - buf2_param = 0; - } - - if (buf2_param != 0) - { - zb_buf_free(buf2_param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_color_control_step_color_temp_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -zb_bool_t zb_zcl_process_color_control_specific_commands_srv(zb_uint8_t param) -{ - zb_bool_t processed = ZB_FALSE; - zb_zcl_parsed_hdr_t *cmd_info; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_color_control_server_cmd_list; - return ZB_TRUE; - } - - cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_color_control_specific_commands_srv: parambuf %d, cmd_info %d", - (FMT__H_H, param, cmd_info->cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_COLOR_CONTROL == cmd_info->cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info->cmd_direction); - - if ( (cmd_info->cmd_id <= ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR_TEMPERATURE) || - (cmd_info->cmd_id >= ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE && - cmd_info->cmd_id <= ZB_ZCL_CMD_COLOR_CONTROL_COLOR_LOOP_SET) || - cmd_info->cmd_id == ZB_ZCL_CMD_COLOR_CONTROL_STOP_MOVE_STEP || - cmd_info->cmd_id == ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR_TEMPERATURE || - cmd_info->cmd_id == ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR_TEMPERATURE - ) - { - zb_buf_get_out_delayed_ext(zb_zcl_process_color_control_specific_commands_srv_2param, param, 0); - processed = ZB_TRUE; - } - - return processed; -} - -void zb_zcl_process_color_control_specific_commands_srv_2param(zb_uint8_t buf2_param, zb_uint16_t cmd_param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t status = RET_OK; - zb_uint8_t param = cmd_param; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_color_control_specific_commands_srv_2param: parambuf %d, cmd_info %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_COLOR_CONTROL == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - switch( cmd_info.cmd_id ) - { - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE: - status = zb_zcl_process_color_control_move_to_hue_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_HUE: - status = zb_zcl_process_color_control_move_hue_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_STEP_HUE: - status = zb_zcl_process_color_control_step_hue_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_SATURATION: - status = zb_zcl_process_color_control_move_to_saturation_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_SATURATION: - status = zb_zcl_process_color_control_move_saturation_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_STEP_SATURATION: - status = zb_zcl_process_color_control_step_saturation_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SATURATION: - status = zb_zcl_process_color_control_move_to_hue_saturation_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR: - status = zb_zcl_process_color_control_move_to_color_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR: - status = zb_zcl_process_color_control_move_color_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR: - status = zb_zcl_process_color_control_step_color_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR_TEMPERATURE: - status = zb_zcl_process_color_control_move_to_color_temp_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE: - status = zb_zcl_process_color_control_enhanced_move_to_hue_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_HUE: - status = zb_zcl_process_color_control_enhanced_move_hue_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_STEP_HUE: - status = zb_zcl_process_color_control_enhanced_step_hue_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_SATURATION: - status = zb_zcl_process_color_control_enhanced_move_to_hue_saturation_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_COLOR_LOOP_SET: - status = zb_zcl_process_color_control_color_loop_set_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_STOP_MOVE_STEP: - status = zb_zcl_process_color_control_stop_move_step_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR_TEMPERATURE: - status = zb_zcl_process_color_control_move_color_temp_handler(param, buf2_param); - break; - - case ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR_TEMPERATURE: - status = zb_zcl_process_color_control_step_color_temp_handler(param, buf2_param); - break; - - default: - /* processed = ZB_FALSE; */ - ZB_ASSERT(0); /* should not happen */ - break; - } - - /* if( processed ) */ - { - if( cmd_info.disable_default_response && status == RET_OK) - { - TRACE_MSG( TRACE_ZCL3, - "Default response disabled", - (FMT__0)); - zb_buf_free(param); - } - else if (status != RET_BUSY) - { - ZB_ZCL_SEND_DEFAULT_RESP( param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - cmd_info.seq_number, - cmd_info.cmd_id, - status==RET_OK ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_INVALID_FIELD); - } - } - - TRACE_MSG( TRACE_ZCL1, - "< zb_zcl_process_color_control_specific_commands_srv_2param", - (FMT__0)); -} - -zb_bool_t zb_zcl_process_color_control_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_color_control_client_cmd_list; - return ZB_TRUE; - } - return ZB_FALSE; -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE implementation */ - -static inline void zb_zcl_color_control_send_move_to_hue_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, zb_uint8_t direction, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (hue)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (direction)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_move_to_hue_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, zb_uint8_t direction, - zb_uint16_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (hue)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (direction)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_move_to_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, zb_uint8_t direction, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_to_hue_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_to_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - hue, direction, - transition_time); - break; - case 3: - zb_zcl_color_control_send_move_to_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - hue, direction, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_to_hue_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_move_to_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, zb_uint8_t direction, - zb_uint16_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_to_hue_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_to_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - hue, direction, - transition_time); - break; - case 3: - zb_zcl_color_control_send_move_to_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - hue, direction, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_to_hue_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_MOVE_HUE implementation */ - -static inline void zb_zcl_color_control_send_move_hue_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_HUE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (move_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (rate)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_move_hue_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_HUE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (move_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (rate)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_move_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_hue_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, rate); - break; - case 3: - zb_zcl_color_control_send_move_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, rate, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_hue_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_move_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_hue_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, rate); - break; - case 3: - zb_zcl_color_control_send_move_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, rate, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_hue_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_STEP_HUE implementation */ - -static inline void zb_zcl_color_control_send_step_hue_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_STEP_HUE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_size)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_step_hue_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_STEP_HUE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_size)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_step_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_step_hue_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_step_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, - transition_time); - break; - case 3: - zb_zcl_color_control_send_step_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_step_hue_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_step_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_step_hue_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_step_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, - transition_time); - break; - case 3: - zb_zcl_color_control_send_step_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_step_hue_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_SATURATION implementation */ - -static inline void zb_zcl_color_control_send_move_to_saturation_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t saturation, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_SATURATION); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (saturation)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_move_to_saturation_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t saturation, - zb_uint16_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_SATURATION); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (saturation)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_move_to_saturation_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t saturation, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_to_saturation_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_to_saturation_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - saturation, - transition_time); - break; - case 3: - zb_zcl_color_control_send_move_to_saturation_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - saturation, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_to_saturation_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_move_to_saturation_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t saturation, - zb_uint16_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_to_saturation_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_to_saturation_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - saturation, - transition_time); - break; - case 3: - zb_zcl_color_control_send_move_to_saturation_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - saturation, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_to_saturation_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_MOVE_SATURATION implementation */ - -static inline void zb_zcl_color_control_send_move_saturation_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_SATURATION); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (move_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (rate)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_move_saturation_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_SATURATION); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (move_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (rate)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_move_saturation_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_saturation_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_saturation_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate); - break; - case 3: - zb_zcl_color_control_send_move_saturation_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_saturation_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_move_saturation_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_saturation_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_saturation_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate); - break; - case 3: - zb_zcl_color_control_send_move_saturation_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_saturation_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_STEP_SATURATION implementation */ - -static inline void zb_zcl_color_control_send_step_saturation_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_STEP_SATURATION); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_size)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_step_saturation_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_STEP_SATURATION); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_size)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_step_saturation_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_step_saturation_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_step_saturation_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, - transition_time); - break; - case 3: - zb_zcl_color_control_send_step_saturation_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_step_saturation_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_step_saturation_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint8_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_step_saturation_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_step_saturation_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, - transition_time); - break; - case 3: - zb_zcl_color_control_send_step_saturation_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_step_saturation_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SATURATION implementation */ - -static inline void zb_zcl_color_control_send_move_to_hue_saturation_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, - zb_uint8_t saturation, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SATURATION); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (hue)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (saturation)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_move_to_hue_saturation_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, - zb_uint8_t saturation, - zb_uint16_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_HUE_SATURATION); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (hue)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (saturation)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_move_to_hue_saturation_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, - zb_uint8_t saturation, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_to_hue_saturation_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_to_hue_saturation_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - hue, - saturation, - transition_time); - break; - case 3: - zb_zcl_color_control_send_move_to_hue_saturation_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - hue, - saturation, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_to_hue_saturation_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_move_to_hue_saturation_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t hue, - zb_uint8_t saturation, - zb_uint16_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_to_hue_saturation_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_to_hue_saturation_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - hue, - saturation, - transition_time); - break; - case 3: - zb_zcl_color_control_send_move_to_hue_saturation_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - hue, - saturation, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_to_hue_saturation_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR implementation */ - -static inline void zb_zcl_color_control_send_move_to_color_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_x, - zb_uint16_t color_y, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_x)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_y)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_move_to_color_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_x, - zb_uint16_t color_y, - zb_uint16_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_x)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_y)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_move_to_color_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_x, - zb_uint16_t color_y, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_to_color_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_to_color_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - color_x, - color_y, - transition_time); - break; - case 3: - zb_zcl_color_control_send_move_to_color_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - color_x, - color_y, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_to_color_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_move_to_color_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_x, - zb_uint16_t color_y, - zb_uint16_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_to_color_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_to_color_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - color_x, - color_y, - transition_time); - break; - case 3: - zb_zcl_color_control_send_move_to_color_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - color_x, - color_y, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_to_color_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR implementation */ - -static inline void zb_zcl_color_control_send_move_color_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t rate_x, - zb_uint16_t rate_y, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (rate_x)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (rate_y)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_move_color_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t rate_x, - zb_uint16_t rate_y) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (rate_x)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (rate_y)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_move_color_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t rate_x, - zb_uint16_t rate_y, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_color_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_color_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - rate_x, - rate_y); - break; - case 3: - zb_zcl_color_control_send_move_color_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - rate_x, - rate_y, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_color_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_move_color_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t rate_x, - zb_uint16_t rate_y) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_color_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_color_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - rate_x, - rate_y); - break; - case 3: - zb_zcl_color_control_send_move_color_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - rate_x, - rate_y, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_color_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR implementation */ - -static inline void zb_zcl_color_control_send_step_color_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t step_x, - zb_uint16_t step_y, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (step_x)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (step_y)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_step_color_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t step_x, - zb_uint16_t step_y, - zb_uint16_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (step_x)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (step_y)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_step_color_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t step_x, - zb_uint16_t step_y, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_step_color_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_step_color_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_x, - step_y, - transition_time); - break; - case 3: - zb_zcl_color_control_send_step_color_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_x, - step_y, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_step_color_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_step_color_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t step_x, - zb_uint16_t step_y, - zb_uint16_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_step_color_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_step_color_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_x, - step_y, - transition_time); - break; - case 3: - zb_zcl_color_control_send_step_color_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_x, - step_y, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_step_color_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR_TEMPERATURE implementation */ - -static inline void zb_zcl_color_control_send_move_to_color_temperature_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_temperature, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR_TEMPERATURE); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_temperature)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_move_to_color_temperature_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_temperature, - zb_uint16_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_TO_COLOR_TEMPERATURE); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_temperature)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_move_to_color_temperature_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_temperature, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_to_color_temperature_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_to_color_temperature_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - color_temperature, - transition_time); - break; - case 3: - zb_zcl_color_control_send_move_to_color_temperature_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - color_temperature, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_to_color_temperature_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_move_to_color_temperature_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t color_temperature, - zb_uint16_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_to_color_temperature_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_to_color_temperature_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - color_temperature, - transition_time); - break; - case 3: - zb_zcl_color_control_send_move_to_color_temperature_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - color_temperature, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_to_color_temperature_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE implementation */ - -static inline void zb_zcl_color_control_send_enhanced_move_to_hue_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t direction, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (enhanced_hue)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (direction)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_enhanced_move_to_hue_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t direction, - zb_uint16_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (enhanced_hue)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (direction)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_enhanced_move_to_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t direction, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_enhanced_move_to_hue_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_enhanced_move_to_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - enhanced_hue, - direction, - transition_time); - break; - case 3: - zb_zcl_color_control_send_enhanced_move_to_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - enhanced_hue, - direction, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_enhanced_move_to_hue_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_enhanced_move_to_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t direction, - zb_uint16_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_enhanced_move_to_hue_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_enhanced_move_to_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - enhanced_hue, - direction, - transition_time); - break; - case 3: - zb_zcl_color_control_send_enhanced_move_to_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - enhanced_hue, - direction, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_enhanced_move_to_hue_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_HUE implementation */ - -static inline void zb_zcl_color_control_send_enhanced_move_hue_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_HUE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (move_mode)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (rate)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_enhanced_move_hue_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_HUE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (move_mode)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (rate)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_enhanced_move_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_enhanced_move_hue_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_enhanced_move_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate); - break; - case 3: - zb_zcl_color_control_send_enhanced_move_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_enhanced_move_hue_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_enhanced_move_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_enhanced_move_hue_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_enhanced_move_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate); - break; - case 3: - zb_zcl_color_control_send_enhanced_move_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_enhanced_move_hue_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_STEP_HUE implementation */ - -static inline void zb_zcl_color_control_send_enhanced_step_hue_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_STEP_HUE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (step_size)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_enhanced_step_hue_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_STEP_HUE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (step_size)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_enhanced_step_hue_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_enhanced_step_hue_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_enhanced_step_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, - step_size, - transition_time); - break; - case 3: - zb_zcl_color_control_send_enhanced_step_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, - step_size, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_enhanced_step_hue_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_enhanced_step_hue_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_enhanced_step_hue_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_enhanced_step_hue_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, - step_size, - transition_time); - break; - case 3: - zb_zcl_color_control_send_enhanced_step_hue_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, - step_size, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_enhanced_step_hue_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_SATURATION implementation */ - -static inline void zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t saturation, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_SATURATION); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (enhanced_hue)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (saturation)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t saturation, - zb_uint16_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_SATURATION); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (enhanced_hue)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (saturation)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t saturation, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - enhanced_hue, - saturation, - transition_time); - break; - case 3: - zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - enhanced_hue, - saturation, - transition_time, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint16_t enhanced_hue, - zb_uint8_t saturation, - zb_uint16_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - enhanced_hue, - saturation, - transition_time); - break; - case 3: - zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - enhanced_hue, - saturation, - transition_time, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_enhanced_move_to_hue_saturation_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_COLOR_LOOP_SET implementation */ - -static inline void zb_zcl_color_control_send_color_loop_set_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t update_flags, - zb_uint8_t action, - zb_uint8_t direction, - zb_uint16_t time, - zb_uint16_t start_hue, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_COLOR_LOOP_SET); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (update_flags)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (action)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (direction)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (time)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (start_hue)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_color_loop_set_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t update_flags, - zb_uint8_t action, - zb_uint8_t direction, - zb_uint16_t time, - zb_uint16_t start_hue) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_COLOR_LOOP_SET); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (update_flags)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (action)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (direction)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (time)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (start_hue)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_color_loop_set_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t update_flags, - zb_uint8_t action, - zb_uint8_t direction, - zb_uint16_t time, - zb_uint16_t start_hue, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_color_loop_set_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_color_loop_set_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - update_flags, - action, - direction, - time, - start_hue); - break; - case 3: - zb_zcl_color_control_send_color_loop_set_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - update_flags, - action, - direction, - time, - start_hue, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_color_loop_set_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_color_loop_set_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t update_flags, - zb_uint8_t action, - zb_uint8_t direction, - zb_uint16_t time, - zb_uint16_t start_hue) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_color_loop_set_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_color_loop_set_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - update_flags, - action, - direction, - time, - start_hue); - break; - case 3: - zb_zcl_color_control_send_color_loop_set_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - update_flags, - action, - direction, - time, - start_hue, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_color_loop_set_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_STOP_MOVE_STEP implementation */ - -static inline void zb_zcl_color_control_send_stop_move_step_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_STOP_MOVE_STEP); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_stop_move_step_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_STOP_MOVE_STEP); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_stop_move_step_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_stop_move_step_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_stop_move_step_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb); - break; - case 3: - zb_zcl_color_control_send_stop_move_step_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_stop_move_step_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_stop_move_step_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_stop_move_step_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_stop_move_step_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb); - break; - case 3: - zb_zcl_color_control_send_stop_move_step_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_stop_move_step_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR_TEMPERATURE implementation */ - -static inline void zb_zcl_color_control_send_move_color_temp_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR_TEMPERATURE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (move_mode)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (rate)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_temp_min)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_temp_max)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_move_color_temp_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_MOVE_COLOR_TEMPERATURE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (move_mode)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (rate)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_temp_min)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_temp_max)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_move_color_temp_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_color_temp_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_color_temp_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate, - color_temp_min, - color_temp_max); - break; - case 3: - zb_zcl_color_control_send_move_color_temp_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate, - color_temp_min, - color_temp_max, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_color_temp_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_move_color_temp_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, - zb_uint16_t rate, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_move_color_temp_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_move_color_temp_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate, - color_temp_min, - color_temp_max); - break; - case 3: - zb_zcl_color_control_send_move_color_temp_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, - rate, - color_temp_min, - color_temp_max, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_move_color_temp_req", (FMT__0)); -} - -/* ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR_TEMPERATURE implementation */ - -static inline void zb_zcl_color_control_send_step_color_temp_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR_TEMPERATURE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (step_size)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_temp_min)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_temp_max)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -static inline void zb_zcl_color_control_send_step_color_temp_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_COLOR_CONTROL_STEP_COLOR_TEMPERATURE); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (step_size)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_temp_min)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (color_temp_max)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, cb); -} - -void zb_zcl_color_control_send_step_color_temp_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_step_color_temp_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_COLOR_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_step_color_temp_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, - step_size, - transition_time, - color_temp_min, - color_temp_max); - break; - case 3: - zb_zcl_color_control_send_step_color_temp_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, - step_size, - transition_time, - color_temp_min, - color_temp_max, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_step_color_temp_req_zcl8", (FMT__0)); -} - -void zb_zcl_color_control_send_step_color_temp_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, - zb_uint16_t step_size, - zb_uint16_t transition_time, - zb_uint16_t color_temp_min, - zb_uint16_t color_temp_max) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_color_control_send_step_color_temp_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_color_control_send_step_color_temp_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, - step_size, - transition_time, - color_temp_min, - color_temp_max); - break; - case 3: - zb_zcl_color_control_send_step_color_temp_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, - step_size, - transition_time, - color_temp_min, - color_temp_max, - ZB_ZCL_COLOR_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_COLOR_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_color_control_send_step_color_temp_req", (FMT__0)); -} - -/** - * @} internal -*/ -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_COLOR_CONTROL */ diff --git a/zboss/development/src/zcl/zcl_common.c b/zboss/development/src/zcl/zcl_common.c deleted file mode 100644 index 910dde2408..0000000000 --- a/zboss/development/src/zcl/zcl_common.c +++ /dev/null @@ -1,2495 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL, common functions implementation -*/ - -#define ZB_TRACE_FILE_ID 2063 -#include "zb_common.h" -#include "zb_zcl.h" -#include "zb_aps.h" -#include "zb_zdo.h" -#include "zcl/zb_zcl_common.h" -#include "zb_ncp.h" -#include "zdo_wwah_stubs.h" - -#if defined (ZB_ENABLE_ZCL) || defined (ZB_ENABLE_ZGPD_ATTR_REPORTING) - -static void broadcast_endpoint_delivery_step(zb_uint8_t param, zb_uint16_t bc_buf_ref); - -static void zb_zcl_init_periodic_activities(zb_uint8_t param) -{ - if (param == 0U) - { - zb_ret_t ret = zb_buf_get_out_delayed(zb_zcl_init_periodic_activities); - if (ret != RET_OK) - { - TRACE_MSG(TRACE_ERROR, "Failed zb_buf_get_out_delayed [%d]", (FMT__D, ret)); - } - } - else - { -#ifdef ZB_HA_ENABLE_POLL_CONTROL_SERVER - zb_uint8_t ep = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE); - if (ep != 0U) - { - zb_zcl_poll_control_start(param, ep); - } - else - { - zb_buf_free(param); - } -#else - zb_buf_free(param); -#endif - } -} - - -/** - Register user or internal ZBOSS ZCL device context. - - To be used to hide GP cluster from the application. - Note that ZB_AF_REGISTER_DEVICE_CTX for user ctx must be called before - registering internal ZBOSS ctx. In practice it means used must call - ZB_AF_REGISTER_DEVICE_CTX macro before zdo_dev_start(). - */ -void zb_zcl_register_device_ctx(zb_af_device_ctx_t *device_ctx) -{ - zb_ret_t ret; - zb_uint_t i; - - /*cstat !MISRAC2012-Rule-13.6 */ - /* After some investigation, the following violation of Rule 13.6 seems to be - * a false positive. There are no side effect to 'ZCL_CTX()'. This - * violation seems to be caused by the fact that 'ZCL_CTX()' is an - * external macro, which cannot be analyzed by C-STAT. */ - for (i = 0; i < ZB_ARRAY_SIZE(ZCL_CTX().device_ctx_arr); ++i) - { - if (ZCL_CTX().device_ctx_arr[i] == NULL) - { - ZCL_CTX().device_ctx_arr[i] = device_ctx; - break; - } - } - - /*cstat !MISRAC2012-Rule-13.6 */ - /* After some investigation, the following violation of Rule 13.6 seems to be - * a false positive. There are no side effect to 'ZCL_CTX()'. This - * violation seems to be caused by the fact that 'ZCL_CTX()' is an - * external macro, which cannot be analyzed by C-STAT. */ - ZB_ASSERT(i < ZB_ARRAY_SIZE(ZCL_CTX().device_ctx_arr)); - if (ZCL_CTX().device_ctx == NULL) - { - ZCL_CTX().device_ctx = (device_ctx); - ret = zb_buf_get_out_delayed(zb_zcl_init_periodic_activities); - if (ret != RET_OK) - { - TRACE_MSG(TRACE_ERROR, "Failed zb_buf_get_out_delayed [%d]", (FMT__D, ret)); - } - } -} - -/* The purpose of this variable is to provide an access to endpoint ID - * that is under initialization at the moment for cluster initialization functions - * The best soultion is to add ep_id as an input parameter to - * void (*zb_zcl_cluster_init_t)(void) - */ - -static zb_uint8_t g_current_endpoint_id = ZB_ZCL_BROADCAST_ENDPOINT; - -/*! @brief get endpoint ID that is under initialization - @return endpoint ID - */ -zb_uint8_t zb_get_current_endpoint_id(void) -{ - return g_current_endpoint_id; -} - -void zb_zcl_init_endpoint(zb_af_endpoint_desc_t* ep) -{ - zb_uindex_t j; - - TRACE_MSG(TRACE_ZCL2, ">> zb_zcl_init_endpoint, ep_id %d", (FMT__D, ep->ep_id)); - - /* Init attribute, if need */ - if(ZCL_CTX().set_default_attr_cb != NULL) - { - (ZCL_CTX().set_default_attr_cb)(ep->ep_id); - } - - g_current_endpoint_id = ep->ep_id; - /* For every cluster in ep_desc - add declared handlers to table */ - for (j = 0; j < ep->cluster_count; j++) - { - if (ep->cluster_desc_list[j].cluster_init != NULL) - { - ep->cluster_desc_list[j].cluster_init(); - } -#ifndef ZB_ZCL_DISABLE_REPORTING - /* Configure default reporting */ - zb_zcl_put_default_reporting_info_for_cluster( - ep->ep_id, - ep->profile_id, - &ep->cluster_desc_list[j]); -#endif - } - g_current_endpoint_id = ZB_ZCL_BROADCAST_ENDPOINT; - - TRACE_MSG(TRACE_ZCL2, "<< zb_zcl_init_endpoint", (FMT__0)); -} - -zb_bool_t zb_zcl_check_cluster_list(void) -{ - zb_uint8_t i, j, k, l; - zb_uint16_t cluster_id1, cluster_id2; - for (i = 0U; i < ZCL_CTX().device_ctx->ep_count; i++) - { - for (j = 0U; j < ZCL_CTX().device_ctx->ep_desc_list[i]->cluster_count; j++) - { - for (k = i; k < ZCL_CTX().device_ctx->ep_count; k++) - { - for (l = j + 1U; l < ZCL_CTX().device_ctx->ep_desc_list[k]->cluster_count; l++) - { - cluster_id1 = (ZCL_CTX().device_ctx->ep_desc_list[i]->cluster_desc_list + j)->cluster_id; - cluster_id2 = (ZCL_CTX().device_ctx->ep_desc_list[k]->cluster_desc_list + l)->cluster_id; - /* Can not have 2 instances of listed clusters. - TODO: Divide by roles? 2 Groups clients or 2 Thermostat clients may be ok, but - currently it is not needed. - */ - if (cluster_id1 == cluster_id2 && - (ZCL_CTX().device_ctx->ep_desc_list[i]->cluster_desc_list + j)->role_mask == - (ZCL_CTX().device_ctx->ep_desc_list[k]->cluster_desc_list + l)->role_mask && - (cluster_id1 == ZB_ZCL_CLUSTER_ID_GROUPS || - cluster_id1 == ZB_ZCL_CLUSTER_ID_OTA_UPGRADE || - cluster_id1 == ZB_ZCL_CLUSTER_ID_POLL_CONTROL || - cluster_id1 == ZB_ZCL_CLUSTER_ID_SUB_GHZ || - cluster_id1 == ZB_ZCL_CLUSTER_ID_THERMOSTAT || - cluster_id1 == ZB_ZCL_CLUSTER_ID_KEY_ESTABLISHMENT || - cluster_id1 == ZB_ZCL_CLUSTER_ID_WWAH)) - { - TRACE_MSG(TRACE_ERROR, "cluster_id 0x%x cluster_role %hd is not unique!", - (FMT__D_H, cluster_id1, - (ZCL_CTX().device_ctx->ep_desc_list[i]->cluster_desc_list + j)->role_mask)); - return ZB_FALSE; - } - } - } - } - } - return ZB_TRUE; -} - -/* Function returns attribute size in bytes. If invalid attribute type is specified, 0xff is returned - param attr_type - attribute data type - param attr_value - attribute data value, is used to calculate size - of attributes with variable size - */ -zb_uint8_t zb_zcl_get_attribute_size(zb_uint8_t attr_type, zb_uint8_t *attr_value) -{ - zb_uint32_t ret = (zb_uint32_t)~0U; - TRACE_MSG( - TRACE_ZCL1, - ">> zb_zcl_get_attribute_size: attr_type 0x%hx attr_value %p", - (FMT__H_P, attr_type, attr_value)); - - switch ( attr_type ) - { - case ZB_ZCL_ATTR_TYPE_8BIT: - case ZB_ZCL_ATTR_TYPE_U8: - case ZB_ZCL_ATTR_TYPE_S8: - case ZB_ZCL_ATTR_TYPE_BOOL: - case ZB_ZCL_ATTR_TYPE_8BITMAP: - case ZB_ZCL_ATTR_TYPE_8BIT_ENUM: - ret = sizeof(zb_uint8_t); - break; - - case ZB_ZCL_ATTR_TYPE_16BIT: - case ZB_ZCL_ATTR_TYPE_U16: - case ZB_ZCL_ATTR_TYPE_S16: - case ZB_ZCL_ATTR_TYPE_16BITMAP: - case ZB_ZCL_ATTR_TYPE_16BIT_ENUM: - case ZB_ZCL_ATTR_TYPE_SEMI: - case ZB_ZCL_ATTR_TYPE_CLUSTER_ID: - case ZB_ZCL_ATTR_TYPE_ATTRIBUTE_ID: - ret = sizeof(zb_uint16_t); - break; - - case ZB_ZCL_ATTR_TYPE_32BIT: - case ZB_ZCL_ATTR_TYPE_U32: - case ZB_ZCL_ATTR_TYPE_S32: - case ZB_ZCL_ATTR_TYPE_32BITMAP: - case ZB_ZCL_ATTR_TYPE_UTC_TIME: - case ZB_ZCL_ATTR_TYPE_TIME_OF_DAY: - case ZB_ZCL_ATTR_TYPE_DATE: - case ZB_ZCL_ATTR_TYPE_BACNET_OID: - case ZB_ZCL_ATTR_TYPE_SINGLE: - ret = sizeof(zb_uint32_t); - break; - - case ZB_ZCL_ATTR_TYPE_S48: - case ZB_ZCL_ATTR_TYPE_U48: - case ZB_ZCL_ATTR_TYPE_48BIT: - case ZB_ZCL_ATTR_TYPE_48BITMAP: -//TODO: fix it, use correct type - ret = ZB_48BIT_SIZE; - break; - - case ZB_ZCL_ATTR_TYPE_S24: - case ZB_ZCL_ATTR_TYPE_U24: - case ZB_ZCL_ATTR_TYPE_24BIT: - case ZB_ZCL_ATTR_TYPE_24BITMAP: -//TODO: fix it, use correct type - ret = ZB_24BIT_SIZE; - break; - - case ZB_ZCL_ATTR_TYPE_U40: - case ZB_ZCL_ATTR_TYPE_S40: - case ZB_ZCL_ATTR_TYPE_40BIT: - case ZB_ZCL_ATTR_TYPE_40BITMAP: - ret = 5; - break; - - case ZB_ZCL_ATTR_TYPE_U56: - case ZB_ZCL_ATTR_TYPE_S56: - case ZB_ZCL_ATTR_TYPE_56BIT: - case ZB_ZCL_ATTR_TYPE_56BITMAP: - ret = 7; - break; - - case ZB_ZCL_ATTR_TYPE_64BIT: - case ZB_ZCL_ATTR_TYPE_64BITMAP: - case ZB_ZCL_ATTR_TYPE_U64: - case ZB_ZCL_ATTR_TYPE_S64: - case ZB_ZCL_ATTR_TYPE_DOUBLE: - ret = sizeof(zb_64bit_data_t); - break; - - case ZB_ZCL_ATTR_TYPE_OCTET_STRING: - case ZB_ZCL_ATTR_TYPE_CHAR_STRING: - if ( attr_value != NULL && *attr_value != ZB_ZCL_INVALID_STRING_VALUE) - { - /* the first byte of the string or array has the size */ - zb_uint8_t ret_u8 = *(zb_uint8_t*)attr_value + 1U; - ret = (zb_uint32_t)ret_u8; - } - break; - - case ZB_ZCL_ATTR_TYPE_ARRAY: - case ZB_ZCL_ATTR_TYPE_CUSTOM_32ARRAY: - case ZB_ZCL_ATTR_TYPE_LONG_OCTET_STRING: - { - zb_uint16_t array_size = 0; - - if (attr_type == ZB_ZCL_ATTR_TYPE_ARRAY || - attr_type == ZB_ZCL_ATTR_TYPE_LONG_OCTET_STRING) - { - ZB_ZCL_ARRAY_GET_SIZE(&array_size, attr_value); - } - else - { - ZB_BYTE_32ARRAY_GET_SIZE(&array_size, attr_value); - } - - if (array_size != ZB_ZCL_INVALID_ARRAY_VALUE) - { - /* the first 2 bytes of the array has the size */ - /* NK:FIXME:FIXME:FIXME: Cast 2 bytes to 1! Current implementation! All arrays - * used now are less then 0xff length. Discussed with VS. */ - ret = (zb_uint32_t)array_size + 2U; - } - break; - } - - case ZB_ZCL_ATTR_TYPE_IEEE_ADDR: - ret = sizeof(zb_ieee_addr_t); - break; - - case ZB_ZCL_ATTR_TYPE_128_BIT_KEY: - ret = 16U; - break; - - default: - TRACE_MSG(TRACE_ZCL1, "Error, unsupported type!", (FMT__0)); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_get_attribute_size: result %hd", (FMT__D, ret)); - ZB_ASSERT(ret <= ZB_UINT8_MAX); - return (zb_uint8_t)ret; -} - -/* - Put attribute value to command packet, fix endian if needed. - Return: modified command pointer -*/ -zb_uint8_t* zb_zcl_put_value_to_packet(zb_uint8_t *cmd_ptr, zb_uint8_t attr_type, zb_uint8_t *attr_value) -{ - zb_uint16_t len; - - TRACE_MSG(TRACE_ZCL1, - ">> zb_zcl_put_value_to_packet: cmd_ptr %p, attr_type 0x%hx attr_value %p", - (FMT__P_H_P, cmd_ptr, attr_type, attr_value)); - - switch ( attr_type ) - { - case ZB_ZCL_ATTR_TYPE_8BIT: - case ZB_ZCL_ATTR_TYPE_U8: - case ZB_ZCL_ATTR_TYPE_S8: - case ZB_ZCL_ATTR_TYPE_BOOL: - case ZB_ZCL_ATTR_TYPE_8BITMAP: - case ZB_ZCL_ATTR_TYPE_8BIT_ENUM: - ZB_ZCL_PACKET_PUT_DATA8(cmd_ptr, *attr_value); - break; - - case ZB_ZCL_ATTR_TYPE_16BIT: - case ZB_ZCL_ATTR_TYPE_U16: - case ZB_ZCL_ATTR_TYPE_S16: - case ZB_ZCL_ATTR_TYPE_16BITMAP: - case ZB_ZCL_ATTR_TYPE_16BIT_ENUM: - ZB_ZCL_PACKET_PUT_DATA16(cmd_ptr, attr_value); - break; - - case ZB_ZCL_ATTR_TYPE_32BIT: - case ZB_ZCL_ATTR_TYPE_U32: - case ZB_ZCL_ATTR_TYPE_S32: - case ZB_ZCL_ATTR_TYPE_32BITMAP: - case ZB_ZCL_ATTR_TYPE_UTC_TIME: - ZB_ZCL_PACKET_PUT_DATA32(cmd_ptr, attr_value); - break; - - case ZB_ZCL_ATTR_TYPE_U48: - case ZB_ZCL_ATTR_TYPE_S48: -//TODO: fix it, put data taking into account bytes order - ZB_ZCL_PACKET_PUT_DATA48(cmd_ptr, attr_value); - break; - - case ZB_ZCL_ATTR_TYPE_S24: - case ZB_ZCL_ATTR_TYPE_U24: - case ZB_ZCL_ATTR_TYPE_24BIT: - case ZB_ZCL_ATTR_TYPE_24BITMAP: -//TODO: fix it, put data taking into account bytes order - ZB_ZCL_PACKET_PUT_DATA24(cmd_ptr, attr_value); - break; - - case ZB_ZCL_ATTR_TYPE_OCTET_STRING: - case ZB_ZCL_ATTR_TYPE_CHAR_STRING: - if ( attr_value != NULL && *attr_value != ZB_ZCL_INVALID_STRING_VALUE) - { - /* the first byte of the string or array has the size */ - zb_uint8_t len_u8 = *(zb_uint8_t *)attr_value + 1U; - len = (zb_uint16_t)len_u8; - ZB_ZCL_PACKET_PUT_DATA_N(cmd_ptr, attr_value, len); - } - break; - - case ZB_ZCL_ATTR_TYPE_ARRAY: - case ZB_ZCL_ATTR_TYPE_CUSTOM_32ARRAY: - case ZB_ZCL_ATTR_TYPE_LONG_OCTET_STRING: - { - zb_uint16_t array_size = 0; - - if (attr_type == ZB_ZCL_ATTR_TYPE_ARRAY || - attr_type == ZB_ZCL_ATTR_TYPE_LONG_OCTET_STRING) - { - ZB_ZCL_ARRAY_GET_SIZE(&array_size, attr_value); - } - else - { - ZB_BYTE_32ARRAY_GET_SIZE(&array_size, attr_value); - } - - if (array_size != ZB_ZCL_INVALID_ARRAY_VALUE) - { - /* the first 2 bytes of the array has the size */ - /* NK:FIXME:FIXME:FIXME: Cast 2 bytes to 1! Current implementation! All arrays - * used now are less then 0xff length. Discussed with VS. */ - - len = array_size + 2U; - ZB_ZCL_PACKET_PUT_DATA_N(cmd_ptr, attr_value, len); - } - break; - } - - case ZB_ZCL_ATTR_TYPE_64BIT: - case ZB_ZCL_ATTR_TYPE_IEEE_ADDR: - ZB_ZCL_PACKET_PUT_DATA64(cmd_ptr, attr_value); - break; - - case ZB_ZCL_ATTR_TYPE_128_BIT_KEY: - ZB_ZCL_PACKET_PUT_DATA_N(cmd_ptr, attr_value, 16); - break; - - default: - TRACE_MSG(TRACE_ZCL1, "Error, unsupported type!", (FMT__0)); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_put_value_to_packet: ret %p", (FMT__P, cmd_ptr)); - return cmd_ptr; -} - -#if defined (ZB_ENABLE_ZCL) -/* - Function returns data size in bytes for analog data types. If invalid data type is specified, 0xff is returned - param attr_type - attribute data type -*/ -zb_uint8_t zb_zcl_get_analog_attribute_size(zb_uint8_t attr_type) -{ - zb_uint32_t ret = 0; - - switch (attr_type) - { - case ZB_ZCL_ATTR_TYPE_U8: - ret = sizeof(zb_uint8_t); - break; - - case ZB_ZCL_ATTR_TYPE_U16: - case ZB_ZCL_ATTR_TYPE_S16: - ret = sizeof(zb_uint16_t); - break; - - case ZB_ZCL_ATTR_TYPE_U24: - case ZB_ZCL_ATTR_TYPE_S24: - ret = ZB_24BIT_SIZE; - break; - - case ZB_ZCL_ATTR_TYPE_U32: - case ZB_ZCL_ATTR_TYPE_S32: - ret = sizeof(zb_uint32_t); - break; - - case ZB_ZCL_ATTR_TYPE_U48: - case ZB_ZCL_ATTR_TYPE_S48: - ret = ZB_48BIT_SIZE; - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "get_analog_attribute_size %hd", (FMT__H, ret)); - ZB_ASSERT(ret <= ZB_UINT8_MAX); - return (zb_uint8_t)ret; -} - -/* - Function returns ZB_TRUE for analog data types, ZB_FALSE otherwise -*/ -zb_bool_t zb_zcl_is_analog_data_type(zb_uint8_t attr_type) -{ - zb_bool_t ret = ZB_FALSE; - switch (attr_type) - { - case ZB_ZCL_ATTR_TYPE_U8: - case ZB_ZCL_ATTR_TYPE_U16: - case ZB_ZCL_ATTR_TYPE_U24: - case ZB_ZCL_ATTR_TYPE_U32: - case ZB_ZCL_ATTR_TYPE_U48: - case ZB_ZCL_ATTR_TYPE_S8: - case ZB_ZCL_ATTR_TYPE_S16: - case ZB_ZCL_ATTR_TYPE_S24: - case ZB_ZCL_ATTR_TYPE_S32: - case ZB_ZCL_ATTR_TYPE_S48: - case ZB_ZCL_ATTR_TYPE_UTC_TIME: - ret = ZB_TRUE; - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "zb_zcl_is_analog_data_type %hd, is analog %hd", (FMT__H_H, attr_type, ret)); - return ret; -} - - -#define ZCL_DEVICE_CONTEXT_ITERATOR(idx) \ - { \ - zb_uint32_t dci; \ - zb_af_device_ctx_t *device_ctx; \ - zb_uint32_t device_ctx_arr_size = ZB_ARRAY_SIZE(ZCL_CTX().device_ctx_arr); \ - for (dci = 0; dci < device_ctx_arr_size; dci++) \ - { \ - (idx) = 0; \ - device_ctx = ZCL_CTX().device_ctx_arr[dci]; \ - if (device_ctx == NULL) \ - { \ - break; \ - } - -#define ZCL_DEVICE_CONTEXT_ITERATOR_END \ - } \ - } - -#define ZCL_DEVICE_CONTEXT_BREAK break - -zb_af_endpoint_desc_t* zb_af_get_endpoint_desc(zb_uint8_t ep_id) -{ - zb_uindex_t i; - zb_af_endpoint_desc_t *ep_desc = NULL; - - /*cstat !MISRAC2012-Rule-13.6 */ - /* After some investigation, the following violation of Rule 13.6 seems to be a false positive. - * There are no side effects to the macro 'ZCL_CTX()' used inside 'ZCL_DEVICE_CONTEXT_ITERATOR()'. - * This violation seems to be caused by the fact that 'ZCL_CTX()' is an external macro, which - * cannot be analyzed by C-STAT.*/ - ZCL_DEVICE_CONTEXT_ITERATOR(i); - TRACE_MSG(TRACE_ZCL3, ">>get_endpoint_desc %p %p ep_id %hd", (FMT__P_P_H, - &ZCL_CTX(), device_ctx, ep_id)); - while (i < device_ctx->ep_count) - { - TRACE_MSG(TRACE_ZCL3, "device_ctx %p, ep_count %hd", - (FMT__P_H, device_ctx, device_ctx->ep_count)); - - TRACE_MSG(TRACE_ZCL3, "ep_id %hd", (FMT__H, device_ctx->ep_desc_list[i]->ep_id)); - if (device_ctx->ep_desc_list[i]->ep_id == ep_id) - { - ep_desc = device_ctx->ep_desc_list[i]; - ZCL_DEVICE_CONTEXT_BREAK; - } - i++; - } - ZCL_DEVICE_CONTEXT_ITERATOR_END; - - TRACE_MSG(TRACE_ZCL3, "<> zb_zcl_get_tsn_from_packet %p", (FMT__P, buffer)); - - /* ZCL spec 2.3.1 ZCL frame format */ - /* | Frame control 1b | Manuf code 0/2b | TSN 1b | Cmd id 1b | Payload xx b | */ - - /* cmd_buf points to Frame control */ - if (!ZB_ZCL_IS_MANUF_SPECIFIC(*cmd_buf)) - { - /* no manufacturer code */ - tsn = *(cmd_buf + sizeof(zb_uint8_t)); - } - else - { - /* manufacturer specific code is set */ - tsn = *(cmd_buf + sizeof(zb_uint8_t) + sizeof(zb_uint16_t)); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_get_tsn_from_packet tsn %hd", (FMT__H, tsn)); - return tsn; -} - -/** - Register callback that should be called when APS acknowledge is - received for ZCL command - @param param - index to buffer with ZCL command - @param cb - pointer to callback function -*/ -zb_ret_t zb_zcl_register_cb(zb_uint8_t param, zb_callback_t cb) -{ - zb_ret_t ret; - zb_uint32_t hash; - zb_uint32_t i; - zcl_cb_hash_ent_t *ent; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_register_cb param %hd, cb %p", (FMT__H_P, param, cb)); - - ZB_ASSERT(param); - - /* Handle frequent case of zero cb. In that case in - * zb_zcl_ack_callback() we were scanning entire zcl_cb[] to find nothing. - * Now add an entry with empty cb to speedup zb_zcl_ack_callback(). - * We can live without an entry with empty cb, so, if we got into it, can reuse it. - */ - ret = RET_NO_MEMORY; - - hash = ZB_ZCL_TRAN_TABLE_HASH_PARAM(param); - - i = hash; - do - { - ent = &ZCL_CTX().zcl_cb[i]; - if (ent->buf == 0U - || ent->func == NULL) - { - /* found free slot */ - ent->func = cb; - ent->buf = param; - - ret = RET_OK; - break; - } - - i = (i + 1U) % ZCL_TRAN_TABLE_SIZE; - } - while (i != hash); - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_register_cb ret %d", (FMT__D, ret)); - - return ret; -} - -/** - Call callback on receiving APS acknowledge for ZCL command - */ -zb_ret_t zb_zcl_ack_callback(zb_uint8_t param) -{ - zb_uint32_t hash; - zb_uint32_t i; - zcl_cb_hash_ent_t *ent; - zb_ret_t ret = RET_NOT_FOUND; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_ack_callback %hd", (FMT__H, param)); - - hash = ZB_ZCL_TRAN_TABLE_HASH_PARAM(param); - i = hash; - do - { - ent = &ZCL_CTX().zcl_cb[i]; - if (ent->buf == param) - { - TRACE_MSG(TRACE_ZCL2, "found callback %p", (FMT__P, ZCL_CTX().zcl_cb[i].func)); - - /* Added +1 turbo poll in zb_zcl_finish_and_send_packet_common() but failed - * to send - need not turbo poll for the next packet. Else may increase - * turbo poll count multiple times. */ - if (ZB_IS_DEVICE_ZED()) - { - if (zb_buf_get_status(param) != RET_OK) - { - zb_zdo_pim_turbo_poll_cancel_packet(); - } - } - - if (ent->func != NULL) - { - /* found - schedule it to execution */ - ZB_SCHEDULE_CALLBACK(ent->func, param); - ret = RET_OK; - ent->func = NULL; - } - - /* mark slot as free */ - ent->buf = 0; - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_ack_callback ret %d", (FMT__D, ret)); - return ret; - } - i = (i + 1U) % ZCL_TRAN_TABLE_SIZE; - } - while (i != hash); - - /* It is ok to have no entry in zcl_cb if zb_zcl_register_cb was called with - * zero cb and then overwritten by another entry. */ - TRACE_MSG(TRACE_ZCL3, "buf 0x%hx not found - maybe, it is ok", (FMT__H, param)); - - /* free buffer on caller level */ - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_ack_callback NOT FOUND", (FMT__0)); - return RET_NOT_FOUND; -} - -#ifndef ZB_LITTLE_ENDIAN -/* - Fix data endian, if needed, and store it in the same buffer - */ -void zb_zcl_fix_endian(zb_uint8_t *data_ptr, zb_uint8_t data_type) -{ - union int_vars_e - { - zb_uint16_t u16; - zb_uint32_t u32; - zb_ieee_addr_t u64; - zb_uint48_t u48; - zb_int24_t i24; - } - int_vars; - - ZB_ASSERT(data_ptr); - - switch ( data_type ) - { - case ZB_ZCL_ATTR_TYPE_16BIT: - case ZB_ZCL_ATTR_TYPE_U16: - case ZB_ZCL_ATTR_TYPE_S16: - case ZB_ZCL_ATTR_TYPE_16BITMAP: - ZB_HTOLE16(&int_vars.u16, data_ptr); - ZB_MEMCPY(data_ptr, &int_vars.u16, sizeof(zb_uint16_t)); - break; - - case ZB_ZCL_ATTR_TYPE_32BIT: - case ZB_ZCL_ATTR_TYPE_U32: - case ZB_ZCL_ATTR_TYPE_S32: - case ZB_ZCL_ATTR_TYPE_32BITMAP: - ZB_HTOLE32(&int_vars.u32, data_ptr); - ZB_MEMCPY(data_ptr, &int_vars.u32, sizeof(zb_uint32_t)); - break; - - case ZB_ZCL_ATTR_TYPE_64BIT: - case ZB_ZCL_ATTR_TYPE_IEEE_ADDR: - ZB_HTOLE64(&int_vars.u64, data_ptr); - ZB_MEMCPY(data_ptr, &int_vars.u64, sizeof(zb_ieee_addr_t)); - break; - - case ZB_ZCL_ATTR_TYPE_U48: - case ZB_ZCL_ATTR_TYPE_S48: - ZB_HTOLE48(&int_vars.u48, data_ptr); - ZB_MEMCPY(data_ptr, &int_vars.u48, ZB_48BIT_SIZE); - break; - - case ZB_ZCL_ATTR_TYPE_S24: - case ZB_ZCL_ATTR_TYPE_U24: - ZB_HTOLE24(&int_vars.i24, data_ptr); - ZB_MEMCPY(data_ptr, &int_vars.i24, ZB_24BIT_SIZE); - break; - - default: - break; - } -} -#endif /* ZB_LITTLE_ENDIAN */ - -/* Check, if attribute value maybe set to a new value - * Note: check_access specifies if it is needed to perform read-only - * check: end-user application may chanage read-only attributes -*/ -zb_uint8_t zb_zcl_check_attribute_writable( - zb_zcl_attr_t* attr_desc, - zb_uint8_t endpoint, - zb_uint16_t cluster_id, - zb_uint8_t cluster_role, - zb_uint8_t *new_value, - zb_bool_t check_access) -{ - zb_uint8_t status = ZB_ZCL_STATUS_SUCCESS; - - TRACE_MSG(TRACE_ZCL1, - ">> zb_zcl_check_attribute_writable, attr_desc %p, endpoint %hd, cluster %d, check_access %hd", - (FMT__P_H_D_H, attr_desc, endpoint, cluster_id, check_access)); - TRACE_MSG(TRACE_ZCL1, "attr_id 0x%x", (FMT__D, attr_desc->id)); - - if (attr_desc != NULL && attr_desc->data_p != NULL) - { - if (check_access) - { - if (ZB_BIT_IS_SET(attr_desc->access, ZB_ZCL_ATTR_ACCESS_INTERNAL)) - { - TRACE_MSG(TRACE_ZCL1, "error, internal attr isn't writable", (FMT__0)); - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - } - else if (!ZB_BIT_IS_SET(attr_desc->access, ZB_ZCL_ATTR_ACCESS_WRITE_ONLY)) - { - TRACE_MSG(TRACE_ZCL1, "error, access to R/O attr", (FMT__0)); - status = ZB_ZCL_STATUS_READ_ONLY; - } - else - { - /* MISRA rule 15.7 requires empty 'else' branch. */ - } - } - /* NOTE: Need to check for authorized write access, but no description for it in spec */ - if (ZB_ZCL_STATUS_SUCCESS == status) - //&& zb_zcl_check_attr_value(cluster_id, cluster_role, endpoint, attr_desc->id, new_value) == RET_ERROR /-- ZB_FALSE) --/ - { - zb_ret_t ret = zb_zcl_check_attr_value(cluster_id, cluster_role, endpoint, attr_desc->id, new_value); - if (ret == RET_ERROR) - { - TRACE_MSG(TRACE_ZCL1, "error, invalid value", (FMT__0)); - status = ZB_ZCL_STATUS_INVALID_VALUE; - } - else if (ret == RET_OUT_OF_RANGE) - { - TRACE_MSG(TRACE_ZCL1, "limit reached value, return SUCCESS acc. to ZCL8", (FMT__0)); - status = ZB_ZCL_STATUS_SUCCESS; - } - else if (ret == RET_BLOCKED) - { - TRACE_MSG(TRACE_ZCL1, "Blocked by internal check, response of status READ_ONLY.", (FMT__0)); - status = ZB_ZCL_STATUS_READ_ONLY; - } - else if (ret == RET_UNAUTHORIZED) - { - TRACE_MSG(TRACE_ZCL1, "unathorized value", (FMT__0)); - status = ZB_ZCL_STATUS_NOT_AUTHORIZED; - } - else - { - /* MISRA rule 15.7 requires empty 'else' branch. */ - } - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "error, not supported attr", (FMT__0)); - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - } - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_check_attribute_writable, ret %hx", (FMT__H, status)); - return status; -} - -/* Sets attribute value, for other endpoint of singleton attribute - * check: end-user application may chanage read-only attributes -*/ -static void zb_zcl_conform_singleton(zb_uint8_t ep_first, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id, zb_uint8_t *value) -{ - zb_uindex_t i; - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_conform_singleton ep %hd, cluster %d, attr %d", - (FMT__H_D_D, ep_first, cluster_id, attr_id)); - - /*cstat !MISRAC2012-Rule-13.6 */ - /* After some investigation, the following violation of Rule 13.6 seems to be a false positive. - * There are no side effects to the macro 'ZCL_CTX()' used inside 'ZCL_DEVICE_CONTEXT_ITERATOR()'. - * This violation seems to be caused by the fact that 'ZCL_CTX()' is an external macro, which - * cannot be analyzed by C-STAT.*/ - ZCL_DEVICE_CONTEXT_ITERATOR(i); - while (device_ctx != NULL && i < device_ctx->ep_count) - { - TRACE_MSG(TRACE_ZCL3, "ep_id %hd", (FMT__H, device_ctx->ep_desc_list[i]->ep_id)); - if (device_ctx->ep_desc_list[i]->ep_id != ep_first) - { - zb_zcl_attr_t *attr_desc; - zb_zcl_cluster_desc_t *cluster_desc = get_cluster_desc( - device_ctx->ep_desc_list[i], cluster_id, cluster_role); - - if (cluster_desc == NULL) - { - continue; - } - - attr_desc = zb_zcl_get_attr_desc(cluster_desc, attr_id); - if (attr_desc == NULL) - { - continue; - } - - zb_zcl_write_attr_hook(device_ctx->ep_desc_list[i]->ep_id, - cluster_id, cluster_role, attr_id, value); - - ZB_MEMCPY(attr_desc->data_p, value, - zb_zcl_get_attribute_size(attr_desc->type, value)); - -#if !(defined ZB_ZCL_DISABLE_REPORTING) - /* check, if reporting is needed for an attribute */ - if (ZB_ZCL_IS_ATTR_REPORTABLE(attr_desc)) - { - zb_zcl_mark_attr_for_reporting(device_ctx->ep_desc_list[i]->ep_id, - cluster_id, cluster_role, attr_id); - } -#endif - } - i++; - } - ZCL_DEVICE_CONTEXT_ITERATOR_END; - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_conform_singleton", (FMT__0)); -} - -/* Sets attribute value, perform all needed checks before and after - * setting new value - * Note: access_check specifies if it is needed to perform read-only - * check: end-user application may chanage read-only attributes -*/ -zb_zcl_status_t zb_zcl_set_attr_val(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, - zb_uint16_t attr_id, zb_uint8_t *value, zb_bool_t check_access) -{ - zb_zcl_attr_t *attr_desc; - zb_zcl_status_t status = ZB_ZCL_STATUS_FAIL; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_set_attr_val check_access %hd, ep %hd, cluster role %hd, cluster 0x%x, attr %d", - (FMT__H_H_H_D_D, check_access, ep, cluster_role, cluster_id, attr_id)); - - attr_desc = zb_zcl_get_attr_desc_a(ep, cluster_id, cluster_role, attr_id); - TRACE_MSG(TRACE_ZCL1, "attr_desc %p, value %p", (FMT__P_P, attr_desc, value)); - - if (attr_desc != NULL && value != NULL) - { - status = (zb_zcl_status_t)zb_zcl_check_attribute_writable(attr_desc, ep, cluster_id, cluster_role, value, check_access); - if (status == ZB_ZCL_STATUS_SUCCESS) - { - zb_zcl_write_attr_hook(ep, cluster_id, cluster_role, attr_id, value); - - ZB_MEMCPY(attr_desc->data_p, value, - zb_zcl_get_attribute_size(attr_desc->type, value)); - -#if !(defined ZB_ZCL_DISABLE_REPORTING) - /* check, if reporting is needed for an attribute */ - if (ZB_ZCL_IS_ATTR_REPORTABLE(attr_desc)) - { - zb_zcl_mark_attr_for_reporting(ep, cluster_id, cluster_role, attr_id); - } -#endif - - if (ZB_ZCL_IS_ATTR_SINGLETON(attr_desc)) - { - zb_zcl_conform_singleton(ep, cluster_id, cluster_role, attr_id, value); - } - } - } - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_set_attr_val, cluster_id 0x%x, attr_id 0x%x status %hx", - (FMT__D_D_H, cluster_id, attr_id, status)); - return status; -} - - -zb_bool_t zb_zcl_is_target_endpoint( - zb_af_endpoint_desc_t *ep_desc, zb_uint16_t profile_id) -{ - zb_bool_t match = (ep_desc != NULL && ep_desc->simple_desc != NULL); - - TRACE_MSG(TRACE_ZCL2, "> zb_zcl_is_target_endpoint: ep_desc %p, profile_id 0x%x", - (FMT__H_H, ep_desc, profile_id)); - - if (!match) - { - TRACE_MSG(TRACE_ZCL3, "ep or simple desc for it doesn't exist!", (FMT__0)); - } - - /* Endpoint and its simple descriptor exist: check if profile matches */ - /* - Deliver packet to endpoint if - - profiles are same; - - profile is wildcard and endpoint is HA or ZLL; - - profile is ZLL and endpoint is HA; - - profile is legacy and endpoint is HA (r21 spec, 2.3.3.2 Profile ID Endpoint Matching rules) - */ - if (match) - { - zb_uint16_t ep_profile_id = ep_desc->profile_id; - - match = (zb_bool_t)(profile_id == ep_profile_id); - - if (!match) /* Profiles are not the same */ - { - zb_bool_t profile_is_legacy = - (zb_bool_t)((profile_id != ZB_AF_HA_PROFILE_ID) - && (profile_id >= ZB_AF_LEGACY_PROFILE1_ID) - && (profile_id <= ZB_AF_LEGACY_PROFILE7_ID)); - - match = (zb_bool_t) - ( - /* profile is wildcard and endpoint is HA or ZLL */ - ((profile_id == ZB_AF_WILDCARD_PROFILE_ID) && - ((ep_profile_id == ZB_AF_HA_PROFILE_ID) || (ep_profile_id == ZB_AF_ZLL_PROFILE_ID))) - || -#if 0 - /* It is wrong because it doesn't correspond r21 specification - (2.3.3.2 Profile ID Endpoint Matching rules) */ - - /* profile is HA and endpoint is ZLL */ - ((profile_id == ZB_AF_HA_PROFILE_ID) && - (ep_profile_id == ZB_AF_ZLL_PROFILE_ID)) - || -#endif - /* profile is ZLL and endpoint is HA */ - ((profile_id == ZB_AF_ZLL_PROFILE_ID) && - (ep_profile_id == ZB_AF_HA_PROFILE_ID)) - || - /* profile is legacy and endpoint is HA */ - (profile_is_legacy && (ep_profile_id == ZB_AF_HA_PROFILE_ID)) - ); - } - - if (!match) - { - TRACE_MSG(TRACE_ZCL3, "ep profile 0x%x doesn't match cmd profile 0x%x!", - (FMT__D_D, ep_profile_id, profile_id)); - } - } - - TRACE_MSG(TRACE_ZCL2, "< zb_zcl_is_target_endpoint, match %hd", - (FMT__H, match)); - - return match; -} - -zb_uint8_t zb_zcl_get_next_target_endpoint( - zb_uint8_t start_from_ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t profile_id) -{ - zb_uint8_t ep = 0; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL2, - "> zb_zcl_get_next_target_endpoint, start_from_ep %hd, cluster_id 0x%x, profile_id 0x%x", - (FMT__H_D_D, start_from_ep, cluster_id, profile_id)); - - /*cstat !MISRAC2012-Rule-13.6 */ - /* After some investigation, the following violation of Rule 13.6 seems to be a false positive. - * There are no side effects to the macro 'ZCL_CTX()' used inside 'ZCL_DEVICE_CONTEXT_ITERATOR()'. - * This violation seems to be caused by the fact that 'ZCL_CTX()' is an external macro, which - * cannot be analyzed by C-STAT.*/ - ZCL_DEVICE_CONTEXT_ITERATOR(i); - { - - if (start_from_ep != 0U) - { - for (i = 0; i < device_ctx->ep_count; i++) - { - if (device_ctx->ep_desc_list[i]->ep_id == start_from_ep) - { - start_from_ep = 0; - break; - } - } - - /* Start from the next to start_from_ep endpoint descriptor */ - i++; - } - - for (; start_from_ep == 0U && i < device_ctx->ep_count; i++) - { - zb_af_endpoint_desc_t *ep_desc = device_ctx->ep_desc_list[i]; - - if ((cluster_role == ZB_ZCL_CLUSTER_ANY_ROLE) - ? (get_cluster_desc(ep_desc, cluster_id, ZB_ZCL_CLUSTER_SERVER_ROLE) != NULL - /*cstat !MISRAC2012-Rule-13.5 */ - /* After some investigation, the following violation of Rule 13.5 seems to be - * a false positive. There are no side effect to - * 'zb_aib_trust_center_address_cmp()'. */ - || get_cluster_desc(ep_desc, cluster_id, ZB_ZCL_CLUSTER_CLIENT_ROLE) != NULL) - : get_cluster_desc(ep_desc, cluster_id, cluster_role) != NULL) - { - if (zb_zcl_is_target_endpoint(ep_desc, profile_id)) - { - ep = ep_desc->ep_id; - ZCL_DEVICE_CONTEXT_BREAK; - } - } - } - } - ZCL_DEVICE_CONTEXT_ITERATOR_END; - - TRACE_MSG(TRACE_ZCL2, "< zb_zcl_get_next_target_endpoint, ep %hd", (FMT__H, ep)); - - return ep; -} - - - -zb_bool_t cluster_needs_aps_encryption(zb_uint8_t endpoint_id, zb_uint16_t cluster_id) -{ - zb_bool_t res = ZB_FALSE; - zb_uint16_t profile_id = get_profile_id_by_endpoint(endpoint_id); - - if (endpoint_id == 0U) - { - return res; - } - - /* See SE 1.4 spec, Table 5-12 – Security Key Assignments per Cluster - * - * Unless stated otherwise, any ZCL clusters added to a Smart Energy endpoint shall be APS - * encrypted. ZCL clusters without APS encryption shall be located on another (non-Smart Energy) - * endpoint. The same restrictions shall also apply to manufacturer-specific clusters. - */ - if (profile_id == ZB_AF_HA_PROFILE_ID - && cluster_id == ZB_ZCL_CLUSTER_ID_WWAH) - { - /* WWAH cluster is always encrypted */ - res = ZB_TRUE; - } - - TRACE_MSG(TRACE_ZCL1, "cluster_needs_aps_encryption: ep %hd cluster 0x%x res %hd", (FMT__H_D_H, endpoint_id, cluster_id, res)); - - return res; -} - -static void ep_process_zcl_cmd(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t ep; - zb_af_endpoint_desc_t *ep_desc; - zb_uint8_t status = ZB_ZCL_STATUS_FAIL; - - TRACE_MSG(TRACE_ZCL2, "> ep_process_zcl_cmd, param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - TRACE_MSG(TRACE_ZCL2, "cmd_id: %hd, cluster_id: 0x%x, is_common_command: %hd", - (FMT__H_D_H, cmd_info.cmd_id, cmd_info.cluster_id, cmd_info.is_common_command)); - - ep = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - ep_desc = zb_af_get_endpoint_desc(ep); - ZB_ASSERT(ep_desc); - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_BASIC - if(!zb_zcl_check_is_device_enabled(ep, cmd_info.cmd_id, cmd_info.cluster_id, cmd_info.is_common_command)) - { - zb_buf_free(param); - status = ZB_ZCL_STATUS_SUCCESS; - goto send_default_response; /* to avoid sending default response */ - } -#endif - -#if defined SNCP_MODE - if (!ZB_SE_MODE()) -#else - if (ZB_SE_MODE()) -#endif - /*cstat !MISRAC2012-Rule-2.1_b */ - /** @mdr{00010,3} */ - { - /* SE 1.4 spec, sublclause 5.4.6 - * - * ... all SE applications shall use and validate the Security key usage as listed in Table 5-12. - * If link key encryption is NOT used but required, the receiving device shall generate a - * ZCL Default Response, employing the Network Key, with a FAILURE (0x01) status code. - */ - - TRACE_MSG(TRACE_ZCL2, "ZCL in: cluster: 0x%x, security: %d", - (FMT__D_D, cmd_info.cluster_id, - cluster_needs_aps_encryption(ep, cmd_info.cluster_id))); - - - /* SE+BDB mode: May be no APS encryption (0 key attrs, 0 key source). - TODO: Check somehow that we have any verified key (CBKE or non-CBKE) with src device? */ - /* SE mode: check key is verified by CBKE */ - if (cluster_needs_aps_encryption(ep, cmd_info.cluster_id) == ZB_TRUE && - (!ZB_APS_FC_IS_SECURE(cmd_info.addr_data.common_data.fc) - ) - ) - { - TRACE_MSG(TRACE_ZCL2, "ZCL in: DROP frame due to unverified/non-cbke APS key was used to secure it", (FMT__0)); - status = ZB_ZCL_STATUS_FAIL; - - /* DV: NOTE I think this is the case when 'goto' leaves code readable and makes - * it shorter. It is used to jump to the function end to the common error processing - * block. Using 'else' here will create nested block. The epic case of multiple nested - * blocks + multiple #ifdef clauses is zb_nlde_data_indication_continue() which is - * almost unreadable and hardly modifiable. - */ - goto send_default_response; - } - - TRACE_MSG(TRACE_ZCL2, "ZCL (in): PASS frame, verified CBKE key was used to secure it", (FMT__0)); - } - - /* On receipt of "APS Link Key Authorization" command, a device SHALL henceforth enforce APS - * (trust center) level security for all cluster commands (including global cluster commands i.e. - * Read/Write Attribute) except for those in the exemption list given. */ -#ifdef ZB_ZCL_SUPPORT_CLUSTER_WWAH - if (ZB_ZDO_CHECK_IF_WWAH_SERVER_BEHAVIOR() && - ((ZB_ZDO_CHECK_IF_APS_LINK_KEY_AUTHORIZATION_NEEDED(cmd_info.cluster_id) && - !cmd_info.addr_data.common_data.aps_key_from_tc) || - !ZB_ZDO_CHECK_SRC_ADDRESS_FOR_CLUSTER(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - cmd_info.cluster_id))) - { - TRACE_MSG(TRACE_ZCL2, "ZCL in: not authorized by WWAH", (FMT__0)); - status = ZB_ZCL_STATUS_NOT_AUTHORIZED; - goto send_default_response; - } -#endif - TRACE_MSG(TRACE_ZCL2, "ep %hd, dev handler %p", (FMT__H_P, ep, ep_desc->device_handler)); - - /* Copy zcl cmd before processing in device_handler. - Rationale: device_handler may decide that command is processed and reuse/clear the buffer, but - for some cases we still need to process this cmd in stack. Copy this cmd to another buffer, and - process it after. - */ -#ifdef ZB_TH_ENABLED - ZB_TH_PUSH_PACKET(ZB_TH_ZCL_DATA, ZB_TH_PRIMITIVE_INDICATION, param); - - if (ep_desc->device_handler) - { - TRACE_MSG(TRACE_ZCL2, "call ep handler %hd", (FMT__H, ep)); - status = ((*ep_desc->device_handler)(param) ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); - } -#else - if (ep_desc->device_handler != NULL -#if defined ZB_SE_COMMISSIONING || (defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && defined ZB_ZCL_ENABLE_WWAH_SERVER) - && (ZCL_SELECTOR().block_zcl_cmd == NULL - || !ZCL_SELECTOR().block_zcl_cmd(&cmd_info)) -#endif /* ZB_SE_COMMISSIONING || (ZB_ZCL_SUPPORT_CLUSTER_WWAH && ZB_ZCL_ENABLE_WWAH_SERVER) */ - ) - { - status = (*ep_desc->device_handler)(param) != 0U ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL; - } - else - { - TRACE_MSG(TRACE_ZCL2, "skip ep handler ep %hd", (FMT__H, ep)); - } -#endif - - if (status != ZB_ZCL_STATUS_SUCCESS) - { - status = zb_zcl_handle(param); - } - -send_default_response: - if (status != ZB_ZCL_STATUS_SUCCESS) - { - zb_zcl_send_default_resp_ext(param, &cmd_info, (zb_zcl_status_t)status); - } - - TRACE_MSG(TRACE_ZCL2, "< ep_process_zcl_cmd", (FMT__0)); -} - - -static void broadcast_endpoint_call_next_delivery_step(zb_uint8_t param) -{ - zb_ret_t ret = zb_buf_get_out_delayed_ext(broadcast_endpoint_delivery_step, param, 0); - if (ret != RET_OK) - { - TRACE_MSG(TRACE_ERROR, "Failed zb_buf_get_out_delayed [%d]", (FMT__D, ret)); - zb_buf_free(param); - } -} - - -static void broadcast_endpoint_delivery_step(zb_uint8_t param, zb_uint16_t bc_buf_ref) -{ - zb_zcl_parsed_hdr_t *cmd_info_ptr; - zb_uint8_t ep; - zb_uint32_t process_command_jitter; - - ZB_ASSERT(bc_buf_ref <= ZB_UINT8_MAX); - cmd_info_ptr = ZB_BUF_GET_PARAM((zb_uint8_t)bc_buf_ref, zb_zcl_parsed_hdr_t); - zb_buf_copy(param, (zb_uint8_t)bc_buf_ref); - - ep = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info_ptr).dst_endpoint; - - TRACE_MSG(TRACE_ZCL2, "> broadcast_endpoint_delivery_step, param %hd, bc_buf_ref %hd", - (FMT__H_H, param, bc_buf_ref)); - TRACE_MSG(TRACE_ZCL3, "deliver to ep %hd", (FMT__H, ep)); - - /* - ZCL 6.0 - 2.3.2.2 A device processing a ZCL message sent to the broadcast endpoint - SHOULD jitter messages that are sent in response - */ - process_command_jitter = ZB_RANDOM_JTR(ZB_ZCL_BROADCAST_ENDPOINT_CMD_RESP_JITTER); - ZB_ASSERT(process_command_jitter <= ZB_UINT16_MAX); - ZB_SCHEDULE_ALARM(ep_process_zcl_cmd, param, (zb_uint16_t)process_command_jitter); - - ep = zb_zcl_get_next_target_endpoint( - ep, - cmd_info_ptr->cluster_id, - cmd_info_ptr->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE, - cmd_info_ptr->profile_id); - /* Cmd is delivered to all matching endpoints: free initial buffer */ - if (ep == 0U) - { - ZB_ASSERT(bc_buf_ref <= ZB_UINT8_MAX); - zb_buf_free((zb_uint8_t)bc_buf_ref); - } - /* Proceed to next endpoint */ - else - { - TRACE_MSG(TRACE_ZCL3, "wait new buf to handle ep %hd, jitter %d", (FMT__H_D, ep, process_command_jitter)); - - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info_ptr).dst_endpoint = ep; - ZB_ASSERT(bc_buf_ref <= ZB_UINT8_MAX); - ZB_SCHEDULE_ALARM(broadcast_endpoint_call_next_delivery_step, (zb_uint8_t)bc_buf_ref, process_command_jitter); - } - TRACE_MSG(TRACE_ZCL2, "< broadcast_endpoint_delivery_step", (FMT__0)); -} - - -void zb_zcl_process_parsed_zcl_cmd(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info_ptr = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_parsed_zcl_cmd %hd", (FMT__H, param)); - - if (ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info_ptr).dst_endpoint == ZB_ZCL_BROADCAST_ENDPOINT) - { - zb_uint8_t ep = zb_zcl_get_next_target_endpoint( - 0, - cmd_info_ptr->cluster_id, - cmd_info_ptr->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE, - cmd_info_ptr->profile_id); - - /* Fixed assert when the coordinator receives its own message relayed by the smart plug */ - /* ZB_ASSERT(ep); */ - - if (ep == 0U) - { - /* Frame with broadcast ep was passed to zcl by zb_apsde_data_indication() with - * ZB_ZCL_CLUSTER_ANY_ROLE. If we receive such frame [Identify Query for example] - * but zcl cluster role does not match, just drop the frame. - */ - TRACE_MSG(TRACE_ZCL1, "zb_zcl_process_parsed_zcl_cmd(): role does not match, drop", (FMT__0)); - zb_buf_free(param); - } - else - { - zb_ret_t ret; - - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info_ptr).dst_endpoint = ep; - ret = zb_buf_get_out_delayed_ext(broadcast_endpoint_delivery_step, param, 0); - if (ret != RET_OK) - { - TRACE_MSG(TRACE_ERROR, "Failed zb_buf_get_out_delayed [%d]", (FMT__D, ret)); - zb_buf_free(param); - } - } - } - else - { - ep_process_zcl_cmd(param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_parsed_zcl_cmd", (FMT__0)); -} - -void zb_zcl_process_device_command(zb_uint8_t param) -{ - /* ZCL command information surely present */ - zb_zcl_parsed_hdr_t cmd_info; - zb_zcl_parsed_hdr_t *cmd_info_ptr; - zb_zcl_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_device_command %hd", (FMT__H, param)); - - ZB_BZERO(&cmd_info, sizeof(cmd_info)); - status = zb_zcl_parse_header(param, &cmd_info); - - if (!NCP_CATCH_ZCL_PACKET(param, &cmd_info, status)) - { - /* Cut ZCL header, asdu buffer points to ZCL payload */ - /* Note: moved here from zb_zcl_parse_header because we must not cut it for NCP. */ - ZB_ZCL_CUT_HEADER(param); - - /* save parsed data to buffer */ - cmd_info_ptr = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - ZB_MEMCPY(cmd_info_ptr, &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - - if(status == ZB_ZCL_STATUS_SUCCESS) - { - zb_zcl_process_parsed_zcl_cmd(param); - } - else - { - zb_zcl_send_default_resp_ext(param, &cmd_info, status); - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_device_command", (FMT__0)); -} - -/* - Search for cluster descriptor by its ID -*/ -zb_zcl_cluster_desc_t* get_cluster_desc(const zb_af_endpoint_desc_t* ep_desc, zb_uint16_t cluster_id, zb_uint8_t cluster_role) -{ - zb_uindex_t i = 0; - zb_zcl_cluster_desc_t *cluster_desc = NULL; - - TRACE_MSG(TRACE_ZCL3, ">>get_cluster_desc ep_desc %p, cluster_id 0x%x cluster_role %hd", (FMT__P_D_H, ep_desc, cluster_id, cluster_role)); - if (ep_desc != NULL) - { - while (i < ep_desc->cluster_count) - { - if (ep_desc->cluster_desc_list[i].cluster_id == cluster_id && - ep_desc->cluster_desc_list[i].role_mask == cluster_role) - { - cluster_desc = &ep_desc->cluster_desc_list[i]; - break; - } - i++; - } - } - - TRACE_MSG(TRACE_ZCL3, "<>get_endpoint_by_cluster cluster id = 0x%x", (FMT__D, cluster_id)); - - /*cstat !MISRAC2012-Rule-13.6 */ - /* After some investigation, the following violation of Rule 13.6 seems to be a false positive. - * There are no side effects to the macro 'ZCL_CTX()' used inside 'ZCL_DEVICE_CONTEXT_ITERATOR()'. - * This violation seems to be caused by the fact that 'ZCL_CTX()' is an external macro, which - * cannot be analyzed by C-STAT.*/ - ZCL_DEVICE_CONTEXT_ITERATOR(i); - while (i < device_ctx->ep_count) - { - ep_desc = device_ctx->ep_desc_list[i]; - if (get_cluster_desc(ep_desc, cluster_id, cluster_role) != NULL) - { - endpoint = device_ctx->ep_desc_list[i]->ep_id; - ZCL_DEVICE_CONTEXT_BREAK; - } - i++; - } - ZCL_DEVICE_CONTEXT_ITERATOR_END; - - TRACE_MSG(TRACE_ZCL1, "<>is_cluster_present cluster id = %hd", (FMT__H, cluster_id)); - - /*cstat !MISRAC2012-Rule-13.6 */ - /* After some investigation, the following violation of Rule 13.6 seems to be a false positive. - * There are no side effects to the macro 'ZCL_CTX()' used inside 'ZCL_DEVICE_CONTEXT_ITERATOR()'. - * This violation seems to be caused by the fact that 'ZCL_CTX()' is an external macro, which - * cannot be analyzed by C-STAT.*/ - ZCL_DEVICE_CONTEXT_ITERATOR(i); - while (i < device_ctx->ep_count) - { - ep_desc = device_ctx->ep_desc_list[i]; - if (ep_desc != NULL) - { - while (j < ep_desc->cluster_count) - { - if (ep_desc->cluster_desc_list[j].cluster_id == cluster_id) - { - ret = ZB_TRUE; - break; - } - j++; - } - } - if (ret == ZB_TRUE) - { - ZCL_DEVICE_CONTEXT_BREAK; - } - i++; - } - ZCL_DEVICE_CONTEXT_ITERATOR_END; - - TRACE_MSG(TRACE_ZCL1, "<>get_profile_id_by_endpoint endpoint_id = %hd", (FMT__H, endpoint_id)); - - /*cstat !MISRAC2012-Rule-13.6 */ - /* After some investigation, the following violation of Rule 13.6 seems to be a false positive. - * There are no side effects to the macro 'ZCL_CTX()' used inside 'ZCL_DEVICE_CONTEXT_ITERATOR()'. - * This violation seems to be caused by the fact that 'ZCL_CTX()' is an external macro, which - * cannot be analyzed by C-STAT.*/ - ZCL_DEVICE_CONTEXT_ITERATOR(i); - while (i < device_ctx->ep_count) - { - if (device_ctx->ep_desc_list[i]->ep_id == endpoint_id) - { - profile_id = device_ctx->ep_desc_list[i]->profile_id; - ZCL_DEVICE_CONTEXT_BREAK; - } - i++; - } - ZCL_DEVICE_CONTEXT_ITERATOR_END; - - TRACE_MSG(TRACE_ZCL1, "<> get_endpoint_by_cluster_with_role, cluster_id 0x%x, cluster_role %hd", - (FMT__D_H, cluster_id, cluster_role)); - - /*cstat !MISRAC2012-Rule-13.6 */ - /* After some investigation, the following violation of Rule 13.6 seems to be a false positive. - * There are no side effects to the macro 'ZCL_CTX()' used inside 'ZCL_DEVICE_CONTEXT_ITERATOR()'. - * This violation seems to be caused by the fact that 'ZCL_CTX()' is an external macro, which - * cannot be analyzed by C-STAT.*/ - ZCL_DEVICE_CONTEXT_ITERATOR(i); - while (i < device_ctx->ep_count) - { - ep_desc = device_ctx->ep_desc_list[i]; - cluster_desc = get_cluster_desc(ep_desc, cluster_id, cluster_role); - TRACE_MSG(TRACE_ZGP2, "cluster_desc %p role_mask 0x%x", (FMT__P_D, cluster_desc, cluster_desc ? cluster_desc->role_mask : -1)); - if ((cluster_desc != NULL) && (cluster_desc->role_mask == cluster_role)) - { - ret = ep_desc; - ZCL_DEVICE_CONTEXT_BREAK; - } - i++; - } - ZCL_DEVICE_CONTEXT_ITERATOR_END; - - TRACE_MSG(TRACE_ZGP2, "<< get_endpoint_by_cluster_with_role, ret %p", (FMT__P, ret)); - - return ret; -} - - -/* Check if command should be handled - check command direction and - * cluster role */ -zb_uint8_t zb_zcl_check_accept_command(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_zcl_cluster_desc_t *cluster_desc; - zb_af_endpoint_desc_t *endpoint_desc; - zb_uint8_t status; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_check_accept_command %hd", (FMT__H, param)); - - endpoint_desc = zb_af_get_endpoint_desc(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - cluster_desc = get_cluster_desc(endpoint_desc, cmd_info->cluster_id, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE); - - ZB_ZCL_DEBUG_DUMP_HEADER(cmd_info); - - /* if command is manufacturer specific - skip handling it by default */ - TRACE_MSG(TRACE_ZCL2, "manuf_spec %hd", (FMT__H, cmd_info->is_manuf_specific)); - - /* ZCL8: CCB 2477: use UNSUP_COMMAND instead of any other Unsupported command status */ - if (zb_zcl_get_backward_compatible_statuses_mode() == ZB_ZCL_STATUSES_ZCL8_MODE) - { - status = ZB_ZCL_STATUS_UNSUP_CMD; - } - else - { - if (cmd_info->is_manuf_specific) - { - status = cmd_info->is_common_command ? - ZB_ZCL_STATUS_UNSUP_MANUF_GEN_CMD : ZB_ZCL_STATUS_UNSUP_MANUF_CLUST_CMD; - } - else - { - status = cmd_info->is_common_command ? - ZB_ZCL_STATUS_UNSUP_GEN_CMD : ZB_ZCL_STATUS_UNSUP_CLUST_CMD; - } - } - - TRACE_MSG(TRACE_ZCL1, "check cluster, cluster_desc %p cluster_desc->attr_desc_list %p", - (FMT__P_P, cluster_desc, cluster_desc ? cluster_desc->attr_desc_list : NULL)); - if (cluster_desc != NULL) - { - TRACE_MSG(TRACE_ZCL1, "cmd_direction %hd, cluster role %hx", - (FMT__H_H, cmd_info->cmd_direction, cluster_desc->role_mask)); - if ((cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_CLI - && ZB_BIT_IS_SET(cluster_desc->role_mask, ZB_ZCL_CLUSTER_CLIENT_ROLE)) - || (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV - && ZB_BIT_IS_SET(cluster_desc->role_mask, ZB_ZCL_CLUSTER_SERVER_ROLE))) - { - status = ZB_ZCL_STATUS_SUCCESS; - } - - } - else - { - status = ZB_ZCL_STATUS_UNSUP_CLUST; - } - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_check_accept_command %hd", (FMT__H, status)); - - return status; -} - -#ifdef ZB_NEED_ALIGN - -zb_uint16_t zb_zcl_attr_get16(zb_uint8_t *value) -{ - zb_uint16_t v; - ZB_MEMCPY(&v, value, 2); - return v; -} - -zb_int16_t zb_zcl_attr_gets16(zb_uint8_t *value) -{ - zb_int16_t v; - ZB_MEMCPY(&v, value, 2); - return v; -} - -zb_uint32_t zb_zcl_attr_get32(zb_uint8_t *value) -{ - zb_uint32_t v; - ZB_MEMCPY(&v, value, 4); - return v; -} - -zb_int32_t zb_zcl_attr_gets32(zb_uint8_t *value) -{ - zb_int32_t v; - ZB_MEMCPY(&v, value, 4); - return v; -} - -zb_int24_t zb_zcl_attr_get24(zb_uint8_t *value) -{ - zb_int24_t v; - -#ifdef ZB_UINT24_48_SUPPORT - ZB_MEMCPY(&v, value, 3); -#else - ZB_MEMCPY(&v, value, 4); -#endif - return v; -} - -zb_uint48_t zb_zcl_attr_get48(zb_uint8_t *value) -{ - zb_uint48_t v; -#ifdef ZB_UINT24_48_SUPPORT - ZB_MEMCPY(&v, value, 6); -#else - ZB_MEMCPY(&v, value, 4); -#endif - return v; -} -#endif - -#ifndef ZB_LITTLE_ENDIAN -void zb_reverse_bytes(zb_uint8_t ZB_XDATA *ptr, zb_uint8_t ZB_XDATA *val, zb_uint8_t size) -{ - zb_uindex_t i; - for (i=0; i dump_zcl_header at 0x%hx", (FMT__H, header)); - TRACE_MSG( - TRACE_ZCL3, - "src: address 0x%x, endpoint %hd", - (FMT__D_H, - ZB_ZCL_PARSED_HDR_SHORT_DATA(header).source.u.short_addr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(header).src_endpoint)); - TRACE_MSG( - TRACE_ZCL3, - "dst: address 0x%x, endpoint %hd", - (FMT__D_H, - ZB_ZCL_PARSED_HDR_SHORT_DATA(header).dst_addr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(header).dst_endpoint)); - TRACE_MSG(TRACE_ZCL3, "profile 0x%x, cluster 0x%x, cmdID 0x%x", - (FMT__D_D_H, header->profile_id, header->cluster_id, header->cmd_id)); - TRACE_MSG( - TRACE_ZCL3, - "command direction flag (0 - to server): %hd", - (FMT__H, header->cmd_direction)); - TRACE_MSG( - TRACE_ZCL3, - "sequence number: %hd, is common: %hd", - (FMT__H_H, header->seq_number, header->is_common_command)); - TRACE_MSG( - TRACE_ZCL3, - "manufacturer specific %hd, manuf specific data %d", - (FMT__H_D, header->is_manuf_specific, header->manuf_specific)); - TRACE_MSG(TRACE_ZCL3, "def resp disabled: %hd", (FMT__H, header->disable_default_response)); - TRACE_MSG(TRACE_ZCL3, "< dump_zcl_header", (FMT__0)); -} -#endif /* TRACE_ENABLED(TRACE_ZCL3) */ - -void zb_zcl_schedule_status_abort(zb_bufid_t buffer, zb_addr_u *addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_callback_t cb) -{ - zb_zcl_command_send_status_t *cmd_send_status = - ZB_BUF_GET_PARAM(buffer, zb_zcl_command_send_status_t); - zb_nwk_unlock_in(buffer); - cmd_send_status->status = (zb_ret_t)ZB_ZCL_STATUS_ABORT; - cmd_send_status->src_endpoint = (ep); - cmd_send_status->dst_endpoint = (dst_ep); - cmd_send_status->dst_addr.addr_type = (dst_addr_mode); - if ((dst_addr_mode) == ZB_APS_ADDR_MODE_64_ENDP_PRESENT) - { - ZB_IEEE_ADDR_COPY(cmd_send_status->dst_addr.u.ieee_addr, (void const *)(addr)); - } - else - { - ZB_MEMCPY(&cmd_send_status->dst_addr.u.short_addr, &(addr), sizeof(zb_uint16_t)); - } - ZB_SCHEDULE_CALLBACK(cb, buffer); -} - -#ifdef ZB_USEALIAS -void zb_zcl_send_command_short_alias(zb_bufid_t buffer, - zb_addr_u *addr, zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t ep, - zb_uint16_t prof_id, zb_uint16_t cluster_id, - zb_uint8_t radius, zb_callback_t cb, zb_uint8_t use_alias, - zb_uint16_t alias_addr, zb_uint8_t alias_seq) -{ - zb_apsde_data_req_t *apsde_req; -#ifdef ZB_ZCL_SUPPORT_CLUSTER_BASIC - zb_zcl_frame_hdr_short_t *zcl_cmd = (zb_zcl_frame_hdr_short_t *)zb_buf_begin(buffer); - if (!zb_zcl_check_is_device_enabled(ep, - zcl_cmd->command_id, - cluster_id, - (zcl_cmd->frame_ctrl.frame_type == ZB_ZCL_FRAME_TYPE_COMMON) ? ZB_TRUE : ZB_FALSE)) - { - (cb != NULL) ? ZB_ZCL_SCHEDULE_STATUS_ABORT(buffer, addr, dst_addr_mode, dst_ep, ep, cb) : zb_buf_free(buffer); - return; - } -#endif - apsde_req = ZB_BUF_GET_PARAM(buffer, zb_apsde_data_req_t); - - ZB_BZERO(apsde_req, sizeof(zb_apsde_data_req_t)); - apsde_req->addr_mode = dst_addr_mode; - apsde_req->dst_addr = *addr; - apsde_req->dst_endpoint = dst_ep; - apsde_req->src_endpoint = ep; - apsde_req->profileid = prof_id; - apsde_req->clusterid = cluster_id; - apsde_req->radius = radius; - - if (use_alias == ZB_TRUE) - { - apsde_req->alias_src_addr = alias_addr; - apsde_req->alias_seq_num = alias_seq; - apsde_req->use_alias = ZB_TRUE; - } - - if ((apsde_req->addr_mode != ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT) && - (!ZB_NWK_IS_ADDRESS_BROADCAST(addr->addr_short))) - { - apsde_req->tx_options = ZB_APSDE_TX_OPT_ACK_TX; - } - - if (zb_zcl_register_cb(buffer, cb) == RET_OK) - { - ZB_ZCL_DEBUG_DUMP_COMMAND(buffer); - TRACE_MSG(TRACE_ZDO3, "Call zb_zdo_pim_start_turbo_poll_packets 1", (FMT__0)); - zb_zdo_pim_start_turbo_poll_packets(1); - ZB_SCHEDULE_CALLBACK(zb_apsde_data_request, buffer); - } - else - { - /* cb != NULL here. */ - ZB_ZCL_SCHEDULE_STATUS_ABORT(buffer, addr, dst_addr_mode, dst_ep, ep, cb); - } -} -#endif /* ZB_USEALIAS */ - -void zb_zcl_send_command_short_schedule(zb_bufid_t buffer, - zb_uint16_t addr, zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t ep, - zb_uint16_t prof_id, zb_uint16_t cluster_id, - zb_callback_t cb, zb_uint64_t delay) -{ - zb_apsde_data_req_t *apsde_req; -#ifdef ZB_ZCL_SUPPORT_CLUSTER_BASIC - zb_zcl_frame_hdr_short_t *zcl_cmd = (zb_zcl_frame_hdr_short_t *)zb_buf_begin(buffer); - if (!zb_zcl_check_is_device_enabled(ep, - zcl_cmd->command_id, - cluster_id, - (zcl_cmd->frame_ctrl.frame_type == ZB_ZCL_FRAME_TYPE_COMMON) ? ZB_TRUE : ZB_FALSE)) - { - zb_addr_u short_addr; - short_addr.addr_short = addr; - (cb != NULL) ? ZB_ZCL_SCHEDULE_STATUS_ABORT(buffer, &short_addr, dst_addr_mode, dst_ep, ep, cb) : zb_buf_free(buffer); - return; - } -#endif - apsde_req = ZB_BUF_GET_PARAM(buffer, zb_apsde_data_req_t); - - ZB_BZERO(apsde_req, sizeof(zb_apsde_data_req_t)); - apsde_req->addr_mode = dst_addr_mode; - apsde_req->dst_addr.addr_short = addr; - apsde_req->dst_endpoint = dst_ep; - apsde_req->src_endpoint = ep; - apsde_req->profileid = prof_id; - apsde_req->clusterid = cluster_id; - - if ((apsde_req->addr_mode != ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT) && - (!ZB_NWK_IS_ADDRESS_BROADCAST(addr))) - { - apsde_req->tx_options = ZB_APSDE_TX_OPT_ACK_TX; - } - - if (zb_zcl_register_cb(buffer, cb) == RET_OK) - { - ZB_ZCL_DEBUG_DUMP_COMMAND(buffer); -#ifdef ZB_ED_FUNC - TRACE_MSG(TRACE_ZDO3, "Call zb_zdo_pim_start_turbo_poll_packets 1 after alarm", (FMT__0)); - ZB_SCHEDULE_ALARM(zb_zdo_pim_start_turbo_poll_packets, 1, ZB_MILLISECONDS_TO_BEACON_INTERVAL(delay)); -#endif - ZB_SCHEDULE_ALARM(zb_apsde_data_request, buffer, ZB_MILLISECONDS_TO_BEACON_INTERVAL(delay)); - } - else - { - /* cb != NULL here. */ - ZB_ZCL_SCHEDULE_STATUS_ABORT(buffer, &(apsde_req->dst_addr), dst_addr_mode, dst_ep, ep, cb); - } -} - -#ifdef APS_FRAGMENTATION - -zb_bool_t zb_zcl_can_cluster_be_fragmented(zb_uint16_t profile_id, zb_uint16_t cluster_id) -{ - zb_bool_t ret; - ZVUNUSED (profile_id); - /* clusters with variable size fields */ - /* if (profile_id == ZB_AF_SE_PROFILE_ID) - { - ret = ZB_TRUE; -} - else */ - { - ret = (cluster_id == ZB_ZCL_CLUSTER_ID_TUNNELING - || cluster_id == ZB_ZCL_CLUSTER_ID_PRICE - || cluster_id == ZB_ZCL_CLUSTER_ID_MESSAGING - || cluster_id == ZB_ZCL_CLUSTER_ID_METERING - || cluster_id == ZB_ZCL_CLUSTER_ID_KEY_ESTABLISHMENT - || cluster_id == ZB_ZCL_CLUSTER_ID_PREPAYMENT - || cluster_id == ZB_ZCL_CLUSTER_ID_CALENDAR - || cluster_id == ZB_ZCL_CLUSTER_ID_DEVICE_MANAGEMENT - || cluster_id == ZB_ZCL_CLUSTER_ID_EVENTS - || cluster_id == ZB_ZCL_CLUSTER_ID_DRLC - || cluster_id == ZB_ZCL_CLUSTER_ID_ENERGY_MANAGEMENT - || cluster_id == ZB_ZCL_CLUSTER_ID_MDU_PAIRING - || cluster_id == ZB_ZCL_CLUSTER_ID_SUB_GHZ - ) ? ZB_TRUE : ZB_FALSE; - } - return ret; -} -#endif /* APS_FRAGMENTATION */ - -static zb_ret_t zb_zcl_finish_and_send_packet_common(zb_bufid_t buffer, - zb_uint8_t *ptr, - zb_callback_t cb, - zb_bool_t disable_aps_ack, - zb_uint16_t delay) -{ -#ifdef APS_FRAGMENTATION - zb_bool_t frag; -#endif - - zb_ret_t res = RET_OK; - zb_apsde_data_req_t *apsde_req = ZB_BUF_GET_PARAM(buffer, zb_apsde_data_req_t); - zb_zcl_frame_hdr_short_t *zcl_cmd = (zb_zcl_frame_hdr_short_t *)zb_buf_begin(buffer); - - zb_uint8_t dst_addr_mode = apsde_req->addr_mode; - zb_addr_u *dst_addr = &apsde_req->dst_addr; - zb_uint8_t dst_ep = apsde_req->dst_endpoint; - zb_uint8_t ep = apsde_req->src_endpoint; - zb_uint16_t cluster_id = apsde_req->clusterid; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_finish_and_send_packet_common param %hd delay %d", (FMT__H_D, buffer, delay)); - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_BASIC - if (!zb_zcl_check_is_device_enabled(apsde_req->src_endpoint, - zcl_cmd->command_id , - apsde_req->clusterid, - (zcl_cmd->frame_ctrl.frame_type == ZB_ZCL_FRAME_TYPE_COMMON) ? ZB_TRUE : ZB_FALSE)) - { - if (cb != NULL) - { - ZB_ZCL_SCHEDULE_STATUS_ABORT(buffer, dst_addr, dst_addr_mode, dst_ep, ep, cb); - /* If cb isn't NULL caller should handle result in zb_zcl_command_send_status_t param */ - return RET_OK; - } - else - { - zb_buf_free(buffer); - return RET_CANCELLED; - } - } -#endif - -#ifdef APS_FRAGMENTATION - frag = zb_zcl_can_cluster_be_fragmented(apsde_req->profileid, cluster_id); -#endif - - if (ptr != NULL) - { - if (ZB_ZCL_GET_BYTES_WRITTEN(buffer, ptr) > zb_buf_len(buffer)) - { - /* TODO: we are currently using zb_buf_alloc_left to set buffer length. Change it to better - suited functions. */ - TRACE_MSG(TRACE_ZCL3, "extending packet to %d bytes", - (FMT__H, ZB_ZCL_GET_BYTES_WRITTEN(buffer, ptr) - zb_buf_len(buffer))); - (void)zb_buf_alloc_left(buffer, ZB_ZCL_GET_BYTES_WRITTEN(buffer, ptr) - zb_buf_len(buffer)); - } - } - - if ( !(((zb_aps_addr_mode_t)(dst_addr_mode) == ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT) - || ((apsde_req->addr_mode == ZB_APS_ADDR_MODE_16_ENDP_PRESENT) && - (ZB_NWK_IS_ADDRESS_BROADCAST(dst_addr->addr_short)))) - /* "Require APS ACKs on Unicasts" command enforces that all unicast commands have APS ACKs enabled, - * except for clusters in exception list. This also applies to global cluster commands (i.e. - * read/write attribute commands). */ - && ZB_ZDO_CHECK_IF_APS_ACK_NEEDED(cluster_id) - && !disable_aps_ack - ) - { - apsde_req->tx_options |= ZB_APSDE_TX_OPT_ACK_TX; - } - -#ifdef APS_FRAGMENTATION - if (frag) - { - apsde_req->tx_options |= ZB_APSDE_TX_OPT_FRAG_PERMITTED; - } -#endif - /*cstat -MISRAC2012-Rule-2.1_b -MISRAC2012-Rule-14.3_b */ - if (res == RET_OK - && !IS_DISTRIBUTED_SECURITY() - && ZB_ZDO_CHECK_IF_WWAH_SERVER_BEHAVIOR() - && ZB_ZDO_CHECK_IF_APS_LINK_KEY_AUTHORIZATION_NEEDED(cluster_id)) - { - /*cstat +MISRAC2012-Rule-2.1_b +MISRAC2012-Rule-14.3_b */ - /** @mdr{00023,2} */ - /** @mdr{00015,10} */ - zb_ieee_addr_t dst_ieee; - ZB_IEEE_ADDR_ZERO(dst_ieee); - switch (dst_addr_mode) - { - case ZB_APS_ADDR_MODE_16_ENDP_PRESENT: - if (zb_address_ieee_by_short(dst_addr->addr_short, dst_ieee) != RET_OK) - { - res = RET_UNAUTHORIZED; - }; - break; - case ZB_APS_ADDR_MODE_64_ENDP_PRESENT: - ZB_IEEE_ADDR_COPY(dst_ieee, dst_addr); - break; - case ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT: - /* TODO: See notes below: - * Bind mode, neither dst addr nor ep is known at this moment. - * Real destination address will be known only in apsde_data_req. */ - break; - case ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT: - /*FALLTHRU*/ - default: - /* Note that enabling "APS Link Key Authorization" requirement also means that - * group/broadcast command for these clusters SHALL no longer be accepted since there is - * no way to establish an APS Key for a Zigbee Group. */ - res = RET_UNAUTHORIZED; - break; - } - -#ifndef ZB_COORDINATOR_ONLY - /*cstat -MISRAC2012-Rule-2.1_b */ - if (ZB_ZDO_CHECK_IF_WWAH_SERVER_BEHAVIOR() - && dst_addr_mode != ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT) - { - /*cstat +MISRAC2012-Rule-2.1_b */ - /** @mdr{00015,1} */ - if (res == RET_OK - /*cstat !MISRAC2012-Rule-13.5 */ - /* After some investigation, the following violation of Rule 13.5 seems to be - * a false positive. There are no side effect to 'zb_aib_trust_center_address_cmp()'. This - * violation seems to be caused by the fact that 'zb_aib_trust_center_address_cmp()' is an - * external function, which cannot be analyzed by C-STAT. */ - && !zb_aib_trust_center_address_cmp(dst_ieee)) - { - res = RET_UNAUTHORIZED; - } - } -#endif - if (res == RET_OK - /*cstat !MISRAC2012-Rule-13.5 */ - /* After some investigation, the following violation of Rule 13.5 seems to be - * a false positive. There are no side effect to 'zb_secur_get_link_key_by_address()'. This - * violation seems to be caused by the fact that 'zb_secur_get_link_key_by_address()' is an - * external function, which cannot be analyzed by C-STAT. */ - && zb_secur_get_link_key_by_address(dst_ieee, ZB_SECUR_VERIFIED_KEY) != NULL) - { - apsde_req->tx_options |= ZB_APSDE_TX_OPT_SECURITY_ENABLED; - } - else - { - res = RET_UNAUTHORIZED; - TRACE_MSG(TRACE_ERROR, - "ZCL (out): DROP frame! Cluster 0x%x forced to use TC with TCLK encryption!", - (FMT__D, cluster_id)); - } - } - - - if (res == RET_OK) - { - if (cluster_needs_aps_encryption(ep, cluster_id) == ZB_TRUE) - { - zb_ieee_addr_t dst_ieee; - zb_aps_device_key_pair_set_t *key = NULL; - zb_secur_key_attributes_t key_attrib = - ZB_SECUR_VERIFIED_KEY; - - TRACE_MSG(TRACE_ZCL2, "ZCL (out): cluster: 0x%x, APS security required: yes", - (FMT__D, cluster_id)); - ZB_IEEE_ADDR_ZERO(dst_ieee); - - switch (dst_addr_mode) - { - case ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT: - /* Bind mode, neither dst addr nor ep is known at this moment. - * Real destination address will be known only in apsde_data_req. - * - * TODO: pass the desired attribute ZB_SECUR_KEY_SRC_CBKE of the link key - * to the APS level! - */ - TRACE_MSG(TRACE_ZCL2, "Bind mode!", (FMT__0)); - break; - - case ZB_APS_ADDR_MODE_16_ENDP_PRESENT: - res = zb_address_ieee_by_short(dst_addr->addr_short, dst_ieee); - if (res == RET_OK) - { - key = zb_secur_get_link_key_by_address(dst_ieee, key_attrib); - TRACE_MSG(TRACE_ZCL2, "Short addr mode!", (FMT__0)); - } - break; - - case ZB_APS_ADDR_MODE_64_ENDP_PRESENT: - ZB_IEEE_ADDR_COPY(dst_ieee, dst_addr); - key = zb_secur_get_link_key_by_address(dst_ieee, key_attrib); - TRACE_MSG(TRACE_ZCL2, "Long addr mode!", (FMT__0)); - break; - - case ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT: - default: - /* What to do with group address mode? Is it possible in SE? */ - ZB_ASSERT(0); - break; - } - - /* NK:FIXME: No check below (in apsde_data_req) that key which will be used to encrypt is - * VERIFIED. May modify zb_secur_get_link_key_pair_set() - it already have - * "valid_only" parameter. - */ - - /* SE+BDB: Just check that we have a VERIFIED key - it may be not CBKE. - TODO: For legacy devices it may be no VERIFIED key - what to do? - */ - if ((key == NULL - ) - && (dst_addr_mode != ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT)) - { - if ((zcl_cmd->command_id == ZB_ZCL_CMD_DEFAULT_RESP) - && (zcl_cmd->frame_ctrl.manufacturer == 0U) - && (zcl_cmd->frame_ctrl.frame_type == ZB_ZCL_FRAME_TYPE_COMMON) - /* TODO: describe where is that status in the packet. Ref to the spec etc. */ - && (*((zb_uint8_t *)zcl_cmd + 4U * sizeof(zb_uint8_t)) == ZB_ZCL_STATUS_FAIL)) - { - TRACE_MSG(TRACE_ERROR, - "ZCL (out): Specific case - failure default response will be sent without encryption if input command [%hd] cluster [%d] was incorrectly secured!", - (FMT__H_D, *((zb_uint8_t *)zcl_cmd + 3 * sizeof(zb_uint8_t)), cluster_id)); - } - else - { - TRACE_MSG(TRACE_ERROR, - "ZCL (out): DROP frame! Cluster 0x%x needs APS encryption but there is no CBKE " - "key available!", - (FMT__D, cluster_id)); - - res = RET_UNAUTHORIZED; - } - } - else - { - apsde_req->tx_options |= ZB_APSDE_TX_OPT_SECURITY_ENABLED; - } - } - else - { - TRACE_MSG(TRACE_ZCL2, "ZCL (out): cluster: 0x%x, APS security required: no", - (FMT__D, cluster_id)); - } - - /* - * APS Acknowledgments shall be suppressed on High Frequency messages - * (messages that are repeated at a rate higher than once every 30 - * seconds) when utilizing sub-GHz frequencies; the Acknowledgement - * Request sub-field in the Frame Control field of the APDU Frame Header - * shall be set to 0. - * - * The Disable Default Response sub-field in the ZCL Frame Control field - * shall be set to 1 (disables positive Default Responses) on High - * Frequency messages when utilizing sub-GHz 2816 frequencies. - */ - } - - if (res == RET_OK) - { - res = zb_zcl_register_cb(buffer, (cb)); - } - - if (res == RET_OK) - { - zb_uint8_t *hdr = zb_buf_begin(buffer); - - ZB_ZCL_DEBUG_DUMP_COMMAND(buffer); - if (!ZB_U2B(ZB_ZCL_GET_DISABLE_DEFAULT_RESPONSE(*hdr))) - { - /* TODO: Poll to number of fragments here (ZG->aps.out_frag.block_num). */ - TRACE_MSG(TRACE_ZDO3, "Call zb_zdo_pim_start_turbo_poll_packets 1", (FMT__0)); - zb_zdo_pim_start_turbo_poll_packets(1); - } - ZB_TH_PUSH_PACKET(ZB_TH_ZCL_DATA, ZB_TH_PRIMITIVE_REQUEST, buffer); - - if (delay == 0U) - { - ZB_SCHEDULE_CALLBACK(zb_apsde_data_request, buffer); - } - else - { - ZB_SCHEDULE_ALARM(zb_apsde_data_request, buffer, delay); - } - } - else if (cb != NULL) - { - zb_zcl_schedule_status_abort(buffer, dst_addr, dst_addr_mode, dst_ep, ep, cb); - /* If cb isn't NULL caller should handle result in zb_zcl_command_send_status_t param */ - res = RET_OK; - } - else - { - /* MISRA rule 15.7 requires empty 'else' branch. */ - } - - return res; -} - -zb_ret_t zb_zcl_finish_and_send_packet(zb_bufid_t buffer, zb_uint8_t *ptr, - const zb_addr_u *dst_addr, zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t ep, - zb_uint16_t prof_id, zb_uint16_t cluster_id, - zb_callback_t cb) -{ - zb_apsde_data_req_t *apsde_req = ZB_BUF_GET_PARAM(buffer, zb_apsde_data_req_t); - ZB_BZERO(apsde_req, sizeof(zb_apsde_data_req_t)); - apsde_req->addr_mode = (dst_addr_mode); - ZB_MEMCPY(&apsde_req->dst_addr, (dst_addr), - (dst_addr_mode == ZB_APS_ADDR_MODE_64_ENDP_PRESENT ? sizeof(zb_addr_u) : sizeof(zb_uint16_t))); - apsde_req->dst_endpoint = (dst_ep); - apsde_req->src_endpoint = (ep); - apsde_req->profileid = (prof_id); - apsde_req->clusterid = (cluster_id); - return zb_zcl_finish_and_send_packet_common(buffer, ptr, cb, ZB_FALSE, 0); -} - -zb_ret_t zb_zcl_finish_and_send_packet_new(zb_bufid_t buffer, zb_uint8_t *ptr, - const zb_addr_u *dst_addr, zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t ep, - zb_uint16_t prof_id, zb_uint16_t cluster_id, - zb_callback_t cb, zb_bool_t aps_secured, - zb_bool_t disable_aps_ack, zb_uint16_t delay) -{ - zb_apsde_data_req_t *apsde_req = ZB_BUF_GET_PARAM(buffer, zb_apsde_data_req_t); - ZB_BZERO(apsde_req, sizeof(zb_apsde_data_req_t)); - apsde_req->addr_mode = (dst_addr_mode); - ZB_MEMCPY(&apsde_req->dst_addr, (dst_addr), - (dst_addr_mode == ZB_APS_ADDR_MODE_64_ENDP_PRESENT ? sizeof(zb_addr_u) : sizeof(zb_uint16_t))); - apsde_req->dst_endpoint = (dst_ep); - apsde_req->src_endpoint = (ep); - apsde_req->profileid = (prof_id); - apsde_req->clusterid = (cluster_id); - apsde_req->tx_options = aps_secured ? (zb_uint8_t)ZB_APSDE_TX_OPT_SECURITY_ENABLED : 0U; - return zb_zcl_finish_and_send_packet_common(buffer, ptr, cb, disable_aps_ack, delay); -} - - -void *zb_zcl_start_command_header(zb_bufid_t zbbuf, zb_uint8_t frame_ctl, zb_uint16_t manuf_code, zb_uint8_t cmd_id, zb_uint8_t* tsn) -{ - zb_uint8_t l_tsn; - zb_uint8_t* data_ptr = ZB_ZCL_START_PACKET(zbbuf); - - *data_ptr = frame_ctl; - data_ptr++; - l_tsn = ZB_ZCL_GET_SEQ_NUM(); - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(data_ptr, l_tsn, ZB_ZCL_IS_MANUF_SPECIFIC(frame_ctl), - manuf_code, cmd_id); - if (tsn != NULL) - { - *tsn = l_tsn; - } - return data_ptr; -} - -zb_zcl_globals_t *zb_zcl_get_ctx() -{ - return &ZG->zcl; -} - -zb_ret_t zb_zcl_set_peer_revision_callback(zb_zcl_peer_revision_cb_t cb) -{ - ZCL_CTX().peer_revision_cb = cb; - - /* NULL, if a user wants to reset the callback */ - if (NULL == cb) - { - return RET_OK; - } - else - { - return zb_zcl_set_backward_comp_mode(ZB_ZCL_COMPATIBILITY_MODE); - } -} - -zb_ret_t zb_zcl_set_backward_comp_mode(zb_uint8_t mode) -{ - if (mode > ZB_ZCL_COMPATIBILITY_MODE) - { - return RET_OUT_OF_RANGE; - } - else - { - ZCL_CTX().backward_comp_mode = mode; - return RET_OK; - } -} - -zb_uint8_t zb_zcl_get_backward_comp_mode(void) -{ - return ZCL_CTX().backward_comp_mode; -} - -zb_uint16_t zb_zcl_get_cluster_rev_by_mode(zb_uint16_t api_revision, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint16_t cluster_id, zb_uint8_t cluster_role, - zb_uint8_t src_ep) -{ - zb_uint8_t mode; - zb_zcl_attr_t *attr_desc_cluster_rev; - zb_uint16_t rev; - zb_uint16_t rev_attr_value; - zb_ieee_addr_t ieee_addr; - zb_uint16_t short_addr; - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_get_cluster_rev_by_mode", (FMT__0)); - - mode = zb_zcl_get_backward_comp_mode(); - - TRACE_MSG(TRACE_ZCL3, "mode %d", (FMT__H, mode)); - - attr_desc_cluster_rev = zb_zcl_get_attr_desc_a(src_ep, cluster_id, - cluster_role, - ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID); - - if (attr_desc_cluster_rev != NULL) - { - rev_attr_value = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_cluster_rev); - } - else - { - /* it means the attribute wasn't declared for the cluster */ - rev_attr_value = ZB_ZCL_CLUSTER_REV_MIN; - } - - TRACE_MSG(TRACE_ZCL3, "rev_attr_value %d", (FMT__D, rev_attr_value)); - - switch(mode) - { - case ZB_ZCL_LEGACY_MODE: - rev = (api_revision > rev_attr_value) ? rev_attr_value : api_revision; - break; - case ZB_ZCL_AUTO_MODE: - /* rev_attr_value is compared to maximum available cluster revision while the revision value is being set, - so we don't have to check for maximum value here */ - rev = rev_attr_value; - break; - case ZB_ZCL_COMPATIBILITY_MODE: - if (NULL == ZCL_CTX().peer_revision_cb) - { - rev = ZB_ZCL_CLUSTER_REV_MIN; - } - else - { - if (dst_addr_mode == ZB_APS_ADDR_MODE_64_ENDP_PRESENT) - { - ZB_IEEE_ADDR_COPY(ieee_addr, dst_addr); - } - else - { - ZB_MEMCPY(&short_addr, (dst_addr), sizeof(short_addr)); - ret = zb_address_ieee_by_short(short_addr, ieee_addr); - } - if (RET_OK == ret) - { - rev = (*ZCL_CTX().peer_revision_cb)(ieee_addr, cluster_id, - ZB_ZCL_REVERT_CLUSTER_ROLE(cluster_role), dst_ep); - if (ZB_ZCL_PEER_CLUSTER_REV_UNKNOWN == rev) - { - rev = ZB_ZCL_CLUSTER_REV_MIN; - } - else - { - rev = (rev > rev_attr_value) ? rev_attr_value : rev; - } - } - else - { - rev = ZB_ZCL_CLUSTER_REV_MIN; - } - } - break; - default: - rev = rev_attr_value; - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_get_cluster_rev_by_mode %d", (FMT__H, rev)); - - return rev; -} - -zb_uint8_t zb_zcl_get_backward_compatible_statuses_mode(void) -{ - return ZCL_CTX().backward_compatible_statuses_mode; -} - -zb_ret_t zb_zcl_set_backward_compatible_statuses_mode(zb_uint8_t statuses_mode) -{ - if (statuses_mode > ZB_ZCL_STATUSES_ZCL8_MODE) - { - return RET_OUT_OF_RANGE; - } - else - { - ZCL_CTX().backward_compatible_statuses_mode = statuses_mode; - return RET_OK; - } -} - -zb_zcl_status_t zb_zcl_zcl8_statuses_conversion(zb_zcl_status_t status) -{ - if (zb_zcl_get_backward_comp_mode() == ZB_ZCL_LEGACY_MODE) - { - return status; - } - else - { - zb_zcl_status_t ret_status; - switch(status) - { - case ZB_ZCL_STATUS_DUPE_EXISTS: /* FALLTHROUGH */ - case ZB_ZCL_STATUS_LIMIT_REACHED: - ret_status = ZB_ZCL_STATUS_SUCCESS; - break; - case ZB_ZCL_STATUS_INCONSISTENT_STARTUP_STATE: /* FALLTHROUGH */ - case ZB_ZCL_STATUS_DEFINED_OUT_OF_BAND: /* FALLTHROUGH */ - case ZB_ZCL_STATUS_ACTION_DENIED: /* FALLTHROUGH */ - case ZB_ZCL_STATUS_HW_FAIL: /* FALLTHROUGH */ - case ZB_ZCL_STATUS_SW_FAIL: - ret_status = ZB_ZCL_STATUS_FAIL; - break; - case ZB_ZCL_STATUS_INCONSISTENT: /* FALLTHROUGH */ - case ZB_ZCL_STATUS_CALIB_ERR: - ret_status = ZB_ZCL_STATUS_RESERVED; - break; - case ZB_ZCL_STATUS_UNSUP_CLUST_CMD: /* FALLTHROUGH */ - case ZB_ZCL_STATUS_UNSUP_GEN_CMD: /* FALLTHROUGH */ - case ZB_ZCL_STATUS_UNSUP_MANUF_CLUST_CMD: /* FALLTHROUGH */ - case ZB_ZCL_STATUS_UNSUP_MANUF_GEN_CMD: - ret_status = ZB_ZCL_STATUS_UNSUP_CMD; - break; - case ZB_ZCL_STATUS_WRITE_ONLY: - ret_status = ZB_ZCL_STATUS_NOT_AUTHORIZED; - break; - default: - ret_status = status; - break; - } - return ret_status; - } -} - -zb_zcl_status_t zb_zcl_get_zcl_status_from_ret(zb_ret_t result) -{ - zb_zcl_status_t zcl_result; - - switch (result) - { - case RET_OK: - zcl_result = ZB_ZCL_STATUS_SUCCESS; - break; - - case RET_INVALID_PARAMETER_1: - zcl_result = ZB_ZCL_STATUS_INVALID_FIELD; - break; - - case RET_INVALID_PARAMETER: - zcl_result = ZB_ZCL_STATUS_INVALID_VALUE; - break; - - case RET_NOT_IMPLEMENTED: - zcl_result = ZB_ZCL_STATUS_UNSUP_CMD; - break; - - default: - zcl_result = (zb_zcl_get_backward_compatible_statuses_mode() == ZB_ZCL_STATUSES_ZCL8_MODE) ? - ZB_ZCL_STATUS_FAIL : ZB_ZCL_STATUS_HW_FAIL; - break; - } - - return zcl_result; -} - -#endif /* defined (ZB_ENABLE_ZCL) */ - -#endif /* defined (ZB_ENABLE_ZCL) || defined (ZB_ENABLE_ZGPD_ATTR_REPORTING) */ diff --git a/zboss/development/src/zcl/zcl_continuous_value_change_commands.c b/zboss/development/src/zcl/zcl_continuous_value_change_commands.c deleted file mode 100644 index 849258fb4f..0000000000 --- a/zboss/development/src/zcl/zcl_continuous_value_change_commands.c +++ /dev/null @@ -1,810 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Continuous Value Change feature commands -*/ -#define ZB_TRACE_FILE_ID 2064 - -#include "zb_common.h" - -#if defined (ZB_CVC_FEATURE_SUPPORT) - -#include "zcl/zb_zcl_cvc_commands.h" - -/* 01/02/2013 CR:MAJOR - General: - The following functions should use CVC: - 1. Move to level command(3.10.2.3.1). Current value -> Target value, step - from technical - practice. Direction from values. - 2. Move command(3.10.2.3.2). Rate and direction(or stop). On min/max values - stop. - 3. Step command(3.10.2.3.3). Target value, direction, transition time. - 4. Enhanced move to hue (6.8.1.3.2...). Target value, direction(or stop), transition time. App should care - about reachable values! - 5. Enhanced move hue (6.8.1.3.3...). Rate and direction(or stop). On margin values - loop. - 6. Enhanced step hue (6.8.1.3.4...). Direction, target value, transition time. On margin values - loop. - 7. Move to XY (6.8.1.3.5). TargetX, TargetY, transition time. - 8. Color loop set. Out of scope. - 9. Stop move step. Out of scope. - 10. Move color temp. Rate, direction(or stop), min and max. After reach - min/max/phyMin/phyMax - stop. - 11. Step color temp. Direction (or stop), target value, transition time, max and min. - After reach min/max/phyMin/phyMax - stop. - - TODO: Continuous value change with loop should be implemented. - - 05/02/2013 "with loop" means overlapped values? - 06/02/2013 Overlapping added. Value change scheme can be, for example, ... -> 1 -> 0 -> 255 -> - 254 -> ..., where 0 and 255 is MIN and MAX values. Tested on Level Control. -*/ - - -#define ZB_ZCL_CVC_GET_TIME_IN_UNITS() ZB_TIME_BEACON_INTERVAL_TO_MSEC(ZB_TIMER_GET()) / 100 - -void zb_zcl_cvc_correct_value(zb_zcl_cvc_input_variables_t* input_var); - -static zb_uint8_t zb_zcl_cvc_calc( - zb_zcl_cvc_input_variables_t* input_variables, - zb_uint8_t buf_id, - zb_bool_t is_recalc) -{ - zb_bufid_t buf = 0; -#ifdef ZB_ZCL_ENABLE_CVC - zb_uint8_t diff; - zb_bool_t direction_decrement = ZB_FALSE; -#endif - zb_zcl_cvc_variables_t* change_variables; - zb_uint8_t ret = ZB_UNDEFINED_BUFFER; - zb_zcl_cvc_input_variables_t* input_var; - zb_time_t transition_time_q = 0; - - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_cvc_calc", (FMT__0)); - - if (is_recalc == ZB_FALSE) - { - /* 1. Correct end level. */ - buf = zb_buf_get_out(); - zb_zcl_cvc_correct_value(input_variables); - } - else - { - buf = buf_id; - } - - ZB_ASSERT(buf != 0); - - change_variables = ZB_BUF_GET_PARAM(buf, zb_zcl_cvc_variables_t); - - if (is_recalc == ZB_FALSE) - { - input_var = input_variables; - } - else - { - input_var = &(change_variables->input_var); - } - - -/* 0. Check that transition_time is correct (> 0)! */ - if (input_var->transition_time == 0) - { - /* This function returns buffer id. - * If input data is wrong, ZB_UNDEFINED_BUFFER will be returned. - * So i think, no error codes from zb_error.h needed here, because this is only 2 cases: valid - * buffer id or invalid buffer id (ZB_UNDEFINED_BUFFER). - */ - TRACE_MSG(TRACE_ZCL1, "Error, transition_time is incorrect!", (FMT__0)); - } - else - { - -/* 2. Set input variables. */ - if (&(change_variables->input_var) != input_var) - { - ZB_MEMCPY(&(change_variables->input_var), input_var, sizeof(zb_zcl_cvc_input_variables_t)); - } -/* change_variables->input_var.current_value16 = input_var->current_value16; - change_variables->input_var.end_value16 = input_var->end_value16; - change_variables->input_var.min_value16 = input_var->min_value16; - change_variables->input_var.max_value16 = input_var->max_value16; - change_variables->input_var.overlap = input_var->overlap; - change_variables->input_var.transition_time = input_var->transition_time; - change_variables->transition_time_q = 0; - change_variables->input_var.value_set_func = input_var->value_set_func; - change_variables->input_var.buf_id = input_var->buf_id; - change_variables->input_var.after_processing_cb = input_var->after_processing_cb; -*/ -#ifndef ZB_ZCL_ENABLE_CVC - input_var->transition_time = ZB_ZCL_CVC_TRANSITION_TIME_AS_FAST_AS_ABLE; - change_variables->transition_time_q = 0; - change_variables->steps_number = 1; - change_variables->delta_time_q = 1; -#else - -/* 3. Calculate direction_decrement */ - - -/* 4. Calculate diff. */ -//TODO: overlap - if (input_var->overlap == ZB_TRUE) - { - if (input_var->end_value16 > input_var->current_value16) - // end_value16 > current_value16 => overlap MIN value - { - diff = (input_var->current_value16 - input_var->min_value16) + - (input_var->max_value16 - input_var->end_value16); - direction_decrement = ZB_TRUE; - } - else - // end_value16 <= current_value16 => overlap MAX value - { - diff = (input_var->max_value16 - input_var->current_value16) + - (input_var->end_value16 - input_var->min_value16); - direction_decrement = ZB_FALSE; - } - } - else - { - diff = ZB_ABS((zb_int32_t)input_var->end_value16 - input_var->current_value16); - direction_decrement = (zb_bool_t)(input_var->end_value16 < input_var->current_value16); - } - TRACE_MSG(TRACE_ZCL1, "diff = %i", (FMT__H, diff)); - - if (diff != 0) - { - if (input_var->transition_time == ZB_ZCL_CVC_TRANSITION_TIME_AS_FAST_AS_ABLE || - input_var->transition_time == ZB_ZCL_CVC_TRANSITION_TIME_MINIMAL) - { - TRACE_MSG(TRACE_ZCL1, "transition_time is 0xffff or 0x0001", (FMT__0)); - change_variables->steps_number = 1; - change_variables->delta_time_q = 1; - } - else - { - transition_time_q = input_var->transition_time * ZB_ZCL_CVC_TRANSITION_TIME_UNIT_IN_QUANTS; - change_variables->transition_time_q = 0; - /* 7. */ -/* 01/02/2013 - I don't understood this comparison. - What they are compared for? - - 05/02/2013 steps_number = min(diff*TRANSITION_TIME_UNITS, transition_time) - Its needed for calculations. -*/ - - /* Each step can be executed with the fastest time of - * ZB_ZCL_CVC_TRANSITION_TIMER_QUANT_MS. Transition time is - * calculated in units of 0.1 sec, that's why multiplication - * is needed */ - if (transition_time_q > diff) - { - /* If transition time */ - change_variables->steps_number = diff; - } - else - { - change_variables->steps_number = transition_time_q; - } - - TRACE_MSG(TRACE_ERROR, "steps_number = %d", (FMT__D, change_variables->steps_number)); - - if (change_variables->steps_number > 1) - { - change_variables->delta_time_q = transition_time_q / change_variables->steps_number; - } - else - { - change_variables->delta_time_q = transition_time_q; - } - - TRACE_MSG(TRACE_ERROR, - "delta_time_q = %d", - (FMT__D, change_variables->delta_time_q)); - -/* 8. */ - if (change_variables->steps_number > 1) - { - change_variables->delta_value16 = diff / change_variables->steps_number; - } - else - { - change_variables->delta_value16 = diff; - } - - TRACE_MSG(TRACE_ERROR, "delta_value = %d", (FMT__D, change_variables->delta_value16)); - -/* 9. */ -/* 10. */ -/* 11. */ - if (direction_decrement == ZB_TRUE) - { - change_variables->delta_value16 = -change_variables->delta_value16; - } - -/* 12. */ - change_variables->end_time_tu = - (ZB_ZCL_CVC_GET_TIME_IN_UNITS() + input_var->transition_time); - - TRACE_MSG(TRACE_ERROR, - "end_time_tu = %d", - (FMT__D, change_variables->end_time_tu)); - } - } - else - { - change_variables->steps_number = 0; -// change_variables->transition_time_q = 0; -// change_variables->input_var.transition_time = ZB_ZCL_CVC_TRANSITION_TIME_AS_FAST_AS_ABLE; - - } -#endif - ret = buf; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_cvc_calc", (FMT__0)); - - return ret; -} - - -zb_uint8_t zb_zcl_cvc_calculate_transition_values(zb_zcl_cvc_input_variables_t* input_var) -{ - return zb_zcl_cvc_calc(input_var, 0, ZB_FALSE); -} - -#define ZB_ZCL_CVC_RECALC_TRANSITION_VALUES(buf_id) \ - zb_zcl_cvc_calc( \ - NULL, \ - buf_id, \ - ZB_TRUE); - - -void zb_zcl_cvc_correct_value(zb_zcl_cvc_input_variables_t* input_var) -{ - if (input_var->end_value16 > input_var->max_value16) - { - input_var->end_value16 = input_var->max_value16; - } - else if (input_var->end_value16 < input_var->min_value16) - { - input_var->end_value16 = input_var->min_value16; - } - -} - -/*! Returns slot number of the reporting info */ -static zb_uint8_t zb_zcl_cvc_get_alarm_id(zb_zcl_cvc_alarm_variables_t *alarm_var) -{ - zb_uindex_t i = 0xff; - zb_uint8_t alarm_id = 0; - - if (alarm_var && ZCL_CTX().device_ctx) - { - for (i = 0; i < ZCL_CTX().device_ctx->ep_count; i++) - { - if (alarm_var->endpoint_id != ZCL_CTX().device_ctx->ep_desc_list[i]->ep_id) - { - alarm_id += ZB_ZCL_MAX_CVC_SLOTS_BY_EP; - } - else - { - alarm_id += alarm_var - ZCL_CTX().device_ctx->ep_desc_list[i]->cvc_alarm_info; - break; - } - } - } - - return (i < ZCL_CTX().device_ctx->ep_count) ? alarm_id : ZB_ZCL_CVC_INVALID_ALARM_ID; -} - -/*! Returns reporting info that is stored in slot with specified number */ -static zb_zcl_cvc_alarm_variables_t *zb_zcl_cvc_get_alarm_variables(zb_uint8_t alarm_id) -{ - zb_uindex_t i; - - if (alarm_id != ZB_ZCL_CVC_INVALID_ALARM_ID && ZCL_CTX().device_ctx) - { - for (i = 0; i < ZCL_CTX().device_ctx->ep_count; i++) - { - if (alarm_id >= ZB_ZCL_MAX_CVC_SLOTS_BY_EP) - { - alarm_id -= ZB_ZCL_MAX_CVC_SLOTS_BY_EP; - } - else - { - return (zb_zcl_cvc_alarm_variables_t *)(ZCL_CTX().device_ctx->ep_desc_list[i]->cvc_alarm_info + alarm_id); - } - } - } - - return NULL; -} - -static void zb_zcl_cvc_next_step_alarm(zb_uint8_t alarm_id) -{ - zb_zcl_cvc_variables_t* change_var; - zb_zcl_cvc_alarm_variables_t* alarm_var; - zb_time_t curr_time_tu; - zb_time_t next_alarm = 0; - zb_int32_t tmp; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_cvc_next_step_alarm alarm_id %i", (FMT__H, alarm_id)); - -/* 1. Get variables from buffer. */ - - if (ZCL_CTX().device_ctx != NULL) - { - alarm_var = zb_zcl_cvc_get_alarm_variables(alarm_id); - if (alarm_var != NULL) - { - change_var = ZB_BUF_GET_PARAM(alarm_var->alarm_buf_id, zb_zcl_cvc_variables_t); - - /* 2. Time calculation part */ - - curr_time_tu = ZB_ZCL_CVC_GET_TIME_IN_UNITS(); - - TRACE_MSG(TRACE_ZCL1, "curr_time_tu = %ld", (FMT__L, curr_time_tu)); - TRACE_MSG(TRACE_ZCL1, "transition_time = %d", (FMT__D, change_var->input_var.transition_time)); - TRACE_MSG(TRACE_ZCL1, "end_time_tu = %d", (FMT__D, change_var->end_time_tu)); - TRACE_MSG(TRACE_ZCL1, "delta_time_q = %d", (FMT__D, change_var->delta_time_q)); - TRACE_MSG(TRACE_ZCL1, "delta_value16 = %d", (FMT__D, change_var->delta_value16)); - TRACE_MSG(TRACE_ZCL1, "steps_number = %d", (FMT__D, change_var->steps_number)); - TRACE_MSG(TRACE_ZCL1, "current_value16 = %d", (FMT__D, change_var->input_var.current_value16)); - - /* Check if recalc needed (in bigger or smaller side). If error is bigger than - move_variables->err value, all move variables will be corrected (with - new transition_time). */ - - if (change_var->input_var.transition_time != ZB_ZCL_CVC_TRANSITION_TIME_AS_FAST_AS_ABLE && - change_var->input_var.transition_time != ZB_ZCL_CVC_TRANSITION_TIME_MINIMAL) - { - /* Check if end_time has already passed. */ - if ((change_var->end_time_tu + ZB_ZCL_CVC_TRANSITION_TIME_ERROR_TU) > curr_time_tu) - { - /* Planned end time */ - zb_uint32_t tmp_val_tu = curr_time_tu + change_var->input_var.transition_time - change_var->delta_time_q / ZB_ZCL_CVC_TRANSITION_TIME_UNIT_IN_QUANTS; - - /* Difference between planned end time and initial end time */ - if (tmp_val_tu > change_var->end_time_tu) - { - tmp_val_tu -= change_var->end_time_tu; - } - else - { - tmp_val_tu = change_var->end_time_tu - tmp_val_tu; - } - - if (tmp_val_tu > ZB_ZCL_CVC_TRANSITION_TIME_ERROR_TU) - { - TRACE_MSG(TRACE_ZCL1, "recalc", (FMT__0)); - - if (change_var->end_time_tu > curr_time_tu) - { - /* (change_var->end_time_tu - curr_time_tu) < ZB_ZCL_CVC_TRANSITION_TIME_ERROR_TU */ - tmp_val_tu = change_var->end_time_tu - curr_time_tu; - } - else - { - tmp_val_tu = curr_time_tu - change_var->end_time_tu; - } - - change_var->input_var.transition_time = tmp_val_tu; - change_var->transition_time_q = 0; - TRACE_MSG(TRACE_ZCL1, "new transition_time = %d", (FMT__D, change_var->input_var.transition_time)); - - ZB_ZCL_CVC_RECALC_TRANSITION_VALUES(alarm_var->alarm_buf_id); - } - else - { - change_var->input_var.transition_time -= change_var->delta_time_q / ZB_ZCL_CVC_TRANSITION_TIME_UNIT_IN_QUANTS; - - if (change_var->transition_time_q < (change_var->delta_time_q % ZB_ZCL_CVC_TRANSITION_TIME_UNIT_IN_QUANTS)) - { - change_var->input_var.transition_time--; - change_var->transition_time_q += ZB_ZCL_CVC_TRANSITION_TIME_UNIT_IN_QUANTS; - } - - change_var->transition_time_q -= change_var->delta_time_q % ZB_ZCL_CVC_TRANSITION_TIME_UNIT_IN_QUANTS; - } - } - else - { - /* curr_time is greater then end_time_tu of all transition - go to last step */ - change_var->steps_number = 1; - } - } - - /* Time calculation part ended */ - - if (change_var->steps_number != 0) - { - - /* step_number == 1 means the LAST step */ - if (change_var->steps_number == 1) - { - change_var->input_var.current_value16 = change_var->input_var.end_value16; - } - else - { -//TODO: overlap - tmp = change_var->input_var.current_value16 + change_var->delta_value16; - - TRACE_MSG(TRACE_ZCL1, "tmp = %d", (FMT__D, tmp)); - - if (tmp >= change_var->input_var.min_value16 && - tmp <= change_var->input_var.max_value16) - { - change_var->input_var.current_value16 = tmp; - } - else - { - if (tmp < change_var->input_var.min_value16) - { - change_var->input_var.current_value16 = change_var->input_var.max_value16 - - ZB_ABS((zb_int32_t)change_var->input_var.min_value16 - tmp) + 1; - } - else - { - change_var->input_var.current_value16 = change_var->input_var.min_value16 + - ZB_ABS((zb_int32_t)tmp - change_var->input_var.max_value16) - 1; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "next level is %d", (FMT__D, change_var->input_var.current_value16)); - - if (change_var->input_var.value_set_func != NULL) - { - zb_uint16_t remaining_time = 0; - - if (change_var->steps_number > 1) - { - remaining_time = change_var->input_var.transition_time; - } - change_var->input_var.value_set_func(alarm_var->endpoint_id, &(change_var->input_var.current_value16), remaining_time); - } - } - - if (change_var->steps_number > 1) - { -/* Checking if time incrmenting is needed */ - next_alarm = change_var->delta_time_q; - ZB_SCHEDULE_ALARM(zb_zcl_cvc_next_step_alarm, - alarm_id, - ZB_ZCL_CVC_TRANSITION_TIMER_QUANT_TO_BE(next_alarm)); - } - else - { - TRACE_MSG(TRACE_ZCL1, "transition with alarm_id %i finished", (FMT__H, alarm_id)); - ZB_SCHEDULE_CALLBACK(change_var->input_var.after_processing_cb, alarm_var->endpoint_id); - alarm_var->is_used = ZB_FALSE; - zb_buf_free(alarm_var->alarm_buf_id); - } -/* - if (change_var->input_var.current_value16 >= 20 && - change_var->input_var.current_value16 <= 50) - { - TRACE_MSG(TRACE_ZCL1, "sleep!", (FMT__0)); - sleep(1); - } -*/ - if (change_var->steps_number > 0U) - { - --(change_var->steps_number); - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_cvc_next_step_alarm", (FMT__0)); -} - - -/** @internal @brief Init alarm info data */ -void zb_zcl_init_cvc_alarm_info() -{ - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_init_cvc_alarm_info", (FMT__0)); - - if (ZCL_CTX().device_ctx != NULL) - { - zb_uindex_t i; - - for (i = 0; i < ZCL_CTX().device_ctx->ep_count; i++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[i]->cvc_alarm_info != NULL) - { - ZB_BZERO(ZCL_CTX().device_ctx->ep_desc_list[i]->cvc_alarm_info, - sizeof(zb_zcl_cvc_alarm_variables_t) * ZCL_CTX().device_ctx->ep_desc_list[i]->cvc_alarm_count); - } - } - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_init_cvc_alarm_info", (FMT__0)); -} - -zb_uint8_t zb_zcl_cvc_check_transition_running( - zb_uint8_t endpoint_id, - zb_uint16_t cluster_id, - zb_uint16_t attribute_id) -{ - zb_zcl_cvc_alarm_variables_t* alarm_info; - zb_zcl_cvc_alarm_variables_t alarm_var; - zb_uindex_t i, j; - zb_uint8_t ret = ZB_ZCL_CVC_INVALID_ALARM_ID; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_cvc_check_transition_running, ep %hd, cluster %d, attr_id %d", - (FMT__H_D_D, endpoint_id, cluster_id, attribute_id)); - - alarm_var.endpoint_id = endpoint_id; - alarm_var.cluster_id = cluster_id; - alarm_var.attribute_id = attribute_id; - alarm_var.is_used = ZB_TRUE; - - if (ZCL_CTX().device_ctx != NULL) - { - for (j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[j]->ep_id == endpoint_id) - { - alarm_info = ZCL_CTX().device_ctx->ep_desc_list[j]->cvc_alarm_info; - for (i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->cvc_alarm_count; i++) - { - if (alarm_info->endpoint_id == alarm_var.endpoint_id && - alarm_info->cluster_id == alarm_var.cluster_id && - alarm_info->attribute_id == alarm_var.attribute_id && - alarm_info->is_used == ZB_TRUE) - { - ret = zb_zcl_cvc_get_alarm_id(alarm_info); - break; - } - alarm_info++; - } - } - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_cvc_check_transition_running ret %i", (FMT__H, ret)); - return ret; -} - -zb_uint8_t zb_zcl_cvc_stop_transition(zb_uint8_t alarm_id) -{ - zb_uint8_t old_buf_id = ZB_UNDEFINED_BUFFER; - zb_bufid_t alarm_buf; - zb_zcl_cvc_alarm_variables_t* alarm_info; - zb_zcl_cvc_variables_t* change_var; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_cvc_stop_transition, alarm_id %i", - (FMT__H, alarm_id)); - if (ZCL_CTX().device_ctx != NULL) - { - alarm_info = zb_zcl_cvc_get_alarm_variables(alarm_id); - - if (alarm_info && alarm_info->is_used) - { - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_cvc_next_step_alarm, alarm_id); - - alarm_buf = alarm_info->alarm_buf_id; - change_var = ZB_BUF_GET_PARAM(alarm_buf, zb_zcl_cvc_variables_t); - old_buf_id = change_var->input_var.buf_id; - - zb_buf_free(alarm_buf); - alarm_info->is_used = ZB_FALSE; - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_cvc_stop_transition", (FMT__0)); - return old_buf_id; -} - - -zb_uint8_t zb_zcl_cvc_start_alarm(zb_uint8_t endpoint_id, - zb_uint16_t cluster_id, - zb_uint16_t attribute_id, - zb_uint8_t alarm_buf_id) -{ - zb_uint8_t alarm_id; - zb_zcl_cvc_alarm_variables_t* alarm_info; - zb_uindex_t i = 0, j = 0; - zb_uint16_t ret = ZB_ZCL_CVC_INVALID_ALARM_ID; - zb_bool_t next_step = ZB_TRUE; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_cvc_start_alarm", (FMT__0)); - -/* 01/02/2013 CR:MAJOR - Use ASSERT for all cases when context is broken/NULL - And t.b.h. I'm not sure that this check is usefull at all. Because it can be - done once and after I doubt that it's really needed for any purpose except code size increasing. - If it's overlapped somehow - it's a zero chance that it became zero. Most likely it will take - some unapropriate value and will cause segmentation fault (or any prot.error) even if it pass - NULL-check - - 05/02/2013 OK, i can remove them if you think its useless. I was look on reporting when - adding it. -*/ - if (ZCL_CTX().device_ctx != NULL) - { - for (j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[j]->ep_id == endpoint_id) - { - alarm_info = ZCL_CTX().device_ctx->ep_desc_list[j]->cvc_alarm_info; - - if (alarm_info == NULL) - { - TRACE_MSG(TRACE_ERROR, "Continuous value change alarm slot is NULL for ep %hd, cluster %d, attr_id %d", - (FMT__H_D_D, endpoint_id, cluster_id, attribute_id)); - continue; - } - - TRACE_MSG(TRACE_ZCL1, "ZCL_CTX().device_ctx && ZCL_CTX().device_ctx->cvc_alarm_info", (FMT__0)); - alarm_id = zb_zcl_cvc_check_transition_running(endpoint_id, - cluster_id, - attribute_id); - if (alarm_id != ZB_ZCL_CVC_INVALID_ALARM_ID) - { - zb_zcl_cvc_stop_transition(alarm_id); - alarm_info = zb_zcl_cvc_get_alarm_variables(alarm_id); - } - else - { -/* We run zb_zcl_cvc_check_transition_running() for check. If other transition - is in progress (alarm_id != ZB_ZCL_CVC_INVALID_ALARM_ID), we dont need to search and - can use its alarm_info. Else we need to check, is there any free alarm_info's (while - (alarm_info->is_used == ZB_TRUE) go to next alarm_info). If alarm_id >= - ZCL_CTX().device_ctx->cvc_alarm_count, we checked all list and didn't - found free alarm_info (need to exit with INVALID_ALARM_ID return), else - use founded alarm_info - and start alarm. -*/ - i = 0; - while (alarm_info->is_used == ZB_TRUE) - { - ++i; - /* to prevent infinite loop */ - if (i >= ZCL_CTX().device_ctx->ep_desc_list[j]->cvc_alarm_count) - { - /* there are no free alarms */ - break; - } - else - { - ++alarm_info; - } - } - - if (i >= ZCL_CTX().device_ctx->ep_desc_list[j]->cvc_alarm_count) - { - TRACE_MSG(TRACE_ZCL1, "(i >= ZCL_CTX().device_ctx->cvc_alarm_count", (FMT__0)); - next_step = ZB_FALSE; - } - else - { - /* Set endpoint_id here to be able to find back alarm_id (next call) */ - alarm_info->endpoint_id = endpoint_id; - alarm_id = zb_zcl_cvc_get_alarm_id(alarm_info); - } - } - - TRACE_MSG(TRACE_ZCL1, "next_step %i", (FMT__H, next_step)); - - if (next_step == ZB_TRUE) - { - zb_zcl_cvc_variables_t* change_var; - - TRACE_MSG(TRACE_ZCL1, "alarm_info found, id %i", (FMT__H, alarm_id)); - - ret = alarm_id; - - alarm_info->endpoint_id = endpoint_id; - alarm_info->cluster_id = cluster_id; - alarm_info->attribute_id = attribute_id; - alarm_info->alarm_buf_id = alarm_buf_id; - alarm_info->is_used = ZB_TRUE; - - change_var = ZB_BUF_GET_PARAM(alarm_info->alarm_buf_id, zb_zcl_cvc_variables_t); - - //scheduling - switch (change_var->steps_number) - { - case 0: - /* Can not call after_processing_cb immediately - let's do 1 iteration. */ - ZB_SCHEDULE_ALARM(zb_zcl_cvc_next_step_alarm, - alarm_id, - ZB_ZCL_CVC_TRANSITION_TIMER_QUANT_TO_BE(ZB_ZCL_CVC_TRANSITION_TIME_MINIMAL)); - break; - - case 1: - { - zb_uint16_t next_alarm; - - if (change_var->input_var.transition_time == ZB_ZCL_CVC_TRANSITION_TIME_AS_FAST_AS_ABLE) - { -/* - Why should it wait for the "minimal" interval when it's said as_fast_as_able? - - 05/02/2013 It was our agreement that as_fast_as_able == at 1 minimal transition time unit. -*/ - next_alarm = ZB_ZCL_CVC_TRANSITION_TIME_MINIMAL; - } - else - { - next_alarm = change_var->delta_time_q; - } - - ZB_SCHEDULE_ALARM(zb_zcl_cvc_next_step_alarm, - alarm_id, - ZB_ZCL_CVC_TRANSITION_TIMER_QUANT_TO_BE(next_alarm)); - } - break; - - default: - ZB_SCHEDULE_CALLBACK(zb_zcl_cvc_next_step_alarm, alarm_id); - break; - } - } - } - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_cvc_start_alarm", (FMT__0)); - return ret; -} - -zb_uint16_t zb_zcl_cvc_get_remaining_time(zb_uint8_t alarm_id) -{ - zb_zcl_cvc_alarm_variables_t* alarm_info; - zb_uint16_t ret = ZB_ZCL_CVC_INVALID_REMAINING_TIME; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_cvc_get_remaining_time alarm_id %i", (FMT__H, alarm_id)); - - if (ZCL_CTX().device_ctx != NULL) - { - alarm_info = zb_zcl_cvc_get_alarm_variables(alarm_id); - - if (alarm_info && alarm_info->is_used) - { - zb_zcl_cvc_variables_t* change_var = - ZB_BUF_GET_PARAM(alarm_info->alarm_buf_id, zb_zcl_cvc_variables_t); - - ret = change_var->input_var.transition_time; - } - } - - return ret; -} -#endif /* defined ZB_CVC_FEATURE_SUPPORT */ diff --git a/zboss/development/src/zcl/zcl_control4_networking.c b/zboss/development/src/zcl/zcl_control4_networking.c deleted file mode 100644 index 6a124af1c5..0000000000 --- a/zboss/development/src/zcl/zcl_control4_networking.c +++ /dev/null @@ -1,773 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Control4 Network Cluster cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2100 - -#include "zb_common.h" - -#if defined ZB_CONTROL4_NETWORK_SUPPORT - -#include "zb_zcl.h" -#include "zcl/zb_zcl_control4_networking.h" -#include "zb_zdo.h" -#include "zb_aps.h" - -/** Global variable stored the cluster current state */ -static zb_zcl_control4_network_state_t g_c4_network_cluster_state = ZB_ZCL_CONTROL4_NETWORK_STATE_IDLE; - -/** Get Control4 Network Cluster state */ -#define ZB_ZCL_CONTROL4_NETWORK_GET_STATE() (g_c4_network_cluster_state) - -/** Get Control4 Network Cluster state */ -#define ZB_ZCL_CONTROL4_NETWORK_SET_STATE(state) (g_c4_network_cluster_state = state) - -/** Check if Control4 Network Cluster is stopped or not */ -#define ZB_ZCL_CONTROL4_NETWORK_IS_STOPPED() (g_c4_network_cluster_state == ZB_ZCL_CONTROL4_NETWORK_STATE_IDLE || \ - g_c4_network_cluster_state == ZB_ZCL_CONTROL4_NETWORK_STATE_STOPPED) - -/** Check if Control4 Network Cluster is running or not */ -#define ZB_ZCL_CONTROL4_NETWORK_IS_RUNNING() (g_c4_network_cluster_state == ZB_ZCL_CONTROL4_NETWORK_STATE_RUNNING) - -/** Check if Control4 Network Cluster is searching for ZAP or not */ -#define ZB_ZCL_CONTROL4_NETWORK_IS_SEARCHING_ZAP() (g_c4_network_cluster_state == ZB_ZCL_CONTROL4_NETWORK_STATE_SEARCHING_ZAP) - -/** Check if Control4 Network is permitted or not */ -#ifdef ZB_ED_FUNC -#define ZB_ZCL_CONTROL4_NETWORK_IS_PERMITTED() (zb_control4_network_permitted()) -#else -#define ZB_ZCL_CONTROL4_NETWORK_IS_PERMITTED() (0) -#endif /* ZB_ED_FUNC */ - -/* Read ZAP Info timeout (in sec) */ -#define ZB_ZCL_CONTROL4_NETWORK_READ_ZAP_INFO_TIMEOUT 30 - -zb_ret_t check_value_control4_networking_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -zb_ret_t check_value_control4_networking_client(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_control4_networking_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); -void zb_zcl_control4_networking_write_attr_hook_client(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -zb_bool_t zb_zcl_process_control4_networking_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_control4_networking_specific_commands_cli(zb_uint8_t param); - -static void zb_zcl_control4_network_cluster_identify(zb_bufid_t buffer); -static void zb_zcl_control4_network_cluster_announce(zb_bufid_t buffer); -static void zb_zcl_control4_network_cluster_quiry_zap_info(zb_bufid_t buffer); - -static const zb_uint16_t control4_network_report_attr[] = -{ - /* TODO: add optional attributes to reporting */ - ZB_ZCL_ATTR_CONTROL4_NETWORKING_DEVICE_TYPE_ID, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_PRODUCT_STRING_ID, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_FIRMWARE_VERSION_ID, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_REFLASH_VERSION_ID, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_BOOT_COUNT_ID, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_MESH_CHANNEL_ID, -}; - -zb_uint8_t gs_control4_networking_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_control4_networking_client_cmd_list = -{ - 0, NULL, - sizeof(gs_control4_networking_server_received_commands), gs_control4_networking_server_received_commands -}; - -zb_discover_cmd_list_t gs_control4_networking_server_cmd_list = -{ - sizeof(gs_control4_networking_server_received_commands), gs_control4_networking_server_received_commands, - 0, NULL -}; - -void zb_zcl_control4_networking_init_server() -{ - zb_zcl_add_control4_cluster_handlers(ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_control4_networking_server, - zb_zcl_control4_networking_write_attr_hook_server, - zb_zcl_process_control4_networking_specific_commands_srv); -} - -void zb_zcl_control4_networking_init_client() -{ - zb_zcl_add_control4_cluster_handlers(ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - NULL, NULL, - zb_zcl_process_control4_networking_specific_commands_cli); -} - -zb_ret_t check_value_control4_networking_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - - ZVUNUSED(endpoint); - switch(attr_id) - { - case ZB_ZCL_ATTR_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_ID: - ret = (ZB_ZCL_ATTR_GET16(value) < ZB_ZCL_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_MIN_VALUE) ? RET_ERROR : RET_OK; - break; - case ZB_ZCL_ATTR_CONTROL4_NETWORKING_MTORR_PERIOD_ID: - ret = (ZB_ZCL_ATTR_GET16(value) < ZB_ZCL_CONTROL4_NETWORKING_MTORR_PERIOD_MIN_VALUE) ? RET_ERROR : RET_OK; - break; - case ZB_ZCL_ATTR_CONTROL4_NETWORKING_MESH_CHANNEL_ID: - ret = (*value < ZB_ZCL_CONTROL4_NETWORKING_MESH_CHANNEL_MIN_VALUE || - *value > ZB_ZCL_CONTROL4_NETWORKING_MESH_CHANNEL_MAX_VALUE) ? RET_ERROR : RET_OK; - break; - } - - return ret; -} - -/** - Notify user application of ZAP (Zigbee Access Point) discovery event - - Possible events defined in zb_zcl_control4_zap_discover_event_t: - ZB_ZCL_CONTROL4_NETWORK_ZAP_UPDATED - ZAP details are updated - ZB_ZCL_CONTROL4_NETWORK_ZAP_DISCOVER_RETRYING - Retrying during searching ZAP state - ZB_ZCL_CONTROL4_NETWORK_ZAP_DISCOVER_FAILED - ZAP Discover failed (Retrying attempts expired) - - @param buffer - buffer id - @param event - ZAP discovery event (zb_zcl_control4_zap_discover_event_t) - */ - -static void zb_zcl_control4_networking_zap_info_notify_user_app(zb_bufid_t buffer, zb_uint16_t event) -{ - static zb_bool_t is_scheduled = ZB_FALSE; - - if (!buffer) - { - if (!is_scheduled) - { - is_scheduled = ZB_TRUE; - zb_buf_get_out_delayed_ext(zb_zcl_control4_networking_zap_info_notify_user_app, event, 0); - } - } - else - { - if (ZCL_CTX().device_cb) - { - zb_zcl_control4_zap_info_notify_t notification = {.event = (zb_zcl_control4_zap_discover_event_t )event}; - - TRACE_MSG(TRACE_ZCL1, "zb_zcl_control4_networking_zap_info_notify_user_app event=%hd", (FMT__H, event)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(buffer, ZB_ZCL_CONTROL4_NETWORK_ZAP_INFO_CB_ID, - RET_OK, NULL, ¬ification, NULL); - - (ZCL_CTX().device_cb)(buffer); - } - - is_scheduled = ZB_FALSE; - zb_buf_free(buffer); - } -} - -void zb_zcl_control4_networking_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value) -{ - zb_zcl_attr_t* attr_desc; - - ZVUNUSED(endpoint); - ZVUNUSED(attr_id); - ZVUNUSED(new_value); - - /* TODO: handle other writable attributes */ - - if (attr_id == ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_ID) - { - attr_desc = zb_zcl_get_attr_desc_a(ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - attr_id); - if (attr_desc) - { - /* Check if ZAP Node ID changed */ - if (ZB_ZCL_ATTR_GET16(new_value) != ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) && - ZB_ZCL_ATTR_GET16(new_value) != ZB_ZCL_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_DEF_VALUE) - { - /* invoke user app */ - zb_zcl_control4_networking_zap_info_notify_user_app(0, ZB_ZCL_CONTROL4_NETWORK_ZAP_UPDATED); - } - } - } - else if (attr_id == ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_ID) - { - zb_ieee_addr_t default_ap_long_id = ZB_ZCL_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_DEF_VALUE; - - attr_desc = zb_zcl_get_attr_desc_a(ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - attr_id); - if (attr_desc) - { - /* Check if ZAP Long ID changed */ - if (!ZB_IEEE_ADDR_CMP(new_value, attr_desc->data_p) && - !ZB_IEEE_ADDR_CMP(new_value, default_ap_long_id)) - { - /* invoke user app */ - zb_zcl_control4_networking_zap_info_notify_user_app(0, ZB_ZCL_CONTROL4_NETWORK_ZAP_UPDATED); - } - } - } -} - -static zb_zcl_status_t zb_zcl_control4_networking_map_ret_code_to_zcl_status(zb_ret_t ret_code) -{ - zb_zcl_status_t status; - - ZB_ASSERT(ret_code != RET_BUSY); - - switch (ret_code) - { - case RET_OK: - status = ZB_ZCL_STATUS_SUCCESS; - break; - case RET_INVALID_PARAMETER_1: - status = ZB_ZCL_STATUS_INVALID_FIELD; - break; - case RET_INVALID_PARAMETER: - status = ZB_ZCL_STATUS_INVALID_VALUE; - break; - case RET_ERROR: - status = ZB_ZCL_STATUS_FAIL; - break; - default: - status = ZB_ZCL_STATUS_FAIL; - break; - } - - return status; -} - -static zb_ret_t zb_zcl_process_control4_networking_immediate_announce_handler(zb_uint8_t param) -{ - zb_uint8_t *ptr; - zb_uint8_t length, i; - zb_uint16_t addr; - zb_ret_t ret = RET_ERROR; - - if (!ZB_ZCL_CONTROL4_NETWORK_IS_STOPPED()) - { - if (zb_buf_len(param) == 0) - { - /* Command received without payload */ - zb_zcl_control4_network_cluster_announce(param); - param = 0; - } - else - { - /* Command received with payload */ - ptr = (zb_uint8_t *)zb_buf_begin(param); - length = *ptr++; - - if (zb_buf_len(param) == (length * sizeof(zb_uint16_t) + sizeof(zb_uint8_t))) - { - for (i = 0; i < length; ++i) - { - ZB_HTOLE16(&addr, ptr); - ptr += sizeof(zb_uint16_t); - - if (addr == zb_get_short_address()) - { - /* Found self address in the command payload */ - zb_zcl_control4_network_cluster_announce(param); - param = 0; - break; - } - } - } - } - - if (param) - { - zb_buf_free(param); - } - - /* Don't send Default response */ - ret = RET_BUSY; - } - - return ret; -} - -zb_bool_t zb_zcl_process_control4_networking_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_control4_networking_specific_commands: param %hd", (FMT__H, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - switch( cmd_info.cmd_id ) - { - case ZB_ZCL_CMD_CONTROL4_NETWORKING_IMMEDIATE_ANNOUNCE_ID: - ret = zb_zcl_process_control4_networking_immediate_announce_handler(param); - break; - default: - processed = ZB_FALSE; - break; - } - - if (processed && ret != RET_BUSY) - { - zb_zcl_send_default_handler(param, &cmd_info, - zb_zcl_control4_networking_map_ret_code_to_zcl_status(ret)); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_control4_networking_specific_commands: processed %hd", (FMT__H, processed)); - - return processed; -} - -zb_bool_t zb_zcl_process_control4_networking_specific_commands_srv(zb_uint8_t param) -{ - if (ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_control4_networking_server_cmd_list; - return ZB_TRUE; - } - - return zb_zcl_process_control4_networking_specific_commands(param); -} - -zb_bool_t zb_zcl_process_control4_networking_specific_commands_cli(zb_uint8_t param) -{ - if (ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_control4_networking_client_cmd_list; - return ZB_TRUE; - } - - return ZB_FALSE; -} - -static void zb_zcl_control4_network_cluster_send_attr_report(zb_bufid_t buffer, zb_uint16_t short_addr) -{ - zb_uint8_t *cmd_data; - zb_zcl_attr_t *attr_desc; - zb_uint16_t bytes_avail; - zb_uint8_t attr_size; - zb_uint32_t i; - /* Keep track of the index of latest attribute reported in case all attributes do not fit in one packet */ - static zb_uint8_t attr_index = 0; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_control4_network_cluster_send_attr_report: addr 0x%x buffer %hd", (FMT__D_H, short_addr, buffer)); - - cmd_data = ZB_ZCL_START_PACKET(buffer); - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_A(cmd_data, ZB_ZCL_FRAME_DIRECTION_TO_CLI, - ZB_FALSE, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(cmd_data, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_REPORT_ATTRIB); - - for (i = attr_index; i < ZB_ARRAY_SIZE(control4_network_report_attr); ++i) - { - attr_desc = zb_zcl_get_attr_desc_a(ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - control4_network_report_attr[i]); - if (attr_desc) - { - bytes_avail = ZB_ZCL_GET_BYTES_AVAILABLE(buffer, - cmd_data, - ZB_AF_CONTROL4_PROFILE_ID, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING); - attr_size = zb_zcl_get_attribute_size(attr_desc->type, attr_desc->data_p); - - /* Decrement read attr response by sizeof(zb_uint8_t), because attr value size is - * calculated separately by attr_size */ - if (bytes_avail >= (sizeof(zb_zcl_report_attr_req_t) - sizeof(zb_uint8_t) + attr_size)) - { - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_data, attr_desc->id); - ZB_ZCL_PACKET_PUT_DATA8(cmd_data, attr_desc->type); - cmd_data = zb_zcl_put_value_to_packet(cmd_data, attr_desc->type, attr_desc->data_p); - attr_index = 0; - } - else - { - attr_index = i; - TRACE_MSG(TRACE_ZCL1, "Attribute reporting will use more than one packet.", (FMT__0)); - break; - } - } - } - - ZB_ZCL_FINISH_N_SEND_PACKET(buffer, - cmd_data, short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_AF_CONTROL4_PROFILE_ID, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - NULL); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_control4_network_cluster_send_attr_report", (FMT__0)); -} - -static void zb_zcl_control4_network_cluster_send_announce(zb_bufid_t buffer) -{ - zb_zcl_attr_t *attr_desc; - zb_uint16_t short_addr; - - if (!ZB_ZCL_CONTROL4_NETWORK_IS_STOPPED()) - { - attr_desc = zb_zcl_get_attr_desc_a(ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_ID); - ZB_ASSERT(attr_desc); - - /* Send Announce to ZAP */ - short_addr = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - if (short_addr == ZB_ZCL_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_DEF_VALUE) - { - /* Send Identify instead of Announce if we don't know ZAP Node ID */ - zb_zcl_control4_network_cluster_identify(buffer); - } - else - { - /* Send Announce */ - zb_zcl_control4_network_cluster_send_attr_report(buffer, short_addr); - } - } - else - { - /* Control4 Network Cluster is not running */ - zb_buf_free(buffer); - } -} - -static void zb_zcl_control4_network_cluster_schedule_announce(void) -{ - zb_zcl_attr_t *attr_desc; - zb_uint16_t announce_window; - - /* Cancel scheduled alarms for Announce */ - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_control4_network_cluster_announce, 0); - - if (ZB_ZCL_CONTROL4_NETWORK_IS_RUNNING()) - { - TRACE_MSG(TRACE_ZCL2, "zb_zcl_control4_network_cluster_schedule_announce", (FMT__0)); - - /* Schedule the next Announce using ANNOUNCE_WINDOW attribute value */ - attr_desc = zb_zcl_get_attr_desc_a(ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_ID); - - /* Calculate timeout value */ - announce_window = (attr_desc ? ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) : ZB_ZCL_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_DEF_VALUE); - announce_window -= ZB_ZCL_CONTROL4_NETWORKING_MTORR_PERIOD_MIN_VALUE; - announce_window = ZB_ZCL_CONTROL4_NETWORKING_MTORR_PERIOD_MIN_VALUE + ZB_RANDOM_VALUE(announce_window); - - ZB_SCHEDULE_ALARM(zb_zcl_control4_network_cluster_announce, 0, - announce_window * ZB_TIME_ONE_SECOND); - } -} - -static void zb_zcl_control4_network_cluster_announce(zb_bufid_t buffer) -{ - if (!buffer) - { - zb_buf_get_out_delayed(zb_zcl_control4_network_cluster_announce); - } - else - { - zb_zcl_control4_network_cluster_send_announce(buffer); - zb_zcl_control4_network_cluster_schedule_announce(); - } -} - -static void zb_zcl_control4_network_cluster_identify(zb_bufid_t buffer) -{ - if (!ZB_ZCL_CONTROL4_NETWORK_IS_STOPPED()) - { - zb_zcl_control4_network_cluster_send_attr_report(buffer, ZB_NWK_BROADCAST_ROUTER_COORDINATOR); - } - else - { - /* Control4 Network Cluster is stopped */ - zb_buf_free(buffer); - } -} - -static void zb_zcl_control4_network_cluster_read_zap_info_status(zb_uint8_t status) -{ - static zb_uint8_t attempts = 0; - - TRACE_MSG(TRACE_ZCL1, "zb_zcl_control4_network_cluster_read_zap_info_status status=%d", (FMT__D, status)); - - if (status == ZB_ZCL_STATUS_SUCCESS) - { - attempts = 0; - } - else if (status == ZB_ZCL_STATUS_FAIL) - { - if (ZB_ZCL_CONTROL4_NETWORK_IS_SEARCHING_ZAP()) - { - if (attempts < ZB_ZCL_CONTROL4_NETWORK_SEARCHING_ZAP_ATTEMPTS) - { - /* Try again obtain ZAP info and send Identify again */ - zb_buf_get_out_delayed(zb_zcl_control4_network_cluster_quiry_zap_info); - zb_buf_get_out_delayed(zb_zcl_control4_network_cluster_identify); - attempts++; - } - else - { - /* Can't obtain ZAP information. Stop the cluster logic */ - attempts = 0; - ZB_ZCL_CONTROL4_NETWORK_SET_STATE(ZB_ZCL_CONTROL4_NETWORK_STATE_STOPPED); - zb_zcl_control4_networking_zap_info_notify_user_app(0, ZB_ZCL_CONTROL4_NETWORK_ZAP_DISCOVER_FAILED); - } - } - } -} - -static void zb_zcl_control4_network_cluster_read_zap_info(zb_bufid_t buffer) -{ - zb_uint8_t *cmd_ptr; - zb_uint8_t ap_node_id; - zb_uint8_t ap_long_id; - zb_uint8_t ap_cost; - zb_uint16_t short_addr; - - if (!ZB_ZCL_CONTROL4_NETWORK_IS_STOPPED()) - { - TRACE_MSG(TRACE_ZCL1, "zb_zcl_control4_network_cluster_read_zap_info: buffer %hd ", (FMT__H, buffer)); - - /* Fill attributes */ - ap_node_id = ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_ID; - ap_long_id = ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_ID; - ap_cost = ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_COST_ID; - - /* Send the request to parent */ - short_addr = zb_nwk_get_parent(); - ZB_ASSERT(short_addr != 0xFFFF); - - ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ((buffer), cmd_ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); - ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, (ap_node_id)); - ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, (ap_long_id)); - ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, (ap_cost)); - ZB_ZCL_GENERAL_SEND_READ_ATTR_REQ((buffer), cmd_ptr, short_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_CONTROL4_NETWORK_ENDPOINT, ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_AF_CONTROL4_PROFILE_ID, ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - NULL); - - ZB_SCHEDULE_ALARM(zb_zcl_control4_network_cluster_read_zap_info_status, ZB_ZCL_STATUS_FAIL, - ZB_ZCL_CONTROL4_NETWORK_READ_ZAP_INFO_TIMEOUT * ZB_TIME_ONE_SECOND); - } - else - { - /* Control4 Network Cluster is stopped */ - zb_buf_free(buffer); - } -} - -static void zb_zcl_control4_network_cluster_schedule_quiry_zap_info(void) -{ - zb_zcl_attr_t *attr_desc; - zb_uint16_t mtorr_period; - - /* Cancel scheduled alarms for Quiry ZAP Info */ - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_control4_network_cluster_quiry_zap_info, 0); - - if (ZB_ZCL_CONTROL4_NETWORK_IS_RUNNING()) - { - TRACE_MSG(TRACE_ZCL2, "zb_zcl_control4_network_cluster_schedule_quiry_zap_info", (FMT__0)); - - /* Schedule the next Quiry ZAP Info using MTORR_PERIOD attribute value */ - attr_desc = zb_zcl_get_attr_desc_a(ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_MTORR_PERIOD_ID); - - /* Calculate timeout value */ - mtorr_period = (attr_desc ? ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) : ZB_ZCL_CONTROL4_NETWORKING_MTORR_PERIOD_DEF_VALUE); - - ZB_SCHEDULE_ALARM(zb_zcl_control4_network_cluster_quiry_zap_info, 0, - mtorr_period * ZB_TIME_ONE_SECOND); - } -} - -static void zb_zcl_control4_network_cluster_quiry_zap_info(zb_bufid_t buffer) -{ - if (!buffer) - { - zb_buf_get_out_delayed(zb_zcl_control4_network_cluster_quiry_zap_info); - } - else - { - zb_zcl_control4_network_cluster_read_zap_info(buffer); - zb_zcl_control4_network_cluster_schedule_quiry_zap_info(); - } -} - -void zb_zcl_control4_network_cluster_read_attr_resp_handler(zb_bufid_t param) -{ - zb_zcl_read_attr_res_t *read_attr_resp = NULL; - zb_bool_t zap_info_received = ZB_FALSE; - - /* Cancel scheduled alarms for Read ZAP Info Fail */ - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_control4_network_cluster_read_zap_info_status, ZB_ALARM_ANY_PARAM); - - if (!ZB_ZCL_CONTROL4_NETWORK_IS_PERMITTED() || - ZB_ZCL_CONTROL4_NETWORK_IS_STOPPED()) - { - /* Control4 Network is not permitted */ - zb_buf_free(param); - return; - } - - TRACE_MSG(TRACE_ZCL1, "zb_zcl_control4_network_cluster_read_attr_resp_handler buffer %hd", (FMT__H, param)); - - do - { - ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES(param, read_attr_resp); - - if (read_attr_resp && read_attr_resp->status == ZB_ZCL_STATUS_SUCCESS) - { - if (read_attr_resp->attr_id == ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_ID) - { - zap_info_received = ZB_TRUE; - ZB_ZCL_SET_ATTRIBUTE(ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_NODE_ID_ID, - (zb_uint8_t* )&read_attr_resp->attr_value, ZB_FALSE); - } - else if (read_attr_resp->attr_id == ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_ID) - { - zap_info_received = ZB_TRUE; - ZB_ZCL_SET_ATTRIBUTE(ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_LONG_ID_ID, - (zb_uint8_t* )&read_attr_resp->attr_value, ZB_FALSE); - } - else if (read_attr_resp->attr_id == ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_COST_ID) - { - ZB_ZCL_SET_ATTRIBUTE(ZB_CONTROL4_NETWORK_ENDPOINT, - ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_CONTROL4_NETWORKING_ACCESS_POINT_COST_ID, - (zb_uint8_t* )&read_attr_resp->attr_value, ZB_FALSE); - } - } - } while (read_attr_resp != NULL); - - if (zap_info_received) - { - zb_zcl_control4_network_cluster_read_zap_info_status(ZB_ZCL_STATUS_SUCCESS); - - if (ZB_ZCL_CONTROL4_NETWORK_IS_SEARCHING_ZAP()) - { - TRACE_MSG(TRACE_ZCL1, "Received ZAP info. Now is running", (FMT__0)); - /* Run the main cluster logic */ - ZB_ZCL_CONTROL4_NETWORK_SET_STATE(ZB_ZCL_CONTROL4_NETWORK_STATE_RUNNING); - ZB_SCHEDULE_ALARM(zb_zcl_control4_network_cluster_announce, 0, - ZB_ZCL_CONTROL4_NETWORKING_ANNOUNCE_WINDOW_MIN_VALUE * ZB_TIME_ONE_SECOND); - zb_zcl_control4_network_cluster_schedule_quiry_zap_info(); - } - } - - zb_buf_free(param); -} - -static void zb_zcl_control4_network_cluster_start_delayed(zb_bufid_t buffer) -{ - ZVUNUSED(buffer); - - /* Start identification process */ - zb_buf_get_out_delayed(zb_zcl_control4_network_cluster_quiry_zap_info); - zb_buf_get_out_delayed(zb_zcl_control4_network_cluster_identify); -} - -zb_ret_t zb_zcl_control4_network_cluster_start(void) -{ - if (!ZB_ZCL_CONTROL4_NETWORK_IS_PERMITTED()) - { - /* Joining Control4 Network is not permitted */ - return RET_UNAUTHORIZED; - } - - if (!ZB_ZCL_CONTROL4_NETWORK_IS_STOPPED()) - { - /* Already started */ - return RET_OK; - } - - TRACE_MSG(TRACE_ZCL1, "zb_zcl_control4_network_cluster_start", (FMT__0)); - - /* Start Control4 Network cluster with random jitter delay */ - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_control4_network_cluster_start_delayed, 0); - ZB_SCHEDULE_ALARM(zb_zcl_control4_network_cluster_start_delayed, 0, ZB_RANDOM_VALUE(ZB_TIME_ONE_SECOND)); - ZB_ZCL_CONTROL4_NETWORK_SET_STATE(ZB_ZCL_CONTROL4_NETWORK_STATE_SEARCHING_ZAP); - - return RET_OK; -} - -void zb_zcl_control4_network_cluster_stop(void) -{ - if (!ZB_ZCL_CONTROL4_NETWORK_IS_STOPPED()) - { - TRACE_MSG(TRACE_ZCL1, "zb_zcl_control4_network_cluster_stop", (FMT__0)); - - /* Stop all cluster logic */ - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_control4_network_cluster_start_delayed, 0); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_control4_network_cluster_announce, 0); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_control4_network_cluster_quiry_zap_info, 0); - ZB_ZCL_CONTROL4_NETWORK_SET_STATE(ZB_ZCL_CONTROL4_NETWORK_STATE_STOPPED); - } -} - -zb_zcl_control4_network_state_t zb_zcl_control4_network_cluster_get_state(void) -{ - return ZB_ZCL_CONTROL4_NETWORK_GET_STATE(); -} - -#endif /* ZB_SUPPORT_CLUSTER_CONTROL4_NETWORKING */ diff --git a/zboss/development/src/zcl/zcl_dehumid_control.c b/zboss/development/src/zcl/zcl_dehumid_control.c deleted file mode 100644 index bc7f5953ef..0000000000 --- a/zboss/development/src/zcl/zcl_dehumid_control.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#define ZB_TRACE_FILE_ID 76 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_DEHUMIDIFICATION_CONTROL) - -zb_ret_t check_value_dehumidification_control_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_dehumidification_control_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_DEHUMID_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_dehumidification_control_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_dehumidification_control_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_DEHUMID_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_dehumidification_control_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = ZB_TRUE; - - switch( attr_id ) - { - case ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_COOLING_ID: - { - zb_zcl_attr_t *attr_desc; - - ret = RET_ERROR; - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_DEHUMID_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_ID); - if ( attr_desc != NULL ) - { - zb_uint8_t max_value = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - ret = (*value <= max_value) ? RET_OK : RET_ERROR; - } - } - break; - case ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_RHDEHUMIDIFICATION_SETPOINT_ID: - ret = (*value >= ZB_ZCL_DEHUMIDIFICATION_CONTROL_RHDEHUMIDIFICATION_SETPOINT_MIN_VALUE && - *value <= ZB_ZCL_DEHUMIDIFICATION_CONTROL_RHDEHUMIDIFICATION_SETPOINT_MAX_VALUE) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_HYSTERESIS_ID: - ret = (*value >= ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_HYSTERESIS_MIN_VALUE && - *value <= ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_HYSTERESIS_MAX_VALUE) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_ID: - ret = (*value >= ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_MIN_VALUE && - *value <= ZB_ZCL_DEHUMIDIFICATION_CONTROL_DEHUMIDIFICATION_MAX_COOL_MAX_VALUE) ? RET_OK : RET_ERROR; - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_fan_control ret %hd", (FMT__H, ret)); - return ret; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_DEHUMIDIFICATION_CONTROL */ diff --git a/zboss/development/src/zcl/zcl_diagnostics_commands.c b/zboss/development/src/zcl/zcl_diagnostics_commands.c deleted file mode 100644 index 9fe3927a96..0000000000 --- a/zboss/development/src/zcl/zcl_diagnostics_commands.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Diagnostics cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2065 - -#include "zb_common.h" - -#if defined(ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS) - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_diagnostics.h" -#include "zdo_diagnostics.h" - -/** @internal - @{ -*/ - -zb_zcl_diagnostics_ctx_t diagnostics_ctx_zcl; - -zb_ret_t check_value_diagnostics_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_diagnostics_init_server() -{ - ZB_BZERO(&diagnostics_ctx_zcl.mac_data, sizeof(zb_mac_diagnostic_info_t)); - ZB_BZERO(&diagnostics_ctx_zcl.zdo_data, sizeof(zdo_diagnostics_info_t)); - - diagnostics_ctx_zcl.sync_data_cb = NULL; - diagnostics_ctx_zcl.cb_param = 0; - - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_DIAGNOSTICS, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_diagnostics_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_diagnostics_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_DIAGNOSTICS, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -static void zb_zcl_diagnostics_sync_counters_cb(zb_uint8_t param) -{ - zdo_diagnostics_full_stats_t *full_stats = zb_buf_begin(param); - - TRACE_MSG(TRACE_ZCL3, ">>zb_zcl_diagnostics_sync_counters_cb(), param %hd", - (FMT__H, param)); - - TRACE_MSG(TRACE_ZCL3, "status 0x%hx", (FMT__H, full_stats->status)); - - if (full_stats->status == MAC_SUCCESS) - { - ZB_MEMCPY(&diagnostics_ctx_zcl.mac_data, - &full_stats->mac_stats, - sizeof(zb_mac_diagnostic_info_t)); - ZB_MEMCPY(&diagnostics_ctx_zcl.zdo_data, - &full_stats->zdo_stats, - sizeof(zdo_diagnostics_info_t)); - } - - if (diagnostics_ctx_zcl.sync_data_cb) - { - TRACE_MSG(TRACE_ZCL3, "schedule cb 0x%p, cb_param %hd", - (FMT__P_H, diagnostics_ctx_zcl.sync_data_cb, diagnostics_ctx_zcl.cb_param)); - - ZB_SCHEDULE_CALLBACK(diagnostics_ctx_zcl.sync_data_cb, diagnostics_ctx_zcl.cb_param); - - diagnostics_ctx_zcl.cb_param = 0; - diagnostics_ctx_zcl.sync_data_cb = NULL; - } - - zb_buf_free(param); - - TRACE_MSG(TRACE_ZCL3, "<>zb_zcl_diagnostics_sync_counters(), cb_param %hd, cb 0x%p", - (FMT__H_P, cb_param, cb)); - - if (diagnostics_ctx_zcl.sync_data_cb == NULL) - { - ret = ZDO_DIAGNOSTICS_GET_STATS(zb_zcl_diagnostics_sync_counters_cb); - if (ret == RET_OK) - { - diagnostics_ctx_zcl.sync_data_cb = cb; - diagnostics_ctx_zcl.cb_param = cb_param; - TRACE_MSG(TRACE_ZCL3, "Synchronization is scheduled!", (FMT__0)); - } - } - else - { - ret = RET_BUSY; - TRACE_MSG(TRACE_ZCL3, "another request is scheduled! cb 0x%p, cb_param 0x%hx", - (FMT__P_H, diagnostics_ctx_zcl.sync_data_cb, diagnostics_ctx_zcl.cb_param)); - } - - TRACE_MSG(TRACE_ZCL3, "< ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_UNLOCKED && *value < ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_UNDEFINED ) - { - ret = RET_ERROR; - } - break; - - case ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_ID: - if( *value > ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_OTHER && *value < ZB_ZCL_ATTR_DOOR_LOCK_LOCK_TYPE_UNDEFINED ) - { - ret = RET_ERROR; - } - break; - - case ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_ID: - if(*value != ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_DISABLED && - *value != ZB_ZCL_ATTR_DOOR_LOCK_ACTUATOR_ENABLED_ENABLED) - { - ret = RET_ERROR; - } - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_door_lock ret %hd", (FMT__H, ret)); - return ret; -} - -static zb_zcl_status_t zb_zcl_door_lock_map_ret_code_to_zcl_status(zb_ret_t ret_code) -{ - ZB_ASSERT(ret_code != RET_BUSY); - - return zb_zcl_get_zcl_status_from_ret(ret_code); -} - -/** @brief Lock Door command */ -static zb_ret_t zb_zcl_door_lock_lock_door_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_door_lock_read_lock_door_res_payload_t pl_out; - zb_bool_t security = (zb_bool_t)ZB_APS_FC_GET_SECURITY(cmd_info->addr_data.common_data.fc); - - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_door_lock_lock_door_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_out, sizeof(pl_out)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DOOR_LOCK_LOCK_DOOR_CB_ID, RET_OK, cmd_info, NULL, &pl_out); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - /* prevent to send response on ZGP command */ - if (!ZB_ZCL_ADDR_TYPE_IS_GPD(cmd_info->addr_data.common_data.source.addr_type)) - { - ZB_ZCL_DOOR_LOCK_SEND_LOCK_DOOR_RES(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->seq_number, - pl_out.status, - security); - } - else - { - zb_buf_free(param); - } - ret = RET_BUSY; - } - else - { - ret = RET_ERROR; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_door_lock_lock_door_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Unlock Door command */ -static zb_ret_t zb_zcl_door_lock_unlock_door_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_door_lock_read_unlock_door_res_payload_t pl_out; - zb_bool_t security = (zb_bool_t)ZB_APS_FC_GET_SECURITY(cmd_info->addr_data.common_data.fc); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_door_lock_unlock_door_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_out, sizeof(pl_out)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DOOR_LOCK_UNLOCK_DOOR_CB_ID, RET_OK, cmd_info, NULL, &pl_out); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - /* prevent to send response on ZGP command */ - if (!ZB_ZCL_ADDR_TYPE_IS_GPD(cmd_info->addr_data.common_data.source.addr_type)) - { - ZB_ZCL_DOOR_LOCK_SEND_UNLOCK_DOOR_RES(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->seq_number, - pl_out.status, - security); - } - else - { - zb_buf_free(param); - } - ret = RET_BUSY; - } - else - { - ret = RET_ERROR; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_door_lock_unlock_door_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Lock Door Response command */ -static zb_ret_t zb_zcl_door_lock_lock_door_resp_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_door_lock_read_lock_door_res_payload_t *pl_in = NULL; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_door_lock_lock_door_resp_handler %hx", (FMT__H, param)); - - pl_in = ZB_ZCL_DOOR_LOCK_READ_LOCK_DOOR_RES(param); - - if (!pl_in) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_DOOR_LOCK_READ_LOCK_DOOR_RES", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DOOR_LOCK_LOCK_DOOR_RESP_CB_ID, RET_OK, cmd_info, pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_door_lock_lock_door_resp_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Unlock Door Response command */ -static zb_ret_t zb_zcl_door_lock_unlock_door_resp_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_door_lock_read_unlock_door_res_payload_t *pl_in = NULL; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_door_lock_unlock_door_resp_handler %hx", (FMT__H, param)); - - pl_in = ZB_ZCL_DOOR_LOCK_READ_UNLOCK_DOOR_RES(param); - - if (!pl_in) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_DOOR_LOCK_READ_UNLOCK_DOOR_RES", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DOOR_LOCK_UNLOCK_DOOR_RESP_CB_ID, RET_OK, cmd_info, pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_door_lock_unlock_door_resp_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -zb_bool_t zb_zcl_process_door_lock_specific_commands_srv(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - - if (ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_door_lock_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, - "> zb_zcl_process_door_lock_specific_commands_srv: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_DOOR_LOCK == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR: - ret = zb_zcl_door_lock_lock_door_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_DOOR: - ret = zb_zcl_door_lock_unlock_door_handler(param, &cmd_info); - break; - default: - processed = ZB_FALSE; - break; - } - - if (processed && ret != RET_BUSY) - { - zb_zcl_send_default_handler(param, &cmd_info, - zb_zcl_door_lock_map_ret_code_to_zcl_status(ret)); - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_door_lock_specific_commands_srv: processed %d", - (FMT__D, processed)); - - return processed; -} - -zb_bool_t zb_zcl_process_door_lock_specific_commands_cli(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - - if (ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_door_lock_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, - "> zb_zcl_process_door_lock_specific_commands_cli: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_DOOR_LOCK == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction); - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR_RES: - ret = zb_zcl_door_lock_lock_door_resp_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_DOOR_RES: - ret = zb_zcl_door_lock_unlock_door_resp_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_DOOR_LOCK_OPERATION_EVENT_NOTIFICATION_ID: - break; - default: - processed = ZB_FALSE; - break; - } - - if (processed && ret != RET_BUSY) - { - zb_zcl_send_default_handler(param, &cmd_info, - zb_zcl_door_lock_map_ret_code_to_zcl_status(ret)); - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_door_lock_specific_commands_cli: processed %d", - (FMT__D, processed)); - - return processed; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_DOOR_LOCK */ diff --git a/zboss/development/src/zcl/zcl_el_measurement.c b/zboss/development/src/zcl/zcl_el_measurement.c deleted file mode 100644 index b6c5150002..0000000000 --- a/zboss/development/src/zcl/zcl_el_measurement.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#define ZB_TRACE_FILE_ID 86 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_ELECTRICAL_MEASUREMENT) - -static zb_ret_t check_value_el_measurement_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_el_measurement_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)check_value_el_measurement_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - - -void zb_zcl_el_measurement_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -static zb_ret_t check_value_el_measurement_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_ELECTRICAL_MEASUREMENT */ diff --git a/zboss/development/src/zcl/zcl_en50523_appliance_events_and_alerts.c b/zboss/development/src/zcl/zcl_en50523_appliance_events_and_alerts.c deleted file mode 100644 index 59903ecac0..0000000000 --- a/zboss/development/src/zcl/zcl_en50523_appliance_events_and_alerts.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Identify cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2071 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_EN50523_APPLIANCE_EVENTS_AND_ALERTS) - -#include "zb_aps.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_en50523_appliance_events_and_alerts.h" - -static zb_uint8_t gs_appl_ev_and_alerts_server_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_APPL_EV_AND_ALERTS_SERVER_ROLE_GENERATED_CMD_LIST -}; - -static zb_uint8_t gs_appl_ev_and_alerts_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_APPL_EV_AND_ALERTS_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -static zb_discover_cmd_list_t gs_appl_ev_and_alerts_client_cmd_list = -{ - sizeof(gs_appl_ev_and_alerts_server_generated_commands), gs_appl_ev_and_alerts_server_generated_commands, - sizeof(gs_appl_ev_and_alerts_server_received_commands), gs_appl_ev_and_alerts_server_received_commands -}; - -static zb_discover_cmd_list_t gs_appl_ev_and_alerts_server_cmd_list = -{ - sizeof(gs_appl_ev_and_alerts_server_received_commands), gs_appl_ev_and_alerts_server_received_commands, - sizeof(gs_appl_ev_and_alerts_server_generated_commands), gs_appl_ev_and_alerts_server_generated_commands -}; - - -zb_bool_t zb_zcl_process_en50523_appliance_events_and_alerts_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_en50523_appliance_events_and_alerts_cli(zb_uint8_t param); - -void zb_zcl_en50523_appliance_events_and_alerts_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_en50523_appliance_events_and_alerts_srv); -} - -void zb_zcl_en50523_appliance_events_and_alerts_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_en50523_appliance_events_and_alerts_cli); -} - -static zb_zcl_status_t zb_zcl_en50523_appliance_events_and_alerts_map_ret_code_to_zcl_status(zb_ret_t ret_code) -{ - ZB_ASSERT(ret_code != RET_BUSY); - - return zb_zcl_get_zcl_status_from_ret(ret_code); -} - -static zb_ret_t zb_zcl_en50523_appliance_events_and_alerts_get_alerts_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_uint8_t *ptr; - zb_uint16_t i; - zb_zcl_en50523_appl_ev_and_alerts_get_alerts_resp_t pl_out; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_en50523_appliance_events_and_alerts_get_alerts_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_out, sizeof(pl_out)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_CB_ID, RET_OK, cmd_info, NULL, &pl_out); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_GET_ALERTS_RESP_START(param, - cmd_info->seq_number, pl_out.alerts_count, ptr); - - for (i = 0; i < ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_COUNT_GET_NUM(pl_out.alerts_count); i++) - { - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_GET_ALERTS_RESP_ADD(ptr, &pl_out.alert_struct[i]); - } - - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_SEND_GET_ALERTS_RESP_END(ptr, param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id); - - ret = RET_BUSY; - } - else - { - ret = RET_ERROR; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_en50523_appliance_events_and_alerts_get_alerts_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -static zb_ret_t zb_zcl_en50523_appliance_events_and_alerts_get_alerts_resp_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_en50523_appl_ev_and_alerts_get_alerts_resp_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_en50523_appliance_events_and_alerts_get_alerts_resp_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_GET_ALERTS_RESP(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_GET_ALERTS_RESP", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_RESP_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_en50523_appliance_events_and_alerts_get_alerts_resp_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -static zb_ret_t zb_zcl_en50523_appliance_events_and_alerts_alerts_notificaton_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_en50523_appl_ev_and_alerts_alerts_notif_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_en50523_appliance_events_and_alerts_alerts_notificaton_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_NOTIF(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_NOTIF", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_ALERTS_NOTIFICATION_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_en50523_appliance_events_and_alerts_alerts_notificaton_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -static zb_ret_t zb_zcl_en50523_appliance_events_and_alerts_event_notificaton_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_en50523_appl_ev_and_alerts_event_notif_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_en50523_appliance_events_and_alerts_event_notificaton_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_EVENT_NOTIF(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_GET_EVENT_NOTIF", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_EN50523_APPL_EV_AND_ALERTS_EVENT_NOTIFICATION_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_en50523_appliance_events_and_alerts_event_notificaton_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -zb_bool_t zb_zcl_process_en50523_appliance_events_and_alerts_srv(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - - if (ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_appl_ev_and_alerts_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, - "> zb_zcl_process_en50523_appliance_events_and_alerts_srv: param %hd", (FMT__H, param)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_ID: - ret = zb_zcl_en50523_appliance_events_and_alerts_get_alerts_handler(param, &cmd_info); - break; - - default: - processed = ZB_FALSE; - break; - } - - if (processed && ret != RET_BUSY) - { - zb_zcl_send_default_handler(param, &cmd_info, - zb_zcl_en50523_appliance_events_and_alerts_map_ret_code_to_zcl_status(ret)); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_en50523_appliance_events_and_alerts_srv: processed %d", - (FMT__D, processed)); - - return processed; -} - -zb_bool_t zb_zcl_process_en50523_appliance_events_and_alerts_cli(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - - if (ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_appl_ev_and_alerts_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, - "> zb_zcl_process_en50523_appliance_events_and_alerts_cli: param %hd", (FMT__H, param)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_APPLIANCE_EVENTS_AND_ALERTS == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction); - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_GET_ALERTS_RESP_ID: - ret = zb_zcl_en50523_appliance_events_and_alerts_get_alerts_resp_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_ALERTS_NOTIFICATION_ID: - ret = zb_zcl_en50523_appliance_events_and_alerts_alerts_notificaton_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_EN50523_APPL_EV_AND_ALERTS_EVENT_NOTIFICATION_ID: - ret = zb_zcl_en50523_appliance_events_and_alerts_event_notificaton_handler(param, &cmd_info); - break; - - default: - processed = ZB_FALSE; - break; - } - - if (processed && ret != RET_BUSY) - { - zb_zcl_send_default_handler(param, &cmd_info, - zb_zcl_en50523_appliance_events_and_alerts_map_ret_code_to_zcl_status(ret)); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_en50523_appliance_events_and_alerts_cli: processed %d", - (FMT__D, processed)); - - return processed; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_EN50523_APPLIANCE_EVENTS_AND_ALERTS */ diff --git a/zboss/development/src/zcl/zcl_fan_control.c b/zboss/development/src/zcl/zcl_fan_control.c deleted file mode 100644 index 0befa1e6a9..0000000000 --- a/zboss/development/src/zcl/zcl_fan_control.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#define ZB_TRACE_FILE_ID 77 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_FAN_CONTROL) - -zb_ret_t check_value_fan_control_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_fan_control_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_FAN_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_fan_control_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_fan_control_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_FAN_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_fan_control_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - - ZVUNUSED(endpoint); - switch( attr_id ) - { - case ZB_ZCL_ATTR_FAN_CONTROL_FAN_MODE_ID: - ret = (*value < ZB_ZCL_FAN_CONTROL_FAN_MODE_RESERVED) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_FAN_CONTROL_FAN_MODE_SEQUENCE_ID: - ret = (*value < ZB_ZCL_FAN_CONTROL_FAN_MODE_SEQUENCE_RESERVED) ? RET_OK : RET_ERROR; - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_fan_control ret %hd", (FMT__H, ret)); - return ret; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_FAN_CONTROL */ diff --git a/zboss/development/src/zcl/zcl_general_commands.c b/zboss/development/src/zcl/zcl_general_commands.c deleted file mode 100644 index 4ca888157b..0000000000 --- a/zboss/development/src/zcl/zcl_general_commands.c +++ /dev/null @@ -1,2050 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL general commands implementation -*/ - - -#define ZB_TRACE_FILE_ID 2066 - -#include "zb_common.h" - -#if defined (ZB_ENABLE_ZCL) - -#include "zb_zcl.h" -#include "zb_aps.h" -#include "zcl/zb_zcl_common.h" -#include "zcl/zcl_ota_upgrade_commands.h" -#if defined ZB_ENABLE_HA -#include "zb_ha.h" -#endif -#include "zdo_wwah_stubs.h" - -#ifdef SWITCH_OFF_SOME_ZCL_TRACE -/* temporary switch trace off here */ -#undef TRACE_ZCL1 -#define TRACE_ZCL1 TRACE_MEM1 -#undef TRACE_ZCL2 -#define TRACE_ZCL2 TRACE_MEM2 -#undef TRACE_ZCL3 -#define TRACE_ZCL3 TRACE_MEM3 -#endif - -/* - Maximum attr for Discover Attributes Response - this limit by packet length (146) and length of MAC, NWK, APS, ZCL headers - with security headers -*/ -#define ZB_ZCL_DISC_ATTR_MAX 14 - - -static zb_bool_t zb_zcl_handle_default_response_commands(zb_uint8_t param); - -/* - Puts attribute value to ZCL packet. - Returns modified data pointer - */ -/* TODO: check - this function doubles functionality of zb_zcl_put_value_to_packet() */ -static zb_uint8_t* zb_zcl_put_attribute_value(zb_uint8_t *data_ptr, zb_zcl_attr_t *attr, - zb_uint8_t *value, zb_uint16_t value_size) -{ - ZB_ASSERT(data_ptr); - ZB_ASSERT(attr); - ZB_ASSERT(value); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_put_attribute_value data_ptr %p, value %p, value_size %hd", - (FMT__P_P_D, data_ptr, value, value_size)); - - switch ( attr->type ) - { - case ZB_ZCL_ATTR_TYPE_8BIT: - case ZB_ZCL_ATTR_TYPE_U8: - case ZB_ZCL_ATTR_TYPE_S8: - case ZB_ZCL_ATTR_TYPE_BOOL: - case ZB_ZCL_ATTR_TYPE_8BITMAP: - case ZB_ZCL_ATTR_TYPE_8BIT_ENUM: - ZB_ZCL_PACKET_PUT_DATA8(data_ptr, *value); - break; - - case ZB_ZCL_ATTR_TYPE_16BIT: - case ZB_ZCL_ATTR_TYPE_U16: - case ZB_ZCL_ATTR_TYPE_S16: - case ZB_ZCL_ATTR_TYPE_16BITMAP: - case ZB_ZCL_ATTR_TYPE_16BIT_ENUM: - case ZB_ZCL_ATTR_TYPE_SEMI: - case ZB_ZCL_ATTR_TYPE_CLUSTER_ID: - case ZB_ZCL_ATTR_TYPE_ATTRIBUTE_ID: - ZB_ZCL_PACKET_PUT_DATA16(data_ptr, value); - break; - - case ZB_ZCL_ATTR_TYPE_32BIT: - case ZB_ZCL_ATTR_TYPE_U32: - case ZB_ZCL_ATTR_TYPE_S32: - case ZB_ZCL_ATTR_TYPE_32BITMAP: - case ZB_ZCL_ATTR_TYPE_UTC_TIME: - case ZB_ZCL_ATTR_TYPE_TIME_OF_DAY: - case ZB_ZCL_ATTR_TYPE_DATE: - case ZB_ZCL_ATTR_TYPE_BACNET_OID: - case ZB_ZCL_ATTR_TYPE_SINGLE: - ZB_ZCL_PACKET_PUT_DATA32(data_ptr, value); - break; - - case ZB_ZCL_ATTR_TYPE_U48: - case ZB_ZCL_ATTR_TYPE_S48: - case ZB_ZCL_ATTR_TYPE_48BIT: - case ZB_ZCL_ATTR_TYPE_48BITMAP: -//TODO: fix it: put bytes taking into account bytes order - ZB_ZCL_PACKET_PUT_DATA48(data_ptr, value); - break; - - case ZB_ZCL_ATTR_TYPE_U24: - case ZB_ZCL_ATTR_TYPE_S24: - case ZB_ZCL_ATTR_TYPE_24BIT: - case ZB_ZCL_ATTR_TYPE_24BITMAP: -//TODO: fix it: put bytes taking into account bytes order - ZB_ZCL_PACKET_PUT_DATA24(data_ptr, value); - break; - - case ZB_ZCL_ATTR_TYPE_U40: - case ZB_ZCL_ATTR_TYPE_S40: - case ZB_ZCL_ATTR_TYPE_40BIT: - case ZB_ZCL_ATTR_TYPE_40BITMAP: -//TODO: fix it: put bytes taking into account bytes order - ZB_ZCL_PACKET_PUT_DATA_N(data_ptr, value, 5); - break; - - case ZB_ZCL_ATTR_TYPE_U56: - case ZB_ZCL_ATTR_TYPE_S56: - case ZB_ZCL_ATTR_TYPE_56BIT: - case ZB_ZCL_ATTR_TYPE_56BITMAP: -//TODO: fix it: put bytes taking into account bytes order - ZB_ZCL_PACKET_PUT_DATA_N(data_ptr, value, 7); - break; - - case ZB_ZCL_ATTR_TYPE_OCTET_STRING: - case ZB_ZCL_ATTR_TYPE_CHAR_STRING: - case ZB_ZCL_ATTR_TYPE_ARRAY: - case ZB_ZCL_ATTR_TYPE_CUSTOM_32ARRAY: - case ZB_ZCL_ATTR_TYPE_LONG_OCTET_STRING: - ZB_ZCL_PACKET_PUT_DATA_N(data_ptr, value, value_size); - break; - - case ZB_ZCL_ATTR_TYPE_64BIT: - case ZB_ZCL_ATTR_TYPE_64BITMAP: - case ZB_ZCL_ATTR_TYPE_U64: - case ZB_ZCL_ATTR_TYPE_S64: - case ZB_ZCL_ATTR_TYPE_DOUBLE: - case ZB_ZCL_ATTR_TYPE_IEEE_ADDR: - ZB_ZCL_PACKET_PUT_DATA64(data_ptr, value); - break; - - case ZB_ZCL_ATTR_TYPE_128_BIT_KEY: - ZB_ZCL_PACKET_PUT_DATA_N(data_ptr, value, 16); - break; - default: - TRACE_MSG(TRACE_ZCL1, "Error, unsupported type!", (FMT__0)); - ZB_ASSERT(0); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_put_attribute_value ret %p", (FMT__P, data_ptr)); - return data_ptr; -} - - -/*! @internal @brief ZCL read attributes handler continue - @param param - index of the buffer with read attributes request -*/ -static void zb_zcl_read_attr_handler_continue(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_bool_t security = ZB_APS_FC_IS_SECURE(cmd_info->addr_data.common_data.fc); - zb_af_endpoint_desc_t *ep_desc; - zb_zcl_cluster_desc_t *cluster_desc; - zb_zcl_attr_t *attr_desc; - zb_uint8_t attr_size; - zb_uint8_t *resp_data; - zb_uint32_t attr_num; - zb_zcl_read_attr_req_t *read_attr_req; - zb_uint16_t attr_id; - zb_uint8_t i; - zb_uint32_t bytes_avail; - zb_uint16_t global_cluster_revision_value; - zb_zcl_status_t status; - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_read_attr_handler_continue param %hd", (FMT__H, param)); - TRACE_MSG(TRACE_ZCL1, "sizeof(zb_zcl_parsed_hdr_t) %ld", (FMT__L, sizeof(zb_zcl_parsed_hdr_t))); - - ep_desc = zb_af_get_endpoint_desc(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - /* EP existence was checked on command accept - it must be in the list */ - ZB_ASSERT(ep_desc); - - cluster_desc = get_cluster_desc(ep_desc, cmd_info->cluster_id, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE); - /* Cluster existence was checked on command accept - it must be in the list */ - ZB_ASSERT(cluster_desc); - - /* ZCL spec, 2.4.2 Read Attributes Response Command */ - /* Read attribute response - | ZCL header 3 b | Read attr status rec 1 XX b | Read attr status rec 2 XX b | ... - - Read attr status rec format - | attr id 2 b | status 1 b | Attr data type 0/1 b | attr value 0/XX b | - */ - - /* ZCL frame format */ - /* frame control 1b | manufacturer code 0/2b | TSN 1b | cmd id 1b | payload XXb */ - - /* frame control */ - /* frame type | manufacturer specific | direction | disable default resp */ - - /* Construct packet header */ - /* Use runtime_buf buffer for composing and sending response, request buffer - * will be saved as runtime_buf */ - resp_data = ZB_ZCL_START_PACKET(ZCL_CTX().runtime_buf); - - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_A( - resp_data, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV ? - ZB_ZCL_FRAME_DIRECTION_TO_CLI : - ZB_ZCL_FRAME_DIRECTION_TO_SRV), - cmd_info->is_manuf_specific); - - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT( - resp_data, - cmd_info->seq_number, - cmd_info->is_manuf_specific, - cmd_info->manuf_specific, - ZB_ZCL_CMD_READ_ATTRIB_RESP); - - read_attr_req = (zb_zcl_read_attr_req_t*)zb_buf_begin(param); - attr_num = zb_buf_len(param) / sizeof(zb_zcl_read_attr_req_t); - TRACE_MSG(TRACE_ZCL2, "read_attr_req %p, attr_num %d", (FMT__P_D, read_attr_req, attr_num)); - - for(i = 0; i < attr_num; i++) - { - status = ZB_ZCL_STATUS_SUCCESS; - ZB_HTOLE16(&attr_id, &read_attr_req->attr_id[i]); - TRACE_MSG(TRACE_ZCL3, "attr_id %d", (FMT__D, attr_id)); - attr_desc = zb_zcl_get_attr_desc(cluster_desc, attr_id); - TRACE_MSG(TRACE_ZCL3, "attr_desc %p", (FMT__P, attr_desc)); - - bytes_avail = ZB_ZCL_GET_BYTES_AVAILABLE(ZCL_CTX().runtime_buf, resp_data, - cmd_info->profile_id, cmd_info->cluster_id); - - TRACE_MSG(TRACE_ZCL3, "attr_desc %p, bytes_avail %d", (FMT__P_D, attr_desc, bytes_avail)); - - if (attr_desc == NULL) - { - if (attr_id == ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID) - { - TRACE_MSG( - TRACE_ZCL1, - "Global revision requested. Return ZB_ZCL_GLOBAL_CLUSTER_REVISION_DEFAULT", - (FMT__0)); - global_cluster_revision_value = ZB_ZCL_GLOBAL_CLUSTER_REVISION_DEFAULT; - ZB_ZCL_PACKET_PUT_DATA16(resp_data, &attr_id); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_STATUS_SUCCESS); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_ATTR_TYPE_U16); - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, global_cluster_revision_value); - } - else - { - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - TRACE_MSG(TRACE_ZCL1, "attr is not found id %hd", (FMT__H, read_attr_req[i])); - } - } - else if (attr_desc->data_p == NULL || ZB_BIT_IS_SET(attr_desc->access, ZB_ZCL_ATTR_ACCESS_INTERNAL)) - { - TRACE_MSG(TRACE_ZCL1, "error, internal attr isn't readable", (FMT__0)); - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - } - else if (!ZB_BIT_IS_SET(attr_desc->access, ZB_ZCL_ATTR_ACCESS_READ_ONLY)) - { - TRACE_MSG(TRACE_ZCL1, "error, attr access mask 0x%hx - isn't readable", (FMT__H, attr_desc->access)); - status = ZB_BIT_IS_SET(attr_desc->access, ZB_ZCL_ATTR_ACCESS_WRITE_ONLY) - /* ZCL8: CCB 2477: use NOT_AUTHORIZED instead of Write-only status*/ - ?((zb_zcl_get_backward_compatible_statuses_mode() == ZB_ZCL_STATUSES_ZCL8_MODE) ? - ZB_ZCL_STATUS_NOT_AUTHORIZED : ZB_ZCL_STATUS_WRITE_ONLY) - : ZB_ZCL_STATUS_FAIL; - } - else - { - TRACE_MSG( - TRACE_ZCL3, - "attribute: id 0x%x, type 0x%hx", - (FMT__D_H, attr_desc->id, attr_desc->type)); - attr_size = zb_zcl_get_attribute_size(attr_desc->type, attr_desc->data_p); - TRACE_MSG(TRACE_ZCL3, "attr_size %hd", (FMT__H, attr_size)); - - /* Decrement read attr response by sizeof(zb_uint8_t), because attr value size is - * calculated separately by attr_size */ - if (bytes_avail >= (sizeof(zb_zcl_read_attr_res_t) - sizeof(zb_uint8_t) + attr_size)) - { - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, attr_desc->id); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_STATUS_SUCCESS); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, attr_desc->type); - resp_data = zb_zcl_put_attribute_value(resp_data, attr_desc, attr_desc->data_p, attr_size); - } - else - { - /* ZCL7 spec, 2.5.1.3: - If the status record does not fit, the device SHALL set the status field of - the corresponding read attribute status record to INSUFFICIENT_SPACE and not - include the data type and value fields. - */ - status = ZB_ZCL_STATUS_INSUFF_SPACE; - TRACE_MSG(TRACE_ZCL1, "ERROR, buffer is full (bytes_avail %d)", (FMT__D, bytes_avail)); - } - } - - if (status != ZB_ZCL_STATUS_SUCCESS) - { - if (bytes_avail >= (sizeof(zb_uint16_t) + sizeof(zb_uint8_t))) - { - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, attr_id); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, status); - } - else - { - TRACE_MSG(TRACE_ZCL1, "ERROR, buffer is full; terminate", (FMT__0)); - break; - } - } - } - - ZB_ZCL_FINISH_N_SEND_PACKET_NEW( - ZCL_CTX().runtime_buf, - resp_data, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - NULL, - security, ZB_FALSE, 0); - - /* Use runtime buffer to send request, use received buffer with - * request data_buf as runtime buffer */ - ZCL_CTX().runtime_buf = param; - - TRACE_MSG(TRACE_ZCL1, "<>zb_zcl_read_attr_handler param %hd", (FMT__H, param)); - -#ifdef ZB_TH_ENABLED - if (TH_CTX().options.block_read_attr_request) - { - TRACE_MSG(TRACE_ZCL1, ">>Read attribute handler is blocked by implementation specific meaning", (FMT__0)); - zb_buf_free(param); - return; - } -#endif - - /* 12/02/2020 EE CR:MAJOR That is not very good solution because, if our build - * includes all clusters but application does not declare diagnostic cluster, - * its code still will be linked. - * Also, we will need similar approach (blocked load of ZDO level data into ZCL) for WWAH. - * So need to design a common mechanism for the cluster to intercept read_attr. - * Add one more type of the cluster handler? - */ - { -#if defined(ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS) - - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - - if (cmd_info->cluster_id == ZB_ZCL_CLUSTER_ID_DIAGNOSTICS) - { - TRACE_MSG(TRACE_ZCL1, "it's the diagnostics cluster! try to sync stats before rsp sending...", - (FMT__0)); - zb_zcl_sync_stats(param); - } - else -#endif /* defined(ZB_ZCL_SUPPORT_CLUSTER_DIAGNOSTICS) */ - { - zb_zcl_read_attr_handler_continue(param); - } - } - - TRACE_MSG(TRACE_ZCL1, "<profile_id == ZB_AF_CONTROL4_PROFILE_ID && - cmd_info->cluster_id == ZB_ZCL_CLUSTER_ID_CONTROL4_NETWORKING) - { - zb_zcl_control4_network_cluster_read_attr_resp_handler(param); - } - else -#endif /* ZB_CONTROL4_NETWORK_SUPPORT */ - { - /* TODO: implement default response handler with notifying - * user about received attribute value via callback */ - zb_buf_free(param); - } -} - -/* - Search for attribute descriptor by its ID -*/ -zb_zcl_attr_t* zb_zcl_get_attr_desc(zb_zcl_cluster_desc_t *cluster_desc, zb_uint16_t attr_id) -{ - zb_zcl_attr_t *attr_desc = cluster_desc->attr_desc_list; - zb_ushort_t i = 0; - - TRACE_MSG( - TRACE_ZCL3, - ">> zb_zcl_get_attr_desc cluster_desc %p, attr_id %d", - (FMT__P_D, cluster_desc, attr_id)); - TRACE_MSG(TRACE_ZCL3, "cluster id: 0x%x", (FMT__D, cluster_desc->cluster_id)); - while (attr_desc != NULL) - { - TRACE_MSG(TRACE_ZCL3, "Looking up attribute with id: 0x%x", - (FMT__D, attr_desc->id)); - - if (attr_desc->id == attr_id) - { - /* attribute is found */ - break; - } - - i++; - attr_desc++; - if (i >= cluster_desc->attr_count) - { - attr_desc = NULL; - break; - } - } - - TRACE_MSG(TRACE_ZCL3, "<< zb_zcl_get_attr_desc, attr_desc %p", (FMT__P, attr_desc)); - return attr_desc; -} - -/* aggregates all calls to find attribute descriptor */ -zb_zcl_attr_t* zb_zcl_get_attr_desc_a(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id) -{ - zb_af_endpoint_desc_t *ep_desc; - zb_zcl_cluster_desc_t *cluster_desc; - zb_zcl_attr_t *attr_desc; - - TRACE_MSG(TRACE_ZCL2, ">> zb_zcl_get_attr_desc_a ep %hd, cluster_id %d, attr_id %d", - (FMT__H_D_D, ep, cluster_id, attr_id)); - - ep_desc = zb_af_get_endpoint_desc(ep); - /* EP existence was checked on command accept - it must be in the list */ - ZB_ASSERT(ep_desc); - - cluster_desc = get_cluster_desc(ep_desc, cluster_id, cluster_role); - /* Cluster existence was checked on command accept - it must be in the list */ - ZB_ASSERT(cluster_desc); - - attr_desc = zb_zcl_get_attr_desc(cluster_desc, attr_id); - TRACE_MSG(TRACE_ZCL2, "<< zb_zcl_get_attr_desc_a ret %p", (FMT__P, attr_desc)); - return attr_desc; -} - - -static void zb_zcl_set_attr_val_cmd_post_process(zb_zcl_parsed_hdr_t *cmd_info, - zb_uint16_t attr_id, - zb_uint8_t *value) -{ - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_set_attr_val_cmd_post_process, cmd_info %p", (FMT__P, cmd_info)); - - ZVUNUSED(attr_id); - ZVUNUSED(value); - - zb_zcl_set_attr_val_post_process_cluster_specific(cmd_info, attr_id, value); - - TRACE_MSG(TRACE_ZCL1, "<id, - value); - ZB_ZCL_INVOKE_USER_APP_SET_ATTR_WITH_RESULT( - buf, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->cluster_id, - attr_desc, - value, - result); - ZVUNUSED(result); - zb_buf_free(buf); - } -} - -/*! @brief ZCL write attributes command handler - @param param - reference to buffer (see @ref zb_buf_t) with read attributes request -*/ -void zb_zcl_write_attr_handler(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_zcl_write_attr_req_t *write_attr_req; - zb_af_endpoint_desc_t *ep_desc; - zb_zcl_cluster_desc_t *cluster_desc; - zb_zcl_attr_t *attr_desc; - zb_zcl_status_t status; - zb_uint8_t *resp_data = NULL; - zb_uint8_t attr_count = 0; - zb_uint8_t endpoint; - zb_uint8_t *data_ptr; - zb_uint32_t buf_len; - zb_bool_t can_write_all_attrs = ZB_TRUE; - - TRACE_MSG( - TRACE_ZCL1, - ">>zb_zcl_write_attr_handler param %d, cmd_info %p", - (FMT__H_P, param, cmd_info)); - - /* ZCL8 spec, 2.5.3.1 Write attributes Command Frame Format */ - /* ZCL header | Write attr record 1 | Write attr record 2 | ... */ - /* write attr record: | attr id 2b | attr type 1b | data XXb | */ - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - ep_desc = zb_af_get_endpoint_desc(endpoint); - - /* EP existence was checked on command accept - it must be in the list */ - ZB_ASSERT(ep_desc); - - cluster_desc = get_cluster_desc(ep_desc, cmd_info->cluster_id, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE); - /* Cluster existence was checked on command accept - it must be in the list */ - ZB_ASSERT(cluster_desc); - - if (ZB_ZCL_CMD_WRITE_ATTRIB_NO_RESP != cmd_info->cmd_id) - { - /* Construct packet header */ - /* Use runtime_buf buffer for composing and sending response, request buffer - * will be saved as runtime_buf */ - resp_data = ZB_ZCL_START_PACKET(ZCL_CTX().runtime_buf); - - /* NOTE: currently, Manufacturer specific is not supported */ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_A( - resp_data, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV ? - ZB_ZCL_FRAME_DIRECTION_TO_CLI : - ZB_ZCL_FRAME_DIRECTION_TO_SRV), - cmd_info->is_manuf_specific); - - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT( - resp_data, - cmd_info->seq_number, - cmd_info->is_manuf_specific, - cmd_info->manuf_specific, - ZB_ZCL_CMD_WRITE_ATTRIB_RESP); - } - - data_ptr = zb_buf_begin(param); - buf_len = zb_buf_len(param); - - do - { - ZB_ZCL_GENERAL_GET_NEXT_WRITE_ATTR_REQ(data_ptr, buf_len, write_attr_req); - - TRACE_MSG(TRACE_ZCL2, "write_attr_req %p", (FMT__P, write_attr_req)); - - if (write_attr_req != NULL) - { - attr_count++; - TRACE_MSG(TRACE_ZCL3, "attr_id %d, attr_type %hd", - (FMT__D_H, write_attr_req->attr_id, write_attr_req->attr_type)); - - attr_desc = zb_zcl_get_attr_desc(cluster_desc, write_attr_req->attr_id); - TRACE_MSG(TRACE_ZCL3, "attr_desc %p", (FMT__P, attr_desc)); - - if (attr_desc == NULL) - { - if (write_attr_req->attr_id == ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID) - { - TRACE_MSG( - TRACE_ZCL1, - "Global revision requested. Return READ_ONLY", - (FMT__0)); - status = ZB_ZCL_STATUS_READ_ONLY; - } - else - { - TRACE_MSG(TRACE_ZCL1, "error, attr not found", (FMT__0)); - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - } - } - else if (attr_desc->data_p == NULL) - { - TRACE_MSG(TRACE_ZCL1, "error, attr not found", (FMT__0)); - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - } - else if (attr_desc->type != write_attr_req->attr_type) - { - TRACE_MSG(TRACE_ZCL1, "error, incorrect attr type", (FMT__0)); - status = ZB_ZCL_STATUS_INVALID_TYPE; - } - else - { - status = (zb_zcl_status_t) - zb_zcl_check_attribute_writable(attr_desc, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->cluster_id, - ((cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE), - write_attr_req->attr_value, - ZB_TRUE); - } - - TRACE_MSG(TRACE_ZCL2, "attr status 0x%hx", (FMT__H, status)); - - if (ZB_ZCL_STATUS_SUCCESS == status) - { - if (ZB_ZCL_CMD_WRITE_ATTRIB_UNDIV != cmd_info->cmd_id) - { - ZVUNUSED(zb_zcl_set_attr_val(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->cluster_id, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE, - attr_desc->id, - write_attr_req->attr_value, - ZB_FALSE)); - zcl_write_attr_post_process(cmd_info, attr_desc, write_attr_req->attr_value); - } - } - else - { - can_write_all_attrs = ZB_FALSE; - - if (ZB_ZCL_CMD_WRITE_ATTRIB_NO_RESP != cmd_info->cmd_id) - { - TRACE_MSG(TRACE_ZCL3, "put error status response, attr_id 0x%x", - (FMT__D, write_attr_req->attr_id)); - if ( - /*cstat !MISRAC2012-Rule-13.5 */ - (resp_data != NULL) && - /* The following violation of Rule 13.5 seems to be - * a false positive. There are no side effect to 'zb_zcl_can_cluster_be_fragmented()'. - * This violation seems to be caused by the fact that - * 'zb_zcl_can_cluster_be_fragmented()' is an - * external function, which cannot be analyzed by C-STAT. */ - (ZB_ZCL_GET_BYTES_AVAILABLE(ZCL_CTX().runtime_buf, resp_data, - cmd_info->profile_id, cmd_info->cluster_id) - >= sizeof(zb_zcl_write_attr_res_t)) - ) - { - ZB_ZCL_PACKET_PUT_DATA8(resp_data, status); - ZB_ZCL_PACKET_PUT_DATA16(resp_data, &write_attr_req->attr_id); - } - } - } - } - } - while (write_attr_req != NULL); - - if (ZB_ZCL_CMD_WRITE_ATTRIB_UNDIV == cmd_info->cmd_id - && can_write_all_attrs) - { - TRACE_MSG(TRACE_ZCL1, "WRITE_ATTRIB_UNDIVIDED all attributes checked success", (FMT__0)); - - data_ptr = zb_buf_begin(param); - buf_len = zb_buf_len(param); - - do - { - ZB_ZCL_GENERAL_GET_NEXT_WRITE_ATTR_REQ(data_ptr, buf_len, write_attr_req); - - if (write_attr_req != NULL) - { - attr_desc = zb_zcl_get_attr_desc(cluster_desc, write_attr_req->attr_id); - TRACE_MSG(TRACE_ZCL3, "attr_desc %p", (FMT__P, attr_desc)); - - ZVUNUSED(zb_zcl_set_attr_val(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->cluster_id, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE, - attr_desc->id, - write_attr_req->attr_value, - ZB_FALSE)); - zcl_write_attr_post_process(cmd_info, attr_desc, write_attr_req->attr_value); - } - } - while (write_attr_req != NULL); - } - - if (ZB_ZCL_CMD_WRITE_ATTRIB_NO_RESP != cmd_info->cmd_id) - { - if (can_write_all_attrs) - { - if ((resp_data != NULL) && (attr_count > 0U)) - {/* If no error found - report status Ok to all attrs, no attr id - * is needed */ - TRACE_MSG(TRACE_ZCL3, "report status OK", (FMT__0)); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_STATUS_SUCCESS); - } - else - {/* ZCL spec Rev 7 p. 2.6.3. The command appears to contain the wrong fields, as - * detected either by the presence of one or more invalid - * field entries or by there being missing fields. - * Command not carried out. Implementer has discretion - * as to whether to return this error or - * INVALID_FIELD*/ - TRACE_MSG(TRACE_ZCL3, "report status MALFORMED_CMD", (FMT__0)); - ZB_ZCL_SEND_DEFAULT_RESP_DIRECTION( ZCL_CTX().runtime_buf, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - cmd_info->seq_number, - cmd_info->cmd_id, - ZB_ZCL_STATUS_MALFORMED_CMD, - ZB_ZCL_REVERT_DIRECTION(cmd_info->cmd_direction)); - param = 0; - } - } - - if (param > 0U) - { - ZB_ZCL_FINISH_N_SEND_PACKET_NEW(ZCL_CTX().runtime_buf, resp_data, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - NULL, - ZB_APS_FC_IS_SECURE(cmd_info->addr_data.common_data.fc), - ZB_FALSE, - 0U); - } - - /* Use runtime buffer to send request, use received buffer with - * request data_buf as runtime buffer */ - ZCL_CTX().runtime_buf = param; - - TRACE_MSG(TRACE_ZCL1, "<> check_config_rep_req", (FMT__0)); - ZB_ASSERT(config_rep_req); - - if (config_rep_req->direction == ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT) - { - TRACE_MSG(TRACE_ZCL3, "send report direction", (FMT__0)); - if (!attr_desc) - { - if (config_rep_req->attr_id == ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID) - { - TRACE_MSG(TRACE_ZCL1, "GLOBAL_CLUSTER_REVISION: attr is not reportable", (FMT__0)); - status = ZB_ZCL_STATUS_UNREPORTABLE_ATTRIB; - } - else - { - TRACE_MSG(TRACE_ZCL1, "attr not found", (FMT__0)); - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - } - } - else if (!attr_desc->data_p) - { - TRACE_MSG(TRACE_ZCL1, "attr not found", (FMT__0)); - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - } - else - { - /* ZCL8 spec 2.5.7.3 Effect on Receipt: if the attribute type is set to array, - structure, set or bag, set status to UNSUPPORTED_ATTRIBUTE */ - /* TODO: add other types checking */ - if (attr_desc->type == ZB_ZCL_ATTR_TYPE_OCTET_STRING || attr_desc->type == ZB_ZCL_ATTR_TYPE_ARRAY - || attr_desc->type == ZB_ZCL_ATTR_TYPE_CUSTOM_32ARRAY) - { - TRACE_MSG(TRACE_ZCL1, "invalid attr type", (FMT__0)); - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - } - else if (!(attr_desc->access & ZB_ZCL_ATTR_ACCESS_REPORTING)) - { - TRACE_MSG(TRACE_ZCL1, "attr is not reportable", (FMT__0)); - status = ZB_ZCL_STATUS_UNREPORTABLE_ATTRIB; - } - else if (attr_desc->type != config_rep_req->u.clnt.attr_type) - { - TRACE_MSG(TRACE_ZCL1, "invalid type attr type %hd, recv type %hd", - (FMT__H_H, attr_desc->type, config_rep_req->u.clnt.attr_type)); - status = ZB_ZCL_STATUS_INVALID_TYPE; - } - else if (config_rep_req->u.clnt.max_interval != 0 && - config_rep_req->u.clnt.max_interval < config_rep_req->u.clnt.min_interval) - { - TRACE_MSG( - TRACE_ZCL1, - "invalid min/max value min %hd, max %hd", - ( FMT__H_H, - config_rep_req->u.clnt.min_interval, - config_rep_req->u.clnt.max_interval)); - status = ZB_ZCL_STATUS_INVALID_VALUE; - } - } /* if !attr_desc*/ - } /* if direction == ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT */ - else - { - /* NOTE: For Reports receiving, a cluster (client, as usual) should support the same - attribute as server, who sends a report. It is implementation specific. */ - TRACE_MSG(TRACE_ZCL3, "recv report direction", (FMT__0)); - } - TRACE_MSG(TRACE_ZCL1, "<< check_config_rep_req status %hd", (FMT__H, status)); - - return status; -} - - -/*! @internal @brief ZCL configure reporting command handler - @param param - buffer number -*/ -/*! @internal @brief ZCL read reporting configuration command handler - @param param - buffer number -*/ -/** - *A device shall generate a read reporting configuration - *response command containing the details of the reporting configuration for each - *of the attributes specified in the command (see ZCL spec 2.4.10). - */ - -void zb_zcl_read_report_config_cmd_handler(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_uint8_t *resp_data; - zb_zcl_read_reporting_cfg_req_t read_rep_cfg_req; - zb_bool_t read_rep_conf_exist; - zb_uint8_t status; - zb_af_endpoint_desc_t *ep_desc; - zb_zcl_cluster_desc_t *cluster_desc; - zb_zcl_reporting_info_t *attr_rep_info = NULL; - zb_zcl_attr_t *attr_desc; - zb_uint16_t free_space = 0; - zb_uint8_t required_space = 0; - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_read_report_config_cmd_handler", (FMT__0)); - - /* ZCL spec, 2.4.10 Read Reporting Configuration Response Command */ - /* Read Reporting Configuration response - | ZCL header 3 b | Attr reporting config rec 1 XX b | Attr reporting config rec 2 XX b | ... - - Attr reporting config rec format - status 1 b | direction 1 b | attr id 2 b | attr data type 0/1 b - | minimum reporting interval 0/2 b | maximum reporting interval - 0/2 b | delta 0/Variable | timeout 0/2 b - */ - - /* ZCL frame format */ - /* frame control 1b | manufacturer code 0/2b | TSN 1b | cmd id 1b | payload XXb */ - - /* frame control */ - /* frame type | manufacturer specific | direction | disable default resp */ - - /* Construct packet header */ - /* Use runtime_buf buffer for composing and sending response, request buffer - * will be saved as runtime_buf */ - - resp_data = ZB_ZCL_START_PACKET(ZCL_CTX().runtime_buf); - - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_A( - resp_data, ZB_ZCL_FRAME_DIRECTION_TO_CLI, cmd_info->is_manuf_specific); - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT( - resp_data, cmd_info->seq_number, - cmd_info->is_manuf_specific, cmd_info->manuf_specific, - ZB_ZCL_CMD_READ_REPORT_CFG_RESP); - - ep_desc = zb_af_get_endpoint_desc(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - /* EP existence was checked on command accept - it must be in the list */ - ZB_ASSERT(ep_desc); - - cluster_desc = get_cluster_desc(ep_desc, cmd_info->cluster_id, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE); - /* Cluster existence was checked on command accept - it must be in the list */ - ZB_ASSERT(cluster_desc); - - do - { - /*Try to get attribute reporting configuration record from request */ - ZB_ZCL_GENERAL_GET_NEXT_READ_REP_CFG_REQ(param, read_rep_cfg_req, read_rep_conf_exist); - - if (read_rep_conf_exist) /*If successful (correct request record found) */ - { - TRACE_MSG(TRACE_ZCL1, ">> read_rep_cfg_req.direction = %d read_rep_cfg_req.attr_id = %d )", - (FMT__D_D, read_rep_cfg_req.direction ,read_rep_cfg_req.attr_id)); - - /* Get available free space in ZCL command buffer*/ - free_space = ZB_ZCL_GET_BYTES_AVAILABLE(ZCL_CTX().runtime_buf,resp_data, - cmd_info->profile_id, cmd_info->cluster_id); - - /*If there is no space for the smallest response record*/ - if(free_spacedata_p) /*Unsupported attribute*/ - { - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - } /*Unsupported attribute condition*/ - - else if (!(attr_desc->access & ZB_ZCL_ATTR_ACCESS_REPORTING)) /*Unreportable attribute*/ - { - status = ZB_ZCL_STATUS_UNREPORTABLE_ATTRIB; - } /*Unreportable attribute condition*/ - - else /*If attribute exists and it is reportable*/ - { - /*Try to get attr_rep_info for attr_id specified in the current - * request record*/ - attr_rep_info = zb_zcl_find_reporting_info(ep_desc->ep_id, - cluster_desc->cluster_id, - cluster_desc->role_mask, - read_rep_cfg_req.attr_id); - - - if(attr_rep_info) /*If requested attribute reporting info found*/ - { - TRACE_MSG(TRACE_ZCL1, "found requested attr_rep_info %p", (FMT__P, attr_rep_info)); - status = ZB_ZCL_STATUS_SUCCESS; /*Set status SUCCESS. See - * spec 2.4.10.1.2 */ - } /* if(attr_rep_info) */ - else /*If requested attribute reporting info not found*/ - { - TRACE_MSG(TRACE_ZCL1, "not found requested attr_rep_info %p", (FMT__P, attr_rep_info)); - status = ZB_ZCL_STATUS_NOT_FOUND; /*Set status - * NOT_FOUND. See - * spec 2.5.10.1.2 */ - } - } /*else If attribute exists and it is reportable*/ - - - - /*Create response record depending on status and direction fields*/ - switch(status) - { - case ZB_ZCL_STATUS_SUCCESS: - TRACE_MSG(TRACE_ZCL1, "setting SUCCESS status", (FMT__0)); - /*Calculate required free space for report record, depending on attribute direction value*/ - required_space = ZB_ZCL_READ_REPORTING_CFG_RES_SIZE; -/* - switch(read_rep_cfg_req.direction) - { - case ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT: - required_space = ZB_ZCL_READ_REPORTING_CFG_FOR_SEND_SIZE; - break; - case ZB_ZCL_CONFIGURE_REPORTING_RECV_REPORT: - required_space = ZB_ZCL_READ_REPORTING_CFG_FOR_RECV_SIZE; - break; - } */ /* switch(read_rep_cfg_req.direction) */ - - if(free_spacetype); /*Add data_type field*/ - ZB_ZCL_PACKET_PUT_2DATA16_VAL(resp_data, attr_rep_info->u.send_info.min_interval, /*Add min_interval field*/ - attr_rep_info->u.send_info.max_interval); /*Add max_interval field*/ - - /* If attribute data type is analog then we need to - add delta field that has the same type then the - attribute. Else this field shall be omitted. See - spec 2.4.10.1.7 */ - - if (zb_zcl_is_analog_data_type(attr_desc->type)) - { - switch (attr_desc->type) - { - case ZB_ZCL_ATTR_TYPE_U8: - ZB_ZCL_PACKET_PUT_DATA8(resp_data, attr_rep_info->u.send_info.delta.u8); /*Add 8-bit unsigned delta field*/ - break; - case ZB_ZCL_ATTR_TYPE_S8: - ZB_ZCL_PACKET_PUT_DATA8(resp_data, attr_rep_info->u.send_info.delta.s8); /*Add 8-bit signed delta field*/ - break; - case ZB_ZCL_ATTR_TYPE_U16: - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, attr_rep_info->u.send_info.delta.u16); /*Add 16-bit delta field*/ - break; - case ZB_ZCL_ATTR_TYPE_S16: - ZB_ZCL_PACKET_PUT_DATA16(resp_data, &attr_rep_info->u.send_info.delta.s16); /*Add signed 16-bit delta field*/ - break; - case ZB_ZCL_ATTR_TYPE_U24: - ZB_ZCL_PACKET_PUT_DATA24(resp_data, &attr_rep_info->u.send_info.delta.u24); /*Add 24-bit delta field*/ - break; - case ZB_ZCL_ATTR_TYPE_S24: - ZB_ZCL_PACKET_PUT_DATA24(resp_data, &attr_rep_info->u.send_info.delta.s24); /*Add signed 24-bit delta field*/ - break; - case ZB_ZCL_ATTR_TYPE_U32: - ZB_ZCL_PACKET_PUT_DATA32(resp_data, &attr_rep_info->u.send_info.delta.u32); /*Add 32-bit delta field*/ - break; - case ZB_ZCL_ATTR_TYPE_S32: - ZB_ZCL_PACKET_PUT_DATA32(resp_data, &attr_rep_info->u.send_info.delta.s32); /*Add signed 32-bit delta field*/ - break; - case ZB_ZCL_ATTR_TYPE_U48: - ZB_ZCL_PACKET_PUT_DATA48(resp_data, &attr_rep_info->u.send_info.delta.u48); /*Add 48-bit delta field*/ - break; - } - } - break; - case ZB_ZCL_CONFIGURE_REPORTING_RECV_REPORT: - TRACE_MSG(TRACE_ZCL1, "case ZB_ZCL_CONFIGURE_REPORTING_RECV_REPORT:", (FMT__0)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, attr_rep_info->u.recv_info.timeout); /*Add timeout field*/ - break; - } /* switch(read_rep_cfg_req.direction) */ - - } - break; /*case ZB_ZCL_STATUS_SUCCESS:*/ - - case ZB_ZCL_STATUS_UNSUP_ATTRIB: - case ZB_ZCL_STATUS_UNREPORTABLE_ATTRIB: - case ZB_ZCL_STATUS_NOT_FOUND: - /*We already have enough space for unsuccess report, so it is no need - * to check it again - */ - TRACE_MSG(TRACE_ZCL1, "setting UNSUCCESS status", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA8(resp_data, status); /*Add status field*/ - ZB_ZCL_PACKET_PUT_DATA8(resp_data, read_rep_cfg_req.direction); /*Add direction field*/ - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, read_rep_cfg_req.attr_id); /*Add attr_id field*/ - - TRACE_MSG(TRACE_ZCL1, "setting UNSUCCESS status end", (FMT__0)); - - break; - } /*switch(status)*/ - } /* if (read_rep_conf_exist)*/ - } while (read_rep_conf_exist); /* Stop if there are no more - * attribute reporting - * configuration records in - * request or there is not enough - * space in ZCL command buffer */ - TRACE_MSG(TRACE_ZCL1, "Finishing ZCL packet", (FMT__0)); - TRACE_MSG(TRACE_ZCL1, "Sending request", (FMT__0)); - ZB_ZCL_FINISH_N_SEND_PACKET(ZCL_CTX().runtime_buf, resp_data, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - NULL); - - /* Use runtime buffer to send request, use received buffer with - * request data_buf as runtime buffer */ - ZCL_CTX().runtime_buf = param; - - - TRACE_MSG(TRACE_ZCL1, "<>zb_zcl_configure_reporting_handler param %d, cmd_info %p", - (FMT__H_P, param, cmd_info)); - - /* ZCL spec, 2.4.7 Configure Reporting Command Frame */ - /* ZCL header | Attr reporting config record 1 | Attr reporting config record 2| ... */ - /* Attr reporting config record: | Direction = 0, 1b | attr id 2b | attr type 1b | min interval 1b | max interval 1b | delta XXb | */ - /* Attr reporting config record: | Direction = 1, 1b | attr id 2b | timeout XXb | */ - - ep_desc = zb_af_get_endpoint_desc(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - /* EP existence was checked on command accept - it must be in the list */ - ZB_ASSERT(ep_desc); - - cluster_desc = get_cluster_desc(ep_desc, cmd_info->cluster_id, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE); - /* Cluster existence was checked on command accept - it must be in the list */ - ZB_ASSERT(cluster_desc); - - /* Construct packet header */ - /* Use runtime_buf buffer for composing and sending response, request buffer - * will be saved as runtime_buf */ - resp_data = ZB_ZCL_START_PACKET(ZCL_CTX().runtime_buf); - - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_A( - resp_data, ZB_ZCL_FRAME_DIRECTION_TO_CLI, cmd_info->is_manuf_specific); - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT( - resp_data, cmd_info->seq_number, - cmd_info->is_manuf_specific, cmd_info->manuf_specific, - ZB_ZCL_CMD_CONFIG_REPORT_RESP); - - do - { - ZB_ZCL_GENERAL_GET_NEXT_CONFIGURE_REPORTING_REQ(param, config_rep_req); - - TRACE_MSG(TRACE_ZCL2, "config_rep_req %p", (FMT__P, config_rep_req)); - if (config_rep_req) - { - req_counter++; - - TRACE_MSG( - TRACE_ZCL3, - "direction %hd, attr_id %d, ", - (FMT__H_D, config_rep_req->direction, config_rep_req->attr_id)); - attr_desc = zb_zcl_get_attr_desc(cluster_desc, config_rep_req->attr_id); - TRACE_MSG(TRACE_ZCL3, "attr_desc %p", (FMT__P, attr_desc)); - - status = check_config_rep_req(config_rep_req, attr_desc); - - if (status == ZB_ZCL_STATUS_SUCCESS) - { - /* Accept reporting setting */ - zb_zcl_attr_addr_info_t addr_info; - - addr_info.src_ep = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - addr_info.cluster_id = cmd_info->cluster_id; - addr_info.dst_ep = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint; - addr_info.dst_short_addr = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr; - addr_info.profile_id = cmd_info->profile_id; - addr_info.cluster_role = (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE; - - ret = zb_zcl_put_reporting_info_from_req(config_rep_req, &addr_info); - if (ret != RET_OK) - { - TRACE_MSG(TRACE_ERROR, "Error saving reporting info %d", (FMT__D, ret)); - status = ZB_ZCL_STATUS_FAIL; - } - } - - if (status != ZB_ZCL_STATUS_SUCCESS) - { - /* Construct error response */ - zb_uint16_t bytes_avail; - error_status = ZB_TRUE; - - TRACE_MSG(TRACE_ZCL3, "put error status response", (FMT__0)); - bytes_avail = ZB_ZCL_GET_BYTES_AVAILABLE(ZCL_CTX().runtime_buf, resp_data, - cmd_info->profile_id, cmd_info->cluster_id); - if (bytes_avail >= sizeof(zb_zcl_configure_reporting_res_t)) - { - ZB_ZCL_PACKET_PUT_DATA8(resp_data, status); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, config_rep_req->direction); - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, config_rep_req->attr_id); - } - } - } /* if config_rep_req */ - else if (!req_counter) - { - /* no configuration record was read, error */ - error_status = ZB_TRUE; - TRACE_MSG(TRACE_ZCL3, "report error in packet", (FMT__0)); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_STATUS_MALFORMED_CMD); - } - } - while(config_rep_req); - - if (error_status == ZB_FALSE) - { - /* If no error found - report status Ok to all attrs, no attr id - * is needed */ - TRACE_MSG(TRACE_ZCL3, "report status OK", (FMT__0)); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_STATUS_SUCCESS); - } - - ZB_ZCL_FINISH_N_SEND_PACKET(ZCL_CTX().runtime_buf, resp_data, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - NULL); - - /* Use runtime buffer to send request, use received buffer with - * request data_buf as runtime buffer */ - ZCL_CTX().runtime_buf = param; - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_configure_reporting_handler", (FMT__0)); -} - - -void zb_zcl_send_report_attr_command(zb_zcl_reporting_info_t *rep_info, zb_uint8_t param) -{ - zb_uint8_t *cmd_data; - zb_zcl_reporting_info_t *cur_rep_info; - zb_zcl_attr_t *attr_desc; - zb_uint16_t bytes_avail; - zb_uint8_t attr_size; - zb_uint8_t send_mode; - zb_uint8_t is_manuf_spec; - - TRACE_MSG( - TRACE_ZCL1, - ">> zb_zcl_send_report_attr_command rep_info %p, param %hd", - (FMT__P_H, rep_info, param)); - - attr_desc = - zb_zcl_get_attr_desc_a(rep_info->ep, rep_info->cluster_id, rep_info->cluster_role, rep_info->attr_id); - - is_manuf_spec = !!ZB_ZCL_IS_ATTR_MANUF_SPEC(attr_desc); - - /* ZCL spec, 2.4.11 Report Attributes Command */ - /* Read attribute command - | ZCL header 3 b | Attr Report 1 XX b | Attr Report 1 XX b | ... - - Attr Report format - | attr id 2 b | Attr data type 1 b | attr value XX b | - */ - /* Construct packet header */ - /* Use buffer specified by input param */ - cmd_data = ZB_ZCL_START_PACKET(param); - - /* NOTE: currently, manufacturer specific is not supported */ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_REQ_FRAME_CONTROL_A( - cmd_data, ZB_ZCL_FRAME_DIRECTION_TO_CLI, - is_manuf_spec, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); - - if (is_manuf_spec) - { - zb_af_endpoint_desc_t *ep_desc = zb_af_get_endpoint_desc(rep_info->ep); - zb_zcl_cluster_desc_t *cluster_desc = get_cluster_desc(ep_desc, rep_info->cluster_id, rep_info->cluster_role); - - ZB_ASSERT(ep_desc && cluster_desc && cluster_desc->manuf_code != ZB_ZCL_MANUF_CODE_INVALID); - - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT(cmd_data, ZB_ZCL_GET_SEQ_NUM(), ZB_TRUE, cluster_desc->manuf_code, ZB_ZCL_CMD_REPORT_ATTRIB); - } - else - { - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(cmd_data, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_REPORT_ATTRIB); - } - - cur_rep_info = rep_info; - - while (cur_rep_info) - { - attr_desc = - zb_zcl_get_attr_desc_a(cur_rep_info->ep, cur_rep_info->cluster_id, cur_rep_info->cluster_role, cur_rep_info->attr_id); - TRACE_MSG(TRACE_ZCL3, "attr_desc %p", (FMT__P, attr_desc)); - - /* attribute description could not be absent, it is checked while accepting configure report - command */ - ZB_ASSERT(attr_desc); - - bytes_avail = ZB_ZCL_GET_BYTES_AVAILABLE(param, cmd_data, - cur_rep_info->dst.profile_id, cur_rep_info->cluster_id); - TRACE_MSG(TRACE_ZCL3, "bytes_avail %hd", (FMT__H, bytes_avail)); - - TRACE_MSG( - TRACE_ZCL3, - "attribute: id 0x%x, type 0x%hx", - (FMT__D_H, attr_desc->id, attr_desc->type)); - attr_size = zb_zcl_get_attribute_size(attr_desc->type, attr_desc->data_p); - TRACE_MSG(TRACE_ZCL3, "attr_size %hd", (FMT__H, attr_size)); - - /* Decrement read attr response by sizeof(zb_uint8_t), because attr value size is - * calculated separately by attr_size */ - if (bytes_avail >= (sizeof(zb_zcl_report_attr_req_t) - sizeof(zb_uint8_t) + attr_size)) - { - ZB_ZCL_PACKET_PUT_DATA16_VAL(cmd_data, attr_desc->id); - ZB_ZCL_PACKET_PUT_DATA8(cmd_data, attr_desc->type); - cmd_data = zb_zcl_put_attribute_value(cmd_data, attr_desc, attr_desc->data_p, attr_size); - - zb_zcl_save_reported_value(cur_rep_info, attr_desc); - - ZB_ZCL_CLR_REPORTING_FLAG(cur_rep_info, ZB_ZCL_REPORT_ATTR); - ZB_ZCL_CLR_REPORTING_FLAG(cur_rep_info, ZB_ZCL_REPORT_IS_ALLOWED); - ZB_ZCL_CLR_REPORTING_FLAG(cur_rep_info, ZB_ZCL_REPORT_TIMER_STARTED); - ZB_ZCL_SET_REPORTING_FLAG(cur_rep_info, ZB_ZCL_REPORT_IS_SENT); - } - else - { - TRACE_MSG(TRACE_ZCL1, "ERROR, buffer is full", (FMT__0)); - break; - } - - /* get next report info for sending report to the same remote device */ - cur_rep_info = zb_zcl_get_next_reporting_info(rep_info, is_manuf_spec); - TRACE_MSG(TRACE_ZCL1, "cur_rep_info %p", (FMT__P, cur_rep_info)); - } - - /* We should always use bindings for reporting (ZCL8, 2.5.7.1.2; ZCL8, 2.5.11.2) */ - send_mode = ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; - TRACE_MSG(TRACE_ZCL1, "ZCL_REPORT send mode ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT:", (FMT__0)); - - ZB_ZCL_FINISH_N_SEND_PACKET(param, cmd_data, - rep_info->dst.short_addr, - send_mode, - rep_info->dst.endpoint, - rep_info->ep /* src ep */, - rep_info->dst.profile_id, - rep_info->cluster_id, - zb_zcl_reporting_cb); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_send_report_attr_command ", (FMT__0)); -} - -#endif - -/*! @internal @brief ZCL discovery attributes handler - @param param - index of the buffer with discovery attributes request -*/ -static void zb_zcl_disc_attr_handler(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_af_endpoint_desc_t *ep_desc; - zb_zcl_cluster_desc_t *cluster_desc; - zb_zcl_attr_t *attr_desc; - zb_uint8_t *resp_data; - zb_zcl_disc_attr_req_t *disc_attr_req; - zb_uint8_t i, j; - zb_uint8_t *complete; - zb_bool_t extended = (zb_bool_t)(cmd_info->cmd_id == ZB_ZCL_CMD_DISCOVER_ATTR_EXT); - zb_uint32_t max_info_num; - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_disc_attr_handler param %hd extended %hd", - (FMT__H_H, param, extended)); - - /* ZCL8 spec, 2.5.13 Discovery Attributes Response Command - HA1.2 spec 12.1.6.1 Discovery Attributes Extended Response Command */ - /* Discovery attribute (extended) response - | Discovery complete 1 b | attribute information 1 4 b | attribute information 1 4 b | ... - - attribute information - | attr id 2 b | Attr data type 1 b | {Attribute access control 1 b - extended info} | - */ - - /* ZCL frame format */ - /* frame control 1b | manufacturer code 0/2b | TSN 1b | cmd id 1b | payload XXb */ - - /* frame control */ - /* frame type | manufacturer specific | direction | disable default resp */ - - /* TODO: implement correct parsing to get request (check command size, convert endianness if needed) */ - /* We are using the same structure/parsing utility for discover - * attr/discover attr extended because commands are completely identical */ - disc_attr_req = (zb_zcl_disc_attr_req_t*)zb_buf_begin(param); - TRACE_MSG(TRACE_ZCL2, "disc_attr_req %p", (FMT__P, disc_attr_req)); - - max_info_num = extended ? - (ZB_ZCL_HI_WO_IEEE_MAX_PAYLOAD_SIZE / sizeof(zb_zcl_disc_attr_ext_info_t)) : - (ZB_ZCL_HI_WO_IEEE_MAX_PAYLOAD_SIZE / sizeof(zb_zcl_disc_attr_info_t)); - - // ZB_ZCL_DISC_ATTR_MAX - max possibly number attr for send - if (disc_attr_req->maximum > max_info_num) - { - ZB_ASSERT(max_info_num <= ZB_UINT8_MAX); - disc_attr_req->maximum = (zb_uint8_t)max_info_num; - } - - /* Construct packet header */ - /* Use runtime_buf buffer for composing and sending response, request buffer - * will be saved as runtime_buf */ - resp_data = ZB_ZCL_START_PACKET(ZCL_CTX().runtime_buf); - - /* generate frame control taking into account manufacturer specific */ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_EXT( - resp_data, cmd_info->is_manuf_specific, ZB_ZCL_REVERT_DIRECTION(cmd_info->cmd_direction)); - - /* Generate command header taking into account manufacturer specific */ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT( - resp_data, cmd_info->seq_number, cmd_info->is_manuf_specific, cmd_info->manuf_specific, - (extended!=ZB_FALSE) ? ZB_ZCL_CMD_DISCOVER_ATTR_EXT_RES : ZB_ZCL_CMD_DISC_ATTRIB_RESP); - - ep_desc = zb_af_get_endpoint_desc(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - /* EP existence was checked on command accept - it must be in the list */ - ZB_ASSERT(ep_desc); - - cluster_desc = get_cluster_desc(ep_desc, cmd_info->cluster_id, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE); - /* Cluster existence was checked on command accept - it must be in the list */ - ZB_ASSERT(cluster_desc); - - // find start - attr_desc = cluster_desc->attr_desc_list; - - complete = resp_data; - /* There is the same beginning for both Discover Attr and Discover attr ext Resp */ - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_DISC_NON_COMPLETE); - - i = 0; - /* Decrement (cluster_desc->attr_count) by 1 because - the last record in cluster_desc->attr_desc_list contain is empty record */ - - if (cluster_desc->attr_count == 0U) - { - /* Special case: need to put ClusterRevision here */ - zb_uint16_t id = ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID; - - ZB_ZCL_PACKET_PUT_DATA16(resp_data, &id); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_ATTR_TYPE_U16); - if (extended) - { - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_ATTR_ACCESS_READ_ONLY); - } - *complete = ZB_ZCL_DISC_COMPLETE; - } - else - { - for (j = 0; j < cluster_desc->attr_count - 1U && i < disc_attr_req->maximum; j++) - { - TRACE_MSG(TRACE_ZCL2, "check attr_id %d", (FMT__D, attr_desc->id)); - if (attr_desc->id >= disc_attr_req->start_attr_id - && ZB_ZCL_ATTR_CHECK_INTERNAL_ID(attr_desc->id) == 0U) - { - if (extended) - { - /* For Discover Attr extended perform additional check - - * manufacturer specific data */ - TRACE_MSG(TRACE_ZCL2, "extended: check is_manuf spec %hd", - (FMT__H, cmd_info->is_manuf_specific)); - if (cmd_info->is_manuf_specific && ZB_ZCL_ATTR_CHECK_CUSTOM_ID(attr_desc->id) == 0U) - { - /* manufacturer specific attr is requested but this attr "common", skip it */ - TRACE_MSG(TRACE_ZCL2, "extended: skip NON manuf specific attr", (FMT__0)); - continue; - } - else if (!cmd_info->is_manuf_specific && ZB_ZCL_ATTR_CHECK_CUSTOM_ID(attr_desc->id) != 0U) - { - /* non-manufacturer specific attr is requested but this attr - * manufacturer specific, skip it */ - TRACE_MSG(TRACE_ZCL2, "extended: skip manuf spec attr", (FMT__0)); - continue; - } - else - { - /* MISRA rule 15.7 requires empty 'else' branch. */ - } - /* TODO: need to handle Manufacturer ID code somehow (compare - * it with this cluster/attribute manufacturer ID) but - * currently no Manufacturer specific ID is supported for the cluster */ - } - - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, attr_desc->id); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, attr_desc->type); - if (extended) - { - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_CONVERT_ATTR_ACCESS_BITMASK(attr_desc->access)); - } - i++; - } - attr_desc++; - } - - // correct complete field - *complete = (j < cluster_desc->attr_count - 1U) ? ZB_ZCL_DISC_NON_COMPLETE : ZB_ZCL_DISC_COMPLETE; - } - - ZB_ZCL_FINISH_N_SEND_PACKET(ZCL_CTX().runtime_buf, resp_data, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - NULL); - - /* Use runtime buffer to send request, use received buffer with - * request data_buf as runtime buffer */ - ZCL_CTX().runtime_buf = param; - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_handle_general_commands param %hd", (FMT__H, param)); - - TRACE_MSG(TRACE_ZCL1, ">cmd_id 0x%hd cluster 0x%x", (FMT__H_D, cmd_info->cmd_id, cmd_info->cluster_id)); - - switch (cmd_info->cmd_id) - { - case ZB_ZCL_CMD_READ_ATTRIB: -/* [AV] fantastic side effect for read attribute! - Time is not 0 or 42 only on PC */ - zb_zcl_read_attr_handler(param); - processed = ZB_TRUE; - break; - - case ZB_ZCL_CMD_READ_ATTRIB_RESP: - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_CMD_READ_ATTRIB_RESP", (FMT__0)); - -#if defined ZB_SE_COMMISSIONING || (defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && defined ZB_ZCL_ENABLE_WWAH_SERVER) - if (ZCL_SELECTOR().read_attr_resp_handler != NULL) - { - processed = ZCL_SELECTOR().read_attr_resp_handler(param); - } -#endif /* ZB_SE_COMMISSIONING || (ZB_ZCL_SUPPORT_CLUSTER_WWAH && ZB_ZCL_ENABLE_WWAH_SERVER) */ - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_TIME) - if (!processed && (ZB_ZCL_CLUSTER_ID_TIME == cmd_info->cluster_id)) - { - processed = zb_zcl_time_server_read_attr_handle(param); - } -#endif - /*cstat !MISRAC2012-Rule-14.3_a */ - /* The 'processed' variable is defined in the beginning of this function and never takes a - * value different than 'ZB_FALSE' due to several reasons: - * Since 'ZB_ZDO_PERIODIC_CHECKIN_BLOCK_ZCL_CMD()' always returns 'ZB_FALSE', the 'if' statement - * above is never evaluated as true and the value of 'processed' never changes. A deviation - * record has been added; - * Parts of the current 'case' clause which change the value of 'processed' are disabled using - * '#ifdef' guards. - */ - if (!processed) - { - zb_zcl_read_attr_resp_handler(param); - processed = ZB_TRUE; - } - break; - - case ZB_ZCL_CMD_WRITE_ATTRIB: - TRACE_MSG(TRACE_ZCL2, "CMD_WRITE_ATTRIB default handler", (FMT__0)); - zb_zcl_write_attr_handler(param); - processed = ZB_TRUE; - break; - - case ZB_ZCL_CMD_WRITE_ATTRIB_RESP: - /* TODO: implement default response handler with notifying - * user about received attribute value via callback */ - zb_buf_free(param); - processed = ZB_TRUE; - break; - -#if !(defined ZB_ZCL_DISABLE_REPORTING) -#ifdef ZB_ZCL_ENABLE_DEFAULT_REPORT_ATTR_PROCESSING - case ZB_ZCL_CMD_REPORT_ATTRIB: - TRACE_MSG(TRACE_ZCL2, "CMD_REPORT_ATTRIB default handler", (FMT__0)); - zb_zcl_report_attr_cmd_handler(param); - processed = ZB_TRUE; - break; -#endif - - case ZB_ZCL_CMD_CONFIG_REPORT: - TRACE_MSG(TRACE_ZCL2, "CMD_CONFIG_REPORT default handler", (FMT__0)); - zb_zcl_configure_reporting_handler(param); - processed = ZB_TRUE; - break; - - case ZB_ZCL_CMD_CONFIG_REPORT_RESP: - TRACE_MSG(TRACE_ZCL2, "CMD_CONFIG_REPORT default handler", (FMT__0)); - zb_buf_free(param); - processed = ZB_TRUE; - break; - - case ZB_ZCL_CMD_READ_REPORT_CFG: - TRACE_MSG(TRACE_ZCL2, "CMD_READ_REPORT_CONFIG default handler", (FMT__0)); - zb_zcl_read_report_config_cmd_handler(param); - processed = ZB_TRUE; - break; - - case ZB_ZCL_CMD_READ_REPORT_CFG_RESP: - /* Nothing to do - just skip it */ - break; - -#endif - - case ZB_ZCL_CMD_WRITE_ATTRIB_UNDIV: - TRACE_MSG(TRACE_ZCL2, "CMD_WRITE_ATTRIB_UNDIV default handler", (FMT__0)); - zb_zcl_write_attr_handler(param); - processed = ZB_TRUE; - break; - - case ZB_ZCL_CMD_WRITE_ATTRIB_NO_RESP: - TRACE_MSG(TRACE_ZCL2, "CMD_WRITE_ATTRIB_NO_RESP default handler", (FMT__0)); - zb_zcl_write_attr_handler(param); - processed = ZB_TRUE; - break; - - case ZB_ZCL_CMD_DISC_ATTRIB: - TRACE_MSG(TRACE_ZCL2, "CMD_DISC_ATTRIB default handler", (FMT__0)); - zb_zcl_disc_attr_handler(param); - processed = ZB_TRUE; - break; - - case ZB_ZCL_CMD_DISC_ATTRIB_RESP: - break; - - case ZB_ZCL_CMD_DEFAULT_RESP: - TRACE_MSG(TRACE_ZCL2, "ZB_ZCL_CMD_DEFAULT_RESP", (FMT__0)); - processed = zb_zcl_handle_default_response_commands(param); - /*cstat !MISRAC2012-Rule-14.3_a */ - if (!processed) - { - /** @mdr{00026,0} */ - zb_buf_free(param); - processed = ZB_TRUE; - } - break; - -#ifdef ZB_ENABLE_HA - case ZB_ZCL_CMD_DISCOVER_COMMANDS_RECEIVED: - zb_zcl_discover_commands_res(param, ZB_TRUE); - processed = ZB_TRUE; - break; - - case ZB_ZCL_CMD_DISCOVER_COMMANDS_GENERATED: - zb_zcl_discover_commands_res(param, ZB_FALSE); - processed = ZB_TRUE; - break; - - case ZB_ZCL_CMD_DISCOVER_ATTR_EXT: - TRACE_MSG(TRACE_ZCL2, "CMD_DISC_ATTR_EXTENDED default handler", (FMT__0)); - zb_zcl_disc_attr_handler(param); - processed = ZB_TRUE; - break; - - - case ZB_ZCL_CMD_DISCOVER_COMMANDS_RECEIVED_RES: - case ZB_ZCL_CMD_DISCOVER_COMMANDS_GENERATED_RES: - case ZB_ZCL_CMD_DISCOVER_ATTR_EXT_RES: - /* Nothing to do - just skip it */ - break; - -#endif /* ZB_ENABLE_HA */ - - default: - TRACE_MSG(TRACE_ERROR, "unknown ZCL cmd", (FMT__0)); - break; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_handle_general_commands processed %hd", (FMT__H, processed)); - return processed; -}/* zb_bool_t zb_zcl_handle_general_commands(zb_uint8_t param) */ - - -static zb_bool_t zb_zcl_handle_default_response_commands(zb_uint8_t param) -{ - zb_bool_t processed; - /*cstat !MISRAC2012-Rule-2.2_c */ - /* Even if both '#if' in this function evaluate to false, cmd_info is used in a trace message in - * the end of this function. */ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_handle_default_response_commands param %hd", (FMT__H, param)); - - /* MISRA Rule 16.6 - * Switch-case statements must have at least two switch-clauses. This was not verified in the - * previous switch when at least one of the switch-clauses was disabled with '#if defined' guards. - * Removed switch and a if-else structure is now used. */ - -#if defined ZB_ZCL_ENABLE_DEFAULT_OTA_UPGRADE_PROCESSING - if (cmd_info->cluster_id == ZB_ZCL_CLUSTER_ID_OTA_UPGRADE) - { - /* There was a call to - * processed = zb_zcl_process_ota_upgrade_default_response_commands(param); - * Now OTA server processes ZB_ZCL_CMD_DEFAULT_RESP itself. - * That is done to exclude calling of OTA srv not via cluster handler. - * Removing that dependency excludes OTA code linking if OTA is not declared by the app. */ - processed = zb_zcl_handle_specific_commands(param); - } - else -#endif /* defined ZB_ZCL_ENABLE_DEFAULT_OTA_UPGRADE_PROCESSING */ -#if defined ZB_ZCL_ENABLE_DEFAULT_TUNNEL_PROCESSING - if (cmd_info->cluster_id == ZB_ZCL_CLUSTER_ID_TUNNEL) - { - processed = zb_zcl_process_tunnel_default_response_commands(param) == RET_OK; - } - else -#endif /* defined ZB_ZCL_ENABLE_DEFAULT_TUNNEL_PROCESSING */ - { - TRACE_MSG(TRACE_ZCL1, "Cluster 0x%04x was not processed", (FMT__D, cmd_info->cluster_id)); - processed = ZB_FALSE; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_handle_default_response_commands processed %hd", - (FMT__H, processed)); - return processed; -} /* zb_uint8_t zb_zcl_handle_default_response_commands(zb_uint8_t param) */ - - -#if defined ZB_ENABLE_HA - -static zb_bool_t zb_zcl_compare_current_role(zb_uint8_t endpoint, zb_uint8_t direction, zb_uint16_t cluster_id) -{ - zb_bool_t ret = ZB_FALSE; - zb_zcl_cluster_desc_t *cluster_desc = NULL; - zb_af_endpoint_desc_t *endpoint_desc; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_compare_current_role endpoint %hd, direction %hd, cluster_id %d", - (FMT__H_H_D, endpoint, direction, cluster_id)); - - endpoint_desc = zb_af_get_endpoint_desc(endpoint); - if(endpoint_desc != NULL) - { - cluster_desc = get_cluster_desc(endpoint_desc, cluster_id, - (direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE); - } - - if (cluster_desc != NULL) - { - ret = (zb_bool_t)(((direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) && (cluster_desc->role_mask & ZB_ZCL_CLUSTER_SERVER_ROLE)) || - ((direction == ZB_ZCL_FRAME_DIRECTION_TO_CLI) && (cluster_desc->role_mask & ZB_ZCL_CLUSTER_CLIENT_ROLE))); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_compare_current_role ret %hd", (FMT__H, ret)); - return ret; -} - -zb_uint8_t zb_zcl_get_cmd_list_by_cluster_id(zb_zcl_cluster_handler_t cluster_id, - zb_bool_t is_received, zb_uint8_t **cmd_list); - -void zb_zcl_discover_commands_res(zb_uint8_t param, zb_bool_t recv_cmd_type) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_zcl_disc_cmd_req_t cmd_req; - zb_uint8_t *cmd_list = NULL; - zb_uint8_t cmd_count = 0; - zb_zcl_parse_status_t status; - - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_discover_commands_res param %hd, recv_cmd_type %hd", - (FMT__H_H, param, recv_cmd_type)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), - sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_GENERAL_GET_DISC_COMMAND(&cmd_req, param, status); - - if (status!=ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of Discovery Command", - (FMT__0)); - - zb_zcl_send_default_handler(param, &cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - } - else - { - if (cmd_info.is_manuf_specific) - { - if(ZCL_CTX().disc_manuf_cmd_cb != NULL) - { - cmd_count = (*ZCL_CTX().disc_manuf_cmd_cb)(cmd_info.cmd_direction, cmd_info.addr_data.common_data.dst_endpoint, - cmd_info.cluster_id, cmd_info.manuf_specific, recv_cmd_type, &cmd_list); - } - } - else - { - if( zb_zcl_compare_current_role(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.cmd_direction, cmd_info.cluster_id) ) - { - zb_zcl_cluster_handler_t cluster_handler; - - cluster_handler = zb_zcl_get_cluster_handler_internal(cmd_info.addr_data.common_data.dst_endpoint, - cmd_info.cluster_id, - (cmd_info.cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE); - - if (cluster_handler) - { - if ( cluster_handler(ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM) ) - { - if(recv_cmd_type) - { - cmd_count = ZCL_CTX().zb_zcl_cluster_cmd_list->received_cnt; - cmd_list = ZCL_CTX().zb_zcl_cluster_cmd_list->received; - ZCL_CTX().zb_zcl_cluster_cmd_list = NULL; - } - else - { - cmd_count = ZCL_CTX().zb_zcl_cluster_cmd_list->generated_cnt; - cmd_list = ZCL_CTX().zb_zcl_cluster_cmd_list->generated; - ZCL_CTX().zb_zcl_cluster_cmd_list = NULL; - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "Commands list not supported for Cluster 0x%04x", (FMT__D, cmd_info.cluster_id)); - cmd_count = 0; - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "Can't resolve Cluster 0x%04x (not loaded or no commands)", (FMT__D, cmd_info.cluster_id)); - cmd_count = 0; - } - } - } - - // create response - { - zb_uint8_t cmd_for_receive = 0; - zb_uint8_t i; - zb_uint8_t j; - zb_uint8_t *cmd_ptr; - zb_uint8_t *complete_ptr; - - cmd_for_receive = (ZB_ZCL_HI_WO_IEEE_MAX_PAYLOAD_SIZE - sizeof(zb_zcl_disc_cmd_resp_t)) / sizeof(zb_uint8_t); - if (cmd_for_receive > cmd_req.maximum) - { - cmd_for_receive = cmd_req.maximum; - } - - ZB_ZCL_GENERAL_INIT_DISC_COMMAND_RESP(cmd_ptr, param, - ZB_ZCL_REVERT_DIRECTION(cmd_info.cmd_direction), - cmd_info.seq_number, - (recv_cmd_type!=ZB_FALSE ? ZB_ZCL_CMD_DISCOVER_COMMANDS_RECEIVED_RES : - ZB_ZCL_CMD_DISCOVER_COMMANDS_GENERATED_RES), - cmd_info.is_manuf_specific, - cmd_info.manuf_specific, - ZB_ZCL_DISC_CMD_NOT_COMPLETE); - - complete_ptr = cmd_ptr-1; - - j = 0; - for(i = 0; i < cmd_count; i++) - { - if (cmd_list[i] >= cmd_req.start_cmd_id) - { - ZB_ZCL_GENERAL_ADD_DISC_COMMAND_RESP(cmd_ptr, cmd_list[i]); - j++; - if (j >= cmd_for_receive) - { - break; - } - } - } - - if (i>=cmd_count) - { - *complete_ptr = ZB_ZCL_DISC_CMD_COMPLETE; - } - - /* send response */ - ZB_ZCL_GENERAL_FINISH_DISC_COMMAND_RESP(param, cmd_ptr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - cmd_info.cluster_id); - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_discover_commands_res", (FMT__0)); -} - -#endif /* ZB_ENABLE_HA */ - -#endif /* ZB_ENABLE_ZCL */ diff --git a/zboss/development/src/zcl/zcl_groups.c b/zboss/development/src/zcl/zcl_groups.c deleted file mode 100644 index 931491f913..0000000000 --- a/zboss/development/src/zcl/zcl_groups.c +++ /dev/null @@ -1,1014 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Groups cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2067 - -#include "zb_common.h" - -#if defined ZB_ENABLE_ZCL - -#include "zb_zcl.h" -#include "zb_zdo.h" -#include "zb_aps.h" - -#if defined ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING \ - || defined ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING_CLIENT -zb_uint8_t gs_groups_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_GROUPS_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_groups_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_GROUPS_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_groups_client_cmd_list = -{ - sizeof(gs_groups_client_received_commands), gs_groups_client_received_commands, - sizeof(gs_groups_server_received_commands), gs_groups_server_received_commands -}; - -zb_discover_cmd_list_t gs_groups_server_cmd_list = -{ - sizeof(gs_groups_server_received_commands), gs_groups_server_received_commands, - sizeof(gs_groups_client_received_commands), gs_groups_client_received_commands -}; -#endif /* defined ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING - * || defined ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING_CLIENT */ - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_GROUPS) - -#ifdef ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING - -static void add_group_handler(zb_uint8_t param, zb_bool_t check_identifying); -static void view_group_handler(zb_uint8_t param); -static void get_group_membership_handler(zb_uint8_t param); -static void remove_group_handler(zb_uint8_t param); -static void remove_all_groups_handler(zb_uint8_t param); - -static zb_ret_t aps_status_to_zcl_status(zb_ret_t aps_status); -static void dummy_handler(zb_uint8_t unused); - -zb_ret_t check_value_groups_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -zb_bool_t zb_zcl_process_groups_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_groups_commands_cli(zb_uint8_t param); - -void zb_zcl_groups_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_GROUPS, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_groups_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_groups_commands_srv); -} - -void zb_zcl_groups_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_GROUPS, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_groups_commands_cli); -} - -zb_ret_t check_value_groups_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} -/* -zb_bool_t zb_zcl_process_groups_commands_mixed(zb_uint8_t param) -{ - zb_bool_t processed = ZB_FALSE; - processed = zb_zcl_process_groups_commands_srv(param); -#ifdef ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING_CLIENT - if (!processed) - { - processed = zb_zcl_process_groups_commands_cli(param); - } -#endif - return processed; -} -*/ -zb_bool_t zb_zcl_process_groups_commands_srv(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t *cmd_info; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_groups_server_cmd_list; - return ZB_TRUE; - } - - cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_groups_commands_srv: param %hd",(FMT__H, param)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_GROUPS == cmd_info->cluster_id); - - TRACE_MSG(TRACE_ZCL2, "direction %hd, cmd_id %hd", - (FMT__H_H, cmd_info->cmd_direction, cmd_info->cmd_id)); - if (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) - { - switch (cmd_info->cmd_id) - { - case ZB_ZCL_CMD_GROUPS_ADD_GROUP: - add_group_handler(param, ZB_FALSE); - break; - - case ZB_ZCL_CMD_GROUPS_VIEW_GROUP: - view_group_handler(param); - break; - - case ZB_ZCL_CMD_GROUPS_GET_GROUP_MEMBERSHIP: - get_group_membership_handler(param); - break; - - case ZB_ZCL_CMD_GROUPS_REMOVE_GROUP: - remove_group_handler(param); - break; - - case ZB_ZCL_CMD_GROUPS_REMOVE_ALL_GROUPS: - remove_all_groups_handler(param); - break; - - case ZB_ZCL_CMD_GROUPS_ADD_GROUP_IF_IDENTIFYING: - add_group_handler(param, ZB_TRUE); - break; - - default: - TRACE_MSG(TRACE_ZCL2, "cmd not supported", (FMT__0)); - processed = ZB_FALSE; - } - } - else - { - TRACE_MSG(TRACE_ZCL2, "direction - to client, skip cmd", (FMT__0)); - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_groups_commands_srv: ret %hd", (FMT__H, processed)); - return processed; -} - -static void add_group_send_default_resp(zb_uint8_t param, zb_zcl_parsed_hdr_t *cmd_info, zb_ret_t status) -{ - TRACE_MSG(TRACE_ZCL1, ">> add_group_send_default_resp", (FMT__0)); - - TRACE_MSG(TRACE_ZCL2, "disable_default_response %hd", (FMT__H, cmd_info->disable_default_response)); - - if (ZB_ZCL_CHECK_IF_SEND_DEFAULT_RESP(*cmd_info, status)) - { - ZB_ZCL_SEND_DEFAULT_RESP( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - cmd_info->seq_number, - cmd_info->cmd_id, - status); - } - else - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "<< add_group_send_default_resp", (FMT__0)); -} - -static void add_group_cb_send_default_resp(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_apsme_add_group_conf_t *conf_param; - zb_ret_t status; - - TRACE_MSG(TRACE_ZCL1, ">> add_group_cb_send_default_resp, param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, zb_buf_begin(param), sizeof(zb_zcl_parsed_hdr_t)); - conf_param = ZB_BUF_GET_PARAM(param, zb_apsme_add_group_conf_t); - status = aps_status_to_zcl_status(conf_param->status); - - /* Send default response, if enabled */ - add_group_send_default_resp(param, &cmd_info, status); - - TRACE_MSG(TRACE_ZCL1, "<< add_group_cb_send_default_resp", (FMT__0)); -} - -static void add_group_send_add_group_resp(zb_uint8_t param, zb_zcl_parsed_hdr_t *cmd_info, - zb_ret_t status, zb_uint16_t group_id) -{ - zb_uint8_t *resp_data; - - TRACE_MSG(TRACE_ZCL1, ">> add_group_send_add_group_resp", (FMT__0)); - - /* Construct response packet header */ - resp_data = ZB_ZCL_START_PACKET(param); - - /* NOTE: currently, manufacturer specific is not supported */ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(resp_data); - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(resp_data, cmd_info->seq_number, ZB_ZCL_CMD_GROUPS_ADD_GROUP_RES); - - /* Add group response format, ZCL8 spec 3.6.2.4.1 */ - /* | status 1b | group id 2b | */ - - ZB_ZCL_PACKET_PUT_DATA8(resp_data, status); - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, group_id); - - ZB_ZCL_FINISH_N_SEND_PACKET(param, resp_data, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - NULL); - - TRACE_MSG(TRACE_ZCL1, "<< add_group_send_add_group_resp", (FMT__0)); -} - -static void add_group_cb_send_add_group_resp(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_apsme_add_group_conf_t *conf_param; - zb_ret_t status; - - TRACE_MSG(TRACE_ZCL1, ">> add_group_cb_send_add_group_resp, param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, zb_buf_begin(param), sizeof(zb_zcl_parsed_hdr_t)); - - conf_param = ZB_BUF_GET_PARAM(param, zb_apsme_add_group_conf_t); - status = aps_status_to_zcl_status(conf_param->status); - - add_group_send_add_group_resp(param, &cmd_info, status, conf_param->group_address); - - TRACE_MSG(TRACE_ZCL1, "<< add_group_cb_send_add_group_resp", (FMT__0)); -} - -static void add_group_handler(zb_uint8_t param, zb_bool_t check_identifying) -{ - zb_zcl_groups_add_group_req_t add_group_req; - zb_apsme_add_group_req_t *aps_req; - zb_ret_t status = ZB_ZCL_STATUS_SUCCESS; - zb_bool_t add_group = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_zcl_parsed_hdr_t *resp_cmd_info = NULL; - zb_bool_t respond_with_default_resp = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, ">> add_group_handler param %hd, check_identifying %hd", - (FMT__H_H, param, check_identifying)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - /* ZCL8 spec. 3.6.2.3.7.2 Effect on Receipt (for Add Group If Identifying Command) - * 1. The device verifies that it is currently identifying itself... - */ - if (check_identifying) - { - add_group = zb_zcl_is_identifying(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint) - ? ZB_TRUE : ZB_FALSE; - TRACE_MSG(TRACE_ZCL2, "add_group %hd", (FMT__H, add_group)); - } - - if (add_group) - { - ZB_ZCL_GROUPS_GET_ADD_GROUP_REQ(param, add_group_req); - - TRACE_MSG( - TRACE_ZCL2, - "group_id %d, ep %hd", - (FMT__D_H, add_group_req.group_id, ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)); - - /* ZCL8 spec. 3.6.2.3.2.2, 3.6.2.3.7.2: The device verifies that the Group ID field contains a valid group identifier - * in the range 0x0001 – 0xfff7. If the Group ID field contains a group identifier outside this range, - * the status SHALL be INVALID_VALUE and the device continues from step 5.*/ - if (add_group_req.group_id >= ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_MIN_VALUE && - add_group_req.group_id <= ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_MAX_VALUE) - { - zb_buf_reuse(param); - - aps_req = ZB_BUF_GET_PARAM(param, zb_apsme_add_group_req_t); - aps_req->group_address = add_group_req.group_id; - aps_req->endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - /* According to ZB spec, we should use appropriate ZDO functions to - * call APS. In this case command result is returned via - * confirmation - call to callback. - * To simplify current implementation, call APS directly: - * result will be received immediately. - * To improve source code and to use ZDO, need to implement hash to - * store cmd_info - it is need to send response to peer. */ - /* zb_apsme_add_group_request calls ZDO_RUN_CALLBACK_BY_INDEX that - kills buffer if callback not found; register dummy handler - to avoid this situation. */ - - aps_req->confirm_cb = NULL; - - if (!check_identifying) - { - if (ZB_APS_FC_GET_DELIVERY_MODE(cmd_info.addr_data.common_data.fc) == ZB_APS_DELIVERY_UNICAST) - { - aps_req->confirm_cb = add_group_cb_send_add_group_resp; - } - } - else - { - aps_req->confirm_cb = add_group_cb_send_default_resp; - } - - resp_cmd_info = zb_buf_initial_alloc(param, sizeof(zb_zcl_parsed_hdr_t)); - ZB_MEMCPY(resp_cmd_info, &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - - zb_zdo_add_group_req(param); - } - else - { - TRACE_MSG(TRACE_ERROR, "Error, invalid group ID for add group request", (FMT__0)); - status = ZB_ZCL_STATUS_INVALID_VALUE; - - if (!check_identifying) - { - if (ZB_APS_FC_GET_DELIVERY_MODE(cmd_info.addr_data.common_data.fc) == ZB_APS_DELIVERY_UNICAST) - { - add_group_send_add_group_resp(param, &cmd_info, status, add_group_req.group_id); - } - else - { - /* Broadcast or Groupcast Add Group - drop packet */ - zb_buf_free(param); - } - } - else - { - respond_with_default_resp = ZB_TRUE; - } - } - } - else - /* ZCL8 spec. 3.6.2.3.7.2 Effect on Receipt (for Add Group If Identifying Command) - * 1. ... If the device it not currently identifying itself ... - */ - { - respond_with_default_resp = ZB_TRUE; - } /* id add_group */ - - if (respond_with_default_resp) - { - if (!add_group) - { - TRACE_MSG(TRACE_ZCL2, "Can't add group - no identifying", (FMT__0)); - /* ZCL8 spec. 3.6.2.3.7.2 Effect on Receipt (for Add Group If Identifying Command) - * 1. ...If the device it not currently identifying - * itself, the Add Group If Identifying command was received as unicast and a default response is - * requested, the device SHALL generate a Default Response command with the Status field set to - * SUCCESS and SHALL transmit it back to the originator of the Add Group If Identifying command... - * Test spec, G-TC-02S - status should be SUCCESS. - */ - status = ZB_ZCL_STATUS_SUCCESS; - } - - add_group_send_default_resp(param, &cmd_info, status); - } - - TRACE_MSG(TRACE_ZCL1, "<< add_group_handler", (FMT__0)); -} - - -static void view_group_handler(zb_uint8_t param) -{ - zb_zcl_groups_view_group_req_t view_group_req; - zb_uint8_t *resp_data; - zb_uint8_t status = ZB_ZCL_STATUS_SUCCESS; - zb_apsme_get_group_membership_req_t *aps_req; - zb_apsme_get_group_membership_conf_t *conf; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, ">> view_group_handler %hd", (FMT__H, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - ZB_ZCL_GROUPS_GET_VIEW_GROUP_REQ(param, view_group_req); - - if (view_group_req.group_id >= ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_MIN_VALUE && - view_group_req.group_id <= ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_MAX_VALUE) - { - zb_buf_reuse(param); - aps_req = zb_buf_initial_alloc(param, sizeof(zb_apsme_get_group_membership_req_t)); - - aps_req->n_groups = 1; - aps_req->groups[0] = view_group_req.group_id; - aps_req->endpoint = cmd_info.addr_data.common_data.dst_endpoint; - - /* TODO: do not rely on function synchronicity and send response from confirm_cb */ - /* See comment to zb_apsme_add_group_request() call */ - aps_req->confirm_cb = dummy_handler; - zb_zdo_get_group_membership_req(param); - conf = ZB_BUF_GET_PARAM(param, zb_apsme_get_group_membership_conf_t); - - TRACE_MSG(TRACE_ZCL2, "n_groups %hd", (FMT__H, conf->n_groups)); - if (!conf->n_groups) - { - status = ZB_ZCL_STATUS_NOT_FOUND; - } - TRACE_MSG(TRACE_ZCL2, "zcl status %hx", (FMT__H, status)); - } - else - { - TRACE_MSG(TRACE_ERROR, "Error, invalid group ID for view group request", (FMT__0)); - status = ZB_ZCL_STATUS_INVALID_VALUE; - } - - /** [ZB_ZCL_CONSTRUCT_FRAME_HEADER] */ - /* Construct response packet header */ - resp_data = ZB_ZCL_START_PACKET(param); - - /* NOTE: currently, manufacturer specific is not supported */ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(resp_data); - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( - resp_data, - cmd_info.seq_number, - ZB_ZCL_CMD_GROUPS_VIEW_GROUP_RES); - /** [ZB_ZCL_CONSTRUCT_FRAME_HEADER] */ - - /* View group response format, ZCL8 spec 3.6.2.4.2.1 */ - /* | status 1b | group id 2b | Group name XXb| */ - - ZB_ZCL_PACKET_PUT_DATA8(resp_data, status); - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, view_group_req.group_id); - /* Group name currently is not supported */ - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_NULL_STRING); - - ZB_ZCL_FINISH_N_SEND_PACKET(param, resp_data, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - cmd_info.cluster_id, - NULL); - - TRACE_MSG(TRACE_ZCL1, "<< view_group_handler", (FMT__0)); -} - - -static void get_group_membership_handler(zb_uint8_t param) -{ - zb_zcl_groups_get_group_membership_req_t *get_member_req; - zb_uint8_t *resp_data; - zb_apsme_get_group_membership_req_t *aps_req; - zb_apsme_get_group_membership_conf_t *conf; - zb_ushort_t i; - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t recv_pkt_is_valid = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, ">> get_group_membership_handler", (FMT__0)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - ZB_ZCL_GROUPS_GET_GROUP_MEMBERSHIP_REQ(param, get_member_req); - TRACE_MSG(TRACE_ZCL2, "get_member_req %p", (FMT__P, get_member_req)); - - recv_pkt_is_valid = (get_member_req) ? ZB_TRUE : ZB_FALSE; - - if (recv_pkt_is_valid) - { - TRACE_MSG(TRACE_ZCL2, "group count %hd", (FMT__H, get_member_req->group_count)); - - /* use runtime buffer - to simplify passing parameters, just copy - * it to the beginning of this buffer */ - zb_buf_reuse(ZCL_CTX().runtime_buf); - aps_req = zb_buf_initial_alloc( - ZCL_CTX().runtime_buf, - ( sizeof(zb_apsme_get_group_membership_req_t) - + (get_member_req->group_count - 1) * sizeof(zb_uint16_t))); - - aps_req->n_groups = get_member_req->group_count; - ZB_MEMCPY(aps_req->groups, get_member_req->group_id, - get_member_req->group_count * sizeof(zb_uint16_t)); - - /* TODO: do not rely on function synchronicity and send response from confirm_cb */ - aps_req->confirm_cb = dummy_handler; - aps_req->endpoint = cmd_info.addr_data.common_data.dst_endpoint; - zb_zdo_get_group_membership_req(ZCL_CTX().runtime_buf); - - TRACE_MSG(TRACE_ZCL2, "get conf...", (FMT__0)); - conf = ZB_BUF_GET_PARAM(ZCL_CTX().runtime_buf, zb_apsme_get_group_membership_conf_t); - } - - /* Construct response packet header */ - resp_data = ZB_ZCL_START_PACKET(param); - - /* NOTE: currently, manufacturer specific is not supported */ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(resp_data); - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( - resp_data, - cmd_info.seq_number, - ZB_ZCL_CMD_GROUPS_GET_GROUP_MEMBERSHIP_RES); - - if (recv_pkt_is_valid) - { - TRACE_MSG( - TRACE_ZCL2, - "capacity %hd, n_groups %hd", - (FMT__H_H, conf->capacity, conf->n_groups)); - - /* Get group membership response format, ZCL8 spec 3.6.2.4.3.1 */ - /* | capacity 1b | group count 1b | Group id 2b x NN | */ - - ZB_ZCL_PACKET_PUT_DATA8(resp_data, conf->capacity); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, conf->n_groups); - for (i = 0; i < conf->n_groups; i++) - { - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, conf->groups[i]); - } - } - else - { - TRACE_MSG(TRACE_ERROR, "Error in received packet, send empty response", (FMT__0)); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, 0); - ZB_ZCL_PACKET_PUT_DATA8(resp_data, 0); - } - - ZB_ZCL_FINISH_N_SEND_PACKET(param, resp_data, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - cmd_info.cluster_id, - NULL); - - TRACE_MSG(TRACE_ZCL1, "<< view_group_handler", (FMT__0)); -} - - -static void remove_group_send_remove_group_resp(zb_uint8_t param, zb_zcl_parsed_hdr_t *cmd_info, - zb_ret_t status, zb_uint16_t group_id) -{ - zb_uint8_t *resp_data; - - TRACE_MSG(TRACE_ZCL1, ">> remove_group_send_remove_group_resp", (FMT__0)); - - /* Construct response packet header */ - resp_data = ZB_ZCL_START_PACKET(param); - - /* NOTE: currently, manufacturer specific is not supported */ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(resp_data); - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( - resp_data, - cmd_info->seq_number, - ZB_ZCL_CMD_GROUPS_REMOVE_GROUP_RES); - - /* Remove group response format, ZCL8 spec 3.6.2.4.4.1 */ - /* | status 1b | group id 2b | */ - - ZB_ZCL_PACKET_PUT_DATA8(resp_data, status); - ZB_ZCL_PACKET_PUT_DATA16_VAL(resp_data, group_id); - - ZB_ZCL_FINISH_N_SEND_PACKET(param, resp_data, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - NULL); - - TRACE_MSG(TRACE_ZCL1, "<< remove_group_send_remove_group_resp", (FMT__0)); -} - -static void remove_group_cb_send_remove_group_resp(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_apsme_remove_group_conf_t *conf_param; - zb_ret_t status; - - TRACE_MSG(TRACE_ZCL1, ">> remove_group_cb_send_remove_group_resp, param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, zb_buf_begin(param), sizeof(zb_zcl_parsed_hdr_t)); - - conf_param = ZB_BUF_GET_PARAM(param, zb_apsme_remove_group_conf_t); - status = aps_status_to_zcl_status(conf_param->status); - - TRACE_MSG(TRACE_ZCL2, "zcl status %hx", (FMT__H, status)); - - remove_group_send_remove_group_resp(param, &cmd_info, status, conf_param->group_address); - - TRACE_MSG(TRACE_ZCL1, "<< remove_group_cb_send_remove_group_resp", (FMT__0)); -} - - -static void remove_group_handler(zb_uint8_t param) -{ - zb_zcl_groups_remove_group_req_t rem_group_req; - zb_apsme_remove_group_req_t *aps_req; - zb_ret_t status = ZB_ZCL_STATUS_SUCCESS; - zb_zcl_parsed_hdr_t cmd_info; - zb_zcl_parsed_hdr_t *resp_cmd_info; - - TRACE_MSG(TRACE_ZCL1, ">> remove_group_handler", (FMT__0)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - ZB_ZCL_GROUPS_GET_REMOVE_GROUP_REQ(param, rem_group_req); - TRACE_MSG(TRACE_ZCL2, "group_id %d", (FMT__D, rem_group_req.group_id)); - - zb_buf_reuse(param); - - resp_cmd_info = zb_buf_initial_alloc(param, sizeof(zb_zcl_parsed_hdr_t)); - ZB_MEMCPY(resp_cmd_info, &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - - if (rem_group_req.group_id >= ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_MIN_VALUE && - rem_group_req.group_id <= ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_MAX_VALUE) - { - aps_req = ZB_BUF_GET_PARAM(param, zb_apsme_remove_group_req_t); - aps_req->group_address = rem_group_req.group_id; - aps_req->endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_SCENES - /* Remove associated scenes */ - zb_buf_get_out_delayed_ext(zb_zcl_scenes_remove_all_scenes_in_all_endpoints_by_group_id, - rem_group_req.group_id, 0); -#endif - - /* See comment for zb_apsme_add_group_request() call */ - aps_req->confirm_cb = remove_group_cb_send_remove_group_resp; - zb_zdo_remove_group_req(param); - } - else - { - TRACE_MSG(TRACE_ERROR, "Error, invalid group ID for remove group request", (FMT__0)); - status = ZB_ZCL_STATUS_INVALID_VALUE; - - remove_group_send_remove_group_resp(param, &cmd_info, status, rem_group_req.group_id); - } - - TRACE_MSG(TRACE_ZCL1, "<< remove_group_handler", (FMT__0)); -} - - -static void remove_all_groups_cb_send_default_resp(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_apsme_remove_all_groups_conf_t *conf_param; - zb_uint8_t *resp_data; - zb_ret_t status; - - TRACE_MSG(TRACE_ZCL1, ">> remove_all_groups_cb_send_default_resp, param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, zb_buf_begin(param), sizeof(zb_zcl_parsed_hdr_t)); - - conf_param = ZB_BUF_GET_PARAM(param, zb_apsme_remove_all_groups_conf_t); - - /* Map APS status to ZCL status */ - status = aps_status_to_zcl_status(conf_param->status); - - /* If no groups founded answer with success status. See ZCL8 Spec 3.6.2.3.6.2 */ - if (status == ZB_ZCL_STATUS_NOT_FOUND) - { - status = ZB_ZCL_STATUS_SUCCESS; - } - - TRACE_MSG(TRACE_ZCL2, "zcl status %hx", (FMT__H, status)); - - /* Construct response packet header */ - resp_data = ZB_ZCL_START_PACKET(param); - - /* NOTE: currently, manufacturer specific is not supported */ - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(resp_data); - ZB_ZCL_CONSTRUCT_COMMAND_HEADER( - resp_data, - cmd_info.seq_number, - ZB_ZCL_CMD_GROUPS_REMOVE_GROUP_RES); - - /* Send default response, if enabled */ - TRACE_MSG(TRACE_ZCL2, "disable_default_response %hd", (FMT__H, cmd_info.disable_default_response)); - if (!cmd_info.disable_default_response) - { - ZB_ZCL_SEND_DEFAULT_RESP( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - cmd_info.cluster_id, - cmd_info.seq_number, - cmd_info.cmd_id, - status); - } - else - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "<< remove_all_groups_cb_send_default_resp", (FMT__0)); -} - - -static void remove_all_groups_handler(zb_uint8_t param) -{ - zb_apsme_remove_all_groups_req_t *aps_req; - zb_zcl_parsed_hdr_t cmd_info; - zb_zcl_parsed_hdr_t *resp_cmd_info; - - TRACE_MSG(TRACE_ZCL1, ">> remove_all_groups_handler", (FMT__0)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - zb_buf_reuse(param); - - resp_cmd_info = zb_buf_initial_alloc(param, sizeof(zb_zcl_parsed_hdr_t)); - ZB_MEMCPY(resp_cmd_info, &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - - aps_req = ZB_BUF_GET_PARAM(param, zb_apsme_remove_all_groups_req_t); - aps_req->endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_SCENES - /* Remove scenes associated with every group in every endpoint */ - zb_buf_get_out_delayed(zb_zcl_scenes_remove_all_scenes_in_all_endpoints); -#endif - - /* See comment for zb_apsme_add_group_request() call */ - aps_req->confirm_cb = remove_all_groups_cb_send_default_resp; - zb_zdo_remove_all_groups_req(param); - - TRACE_MSG(TRACE_ZCL1, "<< remove_all_groups_handler", (FMT__0)); -} - - -static zb_ret_t aps_status_to_zcl_status(zb_ret_t aps_status) -{ - zb_ret_t zcl_status; - - switch (aps_status) - { - case ERROR_CODE(ERROR_CATEGORY_APS, ZB_APS_STATUS_TABLE_FULL): - zcl_status = ZB_ZCL_STATUS_INSUFF_SPACE; - break; - - case ERROR_CODE(ERROR_CATEGORY_APS, ZB_APS_STATUS_INVALID_GROUP): - zcl_status = ZB_ZCL_STATUS_NOT_FOUND; - break; - - case ERROR_CODE(ERROR_CATEGORY_APS, ZB_APS_STATUS_SUCCESS): - zcl_status = ZB_ZCL_STATUS_SUCCESS; - break; - - default: - zcl_status = ZB_ZCL_STATUS_FAIL; - break; - } - - return zcl_status; -} - - -/* Just do nothing, used as gag */ -static void dummy_handler(zb_uint8_t unused) -{ - ZVUNUSED(unused); -} - -#endif /* ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING */ - - -#ifdef ZB_COMPILE_ZCL_SAMPLE -void send_add_group_cmd(zb_bufid_t data_buf, zb_uint16_t prof_id, zb_uint16_t group_id, zb_uint16_t dst_addr, - zb_uint8_t dst_ep, zb_uint8_t src_ep) -{ - - ZB_ZCL_GROUPS_SEND_ADD_GROUP_REQ(data_buf, dst_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, src_ep, prof_id, ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL, group_id); - -} - -void parse_add_group_res(zb_bufid_t buf) -{ - zb_zcl_groups_add_group_res_t *add_group_res; - - ZB_ZCL_GROUPS_GET_ADD_GROUP_RES(buf, add_group_res); - - TRACE_MSG(TRACE_ZCL1, "Response status %hd, group_id %d", - (FMT__H_D, add_group_res->status, add_group_res->group_id)); -} - -void send_view_group_cmd(zb_bufid_t data_buf,zb_uint16_t prof_id, zb_uint16_t group_id, zb_uint16_t dst_addr, - zb_uint8_t dst_ep, zb_uint8_t src_ep) -{ - - ZB_ZCL_GROUPS_SEND_VIEW_GROUP_REQ( - data_buf, - dst_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, - src_ep, - prof_id, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL, - group_id); - -} - -void parse_view_group_res(zb_bufid_t buf) -{ - zb_zcl_groups_view_group_res_t *view_group_res; - - ZB_ZCL_GROUPS_GET_VIEW_GROUP_RES(buf, view_group_res); - - TRACE_MSG(TRACE_ZCL1, "Response status %hd, group_id %d", - (FMT__H_D, view_group_res->status, view_group_res->group_id)); -} - - -void send_get_group_membership_cmd(zb_bufid_t data_buf, zb_uint16_t prof_id, zb_uint16_t dst_addr, - zb_uint8_t dst_ep, zb_uint8_t src_ep) -{ - zb_uint8_t *ptr; - -#define TEST_GROUP_COUNT 3 -#define TEST_GROUP_ID1 12 -#define TEST_GROUP_ID2 13 -#define TEST_GROUP_ID3 14 - - ZB_ZCL_GROUPS_INIT_GET_GROUP_MEMBERSHIP_REQ( - data_buf, - ptr, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - TEST_GROUP_COUNT); - - ZB_ZCL_GROUPS_ADD_ID_GET_GROUP_MEMBERSHIP_REQ(ptr, TEST_GROUP_ID1); - ZB_ZCL_GROUPS_ADD_ID_GET_GROUP_MEMBERSHIP_REQ(ptr, TEST_GROUP_ID2); - ZB_ZCL_GROUPS_ADD_ID_GET_GROUP_MEMBERSHIP_REQ(ptr, TEST_GROUP_ID3); - - ZB_ZCL_GROUPS_SEND_GET_GROUP_MEMBERSHIP_REQ( - data_buf, ptr, dst_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, src_ep, prof_id, NULL); - -} - -void send_remove_group_cmd(zb_bufid_t data_buf, zb_uint16_t prof_id, zb_uint16_t group_id, zb_uint16_t dst_addr, - zb_uint8_t dst_ep, zb_uint8_t src_ep) -{ - - ZB_ZCL_GROUPS_SEND_REMOVE_GROUP_REQ(data_buf, dst_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, src_ep, prof_id, ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL, group_id); - -} - -void parse_remove_group_res(zb_bufid_t buf) -{ - zb_zcl_groups_remove_group_res_t *rem_group_res; - - ZB_ZCL_GROUPS_GET_REMOVE_GROUP_RES(buf, rem_group_res); - - TRACE_MSG(TRACE_ZCL1, "Response status %hd, group_id %d", - (FMT__H_D, rem_group_res->status, rem_group_res->group_id)); -} - -void send_remove_all_groups_cmd(zb_bufid_t data_buf, zb_uint16_t prof_id, zb_uint16_t dst_addr, - zb_uint8_t dst_ep, zb_uint8_t src_ep) -{ - - ZB_ZCL_GROUPS_SEND_REMOVE_ALL_GROUPS_REQ(data_buf, dst_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, src_ep, prof_id, ZB_ZCL_ENABLE_DEFAULT_RESPONSE, NULL); - -} - -void send_add_group_if_ident_cmd( - zb_bufid_t data_buf, - zb_uint16_t prof_id, - zb_uint16_t group_id, - zb_uint16_t dst_addr, - zb_uint8_t dst_ep, - zb_uint8_t src_ep) -{ - - ZB_ZCL_GROUPS_SEND_ADD_GROUP_IF_IDENT_REQ(data_buf, dst_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, src_ep, prof_id, ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL, group_id); - -} - - -#endif /* ZB_COMPILE_ZCL_SAMPLE */ - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_GROUPS */ - -#ifdef ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING_CLIENT - -zb_bool_t zb_zcl_process_groups_commands_cli(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_groups_commands_cli: param %hd",(FMT__H, param)); - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_groups_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_GROUPS); - - TRACE_MSG(TRACE_ZCL2, "direction %hd, cmd_id %hd", - (FMT__H_H, cmd_info.cmd_direction, cmd_info.cmd_id)); - if (cmd_info.cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_CLI) - { - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_GROUPS_ADD_GROUP_RES: - case ZB_ZCL_CMD_GROUPS_VIEW_GROUP_RES: - case ZB_ZCL_CMD_GROUPS_GET_GROUP_MEMBERSHIP: - case ZB_ZCL_CMD_GROUPS_REMOVE_GROUP_RES: - /* Do nothing, just send default response if necessary */ - if (!cmd_info.disable_default_response) - { - ZB_ZCL_SEND_DEFAULT_RESP( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - cmd_info.cluster_id, - cmd_info.seq_number, - cmd_info.cmd_id, - ZB_ZCL_STATUS_SUCCESS); - } - else - { - zb_buf_free(param); - } - processed = ZB_TRUE; - break; - - default: - TRACE_MSG(TRACE_ZCL2, "cmd not supported", (FMT__0)); - processed = ZB_FALSE; - } - } - else - { - TRACE_MSG(TRACE_ZCL2, "direction - to server, skip cmd", (FMT__0)); - processed = ZB_FALSE; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_groups_commands_cli: ret %hd", (FMT__H, processed)); - return processed; -} - -#endif /* ZB_ZCL_ENABLE_DEFAULT_GROUPS_PROCESSING_CLIENT */ - -#endif /* ZB_ENABLE_ZCL */ diff --git a/zboss/development/src/zcl/zcl_ias_ace_commands.c b/zboss/development/src/zcl/zcl_ias_ace_commands.c deleted file mode 100644 index e11a65e45b..0000000000 --- a/zboss/development/src/zcl/zcl_ias_ace_commands.c +++ /dev/null @@ -1,1066 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL IAS ACE cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2068 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_IAS_ACE) - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_ias_ace.h" -#include "zcl/zb_zcl_ias_zone.h" -/** @internal - @{ -*/ - -zb_uint8_t gs_ias_ace_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_IAS_ACE_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_ias_ace_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_IAS_ACE_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_ias_ace_client_cmd_list = -{ - sizeof(gs_ias_ace_client_received_commands), gs_ias_ace_client_received_commands, - sizeof(gs_ias_ace_server_received_commands), gs_ias_ace_server_received_commands -}; - -zb_discover_cmd_list_t gs_ias_ace_server_cmd_list = -{ - sizeof(gs_ias_ace_server_received_commands), gs_ias_ace_server_received_commands, - sizeof(gs_ias_ace_client_received_commands), gs_ias_ace_client_received_commands -}; - -zb_bool_t zb_zcl_process_ias_ace_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_ias_ace_specific_commands_cli(zb_uint8_t param); - -void zb_zcl_ias_ace_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_IAS_ACE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_ias_ace_specific_commands_srv); -} - -void zb_zcl_ias_ace_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_IAS_ACE, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_ias_ace_specific_commands_cli); -} - -static zb_zcl_status_t zb_zcl_ias_ace_map_ret_code_to_zcl_status(zb_ret_t ret_code) -{ - ZB_ASSERT(ret_code != RET_BUSY); - - return zb_zcl_get_zcl_status_from_ret(ret_code); -} - -static zb_uint8_t zb_zcl_ias_ace_get_zone_table_length(zb_uint8_t endpoint) -{ - zb_zcl_attr_t *attr_desc; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ACE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ACE_ZONE_TABLE_LENGTH_ID); - ZB_ASSERT(attr_desc); - - return ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); -} - -static zb_zcl_ias_ace_zone_table_t* zb_zcl_ias_ace_get_zone_table(zb_uint8_t endpoint) -{ - zb_zcl_attr_t *attr_desc; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ACE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ACE_ZONE_TABLE_ID); - ZB_ASSERT(attr_desc); - - return (zb_zcl_ias_ace_zone_table_t *)attr_desc->data_p; -} - -/** @brief Arm command */ -static zb_ret_t zb_zcl_ias_ace_arm_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_arm_t pl_in; - zb_zcl_ias_ace_arm_resp_t pl_out; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_arm_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - ZB_BZERO(&pl_out, sizeof(pl_out)); - - ZB_ZCL_IAS_ACE_GET_ARM_REQ(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_ARM_REQ", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - if (pl_in.arm_mode > ZB_ZCL_IAS_ACE_ARM_MODE_ALL || - pl_in.zone_id > ZB_ZCL_IAS_ACE_ZONE_ID_MAX_VALUE) - { - ret = RET_INVALID_PARAMETER; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_ARM_CB_ID, RET_OK, cmd_info, &pl_in, &pl_out); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - ZB_ZCL_IAS_ACE_SEND_ARM_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->seq_number, - pl_out.arm_notification); - - ret = RET_BUSY; - } - else - { - ret = RET_ERROR; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_arm_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Bypass command */ -static zb_ret_t zb_zcl_ias_ace_bypass_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_bypass_t pl_in; - zb_zcl_ias_ace_bypass_resp_t pl_out; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_bypass_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - ZB_BZERO(&pl_out, sizeof(pl_out)); - - ZB_ZCL_IAS_ACE_GET_BYPASS_REQ(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_BYPASS_REQ", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t *ptr; - zb_uint16_t i; - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_BYPASS_CB_ID, RET_OK, cmd_info, &pl_in, &pl_out); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - ZB_ZCL_IAS_ACE_SEND_BYPASS_RESP_START(param, - cmd_info->seq_number, pl_out.length, ptr); - - for (i = 0; i < pl_out.length; i++) - { - ZB_ZCL_IAS_ACE_SEND_BYPASS_RESP_ADD(ptr, pl_out.bypass_result[i]); - } - - ZB_ZCL_IAS_ACE_SEND_BYPASS_RESP_END(ptr, param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id); - - ret = RET_BUSY; - } - else - { - ret = RET_ERROR; - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_bypass_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Emergency command */ -static zb_ret_t zb_zcl_ias_ace_emergency_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_emergency_handler %hx", (FMT__H, param)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_EMERGENCY_CB_ID, RET_OK, cmd_info, NULL, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_emergency_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Fire command */ -static zb_ret_t zb_zcl_ias_ace_fire_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_fire_handler %hx", (FMT__H, param)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_FIRE_CB_ID, RET_OK, cmd_info, NULL, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_fire_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Panic command */ -static zb_ret_t zb_zcl_ias_ace_panic_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_panic_handler %hx", (FMT__H, param)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_PANIC_CB_ID, RET_OK, cmd_info, NULL, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_panic_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Get Zone ID Map command */ -static zb_ret_t zb_zcl_ias_ace_get_zone_id_map_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_ias_ace_get_zone_id_map_resp_t zone_id_map_resp; - zb_zcl_ias_ace_zone_table_t *table; - zb_uint16_t length; - zb_uint16_t i; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_get_zone_id_map_handler %hx", (FMT__H, param)); - - ZB_BZERO(&zone_id_map_resp, sizeof(zone_id_map_resp)); - length = zb_zcl_ias_ace_get_zone_table_length(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - table = zb_zcl_ias_ace_get_zone_table(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - - for (i = 0; i < length; i++) - { - if (table[i].zone_type != ZB_ZCL_IAS_ZONE_ZONETYPE_INVALID) - { - zone_id_map_resp.zone_id_map[table[i].zone_id / 16] |= (1 << (table[i].zone_id % 16)); - } - } - - ZB_ZCL_IAS_ACE_SEND_GET_ZONE_ID_MAP_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->seq_number, - zone_id_map_resp.zone_id_map); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_get_zone_id_map_handler", (FMT__0)); - - return RET_BUSY; -} - -/** @brief Get Zone Information command */ -static zb_ret_t zb_zcl_ias_ace_get_zone_info_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_get_zone_info_t payload; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_get_zone_info_handler %hx", (FMT__H, param)); - - ZB_BZERO(&payload, sizeof(payload)); - - ZB_ZCL_IAS_ACE_GET_GET_ZONE_INFO_REQ(&payload, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_GET_ZONE_INFO_REQ", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - if (payload.zone_id > ZB_ZCL_IAS_ACE_ZONE_ID_MAX_VALUE) - { - ret = RET_INVALID_PARAMETER; - } - else - { - zb_ieee_addr_t def_address; - zb_char_t def_zone_label = ZB_ZCL_NULL_STRING; - zb_zcl_ias_ace_zone_table_t *table; - zb_uint16_t length; - zb_uint16_t i; - - ZB_ZCL_IAS_ACE_SET_ZONE_ADDRESS_DEFAULT_VALUE(def_address); - - length = zb_zcl_ias_ace_get_zone_table_length(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - table = zb_zcl_ias_ace_get_zone_table(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - - for (i = 0; i < length; i++) - { - if (table[i].zone_id == payload.zone_id) - { - break; - } - } - - ZB_ZCL_IAS_ACE_SEND_GET_ZONE_INFO_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->seq_number, - payload.zone_id, - (i < length ? table[i].zone_type : ZB_ZCL_IAS_ZONE_ZONETYPE_INVALID), - (i < length ? table[i].zone_address : def_address), - (i < length ? (table[i].zone_label ? table[i].zone_label : &def_zone_label) : &def_zone_label)); - - ret = RET_BUSY; - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_get_zone_info_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Get Panel Status command */ -static zb_ret_t zb_zcl_ias_ace_get_panel_status_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_get_panel_status_resp_t pl_out; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_get_panel_status_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_out, sizeof(pl_out)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_GET_PANEL_STATUS_CB_ID, RET_OK, cmd_info, NULL, &pl_out); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - ZB_ZCL_IAS_ACE_SEND_GET_PANEL_STATUS_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, cmd_info->seq_number, - pl_out.panel_status, pl_out.seconds_remaining, - pl_out.aud_notification, pl_out.alarm_status); - - ret = RET_BUSY; - } - else - { - ret = RET_ERROR; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_get_panel_status_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Get Bypassed Zone List command */ -static zb_ret_t zb_zcl_ias_ace_get_bypassed_zone_list_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_uint8_t *ptr; - zb_uint16_t i; - zb_zcl_ias_ace_set_bypassed_zone_list_t pl_out; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_get_bypassed_zone_list_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_out, sizeof(pl_out)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_GET_BYPASSED_ZONE_LIST_CB_ID, RET_OK, cmd_info, NULL, &pl_out); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_START_RESP(param, - cmd_info->seq_number, pl_out.length, ptr); - - for (i = 0; i < pl_out.length; i++) - { - ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_ADD(ptr, pl_out.zone_id[i]); - } - - ZB_ZCL_IAS_ACE_SEND_SET_BYPASSED_ZONE_LIST_END(ptr, param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, NULL); - - ret = RET_BUSY; - } - else - { - ret = RET_ERROR; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_get_bypassed_zone_list_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Get Zone Status command */ -static zb_ret_t zb_zcl_ias_ace_get_zone_status_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_get_zone_status_t pl_in; - zb_zcl_ias_ace_get_zone_status_resp_t pl_out; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_get_zone_status_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - ZB_BZERO(&pl_out, sizeof(pl_out)); - - ZB_ZCL_IAS_ACE_GET_GET_ZONE_STATUS_REQ(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_GET_ZONE_STATUS_REQ", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - if (pl_in.starting_zone_id + pl_in.max_num_zone_ids > ZB_ZCL_IAS_ACE_ZONE_TABLE_LENGTH) - { - ret = RET_INVALID_PARAMETER; - } - else - { - zb_uint8_t *ptr; - zb_uint16_t i; - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_GET_ZONE_STATUS_CB_ID, RET_OK, cmd_info, &pl_in, &pl_out); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_RESP_START(param, - cmd_info->seq_number, pl_out.zone_status_complete, pl_out.length, ptr); - - for (i = 0; i < pl_out.length; i++) - { - ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_RESP_ADD(ptr, - pl_out.zone_id_status[i].zone_id, pl_out.zone_id_status[i].zone_status); - } - - ZB_ZCL_IAS_ACE_SEND_GET_ZONE_STATUS_RESP_END(ptr, param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id); - - ret = RET_BUSY; - } - else - { - ret = RET_ERROR; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_get_zone_status_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Arm Response command */ -static zb_ret_t zb_zcl_ias_ace_arm_resp_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_arm_resp_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_arm_resp_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_IAS_ACE_GET_ARM_RESP(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_ARM_RESP", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_ARM_RESP_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_arm_resp_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Get Zone ID Map Response command */ -static zb_ret_t zb_zcl_ias_ace_get_zone_id_map_resp_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_get_zone_id_map_resp_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_get_zone_id_map_resp_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_IAS_ACE_GET_GET_ZONE_ID_MAP_RESP(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_GET_ZONE_ID_MAP_RESP", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_GET_ZONE_ID_MAP_RESP_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_get_zone_id_map_resp_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Get Zone Info Response command */ -static zb_ret_t zb_zcl_ias_ace_get_zone_info_resp_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_get_zone_info_resp_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_get_zone_info_resp_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_IAS_ACE_GET_GET_ZONE_INFO_RESP(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_GET_ZONE_INFO_RESP", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_GET_ZONE_INFO_RESP_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_get_zone_info_resp_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Zone Status Changed command */ -static zb_ret_t zb_zcl_ias_ace_zone_status_changed_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_zone_status_changed_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_zone_status_changed_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_IAS_ACE_GET_ZONE_STATUS_CHANGED_REQ(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_ZONE_STATUS_CHANGED_REQ", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_ZONE_STATUS_CHANGED_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_zone_status_changed_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Panel Status Changed command */ -static zb_ret_t zb_zcl_ias_ace_panel_status_changed_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_panel_status_changed_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_panel_status_changed_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_IAS_ACE_GET_PANEL_STATUS_CHANGED_REQ(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_PANEL_STATUS_CHANGED_REQ", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_PANEL_STATUS_CHANGED_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_panel_status_changed_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Get Panel Status Response command */ -static zb_ret_t zb_zcl_ias_ace_get_panel_status_resp_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_get_panel_status_resp_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_get_panel_status_resp_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_IAS_ACE_GET_GET_PANEL_STATUS_RESP(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_GET_PANEL_STATUS_RESP", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_GET_PANEL_STATUS_RESP_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_get_panel_status_resp_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Set Bypassed Zone List command */ -static zb_ret_t zb_zcl_ias_ace_set_bypassed_zone_list_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_set_bypassed_zone_list_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_set_bypassed_zone_list_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_IAS_ACE_GET_SET_BYPASSED_ZONE_LIST(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_SET_BYPASSED_ZONE_LIST", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_SET_BYPASSED_ZONE_LIST_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_set_bypassed_zone_list_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Bypass Response command */ -static zb_ret_t zb_zcl_ias_ace_bypass_resp_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_bypass_resp_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_bypass_resp_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_IAS_ACE_GET_BYPASS_RESP(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_BYPASS_RESP", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_BYPASS_RESP_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_bypass_resp_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -/** @brief Get Zone Status Response command */ -static zb_ret_t zb_zcl_ias_ace_get_zone_status_resp_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_ace_get_zone_status_resp_t pl_in; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_ace_get_zone_status_resp_handler %hx", (FMT__H, param)); - - ZB_BZERO(&pl_in, sizeof(pl_in)); - - ZB_ZCL_IAS_ACE_GET_GET_ZONE_STATUS_RESP(&pl_in, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ACE_GET_GET_ZONE_STATUS_RESP", (FMT__0)); - - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_IAS_ACE_GET_ZONE_STATUS_RESP_CB_ID, RET_OK, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_ace_get_zone_status_resp_handler ret %hx", (FMT__H, ret)); - - return ret; -} - -zb_bool_t zb_zcl_process_ias_ace_specific_commands_srv(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - - if (ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_ias_ace_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, - "> zb_zcl_process_ias_ace_specific_commands_srv: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_IAS_ACE == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_IAS_ACE_ARM_ID: - ret = zb_zcl_ias_ace_arm_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_BYPASS_ID: - ret = zb_zcl_ias_ace_bypass_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_EMERGENCY_ID: - ret = zb_zcl_ias_ace_emergency_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_FIRE_ID: - ret = zb_zcl_ias_ace_fire_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_PANIC_ID: - ret = zb_zcl_ias_ace_panic_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_GET_ZONE_ID_MAP_ID: - ret = zb_zcl_ias_ace_get_zone_id_map_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_GET_ZONE_INFO_ID: - ret = zb_zcl_ias_ace_get_zone_info_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_GET_PANEL_STATUS_ID: - ret = zb_zcl_ias_ace_get_panel_status_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_GET_BYPASSED_ZONE_LIST_ID: - ret = zb_zcl_ias_ace_get_bypassed_zone_list_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_GET_ZONE_STATUS_ID: - ret = zb_zcl_ias_ace_get_zone_status_handler(param, &cmd_info); - break; - default: - processed = ZB_FALSE; - break; - } - - if (processed && ret != RET_BUSY) - { - zb_zcl_send_default_handler(param, &cmd_info, - zb_zcl_ias_ace_map_ret_code_to_zcl_status(ret)); - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_ias_ace_specific_commands_srv: processed %d", - (FMT__D, processed)); - - return processed; -} - -zb_bool_t zb_zcl_process_ias_ace_specific_commands_cli(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - - if (ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_ias_ace_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, - "> zb_zcl_process_ias_ace_specific_commands_cli: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_IAS_ACE == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction); - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_IAS_ACE_ARM_RESP_ID: - ret = zb_zcl_ias_ace_arm_resp_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_GET_ZONE_ID_MAP_RESP_ID: - ret = zb_zcl_ias_ace_get_zone_id_map_resp_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_GET_ZONE_INFO_RESP_ID: - ret = zb_zcl_ias_ace_get_zone_info_resp_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_ZONE_STATUS_CHANGED_ID: - ret = zb_zcl_ias_ace_zone_status_changed_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_PANEL_STATUS_CHANGED_ID: - ret = zb_zcl_ias_ace_panel_status_changed_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_GET_PANEL_STATUS_RESPONSE_ID: - ret = zb_zcl_ias_ace_get_panel_status_resp_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_SET_BYPASSED_ZONE_LIST_ID: - ret = zb_zcl_ias_ace_set_bypassed_zone_list_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_BYPASS_RESPONSE_ID: - ret = zb_zcl_ias_ace_bypass_resp_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_IAS_ACE_GET_ZONE_STATUS_RESPONSE_ID: - ret = zb_zcl_ias_ace_get_zone_status_resp_handler(param, &cmd_info); - break; - - default: - processed = ZB_FALSE; - break; - } - - if (processed && ret != RET_BUSY) - { - zb_zcl_send_default_handler(param, &cmd_info, - zb_zcl_ias_ace_map_ret_code_to_zcl_status(ret)); - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_ias_ace_specific_commands_cli: processed %d", - (FMT__D, processed)); - - return processed; -} - -/** - * @} internal -*/ -#endif /* ZB_ZCL_SUPPORT_CLUSTER_IAS_ACE */ diff --git a/zboss/development/src/zcl/zcl_ias_wd_commands.c b/zboss/development/src/zcl/zcl_ias_wd_commands.c deleted file mode 100644 index cfab610d20..0000000000 --- a/zboss/development/src/zcl/zcl_ias_wd_commands.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL IAS WD cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2069 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_IAS_WD) - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zb_zdo.h" -#include "zb_aps.h" -#include "zcl/zb_zcl_ias_wd.h" -#include "zcl/zb_zcl_ias_zone.h" -/** @internal - @{ -*/ - -zb_uint8_t gs_ias_wd_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_IAS_WD_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_ias_wd_client_cmd_list = -{ - 0, NULL, - sizeof(gs_ias_wd_server_received_commands), gs_ias_wd_server_received_commands -}; - -zb_discover_cmd_list_t gs_ias_wd_server_cmd_list = -{ - sizeof(gs_ias_wd_server_received_commands), gs_ias_wd_server_received_commands, - 0, NULL -}; - -zb_ret_t check_value_ias_wd_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -zb_bool_t zb_zcl_process_ias_wd_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_ias_wd_specific_commands_cli(zb_uint8_t param); - -void zb_zcl_ias_wd_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_IAS_WD, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_ias_wd_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_ias_wd_specific_commands_srv); -} - -void zb_zcl_ias_wd_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_IAS_WD, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_ias_wd_specific_commands_cli); -} - -zb_ret_t check_value_ias_wd_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - ZVUNUSED(endpoint); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_IAS_WD_MAX_DURATION_ID: - ret = (ZB_ZCL_ATTR_GET16(value) <= ZB_ZCL_ATTR_IAS_WD_MAX_DURATION_MAX_VALUE) ? RET_OK : RET_ERROR; - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_ias_wd ret %hd", (FMT__H, ret)); - return ret; -} -/* Invoke User App for "Start Warning" command - */ -void zb_zcl_ias_wd_start_warning_invoke_user_app(zb_uint8_t param) -{ - zb_zcl_ias_wd_start_warning_user_app_schedule_t* invoke_data = - ZB_BUF_GET_PARAM(param, zb_zcl_ias_wd_start_warning_user_app_schedule_t); - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t result; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_wd_start_warning_invoke_user_app param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, &(invoke_data->cmd_info), sizeof(zb_zcl_parsed_hdr_t)); - - if (ZCL_CTX().device_cb!=NULL) - { - zb_zcl_device_callback_param_t *user_app_data = ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - ZB_MEMMOVE(&(user_app_data->cb_param.start_warning_value_param), - &(invoke_data->param), - sizeof(zb_zcl_ias_wd_start_warning_value_param_t)); - user_app_data->device_cb_id = ZB_ZCL_IAS_WD_START_WARNING_VALUE_CB_ID; - user_app_data->endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - user_app_data->status = RET_OK; - (ZCL_CTX().device_cb)(param); - result = user_app_data->status; - } - else - { - result = RET_NOT_IMPLEMENTED; - } - - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, zb_zcl_get_zcl_status_from_ret(result)); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_wd_start_warning_invoke_user_app", (FMT__0)); -} - -/** @brief Start Warning command */ -static zb_ret_t start_warning_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_wd_start_warning_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> start_warning_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_IAS_WD_GET_START_WARNING_REQ(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_WD_GET_START_WARNING_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_zcl_attr_t *attr_desc; - zb_uint16_t max_dur; - attr_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_IAS_WD, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_WD_MAX_DURATION_ID); - ZB_ASSERT(attr_desc); - - max_dur = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - ZB_ZCL_IAS_WD_START_WARNING_SCHEDULE_USER_APP(param, &cmd_info, - ZB_ZCL_IAS_WD_GET_WARNING_MODE(payload.status), - ZB_ZCL_IAS_WD_GET_STROBE(payload.status), - ZB_ZCL_IAS_WD_GET_SIREN_LEVEL(payload.status), - (payload.duration < max_dur ? payload.duration : max_dur), - (payload.strobe_duty_cycle < ZB_ZCL_IAS_WD_STROBE_DUTY_CYCLE_MAX_VALUE ? - payload.strobe_duty_cycle : ZB_ZCL_IAS_WD_STROBE_DUTY_CYCLE_MAX_VALUE), - payload.strobe_level); - - ret = RET_BUSY; - } - - TRACE_MSG(TRACE_ZCL1, "< start_warning_handler ret %hx", (FMT__H, ret)); - return ret; -} - -/* Invoke User App for "Squawk" command - */ -void zb_zcl_ias_wd_squawk_invoke_user_app(zb_uint8_t param) -{ - zb_zcl_ias_wd_squawk_user_app_schedule_t* invoke_data = - ZB_BUF_GET_PARAM(param, zb_zcl_ias_wd_squawk_user_app_schedule_t); - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t result; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_wd_squawk_invoke_user_app param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, &(invoke_data->cmd_info), sizeof(zb_zcl_parsed_hdr_t)); - - if (ZCL_CTX().device_cb!=NULL) - { - zb_zcl_device_callback_param_t *user_app_data = ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - ZB_MEMMOVE(&(user_app_data->cb_param.squawk_value_param), - &(invoke_data->param), - sizeof(zb_zcl_ias_wd_squawk_value_param_t)); - user_app_data->device_cb_id = ZB_ZCL_IAS_WD_SQUAWK_VALUE_CB_ID; - user_app_data->endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - user_app_data->status = RET_OK; - (ZCL_CTX().device_cb)(param); - result = user_app_data->status; - } - else - { - result = RET_NOT_IMPLEMENTED; - } - - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, zb_zcl_get_zcl_status_from_ret(result)); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_wd_squawk_invoke_user_app", (FMT__0)); -} - -/** @brief Squawk command */ -static zb_ret_t squawk_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_wd_squawk_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> squawk_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_IAS_WD_GET_SQUAWK_REQ(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_WD_GET_SQUAWK_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - ZB_ZCL_IAS_WD_SQUAWK_SCHEDULE_USER_APP(param, &cmd_info, - ZB_ZCL_IAS_WD_GET_SQUAWK_MODE(payload.status), - ZB_ZCL_IAS_WD_GET_SQUAWK_STROBE(payload.status), - ZB_ZCL_IAS_WD_GET_SQUAWK_LEVEL(payload.status)); - - ret = RET_BUSY; - } - - TRACE_MSG(TRACE_ZCL1, "< squawk_handler ret %hx", (FMT__H, ret)); - return ret; -} - -zb_bool_t zb_zcl_process_ias_wd_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t status = RET_OK; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_ias_wd_specific_commands: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_IAS_WD == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - switch( cmd_info.cmd_id ) - { - case ZB_ZCL_CMD_IAS_WD_START_WARNING_ID: - status = start_warning_handler(param); - break; - - case ZB_ZCL_CMD_IAS_WD_SQUAWK_ID: - status = squawk_handler(param); - break; - - default: - processed = ZB_FALSE; - break; - } - - if( processed ) - { - if( cmd_info.disable_default_response && status == RET_OK) - { - TRACE_MSG( TRACE_ZCL3, - "Default response disabled", - (FMT__0)); - zb_buf_free(param); - } - else if (status != RET_BUSY) - { - ZB_ZCL_SEND_DEFAULT_RESP( param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_IAS_WD, - cmd_info.seq_number, - cmd_info.cmd_id, - status==RET_OK ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_INVALID_FIELD); - } - } - - TRACE_MSG( TRACE_ZCL1, - "< zb_zcl_process_ias_wd_specific_commands: processed %d", - (FMT__D, processed)); - return processed; -} - -zb_bool_t zb_zcl_process_ias_wd_specific_commands_srv(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_ias_wd_server_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_ias_wd_specific_commands(param); -} -zb_bool_t zb_zcl_process_ias_wd_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_ias_wd_client_cmd_list; - return ZB_TRUE; - } - return ZB_FALSE; -} - -/** - * @} internal -*/ -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_IAS_WD */ diff --git a/zboss/development/src/zcl/zcl_ias_zone_commands.c b/zboss/development/src/zcl/zcl_ias_zone_commands.c deleted file mode 100644 index f5c54d5fa2..0000000000 --- a/zboss/development/src/zcl/zcl_ias_zone_commands.c +++ /dev/null @@ -1,1106 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL IAS Zone cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2070 - -#if defined ZB_ENABLE_HA -/* #include "ha/zb_zcl_ias_zone_ha_adds.h" */ -#endif /* defined ZB_ENABLE_HA */ - -#include "zb_common.h" - -#if defined ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_ias_zone.h" -#include "zb_nvram.h" -#include "zb_osif.h" -#include "zb_zdo.h" -#include "zb_aps.h" - -/** @internal - @{ -*/ - -static zb_uint8_t gs_ias_zone_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_IAS_ZONE_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -static zb_uint8_t gs_ias_zone_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_IAS_ZONE_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_ias_zone_server_cmd_list = -{ - sizeof(gs_ias_zone_server_received_commands), gs_ias_zone_server_received_commands, - sizeof(gs_ias_zone_client_received_commands), gs_ias_zone_client_received_commands -}; - -zb_discover_cmd_list_t gs_ias_zone_client_cmd_list = -{ - sizeof(gs_ias_zone_client_received_commands), gs_ias_zone_client_received_commands, - sizeof(gs_ias_zone_server_received_commands), gs_ias_zone_server_received_commands -}; - - -void zb_zcl_ias_zone_restore_curr_zone_sens_level(zb_uint8_t endpoint); -zb_ret_t zb_zcl_ias_zone_init_mode(zb_zcl_ias_zone_int_ctx_t *int_ctx, zb_uint8_t mode, zb_uint16_t val); -void zb_zcl_ias_zone_restore_normal_mode(zb_uint8_t endpoint); -void zb_zcl_ias_zone_set_test_bit_delayed(zb_uint8_t endpoint, zb_uint8_t test_bit); -void zb_zcl_ias_zone_set_test_bit(zb_uint8_t param, zb_uint16_t user_param); -zb_ret_t check_value_ias_zone_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -void zb_zcl_ias_zone_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); -zb_bool_t zb_zcl_process_ias_zone_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_ias_zone_specific_commands_cli(zb_uint8_t param); - -void zb_zcl_ias_zone_init_server() -{ - zb_uint8_t ep_id = zb_get_current_endpoint_id(); - - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_IAS_ZONE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_ias_zone_server, - zb_zcl_ias_zone_write_attr_hook_server, - zb_zcl_process_ias_zone_specific_commands_srv); - - zb_zcl_ias_zone_check_cie_addr_on_zcl_initialization(ep_id); -} - -void zb_zcl_ias_zone_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_IAS_ZONE, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_ias_zone_specific_commands_cli); -} - -zb_ret_t check_value_ias_zone_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - ZVUNUSED(endpoint); - - TRACE_MSG(TRACE_ZCL1, "> check_value_ias_zone", (FMT__0)); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_IAS_ZONE_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_ID: - { - if( ZB_ZCL_IAS_ZONE_NUMBER_OF_ZONE_SENSITIVITY_LEVELS_SUPPORTED_MIN_VALUE > *value ) - { - ret = RET_ERROR; - } - break; - } - case ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID: - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET); - ZB_ASSERT(attr_desc != NULL); - if (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) == ZB_B2U(ZB_TRUE)) - { - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID); - if (ZB_MEMCMP(attr_desc->data_p, value, zb_zcl_get_attribute_size(attr_desc->type, value)) != 0) - { - ret = RET_UNAUTHORIZED; - } - } - } - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_ias_zone ret %hd", (FMT__H, ret)); - return ret; -} - -static zb_ret_t check_cie_establishment(zb_uint8_t endpoint) -{ - zb_ret_t ret = RET_OK; - - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET); - ZB_ASSERT(attr_desc); - - if (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) == ZB_B2U(ZB_FALSE)) - { - TRACE_MSG(TRACE_ZCL1, "CIE addr isn't set on IAS Zone server", (FMT__0)); - ret = RET_UNAUTHORIZED; - } - - return ret; -} - -static zb_bool_t check_cie_authorization(zb_uint8_t endpoint, zb_uint16_t short_addr) -{ - zb_uint16_t cie_short_addr; - - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID); - ZB_ASSERT(attr_desc); - - /* AN: We have already put entry in address table during step 2 of each commissioning method. */ - cie_short_addr = zb_address_short_by_ieee(attr_desc->data_p); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_SHORT_ADDR); - - ZB_ASSERT(attr_desc); - - return (cie_short_addr == ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) && - cie_short_addr == short_addr) ? ZB_TRUE : ZB_FALSE; -} - -zb_ret_t zb_zcl_ias_zone_put_cie_address_to_binding_whitelist(zb_uint8_t ep_id) -{ - zb_ret_t ret = RET_OK; - - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(ep_id, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID); - ZB_ASSERT(attr_desc); - - ret = zb_aps_add_binding_whitelist_entry(ep_id, ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, (zb_uint8_t *)attr_desc->data_p); - - return ret; -} - -/** @brief Initiate Test mode command */ -static zb_ret_t zb_zcl_ias_zone_init_test_mode_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_zone_init_test_mode_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_zone_init_test_mode_handler param %d", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - ZB_ZCL_IAS_ZONE_GET_INITIATE_TEST_MODE_REQ(&payload, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ZONE_GET_INITIATE_TEST_MODE_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - ret = check_cie_establishment(endpoint); - - if (ret == RET_OK) - { - if(check_cie_authorization(endpoint, cmd_info.addr_data.common_data.source.u.short_addr)) - { - zb_zcl_attr_t *attr_desc_level = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_CURRENT_ZONE_SENSITIVITY_LEVEL_ID); - zb_zcl_attr_t *attr_desc_int_ctx = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_INT_CTX_ID); - zb_zcl_ias_zone_int_ctx_t *int_ctx; - zb_ret_t retcode; - - ZB_ASSERT(attr_desc_level != NULL); - ZB_ASSERT(attr_desc_int_ctx != NULL); - - int_ctx = (zb_zcl_ias_zone_int_ctx_t*)attr_desc_int_ctx->data_p; - int_ctx->restore_current_zone_sens_level = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_level); - - /* NK: Set attribute value directly. Reason: do not call general_cb with SENSITIVITY_SET param here, - * use only one general_cb - with TEST_MODE. It can do some specific checks of this attribute - * and return some result with retcode. */ - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc_level, payload.current_zone_sens_level); - - retcode = zb_zcl_ias_zone_init_mode(int_ctx, ZB_ZCL_INIT_TEST_MODE, payload.current_zone_sens_level); - - if (retcode == RET_INVALID_PARAMETER) - { - /* NK: Send ZCL response with invalid parameter code. */ - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc_level, int_ctx->restore_current_zone_sens_level); - return retcode; - } - else - { - /* NK: If zb_zcl_ias_zone_init_mode() returned RET_OK, than do not set test bit from ZCL layer. */ - if (retcode != RET_OK) - { - zb_zcl_ias_zone_set_test_bit_delayed(endpoint, 1); - } - - /* Schedule current_zone_sens_level restore and turning to normal mode */ - ZB_SCHEDULE_ALARM(zb_zcl_ias_zone_restore_normal_mode, endpoint, payload.test_mode_duration * ZB_TIME_ONE_SECOND); - } - } - else - { - ret = RET_UNAUTHORIZED; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_zone_init_test_mode_handler ret %hx", (FMT__H, ret)); - return ret; -} - -void zb_zcl_ias_zone_set_test_bit_delayed(zb_uint8_t endpoint, zb_uint8_t test_bit) -{ - zb_buf_get_out_delayed_ext(zb_zcl_ias_zone_set_test_bit, endpoint | (test_bit << 8), 0); -} - -void zb_zcl_ias_zone_set_test_bit(zb_uint8_t param, zb_uint16_t user_param) -{ - zb_uint8_t endpoint = ZB_GET_LOW_BYTE(user_param); - zb_uint8_t test_bit = ZB_GET_HI_BYTE(user_param); - zb_uint16_t curr_zone_status; - - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID); - - ZB_ASSERT(attr_desc != NULL); - - curr_zone_status = *(zb_uint16_t*)attr_desc->data_p; - if (test_bit) - { - curr_zone_status |= (zb_uint16_t)ZB_ZCL_IAS_ZONE_ZONE_STATUS_TEST; - } - else - { - curr_zone_status &= ~(zb_uint16_t)ZB_ZCL_IAS_ZONE_ZONE_STATUS_TEST; - } - - zb_zcl_ias_zone_set_status(endpoint, curr_zone_status, 0, param); -} - -/** @brief Initiate Normal mode command */ -static zb_ret_t zb_zcl_ias_zone_init_normal_mode_handler(zb_uint8_t param) -{ - zb_uint8_t alarm_buf_param = 0; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - zb_zcl_attr_t *attr_desc_int_ctx; - zb_zcl_ias_zone_int_ctx_t *int_ctx; - zb_ret_t retcode; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_zone_init_normal_mode_handler param %d", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - retcode = check_cie_establishment(endpoint); - - if (retcode == RET_OK) - { - if(check_cie_authorization(endpoint, cmd_info.addr_data.common_data.source.u.short_addr)) - { - attr_desc_int_ctx = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_INT_CTX_ID); - - ZB_ASSERT(attr_desc_int_ctx != NULL); - - int_ctx = (zb_zcl_ias_zone_int_ctx_t*)attr_desc_int_ctx->data_p; - - ZB_SCHEDULE_ALARM_CANCEL_AND_GET_BUF(zb_zcl_ias_zone_restore_normal_mode, ZB_ALARM_ANY_PARAM, &alarm_buf_param); - - if (alarm_buf_param) - { - zb_zcl_ias_zone_restore_normal_mode(alarm_buf_param); - } - else - { - /* NK: Turn on Normal Mode even if it was no Test Mode command before. */ - retcode = zb_zcl_ias_zone_init_mode(int_ctx, ZB_ZCL_INIT_NORMAL_MODE, 0); - - /* NK: If zb_zcl_ias_zone_init_mode() returned RET_OK, then do not set test bit from ZCL layer. */ - if (retcode != RET_OK) - { - zb_zcl_ias_zone_set_test_bit_delayed(endpoint, 0); - retcode = RET_OK; - } - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_zone_init_normal_mode_handler", (FMT__0)); - } - else - { - retcode = RET_UNAUTHORIZED; - } - } - return retcode; -} - -#if defined ZB_ENABLE_HA - -/* Invoke User App for "Enroll Response" command - */ -void zb_zcl_ias_zone_enroll_response_invoke_user_app(zb_uint8_t param) -{ - zb_zcl_ias_zone_enroll_response_user_app_schedule_t* invoke_data = - ZB_BUF_GET_PARAM(param, zb_zcl_ias_zone_enroll_response_user_app_schedule_t); - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t result; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_zone_enroll_response_invoke_user_app param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, &(invoke_data->cmd_info), sizeof(zb_zcl_parsed_hdr_t)); - - if (ZCL_CTX().device_cb != NULL) - { - - zb_zcl_device_callback_param_t *user_app_data = ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - ZB_MEMMOVE(&(user_app_data->cb_param.enroll_response_value_param), - &(invoke_data->param), - sizeof(zb_zcl_ias_zone_enroll_response_value_param_t)); - user_app_data->device_cb_id = ZB_ZCL_IAS_ZONE_ENROLL_RESPONSE_VALUE_CB_ID; - - user_app_data->status = RET_OK; - (ZCL_CTX().device_cb)(param); - result = user_app_data->status; - } - else - { - result = RET_NOT_IMPLEMENTED; - } - - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, zb_zcl_get_zcl_status_from_ret(result)); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_zone_enroll_response_invoke_user_app", (FMT__0)); -} - -#endif /* defined ZB_ENABLE_HA */ - -/** @brief Zone Enroll Response command */ -static zb_ret_t zone_enroll_res_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ias_zone_enroll_res_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zone_enroll_res_handler param %d", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - ZB_ZCL_IAS_ZONE_GET_ZONE_ENROLL_RES(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_IAS_ZONE_GET_ZONE_ENROLL_RES", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - ret = check_cie_establishment(endpoint); - - if (ret == RET_OK) - { - if(check_cie_authorization(endpoint, cmd_info.addr_data.common_data.source.u.short_addr)) - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONESTATE_ID); - ZB_ASSERT(attr_desc); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, - payload.code==ZB_ZCL_IAS_ZONE_ENROLL_RESPONCE_CODE_SUCCESS ? - ZB_ZCL_IAS_ZONE_ZONESTATE_ENROLLED : - ZB_ZCL_IAS_ZONE_ZONESTATE_NOT_ENROLLED); - -#if defined ZB_ENABLE_HA - - /* ZCL 8.2.2.3.1.1 says (about 'zone_id' field): - "This field is only relevant if the response code is success". */ - if (payload.code == ZB_ZCL_IAS_ZONE_ENROLL_RESPONCE_CODE_SUCCESS) - { - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONEID_ID); - ZB_ASSERT(attr_desc); - if ((*(zb_uint8_t*)attr_desc->data_p) != (zb_uint8_t)payload.zone_id) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, payload.zone_id); -#ifdef ZB_USE_NVRAM - /* If we fail, trace is given and assertion is triggered */ - (void)zb_nvram_write_dataset(ZB_NVRAM_HA_DATA); -#endif - } - } - ZB_ZCL_IAS_ZONE_ENROLL_RESPONSE_SCHEDULE_USER_APP(param, &cmd_info, - payload.code, - payload.zone_id); - ret = RET_BUSY; -#endif /* defined ZB_ENABLE_HA */ - } - else - { - ret = RET_UNAUTHORIZED; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< zone_enroll_res_handler ret %hx", (FMT__H, ret)); - return ret; -} - -zb_ret_t zb_zcl_ias_zone_init_mode(zb_zcl_ias_zone_int_ctx_t *int_ctx, zb_uint8_t mode, zb_uint16_t val) -{ - return (int_ctx->general_cb) ? int_ctx->general_cb(mode, val) : RET_ERROR; -} - -/* NK:TODO: Modify this: zb_zcl_ias_zone_restore_normal_mode(endpoint, restore_bit); to use this - * func in scheduling and in normal mode handling */ -void zb_zcl_ias_zone_restore_normal_mode(zb_uint8_t endpoint) -{ - zb_zcl_attr_t *attr_desc_level = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_CURRENT_ZONE_SENSITIVITY_LEVEL_ID); - zb_zcl_attr_t *attr_desc_int_ctx = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_INT_CTX_ID); - zb_zcl_ias_zone_int_ctx_t *int_ctx; - zb_ret_t retcode; - - ZB_ASSERT(attr_desc_level != NULL); - ZB_ASSERT(attr_desc_int_ctx != NULL); - - int_ctx = (zb_zcl_ias_zone_int_ctx_t*)attr_desc_int_ctx->data_p; - - ZB_ASSERT(attr_desc_int_ctx); - - /* NK: Temporary disable current_zone_sens_level restoring */ - - /* ZB_ZCL_SET_ATTRIBUTE(endpoint, ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_ATTR_IAS_ZONE_CURRENT_ZONE_SENSITIVITY_LEVEL_ID, */ - /* &(int_ctx->restore_current_zone_sens_level), ZB_FALSE); */ - - retcode = zb_zcl_ias_zone_init_mode(int_ctx, ZB_ZCL_INIT_NORMAL_MODE, 0); - - /* NK: If zb_zcl_ias_zone_init_mode() returned RET_OK, then do not set test bit from ZCL layer. */ - if (retcode != RET_OK) - { - zb_zcl_ias_zone_set_test_bit_delayed(endpoint, 0); - } -} - -zb_bool_t zb_zcl_process_ias_zone_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t status = RET_OK; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_ias_zone_specific_commands: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_IAS_ZONE == cmd_info.cluster_id); - - if(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction) - { - switch( cmd_info.cmd_id ) - { - case ZB_ZCL_CMD_IAS_ZONE_ZONE_ENROLL_RESPONSE_ID: - status = zone_enroll_res_handler(param); - break; - - case ZB_ZCL_CMD_IAS_ZONE_INITIATE_NORMAL_OPERATION_MODE_ID: - status = zb_zcl_ias_zone_init_normal_mode_handler(param); - break; - - case ZB_ZCL_CMD_IAS_ZONE_INITIATE_TEST_MODE_ID: - status = zb_zcl_ias_zone_init_test_mode_handler(param); - break; - - default: - processed = ZB_FALSE; - break; - } - } - else // ZB_ZCL_FRAME_DIRECTION_TO_CLI - { - switch( cmd_info.cmd_id ) - { - case ZB_ZCL_CMD_IAS_ZONE_ZONE_STATUS_CHANGE_NOT_ID: - // send response below the code - break; - - default: - processed = ZB_FALSE; - break; - } - } - - if( processed ) - { - if( cmd_info.disable_default_response && status == RET_OK) - { - TRACE_MSG( TRACE_ZCL3, - "Default response disabled", - (FMT__0)); - zb_buf_free(param); - } - else if (status != RET_BUSY) - { - zb_uint8_t zcl_status = ZB_ZCL_STATUS_SUCCESS; - switch (status) - { - case RET_UNAUTHORIZED: - zcl_status = ZB_ZCL_STATUS_NOT_AUTHORIZED; - break; - case RET_INVALID_PARAMETER: - case RET_INVALID_PARAMETER_1: - zcl_status = ZB_ZCL_STATUS_INVALID_FIELD; - break; - default: - break; - } - ZB_ZCL_SEND_DEFAULT_RESP_DIRECTION( param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, - cmd_info.seq_number, - cmd_info.cmd_id, - zcl_status, - cmd_info.cmd_direction==ZB_ZCL_FRAME_DIRECTION_TO_SRV - ? ZB_ZCL_FRAME_DIRECTION_TO_CLI - : ZB_ZCL_FRAME_DIRECTION_TO_SRV); - } - } - - TRACE_MSG( TRACE_ZCL1, - "< zb_zcl_process_ias_zone_specific_commands: processed %d", - (FMT__D, processed)); - return processed; -} - - -zb_bool_t zb_zcl_process_ias_zone_specific_commands_srv(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_ias_zone_server_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_ias_zone_specific_commands(param); -} - -zb_bool_t zb_zcl_process_ias_zone_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_ias_zone_client_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_ias_zone_specific_commands(param); -} -/**********************************************************************/ - -/* Set or clear Zone Status bits - * for User App - */ -void zb_zcl_ias_zone_change_status(zb_uint8_t param) -{ - zb_zcl_ias_zone_status_param_t* params = ZB_BUF_GET_PARAM(param, zb_zcl_ias_zone_status_param_t); - zb_zcl_attr_t *attr_desc; - zb_uint16_t val; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_zone_change_status param %hd", (FMT__H, param)); - - attr_desc = zb_zcl_get_attr_desc_a(params->endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID); - ZB_ASSERT(attr_desc); - - val = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - TRACE_MSG(TRACE_ZCL2, "old val 0x%x bits 0x%x is_set %hd", (FMT__D_D_H, - val, params->bits, params->is_set)); - - if(params->is_set) - { - val |= (params->bits); - } - else - { - val &= ~(params->bits); - } - - TRACE_MSG(TRACE_ZCL2, "new val 0x%x", (FMT__D, val)); - - zb_zcl_ias_zone_set_status( - params->endpoint, val, - 0 /* delay value is not used for in pure ZCL (no HA) */, - param); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_zone_change_status", (FMT__0)); -} - -zb_bool_t zb_zcl_ias_zone_set_status( - zb_uint8_t ep, - zb_uint16_t new_val, - zb_uint16_t delay, - zb_uint8_t buf_param) -{ - zb_zcl_attr_t *attr_desc; - zb_bool_t ret = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, - ">> zb_zcl_ias_zone_set_status ep %hd, buf_param %hd, new_val %d, delay %d", - (FMT__H_H_D_D, ep, buf_param, new_val, delay)); - - if (buf_param != ZB_UNDEFINED_BUFFER) - { - zb_zcl_ias_zone_notification_param_t* notify_param = - ZB_BUF_GET_PARAM(buf_param, zb_zcl_ias_zone_notification_param_t); - - TRACE_MSG(TRACE_ZCL2, "buffer is provided %hd", (FMT__H, buf_param)); - notify_param->ep = ep; - notify_param->status_val = new_val; - notify_param->delay = delay; - - ret = zb_zcl_ias_zone_check_attr_notify(buf_param); - } - else - { - /* - Notification is NOT sent if buffer is not specified. User App - should provide buffer for a command. - Reason: simplify source code and make memory using transparent - for use App - */ - } - - attr_desc = zb_zcl_get_attr_desc_a( - ep, ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID); - ZB_ASSERT(attr_desc); - TRACE_MSG(TRACE_ZCL2, "set new value for zone status anyway %xd", (FMT__D, new_val)); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, new_val); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_ias_zone_set_status ret %hd", (FMT__H, ret)); - return ret; -} - -zb_bool_t zb_zcl_ias_zone_check_attr_notify( - zb_uint8_t buf_param) -{ - zb_bool_t send_not = ZB_FALSE; - zb_zcl_attr_t *attr_desc; - zb_uint16_t cur_val; - zb_uint8_t zone_state; - zb_zcl_ias_zone_notification_param_t* notify_param = - ZB_BUF_GET_PARAM(buf_param, zb_zcl_ias_zone_notification_param_t); - - TRACE_MSG(TRACE_ZCL1, - ">> zb_zcl_ias_zone_check_attr_notify buf_param %hd", - (FMT__H, buf_param)); - - attr_desc = zb_zcl_get_attr_desc_a( - notify_param->ep, ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONESTATUS_ID); - ZB_ASSERT(attr_desc); - cur_val = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - /* send notification if ZoneState is enroll */ - attr_desc = zb_zcl_get_attr_desc_a( - notify_param->ep, ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONESTATE_ID); - ZB_ASSERT(attr_desc); - zone_state = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - TRACE_MSG(TRACE_ZCL2, "zone_state %hd", (FMT__H, zone_state)); - if (zone_state == ZB_ZCL_IAS_ZONE_ZONESTATE_ENROLLED) - { - zb_uint16_t test_clear = 0xFFFF; - zb_uint16_t test_set = - ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM1 | - ZB_ZCL_IAS_ZONE_ZONE_STATUS_ALARM2 | - ZB_ZCL_IAS_ZONE_ZONE_STATUS_TAMPER | - ZB_ZCL_IAS_ZONE_ZONE_STATUS_BATTERY | - ZB_ZCL_IAS_ZONE_ZONE_STATUS_TROUBLE | - ZB_ZCL_IAS_ZONE_ZONE_STATUS_AC_MAINS -#if defined ZB_ENABLE_HA - | ZB_ZCL_IAS_ZONE_ZONE_STATUS_TEST - | ZB_ZCL_IAS_ZONE_ZONE_STATUS_BATTERY_DEFECT -#endif /* defined ZB_ENABLE_HA*/ - ; - - TRACE_MSG(TRACE_ZCL2, "current val 0x%x new val 0x%x", (FMT__D_D, cur_val, notify_param->status_val)); - - /* TODO: check this if-check!!! */ - if (/* old -> new : (0->1)=1 only */ - (~(cur_val & test_set) & (notify_param->status_val & test_set) ) || - /* old -> new : (1->0)=1 only && set StatusRestore */ - ( ((cur_val & test_clear) & ~(notify_param->status_val & test_clear) ) && - (cur_val & ZB_ZCL_IAS_ZONE_ZONE_STATUS_RESTORE)) ) - { - TRACE_MSG(TRACE_ZCL2, "Will send notification", (FMT__0)); - send_not = ZB_TRUE; - ZB_SCHEDULE_CALLBACK(zb_zcl_ias_zone_send_status_change_not, buf_param); - } - } /* zone state == ENROLLED */ - - /* NK:WARNING: Do not free the buffer here, even if notification is not sent! It is application responsibility! */ - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_ias_zone_check_attr_notify send_not %hd", (FMT__H, send_not)); - return send_not; -} - - -void zb_zcl_ias_zone_send_status_change_not(zb_uint8_t param) -{ - zb_zcl_ias_zone_notification_param_t *notify_param = - ZB_BUF_GET_PARAM(param, zb_zcl_ias_zone_notification_param_t); - zb_zcl_attr_t *attr_desc; - zb_af_endpoint_desc_t *ep_desc; - zb_zcl_ias_zone_int_ctx_t *int_ctx; - zb_uint8_t endpoint; - zb_uint16_t zone_status; - zb_uint16_t delay; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_zone_send_status_change_not param %d", - (FMT__H, param)); - - endpoint = notify_param->ep; - zone_status = notify_param->status_val; - delay = notify_param->delay; - ep_desc = zb_af_get_endpoint_desc(endpoint); - - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_IAS_ZONE_INT_CTX_ID); - ZB_ASSERT(attr_desc != NULL); - int_ctx = (zb_zcl_ias_zone_int_ctx_t*)attr_desc->data_p; - - -#if defined ZB_ENABLE_HA - { - zb_uint8_t zone_id; - zb_uint8_t cie_ep; - zb_uint16_t cie_addr; - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_IAS_ZONE_ZONEID_ID); - zone_id = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_CUSTOM_CIE_EP); - cie_ep = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_CUSTOM_CIE_SHORT_ADDR); - cie_addr = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - TRACE_MSG(TRACE_ZCL1, "send notification cie addr %d, ep %hd", (FMT__D_H, cie_addr, cie_ep)); - ZB_ZCL_IAS_ZONE_SEND_STATUS_CHANGE_NOTIFICATION_REQ( - param, - cie_addr, ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT, //ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - cie_ep, endpoint, ep_desc->profile_id, int_ctx->process_result_cb, - zone_status, 0, zone_id, - delay); - - - } - -#else /* defined ZB_ENABLE_HA */ - - ZB_ZCL_IAS_ZONE_SEND_STATUS_CHANGE_NOTIFICATION_REQ( - param, - zb_get_short_address(), ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT, - 0, endpoint, ep_desc->profile_id, int_ctx->process_result_cb, - zone_status, 0); - -#endif /* defined ZB_ENABLE_HA*/ - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_zone_send_status_change_not", (FMT__0)); -} - -/**********************************************************************/ - -/** - * @} internal -*/ - - -void zb_zcl_ias_zone_register_cb( - zb_uint8_t endpoint, - zb_callback_t process_result_cb, - zb_ias_zone_app_callback_t general_cb) -{ - zb_zcl_attr_t* attr_desc; - zb_zcl_ias_zone_int_ctx_t *int_ctx; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_zone_queue_registry ep %hx", (FMT__H, endpoint)); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_IAS_ZONE_INT_CTX_ID); - ZB_ASSERT(attr_desc != NULL); - - int_ctx = (zb_zcl_ias_zone_int_ctx_t*)attr_desc->data_p; - int_ctx->process_result_cb = process_result_cb; - int_ctx->general_cb = general_cb; - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_zone_queue_registry", (FMT__0)); -} - -static void handle_bind_confirm(zb_uint8_t param) -{ - if (zb_buf_get_status(param) != RET_OK) - { - TRACE_MSG(TRACE_ZCL1, "Failed to create CIE apt binding!", (FMT__0)); - } - - zb_buf_free(param); -} - -static void handle_bind_check_response(zb_bufid_t param) -{ - zb_aps_check_binding_resp_t *check_binding_resp = NULL; - - check_binding_resp = ZB_BUF_GET_PARAM(param, zb_aps_check_binding_resp_t); - - if (check_binding_resp->exists == ZB_TRUE) - { - TRACE_MSG(TRACE_ZCL3, "CIE binding already exists!", (FMT__0)); - zb_buf_free(param); - } - else - { - /* zb_zcl_set_attr_val_cmd_post_process put zdo bind request params into the buffer body */ - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zdo_bind_req_param_t), - zb_buf_begin(param), - sizeof(zb_zdo_bind_req_param_t)); - - zb_zdo_bind_req(param, handle_bind_confirm); - } -} - -void zb_zcl_ias_zone_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value) -{ - zb_zcl_attr_t* attr_desc; - zb_zcl_ias_zone_int_ctx_t *int_ctx; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ias_zone_write_attr_hook endpoint %hx attr_id %d", - (FMT__H_D, endpoint, attr_id)); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_IAS_ZONE_INT_CTX_ID); - ZB_ASSERT(attr_desc != NULL); - - ZB_ASSERT(new_value); - - int_ctx = (zb_zcl_ias_zone_int_ctx_t*)attr_desc->data_p; - - if(attr_id == ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID) - { - if (!ZB_IEEE_ADDR_IS_ZERO(new_value)) - { - TRACE_MSG(TRACE_ZCL1, "valid CIE addr is being set", (FMT__0)); - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET); - ZB_ASSERT(attr_desc != NULL); - - if (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) == ZB_B2U(ZB_FALSE)) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ZB_B2U(ZB_TRUE)); - } - if (int_ctx->general_cb) - { - int_ctx->general_cb(ZB_ZCL_VALID_CIE_ADDR_SET, 0); - } - } - } - else if (attr_id == ZB_ZCL_ATTR_IAS_ZONE_CURRENT_ZONE_SENSITIVITY_LEVEL_ID) - { - if (int_ctx->general_cb) - { - int_ctx->general_cb(ZB_ZCL_CURR_ZONE_SENSITIVITY_LEVEL_SET, *new_value); - } - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ias_zone_write_attr_hook", (FMT__0)); -} - -void zb_zcl_ias_zone_check_cie_addr_on_zcl_initialization(zb_uint8_t ep_id) -{ - zb_ret_t ret; - zb_ieee_addr_t zeroed_ieee_addr = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - ret = zb_aps_add_binding_whitelist_entry(ep_id, ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, zeroed_ieee_addr); - if (ret != RET_OK) - { - TRACE_MSG(TRACE_ERROR, "Add binding whitelist zeroed IEEE addr entry for ias zone failed ret=%hu", (FMT__D, ret)); - ZB_ASSERT(0); - } -} - -void zb_zcl_ias_set_attr_val_post_process(zb_zcl_parsed_hdr_t *cmd_info, zb_uint16_t attr_id, zb_uint8_t *value) -{ - ZVUNUSED(cmd_info); - ZVUNUSED(attr_id); - ZVUNUSED(value); - - if (attr_id == ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID) - { - /* ZCL 8.2.2.2.3 (Trip-to-Pair, Auto-Enroll-Response, Auto-Enroll-Request): - * "The IAS Zone server MAY configure a binding table entry for the IAS CIE’s - * address because all of its communication will be directed to the IAS CIE." */ - zb_zdo_bind_req_param_t *zdo_bind_req; - zb_aps_check_binding_req_t *check_binding_req; - zb_zcl_attr_t *attr_desc; - zb_ret_t ret; - - zb_bufid_t buf = zb_buf_get_out(); - - ZB_ASSERT(buf != ZB_BUF_INVALID); - - attr_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->cluster_id, ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id); - - zdo_bind_req = (zb_zdo_bind_req_param_t *)zb_buf_initial_alloc(buf, sizeof(*zdo_bind_req)); - - ZB_BZERO(zdo_bind_req, sizeof(zb_zdo_bind_req_param_t)); - - /* get "set CIE address" originator's ieee address */ - - ret = zb_address_ieee_by_short(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - zdo_bind_req->dst_address.addr_long); - - /* If address table entry doesn't exist, it should be added */ - - if (ret == RET_NOT_FOUND) - { - zb_address_ieee_ref_t addr_ref; - zb_address_update(value, ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, ZB_TRUE, &addr_ref); - } - /* Compare "set CIE address" originator's ieee address to - * CIE address from request and to current CIE ieee address - * in IAS Zone Cluster's attribute */ - - if (ret != RET_OK) - { - TRACE_MSG(TRACE_ZCL2, "Failed to obtain CIE ieee address from addr map, skip addr check!", - (FMT__0)); - - ZB_IEEE_ADDR_COPY(zdo_bind_req->dst_address.addr_long, value); - ret = RET_OK; - } - else - { - if (ZB_MEMCMP(zdo_bind_req->dst_address.addr_long, value, - zb_zcl_get_attribute_size(attr_desc->type, value)) != 0) - { - ret = RET_ERROR; - } - } - - /* Check the attribute was really updated with the new address value. - If not, don't create a new binding */ - if (ret == RET_OK) - { - if (ZB_MEMCMP(attr_desc->data_p, value, - zb_zcl_get_attribute_size(attr_desc->type, value)) != 0) - { - ret = RET_ERROR; - } - } - - if (ret == RET_ERROR) - { - TRACE_MSG(TRACE_ZCL2, "Originator's ieee check failed!", (FMT__0)); - } - - ret = zb_zcl_ias_zone_put_cie_address_to_binding_whitelist(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - - if (ret == RET_OK) - { - attr_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->cluster_id, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_EP); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc,ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint); - - attr_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->cluster_id, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_SHORT_ADDR); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc,ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr); - - /* Fill in the rest fields of binding request */ - zb_get_long_address(zdo_bind_req->src_address); - zdo_bind_req->src_endp = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - zdo_bind_req->dst_endp = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint; - zdo_bind_req->cluster_id = cmd_info->cluster_id; - zdo_bind_req->dst_addr_mode = ZB_APS_ADDR_MODE_64_ENDP_PRESENT; - zdo_bind_req->req_dst_addr = zb_get_short_address(); - - check_binding_req = ZB_BUF_GET_PARAM(buf, zb_aps_check_binding_req_t); - ZB_BZERO(check_binding_req, sizeof(*check_binding_req)); - - check_binding_req->cluster_id = cmd_info->cluster_id; - check_binding_req->src_endpoint = ZB_ZCL_BROADCAST_ENDPOINT; - check_binding_req->response_cb = handle_bind_check_response; - - zb_aps_check_binding_request(buf); - buf = ZB_BUF_INVALID; - } - - if (buf != ZB_BUF_INVALID) - { - zb_buf_free(buf); - } - } -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE */ diff --git a/zboss/development/src/zcl/zcl_identify_commands.c b/zboss/development/src/zcl/zcl_identify_commands.c deleted file mode 100644 index 192c2943cd..0000000000 --- a/zboss/development/src/zcl/zcl_identify_commands.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Identify cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 1636 - -#include "zb_common.h" - -#if defined(ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY) - -#include "zb_zcl.h" -#include "zcl/zb_zcl_identify.h" -#include "zb_bdb_internal.h" -#include "zb_zdo.h" -#include "zb_aps.h" - -static zb_uint8_t gs_identify_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_IDENTIFY_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -static zb_uint8_t gs_identify_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_IDENTIFY_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_identify_server_cmd_list = -{ - sizeof(gs_identify_server_received_commands), gs_identify_server_received_commands, - sizeof(gs_identify_client_received_commands), gs_identify_client_received_commands -}; - -zb_discover_cmd_list_t gs_identify_client_cmd_list = -{ - sizeof(gs_identify_client_received_commands), gs_identify_client_received_commands, - sizeof(gs_identify_server_received_commands), gs_identify_server_received_commands -}; - -void zb_zcl_identify_time_handler(zb_uint8_t param); - -#define GET_IDENTIFY_HANDLER(endpoint) \ - (zb_af_get_endpoint_desc((endpoint))->identify_handler) - -zb_ret_t check_value_identify_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -zb_bool_t zb_zcl_process_identify_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_identify_specific_commands_cli(zb_uint8_t param); - -void zb_zcl_identify_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -void zb_zcl_identify_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_IDENTIFY, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_identify_server, - zb_zcl_identify_write_attr_hook_server, - zb_zcl_process_identify_specific_commands_srv); -} - -void zb_zcl_identify_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_IDENTIFY, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_identify_specific_commands_cli); -} - -zb_ret_t check_value_identify_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} -/* Invoke User App for "Identify effect" command - * - * Invoke User App with effect parameters : EffectId and EffectVariant - * if invoke result RET_OK then schedule invoke User App with attribute Identify - * else send response command with error - */ -void zb_zcl_identify_effect_invoke_user_app(zb_uint8_t param) -{ - zb_zcl_identify_effect_user_app_schedule_t* invoke_data = ZB_BUF_GET_PARAM(param, zb_zcl_identify_effect_user_app_schedule_t); - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t result; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_invoke_effect_invoke_user_app param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, &(invoke_data->cmd_info), sizeof(zb_zcl_parsed_hdr_t)); - - if (ZCL_CTX().device_cb!=NULL) - { - zb_zcl_device_callback_param_t *user_app_data = ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - ZB_MEMMOVE(&(user_app_data->cb_param.identify_effect_value_param), - &(invoke_data->param), - sizeof(zb_zcl_identify_effect_value_param_t)); - user_app_data->device_cb_id = ZB_ZCL_IDENTIFY_EFFECT_CB_ID; - user_app_data->endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - user_app_data->status = RET_OK; - (ZCL_CTX().device_cb)(param); - result = user_app_data->status; - /* TODO: check - free buffer after a call? */ - } - else - { - result = RET_NOT_IMPLEMENTED; - } - - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, zb_zcl_get_zcl_status_from_ret(result)); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_on_off_effect_invoke_user_app param", (FMT__0)); -} - -zb_bool_t zb_zcl_process_identify_specific_commands(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t processed = ZB_TRUE; - zb_uint8_t status = ZB_ZCL_STATUS_SUCCESS; - zb_zcl_identify_req_t payload; - zb_zcl_parse_status_t st; - zb_zcl_identify_effect_req_t payload_effect; - zb_zcl_attr_t * attr_desc; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( - TRACE_ZCL1, - "> zb_zcl_process_identify_specific_commands: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_IDENTIFY == cmd_info.cluster_id); - - switch (cmd_info.cmd_id) - { - /* NOTE: pay attention that following case handles two commands Identify and - * IdentifyQueryResponse. This commands have the same ids values (ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID - * and ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_RSP_ID) but differ by direction. - */ - case ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID: - if (cmd_info.cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) - { - ZB_ZCL_IDENTIFY_GET_IDENTIFY_REQ(&payload, param, st); - if (st != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ERROR, "Got erroneous payload length %hd != 2", - (FMT__H, zb_buf_len(param))); - status = ZB_ZCL_STATUS_MALFORMED_CMD; - } - else - { - zb_zcl_start_identifying( - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, payload.timeout); - } - - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, status); - } -#if defined ZB_BDB_ENABLE_FINDING_BINDING - else if (ZCL_SELECTOR().process_identify_query_res != NULL) -/* direction = from server to client - identify query response */ - { - /* ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_RSP_ID */ - ZCL_SELECTOR().process_identify_query_res(param); - } -#endif /* defined ZB_BDB_ENABLE_FINDING_BINDING */ - break; - case ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_ID: - TRACE_MSG(TRACE_ERROR, "Received identify query request", (FMT__0)); - if (zb_zcl_is_identifying(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)) - { - attr_desc = zb_zcl_get_attr_desc_a( - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_IDENTIFY, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID); - ZB_ZCL_IDENTIFY_SEND_IDENTIFY_QUERY_RES( - param, - *(zb_uint16_t*)attr_desc->data_p, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - cmd_info.seq_number, - (zb_bool_t)ZB_APS_FC_GET_SECURITY(cmd_info.addr_data.common_data.fc)); - } - else - { - status = ZB_ZCL_STATUS_SUCCESS; - ZB_ZCL_PROCESS_COMMAND_FINISH_NEW(param, &cmd_info, status); - } - break; - - case ZB_ZCL_CMD_IDENTIFY_TRIGGER_EFFECT_ID: - ZB_ZCL_IDENTIFY_GET_TRIGGER_VARIANT_REQ(&payload_effect, param, status); - if (status!=ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ERROR, "Got erroneous payload length %hd != 2", - (FMT__H, zb_buf_len(param))); - ZB_ZCL_SEND_DEFAULT_RESP( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_IDENTIFY, - cmd_info.seq_number, - ZB_ZCL_CMD_IDENTIFY_TRIGGER_EFFECT_ID, - ZB_ZCL_STATUS_MALFORMED_CMD); - } - else - { - ZB_ZCL_IDENTIFY_EFFECT_SCHEDULE_USER_APP(param, &cmd_info, - payload_effect.effect_id, payload_effect.effect_variant); - } - break; - - default: - processed = ZB_FALSE; - break; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_identify_specific_commands: processed %d", - (FMT__D, processed)); - return processed; -} - -zb_bool_t zb_zcl_process_identify_specific_commands_srv(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_identify_server_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_identify_specific_commands(param); -} -zb_bool_t zb_zcl_process_identify_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_identify_client_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_identify_specific_commands(param); -} - -/* Assumes param contains an endpoint number */ -void zb_zcl_identify_time_handler(zb_uint8_t param) -{ - zb_zcl_attr_t *attr_desc; - zb_callback_t identify_handler; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_identify_time_handler %hd", (FMT__H, param)); - attr_desc = zb_zcl_get_attr_desc_a( - param, - ZB_ZCL_CLUSTER_ID_IDENTIFY, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID); - if (attr_desc && attr_desc->data_p) - { - zb_uint16_t * value_ptr = (zb_uint16_t*)attr_desc->data_p; - if (*value_ptr) - { - (*value_ptr)--; - ZB_SCHEDULE_ALARM(zb_zcl_identify_time_handler, param, ZB_TIME_ONE_SECOND); - TRACE_MSG(TRACE_ZCL3, "new value is: %d", (FMT__D, *value_ptr)); - } - else - { - identify_handler = GET_IDENTIFY_HANDLER(param); - TRACE_MSG(TRACE_ZCL2, "identify timeout, handler %p", (FMT__P, identify_handler)); - if (identify_handler) - { - ZB_SCHEDULE_CALLBACK(identify_handler, ZB_FALSE); - } - } - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_identify_time_handler", (FMT__0)); -} - -zb_uint8_t zb_zcl_start_identifying(zb_uint8_t endpoint, zb_uint16_t timeout) -{ - zb_uint8_t status = ZB_ZCL_STATUS_SUCCESS; - zb_zcl_attr_t * attr_desc; - zb_uint16_t old_timeout; - zb_callback_t identify_handler; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_start_identifying endpoint %hd timeout %ds", (FMT__D_H, endpoint, timeout)); - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IDENTIFY, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID); - if (!attr_desc || !attr_desc->data_p) - { - status = ZB_ZCL_STATUS_UNSUP_ATTRIB; - } - else - { - /* TODO read attribute call? */ - old_timeout = *(zb_uint16_t*)attr_desc->data_p; - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, timeout); - if (*(zb_uint16_t*)attr_desc->data_p) - { - if (!old_timeout) - { - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_identify_time_handler, endpoint); - ZB_SCHEDULE_ALARM(zb_zcl_identify_time_handler, endpoint, ZB_TIME_ONE_SECOND); - identify_handler = GET_IDENTIFY_HANDLER(endpoint); - if (identify_handler) - { - ZB_SCHEDULE_CALLBACK(identify_handler, ZB_TRUE); - } - } - } - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_start_identifying status %hd", (FMT__H, status)); - return status; -} - -zb_uint8_t zb_zcl_is_identifying(zb_uint8_t endpoint) -{ - zb_uint8_t result = ZB_FALSE; - zb_zcl_attr_t * attr_desc; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_is_identifying: endpoint %hd", (FMT__H, endpoint)); - - if (endpoint) - { - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IDENTIFY, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID); - if (attr_desc) - { - result = (0 != (*(zb_uint16_t*)attr_desc->data_p)); - } - else - { - TRACE_MSG(TRACE_ERROR, "Attribute not found", (FMT__0)); - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_is_identifying: result %hd", (FMT__H, result)); - return result; -} - -void zb_zcl_stop_identifying(zb_uint8_t endpoint) -{ - zb_zcl_attr_t * attr_desc; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_stop_identifying: endpoint %hd", (FMT__H, endpoint)); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IDENTIFY, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID); - - if (attr_desc) - { - zb_callback_t identify_handler; - - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_identify_time_handler, endpoint); - - /* Write 0 to identify time attribute. */ - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, 0); - - /* Notify application that identify is finished. */ - identify_handler = GET_IDENTIFY_HANDLER(endpoint); - TRACE_MSG(TRACE_ZCL2, "identify manually stopped, handler %p", (FMT__P, identify_handler)); - if (identify_handler) - { - ZB_SCHEDULE_CALLBACK(identify_handler, ZB_FALSE); - } - } - else - { - TRACE_MSG(TRACE_ERROR, "error: Attribute not found", (FMT__0)); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_stop_identifying", (FMT__0)); -} - -/** @brief Hook on Write attribute - * Start Identifying on IdentifyTime attribute set */ -void zb_zcl_identify_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value) -{ - zb_uint16_t val = 0; - (void)endpoint; - (void)attr_id; - ZB_ASSIGN_UINT16(&val, new_value); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_identify_write_attr_hook endpoint %hx attr_id %d", - (FMT__H_D, endpoint, attr_id)); - - /* ZCL8, 3.5.2.2.1 IdentifyTime attribute: - * If this attribute is set to a value other than 0x0000 then the device SHALL enter its - * identification procedure, in order to indicate to an observer which of several devices it is. It - * is recommended that this procedure consists of flashing a light with a period of 0.5 - * seconds. The IdentifyTime attribute SHALL be decremented every second. */ - if (attr_id == ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID) - { - if (val != 0) - { - TRACE_MSG(TRACE_ZCL1, "start identifying", (FMT__0)); - zb_zcl_start_identifying(endpoint, val); - } - else - { - TRACE_MSG(TRACE_ZCL1, "stop identifying", (FMT__0)); - zb_zcl_stop_identifying(endpoint); - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_identify_write_attr_hook", (FMT__0)); -} - -#endif /* defined(ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY) */ diff --git a/zboss/development/src/zcl/zcl_illuminance_measurement.c b/zboss/development/src/zcl/zcl_illuminance_measurement.c deleted file mode 100644 index efd27e3740..0000000000 --- a/zboss/development/src/zcl/zcl_illuminance_measurement.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#define ZB_TRACE_FILE_ID 79 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_ILLUMINANCE_MEASUREMENT) - -zb_ret_t check_value_illuminance_measurement_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_illuminance_measurement_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_illuminance_measurement_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_illuminance_measurement_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_illuminance_measurement_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> check_value_illuminance_measurement", (FMT__0)); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID: - { - zb_uint16_t val = ZB_ZCL_ATTR_GET16(value); - - if( val == ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_TOO_LOW || - val == ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_INVALID) - { - ret = RET_OK; - } - else - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_ID); - - ZB_ASSERT(attr_desc); - - ret = (ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) == - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_UNDEFINED - || ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) <= val) - ? RET_OK : RET_ERROR; - - if (ret != RET_OK) - { - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_ID); - - ZB_ASSERT(attr_desc); - - ret = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) == - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_UNDEFINED || - val <= ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) - ? RET_OK : RET_ERROR; - } - } - } - break; - - case ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_ID: - ret = ( - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_MIN_VALUE <= ZB_ZCL_ATTR_GET16(value) && - (ZB_ZCL_ATTR_GET16(value) <= ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_MAX_VALUE) ) - ? RET_OK : RET_ERROR; - - if (ret != RET_OK) - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_ID); - - ZB_ASSERT(attr_desc); - - ret = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) == - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_UNDEFINED || - ZB_ZCL_ATTR_GET16(value) < ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) - ? RET_OK : RET_ERROR; - } - break; - - case ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_ID: - ret = ( (ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_MIN_VALUE <= ZB_ZCL_ATTR_GET16(value)) && - (ZB_ZCL_ATTR_GET16(value) <= ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MAX_MEASURED_VALUE_MAX_VALUE) ) - ? RET_OK : RET_ERROR; - - if (ret != RET_OK) - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_ID); - - ZB_ASSERT(attr_desc); - - ret = (ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) == - ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MIN_MEASURED_VALUE_UNDEFINED - || ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) < ZB_ZCL_ATTR_GET16(value)) - ? RET_OK : RET_ERROR; - } - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "< check_value_illuminance_measurement ret %hd", (FMT__H, ret)); - return ret; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_ILLUMINANCE_MEASUREMENT */ diff --git a/zboss/development/src/zcl/zcl_level_control_commands.c b/zboss/development/src/zcl/zcl_level_control_commands.c deleted file mode 100644 index f1dfa08055..0000000000 --- a/zboss/development/src/zcl/zcl_level_control_commands.c +++ /dev/null @@ -1,1507 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Level Control cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2072 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_LEVEL_CONTROL) - -#include "zb_zcl.h" - -/* #ifdef ZB_ZCL_SUPPORT_CLUSTER_ON_OFF - use it if extra functionality is needed */ - -#define ZB_LEVEL_CONTROL_TRANSITION_TIME_UNIT ZB_TIME_ONE_SECOND / 10 - -#define ZB_LEVEL_CONTROL_TRANSITION_TIME_ONE_SECOND 10 - -#define ZB_LEVEL_CONTROL_GET_TIME_IN_UNITS() ZB_TIME_BEACON_INTERVAL_TO_MSEC(ZB_TIMER_GET()) / 100 - -#define ZB_LEVEL_CONTROL_MIN_TRANSITION_TIME 1 - -zb_uint8_t gs_level_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_LEVEL_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_level_client_cmd_list = -{ - 0, NULL, - sizeof(gs_level_server_received_commands), gs_level_server_received_commands -}; - -zb_discover_cmd_list_t gs_level_server_cmd_list = -{ - sizeof(gs_level_server_received_commands), gs_level_server_received_commands, - 0, NULL -}; - -static void move_to_level_continue(zb_uint8_t param); -static void level_control_stop_internal(zb_uint8_t endpoint); - -static zb_ret_t check_value_level_control_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -static zb_ret_t check_value_level_control_client(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -zb_bool_t zb_zcl_process_level_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_level_specific_commands_cli(zb_uint8_t param); - -void zb_zcl_level_control_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_level_control_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_level_specific_commands_srv); -} - -void zb_zcl_level_control_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - check_value_level_control_client, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_level_specific_commands_cli); -} - -static zb_ret_t check_value_level_control_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - - ZVUNUSED(endpoint); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID: - if( ZB_ZCL_ATTR_GET16(value) > ZB_ZCL_LEVEL_CONTROL_CLUSTER_REVISION_MAX ) - { - ret = RET_ERROR; - } - break; - default: - break; - } - - return ret; -} - -static zb_ret_t check_value_level_control_client(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - - ZVUNUSED(endpoint); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID: - if( ZB_ZCL_ATTR_GET16(value) > ZB_ZCL_LEVEL_CONTROL_CLUSTER_REVISION_MAX ) - { - ret = RET_ERROR; - } - break; - default: - break; - } - - return ret; -} - -zb_zcl_level_control_move_variables_t *level_control_get_move_variables(zb_uint8_t endpoint) -{ - zb_zcl_attr_t* move_status_desc; - - move_status_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_MOVE_STATUS_ID); - - return (move_status_desc) ? - &((zb_zcl_level_control_move_status_t*)move_status_desc->data_p)->move_var : - NULL; -} - -zb_ret_t level_control_value_set_func(zb_uint8_t endpoint, zb_uint16_t* value, zb_uint16_t remaining_time) -{ - zb_zcl_device_callback_param_t *device_cb_param; - zb_bufid_t dev_buf = zb_buf_get_out(); - zb_uint8_t current_value8 = *value & 0xff; - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "level_control_value_set_func: level %hd remaining_time %d", (FMT__H_D, current_value8, remaining_time)); - - ZB_ASSERT(dev_buf != 0); - ZB_ASSERT(endpoint); - device_cb_param = ZB_BUF_GET_PARAM(dev_buf, zb_zcl_device_callback_param_t); - - device_cb_param->device_cb_id = ZB_ZCL_LEVEL_CONTROL_SET_VALUE_CB_ID; - device_cb_param->endpoint = endpoint; - device_cb_param->cb_param.level_control_set_value_param.new_value = current_value8; - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(dev_buf); - ret = device_cb_param->status; - } - - if (ret == RET_OK) - { - zb_zcl_attr_t* remaining_time_desc; - /* Use SET_ATTRIBUTE to report attribute change if needed. */ - ZB_ZCL_SET_ATTRIBUTE(endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, - ¤t_value8, - ZB_FALSE); - - remaining_time_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_REMAINING_TIME_ID); - - if (remaining_time_desc && - (ZB_ZCL_GET_ATTRIBUTE_VAL_16(remaining_time_desc) > remaining_time)) - { - TRACE_MSG(TRACE_ZCL1, "update remaining_time", (FMT__0)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(remaining_time_desc, remaining_time); - } - } - - zb_buf_free(dev_buf); - return ret; -} - -static zb_bool_t level_control_check_req_options(zb_uint8_t param, zb_uint8_t endpoint) -{ - zb_zcl_level_control_req_options_t req_options; - zb_bool_t res = ZB_TRUE; - zb_zcl_attr_t *attr_desc; - zb_zcl_level_control_move_variables_t* move_variables = level_control_get_move_variables(endpoint); - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_ON_OFF - zb_af_endpoint_desc_t *ep_desc; - zb_zcl_cluster_desc_t *cluster_desc; -#endif - - ZB_ASSERT(move_variables); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_OPTIONS_ID); - - if (attr_desc != NULL) - { - zb_uint8_t options = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - ZB_ZCL_LEVEL_CONTROL_GET_CMD_OPTIONS(param, req_options); - - /* Check and override bits if needed */ - if (ZB_CHECK_BIT_IN_BIT_VECTOR(&req_options.options_mask, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_EXECUTE_IF_OFF)) - { - if (ZB_CHECK_BIT_IN_BIT_VECTOR(&req_options.options_override, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_EXECUTE_IF_OFF)) - { - ZB_SET_BIT_IN_BIT_VECTOR(&options, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_EXECUTE_IF_OFF); - } - else - { - ZB_CLR_BIT_IN_BIT_VECTOR(&options, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_EXECUTE_IF_OFF); - } - } - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_ON_OFF - /* ZCL8, 3.10.2.2.8.1 ExecuteIfOff Options Bit - Command execution SHALL NOT continue beyond the Options proceeding if all of thee criteria - are true: - - The command is on of the "without On/Off" commands - - The On/Off cluster exists on the same endpoint as this cluster - - The OnOff attribute of the On/Off cluster, on this endpoint, is 0x00 (FALSE) - - The value of the ExecuteIfOff bit is 0 - */ - - if (move_variables->addr.cmd_id == ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL || - move_variables->addr.cmd_id == ZB_ZCL_CMD_LEVEL_CONTROL_MOVE || - move_variables->addr.cmd_id == ZB_ZCL_CMD_LEVEL_CONTROL_STEP || - move_variables->addr.cmd_id == ZB_ZCL_CMD_LEVEL_CONTROL_STOP) - { - ep_desc = zb_af_get_endpoint_desc(endpoint); - cluster_desc = get_cluster_desc(ep_desc, ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE); - /* On/Off cluster may not be on the endpoint. - * In this case return true and continue command execution .*/ - if (cluster_desc) - { - attr_desc = zb_zcl_get_attr_desc(cluster_desc, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID); - - if (attr_desc && - !ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) && /* On/Off attribute is Off */ - !ZB_CHECK_BIT_IN_BIT_VECTOR(&options, ZB_ZCL_LEVEL_CONTROL_OPTIONS_EXECUTE_IF_OFF)) /* ExecuteIfOff - * is False */ - { - /* ExecuteIfOff policy, deny */ - res = ZB_FALSE; - } - } - } -#endif - } - - TRACE_MSG(TRACE_ZCL1, "level_control_check_req_options: enabled %hd", (FMT__H, res)); - return res; -} - -void level_control_default_resp(zb_uint8_t param, zb_uint16_t user_param) -{ - zb_zcl_level_control_move_variables_t* move_variables; - zb_uint8_t endpoint = ZB_GET_HI_BYTE(user_param); - zb_uint8_t status = ZB_GET_LOW_BYTE(user_param); - - TRACE_MSG(TRACE_ZCL1, "level_control_default_resp param %hd user_param %hd %hd", (FMT__H_H_H, param, endpoint, status)); - - move_variables = level_control_get_move_variables(endpoint); - ZB_ASSERT(move_variables); - - ZB_ZCL_SEND_DEFAULT_RESP(param, - move_variables->addr.src_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - move_variables->addr.src_endpoint, - move_variables->addr.dst_endpoint, - move_variables->addr.profile_id, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - move_variables->addr.seq_number, - move_variables->addr.cmd_id, - (status ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL)); -} - -zb_bool_t level_control_calculate_and_start_cvc(zb_zcl_cvc_input_variables_t *input_var, zb_bool_t is_onoff, zb_uint8_t endpoint) -{ - zb_bool_t status = ZB_TRUE; - zb_uint8_t alarm_buf_id; - zb_zcl_level_control_move_variables_t* move_variables; - zb_bool_t on_value = ZB_TRUE; - zb_uint8_t alarm_id; - - move_variables = level_control_get_move_variables(endpoint); - ZB_ASSERT(move_variables); - - alarm_buf_id = zb_zcl_cvc_calculate_transition_values(input_var); - - status = (alarm_buf_id != ZB_UNDEFINED_BUFFER) ? ZB_TRUE : ZB_FALSE; - - if (status == ZB_TRUE) - { - zb_zcl_cvc_variables_t* change_var = - ZB_BUF_GET_PARAM((alarm_buf_id), zb_zcl_cvc_variables_t); - - if (is_onoff && (change_var->input_var.end_value16 > ZB_ZCL_LEVEL_CONTROL_LEVEL_MIN_VALUE)) - { - /* for with_On/Off commands need to send On if necessary, - see ZCL spec, 3.10.2.3.5 */ - TRACE_MSG(TRACE_ZCL1, "with ON/OFF cmd, set ON", (FMT__0)); - ZB_ZCL_SET_ATTRIBUTE(move_variables->addr.dst_endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, - (zb_uint8_t*)&on_value, - ZB_FALSE); - } - - alarm_id = zb_zcl_cvc_start_alarm(move_variables->addr.dst_endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, - alarm_buf_id); - - status = (alarm_id != ZB_ZCL_CVC_INVALID_ALARM_ID) ? ZB_TRUE : ZB_FALSE; - - if (status) - { - zb_uint16_t remaining_time = 0; - - if (change_var->steps_number > 1) - { - remaining_time = change_var->input_var.transition_time; - } - ZB_ZCL_SET_ATTRIBUTE(endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_REMAINING_TIME_ID, - (zb_uint8_t*)&remaining_time, - ZB_FALSE); - } - else - { - zb_buf_free(alarm_buf_id); - } - } - - return status; -} - -static void move_to_level_handler( - zb_uint8_t param, zb_bool_t is_onoff, zb_uint8_t endpoint) -{ - zb_zcl_level_control_move_variables_t* move_variables; - zb_zcl_level_control_move_to_level_req_t move_to_level_req; - zb_bool_t status; - zb_zcl_cvc_input_variables_t input_var; - zb_uint8_t min_value = ZB_ZCL_LEVEL_CONTROL_LEVEL_MIN_VALUE; - zb_uint8_t max_value = ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE; - - - TRACE_MSG(TRACE_ZCL1, "> move_to_level_handler param %i", (FMT__H, param)); - - move_variables = level_control_get_move_variables(endpoint); - ZB_ASSERT(move_variables); - - ZB_ZCL_LEVEL_CONTROL_GET_MOVE_TO_LEVEL_REQ(param, move_to_level_req, status); - - if (status == ZB_TRUE) - { - if (!level_control_check_req_options(param, endpoint)) - { - TRACE_MSG(TRACE_ZCL1, "Command execution SHALL NOT continue beyond the Options processing", (FMT__0)); - } - else - { - TRACE_MSG(TRACE_ZCL1, - "ZB_ZCL_LEVEL_CONTROL_GET_MOVE_TO_LEVEL_REQ: new level is %i", - (FMT__H, move_to_level_req.level)); - - TRACE_MSG(TRACE_ZCL1, - "ZB_ZCL_LEVEL_CONTROL_GET_MOVE_TO_LEVEL_REQ: transition time is %d", - (FMT__D, move_to_level_req.transition_time)); - - level_control_stop_internal(endpoint); - - if (move_to_level_req.transition_time != 0) - { - input_var.transition_time = move_to_level_req.transition_time; - } - else - { - /*If Transition Time given is 0, then need to to move as fast as able */ - input_var.transition_time = ZB_ZCL_LEVEL_CONTROL_TRANSITION_TIME_AS_FAST_AS_ABLE; - }; - - move_variables->is_onoff = is_onoff; - - input_var.current_value16 = move_variables->curr_level; - input_var.end_value16 = move_to_level_req.level; - - /* This needed to set OFF from move_to_level_continue() when necessary */ - move_variables->end_level = move_to_level_req.level; - - input_var.buf_id = 0; - input_var.after_processing_cb = move_to_level_continue; - input_var.value_set_func = level_control_value_set_func; - - input_var.min_value16 = min_value; - input_var.max_value16 = max_value; - input_var.overlap = ZB_FALSE; - - status = level_control_calculate_and_start_cvc(&input_var, is_onoff, endpoint); - } - } - else - { - TRACE_MSG(TRACE_ERROR, "cant read Move REQ", (FMT__0)); - } - - if (!(status && move_variables->addr.disable_default_response)) - { - zb_uint16_t user_param = status; - - ZB_SET_HI_BYTE(user_param, move_variables->addr.dst_endpoint); - level_control_default_resp(param, user_param); - } - else if (param != 0) - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< move_to_level_handler", (FMT__0)); -} - - -static void move_to_level_continue(zb_uint8_t endpoint) -{ - zb_zcl_level_control_move_variables_t* move_variables; - zb_uint8_t off_value = 0; - - TRACE_MSG(TRACE_ZCL1, "move_to_level_continue ep %hd", (FMT__H, endpoint)); - move_variables = level_control_get_move_variables(endpoint); - ZB_ASSERT(move_variables); - - if (move_variables->is_onoff && - move_variables->end_level == ZB_ZCL_LEVEL_CONTROL_LEVEL_MIN_VALUE) - { - - ZB_ZCL_SET_ATTRIBUTE(move_variables->addr.dst_endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, - &off_value, - ZB_FALSE); - } -} - - -static void move_handler(zb_uint8_t param, zb_bool_t is_onoff, zb_uint8_t endpoint) -{ - zb_zcl_level_control_move_req_t move_req; - zb_int16_t tmp; - zb_uint8_t diff; - zb_bool_t status; - zb_zcl_level_control_move_variables_t* move_variables; - zb_zcl_cvc_input_variables_t input_var; - zb_uint8_t min_value = ZB_ZCL_LEVEL_CONTROL_LEVEL_MIN_VALUE; - zb_uint8_t max_value = ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE; - - TRACE_MSG(TRACE_ZCL1, "> move_handler", (FMT__0)); - - move_variables = level_control_get_move_variables(endpoint); - ZB_ASSERT(move_variables); - - ZB_ZCL_LEVEL_CONTROL_GET_MOVE_REQ(param, move_req, status); - - if (status == ZB_TRUE) - { - if (!level_control_check_req_options(param, endpoint)) - { - TRACE_MSG(TRACE_ZCL1, "Command execution SHALL NOT continue beyond the Options processing", (FMT__0)); - } - else - { - TRACE_MSG(TRACE_ZCL1, "move_mode = %i", (FMT__H, move_req.move_mode)); - TRACE_MSG(TRACE_ZCL1, "rate = %i", (FMT__H, move_req.rate)); - - level_control_stop_internal(endpoint); - - if (move_req.move_mode <= ZB_ZCL_LEVEL_CONTROL_MOVE_MODE_DOWN) - { - move_variables->is_onoff = is_onoff; - - /* end_level for Move command is MIN_VALUE or MAX_VALUE */ - if (!move_req.move_mode) - { - move_variables->end_level = ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE; - } - else - { - move_variables->end_level = ZB_ZCL_LEVEL_CONTROL_LEVEL_MIN_VALUE; - } - - TRACE_MSG(TRACE_ZCL1, "end_level = %i", (FMT__H, move_variables->end_level)); - - /* If Rate is 0xff, need to move fast as able, so transition time setting to minimum, - see ZCL spec */ - - if (move_req.rate == ZB_ZCL_LEVEL_CONTROL_RATE_AS_FAST_AS_ABLE) - { - /* Its minimal transition time */ - input_var.transition_time = ZB_ZCL_LEVEL_CONTROL_TRANSITION_TIME_AS_FAST_AS_ABLE; - } - else - { - tmp = move_variables->curr_level - move_variables->end_level; - - tmp = ZB_ABS(tmp); - diff = (zb_uint8_t)tmp; - - /* NK: we can work with 1/10 of second already here, to increase accuracy of Move command */ - input_var.transition_time = (diff * ZB_LEVEL_CONTROL_TRANSITION_TIME_ONE_SECOND) / move_req.rate; - - /* Move command operates with seconds, when transition_time is in 1/10 of second. - If rate is greater then diff, need to do one transition (1 second) for setting level */ - if (!input_var.transition_time) - { - input_var.transition_time = ZB_LEVEL_CONTROL_TRANSITION_TIME_ONE_SECOND; - } - } - - TRACE_MSG(TRACE_ZCL1, - "Redirect to Move to Level: level = %i", - (FMT__D, move_variables->end_level)); - - TRACE_MSG(TRACE_ZCL1, - "Redirect to Move to Level: transition time = %d", - (FMT__D, input_var.transition_time)); - - - //TODO: CVC start - input_var.current_value16 = move_variables->curr_level; - input_var.end_value16 = move_variables->end_level; - - input_var.buf_id = 0; - input_var.after_processing_cb = move_to_level_continue; - input_var.value_set_func = level_control_value_set_func; - - input_var.min_value16 = min_value; - input_var.max_value16 = max_value; - input_var.overlap = ZB_FALSE; - - status = level_control_calculate_and_start_cvc(&input_var, is_onoff, endpoint); - } - else - { - TRACE_MSG(TRACE_ERROR, "Mode parameter is invalid", (FMT__0)); - status = ZB_FALSE; - } - } - } - else - { - TRACE_MSG(TRACE_ERROR, "cant read Move REQ", (FMT__0)); - } - - if (!(status && move_variables->addr.disable_default_response)) - { - zb_uint16_t user_param = status; - - ZB_SET_HI_BYTE(user_param, move_variables->addr.dst_endpoint); - level_control_default_resp(param, user_param); - } - else if (param != 0) - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< move_handler", (FMT__0)); -} - -static void step_handler( - zb_uint8_t param, zb_bool_t is_onoff, zb_uint8_t endpoint) -{ - zb_zcl_level_control_step_req_t step_req; - zb_int16_t tmp; - zb_uint8_t diff; - zb_bool_t status; - zb_zcl_level_control_move_variables_t* move_variables; - zb_zcl_cvc_input_variables_t input_var; - zb_uint8_t min_value = ZB_ZCL_LEVEL_CONTROL_LEVEL_MIN_VALUE; - zb_uint8_t max_value = ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE; - - TRACE_MSG(TRACE_ZCL1, "> step_handler", (FMT__0)); - - move_variables = level_control_get_move_variables(endpoint); - ZB_ASSERT(move_variables); - - ZB_ZCL_LEVEL_CONTROL_GET_STEP_REQ(param, step_req, status); - - if (status == ZB_TRUE) - { - if (!level_control_check_req_options(param, endpoint)) - { - TRACE_MSG(TRACE_ZCL1, "Command execution SHALL NOT continue beyond the Options processing", (FMT__0)); - } - else - { - TRACE_MSG(TRACE_ZCL1, "step_mode = %i", (FMT__H, step_req.step_mode)); - TRACE_MSG(TRACE_ZCL1, "step_size = %i", (FMT__H, step_req.step_size)); - TRACE_MSG(TRACE_ZCL1, "transition_time = %d", (FMT__D, step_req.transition_time)); - - level_control_stop_internal(endpoint); - - if (step_req.step_mode <= ZB_ZCL_LEVEL_CONTROL_STEP_MODE_DOWN) - { - move_variables->is_onoff = is_onoff; - - if (step_req.transition_time == 0) - { - /*If Transition Time given is 0, then need to to move as fast as able */ - input_var.transition_time = ZB_ZCL_LEVEL_CONTROL_TRANSITION_TIME_AS_FAST_AS_ABLE; - } - - if (!step_req.step_mode) - { - tmp = move_variables->curr_level + step_req.step_size; - if (tmp > ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE) - { - move_variables->end_level = ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE; - diff = move_variables->end_level - move_variables->curr_level; - - input_var.transition_time = diff * step_req.transition_time / step_req.step_size + 1; - } - else - { - move_variables->end_level = tmp; - input_var.transition_time = step_req.transition_time; - } - } - else - { - tmp = move_variables->curr_level - step_req.step_size; - if (tmp < ZB_ZCL_LEVEL_CONTROL_LEVEL_MIN_VALUE) - { - move_variables->end_level = ZB_ZCL_LEVEL_CONTROL_LEVEL_MIN_VALUE; - diff = move_variables->curr_level - move_variables->end_level; - input_var.transition_time = diff * step_req.transition_time / step_req.step_size + 1; - } - else - { - move_variables->end_level = tmp; - input_var.transition_time = step_req.transition_time; - } - } - - TRACE_MSG(TRACE_ZCL1, "end level = %i", (FMT__H, move_variables->end_level)); - TRACE_MSG(TRACE_ZCL1, - "Redirect to Move to Level: level = %i", - (FMT__D, move_variables->end_level)); - - TRACE_MSG(TRACE_ZCL1, - "Redirect to Move to Level: transition time = %d", - (FMT__D, input_var.transition_time)); - - input_var.current_value16 = move_variables->curr_level; - input_var.end_value16 = move_variables->end_level; - - input_var.buf_id = 0; - input_var.after_processing_cb = move_to_level_continue; - input_var.value_set_func = level_control_value_set_func; - - input_var.min_value16 = min_value; - input_var.max_value16 = max_value; - input_var.overlap = ZB_FALSE; - - status = level_control_calculate_and_start_cvc(&input_var, is_onoff, endpoint); - } - else - { - TRACE_MSG(TRACE_ERROR, "step_mode parameter is invalid", (FMT__0)); - status = ZB_FALSE; - } - } - } - else - { - TRACE_MSG(TRACE_ERROR, "cant read Step REQ", (FMT__0)); - } - - if (!(status && move_variables->addr.disable_default_response)) - { - zb_uint16_t user_param = status; - - ZB_SET_HI_BYTE(user_param, move_variables->addr.dst_endpoint); - level_control_default_resp(param, user_param); - } - else if (param != 0) - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< step_handler", (FMT__0)); -} - -static void level_control_stop_internal(zb_uint8_t endpoint) -{ - zb_zcl_level_control_move_status_t* move_status; - zb_zcl_attr_t* move_status_desc; - zb_uint8_t alarm_id; - zb_uint16_t remaining_time = 0; - - ZB_ZCL_SET_ATTRIBUTE(endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_REMAINING_TIME_ID, - (zb_uint8_t*)&remaining_time, - ZB_FALSE); - - // - move_status_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_MOVE_STATUS_ID); - - ZB_ASSERT(move_status_desc != NULL); - - move_status = (zb_zcl_level_control_move_status_t*)move_status_desc->data_p; - - alarm_id = zb_zcl_cvc_check_transition_running(move_status->move_var.addr.dst_endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID); - - if (alarm_id != ZB_ZCL_CVC_INVALID_ALARM_ID) - { - zb_zcl_cvc_stop_transition(alarm_id); - TRACE_MSG(TRACE_ZCL3, "prev command killed", (FMT__0)); - } -} - -static void stop_handler(zb_uint8_t param, zb_uint8_t endpoint) -{ - - zb_zcl_parsed_hdr_t cmd_info; - zb_zcl_level_control_move_variables_t* move_variables; - zb_uint8_t status = ZB_TRUE; - - TRACE_MSG(TRACE_ZCL1, "> stop_handler param %i", (FMT__H, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, "cmd_id is %i", (FMT__H, cmd_info.cmd_id)); - - move_variables = level_control_get_move_variables(endpoint); - ZB_ASSERT(move_variables); - - if (level_control_check_req_options(param, endpoint)) - { - level_control_stop_internal(endpoint); - } - else - { - TRACE_MSG(TRACE_ZCL1, "Command execution SHALL NOT continue beyond the Options processing", (FMT__0)); - } - - if (!(status && move_variables->addr.disable_default_response)) - { - zb_uint16_t user_param = status; - - ZB_SET_HI_BYTE(user_param, move_variables->addr.dst_endpoint); - level_control_default_resp(param, user_param); - } - else if (param != 0) - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< stop_handler", (FMT__0)); -} - -zb_bool_t zb_zcl_process_level_control_specific_commands(zb_uint8_t param) -{ - zb_zcl_attr_t* curr_level_desc; - zb_zcl_attr_t* move_status_desc; - zb_zcl_level_control_move_variables_t* move_variables; - zb_uint8_t curr_level; - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_zcl_level_control_move_addr_t main_addr; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_level_control_specific_commands: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - main_addr.src_addr = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr; - main_addr.src_endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint; - main_addr.dst_endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - main_addr.cmd_id = cmd_info.cmd_id; - main_addr.seq_number = cmd_info.seq_number; - main_addr.disable_default_response = (zb_bool_t)cmd_info.disable_default_response; - main_addr.profile_id = cmd_info.profile_id; - - curr_level_desc = zb_zcl_get_attr_desc_a(main_addr.dst_endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID); - - move_status_desc = zb_zcl_get_attr_desc_a(main_addr.dst_endpoint, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_LEVEL_CONTROL_MOVE_STATUS_ID); - - ZB_ASSERT(move_status_desc != NULL); - ZB_ASSERT(curr_level_desc != NULL); - - curr_level = *(zb_uint8_t*)curr_level_desc->data_p; - - TRACE_MSG(TRACE_ZCL1, "current level is %i", (FMT__H, curr_level)); - - move_variables = level_control_get_move_variables(main_addr.dst_endpoint); - ZB_ASSERT(move_variables); - - move_variables->curr_level = curr_level; - - ZB_MEMCPY(&(move_variables->addr), &main_addr, sizeof(zb_zcl_level_control_move_addr_t)); - - switch (main_addr.cmd_id) - { - case ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL: - move_to_level_handler(param, ZB_FALSE, main_addr.dst_endpoint); - TRACE_MSG(TRACE_ZCL3, "Processed MOVE_TO_LEVEL command", (FMT__0)); - break; - - case ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_TO_LEVEL_WITH_ON_OFF: - move_to_level_handler(param, ZB_TRUE, main_addr.dst_endpoint); - TRACE_MSG(TRACE_ZCL3, "Processed MOVE_TO_LEVEL_WITH_ON_OFF command", (FMT__0)); - break; - - case ZB_ZCL_CMD_LEVEL_CONTROL_MOVE: - move_handler(param, ZB_FALSE, main_addr.dst_endpoint); - TRACE_MSG(TRACE_ZCL3, "Processed MOVE command", (FMT__0)); - break; - - case ZB_ZCL_CMD_LEVEL_CONTROL_MOVE_WITH_ON_OFF: - move_handler(param, ZB_TRUE, main_addr.dst_endpoint); - TRACE_MSG(TRACE_ZCL3, "Processed MOVE_WITH_ON_OFF command", (FMT__0)); - break; - - case ZB_ZCL_CMD_LEVEL_CONTROL_STEP: - step_handler(param, ZB_FALSE, main_addr.dst_endpoint); - TRACE_MSG(TRACE_ZCL3, "Processed STEP command", (FMT__0)); - break; - - case ZB_ZCL_CMD_LEVEL_CONTROL_STEP_WITH_ON_OFF: - step_handler(param, ZB_TRUE, main_addr.dst_endpoint); - TRACE_MSG(TRACE_ZCL3, "Processed STEP_WITH_ON_OFF command", (FMT__0)); - break; - - case ZB_ZCL_CMD_LEVEL_CONTROL_STOP: - case ZB_ZCL_CMD_LEVEL_CONTROL_STOP_WITH_ON_OFF: - { - zb_zcl_level_control_move_addr_t *addr = - ZB_BUF_GET_PARAM(param, zb_zcl_level_control_move_addr_t); - - ZB_MEMCPY(addr, &main_addr, sizeof(zb_zcl_level_control_move_addr_t)); - stop_handler(param, main_addr.dst_endpoint); - - TRACE_MSG(TRACE_ZCL3, "STOP command processed", (FMT__0)); - } - break; - - default: - processed = ZB_FALSE; - break; - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_level_control_specific_commands: processed %d", - (FMT__D, processed)); - - return processed; -} - -zb_bool_t zb_zcl_process_level_specific_commands_srv(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_level_server_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_level_control_specific_commands(param); -} - -zb_bool_t zb_zcl_process_level_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_level_client_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_level_control_specific_commands(param); -} - -static inline void zb_zcl_level_control_send_move_cmd_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t cmd_id) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), cmd_id); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (move_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (rate)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, cb); -} - -static inline void zb_zcl_level_control_send_move_cmd_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override, - zb_uint8_t cmd_id) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), cmd_id); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (move_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (rate)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, cb); -} - -void zb_zcl_level_control_send_move_cmd_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t options_mask, zb_uint8_t options_override, - zb_uint8_t cmd_id) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_level_control_send_move_cmd_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_LEVEL_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_level_control_send_move_cmd_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, rate, - cmd_id); - break; - case 3: - zb_zcl_level_control_send_move_cmd_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, rate, - options_mask, options_override, - cmd_id); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_level_control_send_move_cmd_zcl8", (FMT__0)); -} - -void zb_zcl_level_control_send_move_cmd(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t move_mode, zb_uint8_t rate, - zb_uint8_t cmd_id) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_level_control_send_move_cmd", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_level_control_send_move_cmd_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, rate, - cmd_id); - break; - case 3: - zb_zcl_level_control_send_move_cmd_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - move_mode, rate, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE, - cmd_id); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_level_control_send_move_cmd", (FMT__0)); -} - -static inline void zb_zcl_level_control_send_move_to_level_cmd_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t level, zb_uint16_t transition_time, - zb_uint8_t cmd_id) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), (cmd_id)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (level)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, cb); -} - -static inline void zb_zcl_level_control_send_move_to_level_cmd_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t level, zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override, - zb_uint8_t cmd_id) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, (def_resp)) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), (cmd_id)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (level)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, cb); -} - -void zb_zcl_level_control_send_move_to_level_cmd_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t level, zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override, - zb_uint8_t cmd_id) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_level_control_send_move_to_level_cmd_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_LEVEL_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_level_control_send_move_to_level_cmd_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - level, transition_time, - cmd_id); - break; - case 3: - zb_zcl_level_control_send_move_to_level_cmd_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - level, transition_time, - options_mask, options_override, - cmd_id); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_level_control_send_move_to_level_cmd_zcl8", (FMT__0)); -} - -void zb_zcl_level_control_send_move_to_level_cmd(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t level, zb_uint16_t transition_time, - zb_uint8_t cmd_id) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_level_control_send_move_to_level_cmd", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_level_control_send_move_to_level_cmd_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - level, transition_time, - cmd_id); - break; - case 3: - zb_zcl_level_control_send_move_to_level_cmd_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - level, transition_time, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE, - cmd_id); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_level_control_send_move_to_level_cmd", (FMT__0)); -} - -static inline void zb_zcl_level_control_send_step_cmd_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint16_t transition_time, - zb_uint8_t cmd_id) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), cmd_id); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_size)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, cb); -} - -static inline void zb_zcl_level_control_send_step_cmd_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override, - zb_uint8_t cmd_id) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), cmd_id); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_mode)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (step_size)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, cb); -} - -void zb_zcl_level_control_send_step_cmd_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint16_t transition_time, - zb_uint8_t options_mask, zb_uint8_t options_override, - zb_uint8_t cmd_id) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_level_control_send_step_cmd_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_LEVEL_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_level_control_send_step_cmd_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, transition_time, - cmd_id); - break; - case 3: - zb_zcl_level_control_send_step_cmd_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, transition_time, - options_mask, options_override, - cmd_id); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_level_control_send_step_cmd_zcl8", (FMT__0)); -} - -void zb_zcl_level_control_send_step_cmd(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t step_mode, zb_uint8_t step_size, - zb_uint16_t transition_time, - zb_uint8_t cmd_id) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_level_control_send_step_cmd", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_level_control_send_step_cmd_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, transition_time, - cmd_id); - break; - case 3: - zb_zcl_level_control_send_step_cmd_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - step_mode, step_size, transition_time, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE, - cmd_id); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_level_control_send_step_cmd", (FMT__0)); -} - -static inline void zb_zcl_level_control_send_stop_req_rev1(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_LEVEL_CONTROL_STOP); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, cb); -} - -static inline void zb_zcl_level_control_send_stop_req_rev3(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_LEVEL_CONTROL_STOP); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_mask)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (options_override)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, cb); -} - -void zb_zcl_level_control_send_stop_req_zcl8(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb, - zb_uint8_t options_mask, zb_uint8_t options_override) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_level_control_send_stop_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_LEVEL_CONTROL_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_level_control_send_stop_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb); - break; - case 3: - zb_zcl_level_control_send_stop_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - options_mask, options_override); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_level_control_send_stop_req_zcl8", (FMT__0)); -} - -void zb_zcl_level_control_send_stop_req(zb_bufid_t buffer, const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t ep, zb_uint16_t prof_id, - zb_uint8_t def_resp, zb_callback_t cb) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_level_control_send_stop_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - /* FALLTHROUGH */ - case 2: - zb_zcl_level_control_send_stop_req_rev1(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb); - break; - case 3: - zb_zcl_level_control_send_stop_req_rev3(buffer, dst_addr, - dst_addr_mode, dst_ep, - ep, prof_id, - def_resp, cb, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_MASK_DEFAULT_FIELD_VALUE, - ZB_ZCL_LEVEL_CONTROL_OPTIONS_OVERRIDE_DEFAULT_FIELD_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_level_control_send_stop_req", (FMT__0)); -} - -#ifdef ZB_COMPILE_ZCL_SAMPLE - -void send_move_to_level_req(zb_bufid_t data_buf, zb_uint16_t prof_id, zb_uint16_t dst_addr, - zb_uint8_t dst_ep, zb_uint8_t src_ep, zb_uint8_t level, - zb_uint16_t transition_time) -{ - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_REQ(data_buf, - dst_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, - src_ep, - prof_id, ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL, - level, - transition_time); - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_TO_LEVEL_WITH_ON_OFF_REQ(data_buf, - dst_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, - src_ep, - prof_id, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL, - level, - transition_time); -} - - -void send_move_req(zb_bufid_t data_buf, zb_uint16_t prof_id, zb_uint16_t dst_addr, - zb_uint8_t dst_ep, zb_uint8_t src_ep, zb_uint8_t move_mode, - zb_uint8_t rate) -{ - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_REQ(data_buf, dst_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, src_ep, prof_id, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL, move_mode, rate); - ZB_ZCL_LEVEL_CONTROL_SEND_MOVE_WITH_ON_OFF_REQ(data_buf, - dst_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, src_ep, prof_id, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL, move_mode, rate); -} - - -void send_step_req(zb_bufid_t data_buf, zb_uint16_t prof_id, zb_uint16_t dst_addr, - zb_uint8_t dst_ep, zb_uint8_t src_ep, zb_uint8_t step_mode, - zb_uint8_t step_size, zb_uint16_t transition_time) -{ - ZB_ZCL_LEVEL_CONTROL_SEND_STEP_REQ(data_buf, dst_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, src_ep, prof_id, ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL, step_mode, step_size, transition_time); - ZB_ZCL_LEVEL_CONTROL_SEND_STEP_WITH_ON_OFF_REQ(data_buf, - dst_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, src_ep, prof_id, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL, step_mode, step_size, transition_time); -} - - - -void send_stop_req(zb_bufid_t data_buf, zb_uint16_t prof_id, zb_uint16_t dst_addr, - zb_uint8_t dst_ep, zb_uint8_t src_ep) -{ - ZB_ZCL_LEVEL_CONTROL_SEND_STOP_REQ(data_buf, dst_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_ep, src_ep, prof_id, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - NULL); -} - -#endif /* defined ZB_COMPILE_ZCL_SAMPLE */ - -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_LEVEL_CONTROL */ diff --git a/zboss/development/src/zcl/zcl_main.c b/zboss/development/src/zcl/zcl_main.c deleted file mode 100644 index 3214ee6c19..0000000000 --- a/zboss/development/src/zcl/zcl_main.c +++ /dev/null @@ -1,893 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: Zigbee cluster library, the main module -*/ - -#define ZB_TRACE_FILE_ID 2074 - -#include "zb_common.h" - -/* #define ZB_ZCL_ENABLE_DEFAULT_ALARMS_PROCESSING */ - -#if defined (ZB_ENABLE_ZCL) - -#include "zb_zcl.h" -#include "zb_aps.h" -#include "zcl/zb_zcl_common.h" - -#if !(defined ZB_ZCL_DISABLE_REPORTING) -#include "zcl/zb_zcl_reporting.h" -#endif - -#include "zcl/zb_zcl_cvc_commands.h" -#include "zcl/zcl_ota_upgrade_commands.h" -#ifdef ZB_ENABLE_HA_SAS -#include "ha/zb_ha_sas.h" -#endif -#include "zb_bdb_internal.h" -#include "zb_zdo.h" -#include "zb_aps.h" - -#include "zdo_wwah_stubs.h" - -static zb_uint_t zb_zcl_get_header_size(zb_bufid_t buf) -{ - zb_uint8_t* zcl_packet = zb_buf_begin(buf); - return ZB_ZCL_GET_HEADER_SIZE(*zcl_packet); -} - -#if defined HA_CERTIFICATION -zb_bool_t zb_zcl_rejected_command(zb_uint8_t param); -#endif /* HA_CERTIFICATION */ - -void zb_zcl_init() -{ - TRACE_MSG(TRACE_ZCL1, ">>zcl_init", (FMT__0)); - - ZB_BZERO(&ZCL_CTX(), sizeof(zb_zcl_globals_t)); -/* - min_interval and max_interval are set to ZERO value by BZERO call -#if !(defined ZB_ZCL_DISABLE_REPORTING) - ZCL_CTX().reporting_ctx.min_interval == ZB_ZCL_TIMEOUT_ZERO; - ZCL_CTX().reporting_ctx.max_interval == ZB_ZCL_TIMEOUT_ZERO; -#endif -*/ - - ZCL_CTX().runtime_buf = zb_buf_get_any(); - - ZB_ASSERT(ZCL_CTX().runtime_buf); - -#if !(defined ZB_ZCL_DISABLE_REPORTING) -/* - Initialize reporting context, allocate free out buffer for reporting. - TODO: comment if reporting is not supported. -*/ - zb_zcl_init_reporting_ctx(); -#endif - -#if defined ZB_ENABLE_HA_SAS - zb_ha_process_sas(); -#endif /* defined ZB_ENABLE_HA_SAS */ - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_handle param %hd", (FMT__H, param)); - - TRACE_MSG( - TRACE_ZCL2, - "f type %d cmd %d", - (FMT__D_D, cmd_info_ptr->is_common_command, cmd_info_ptr->cmd_id)); - - status = zb_zcl_check_accept_command(param); - if (status == ZB_ZCL_STATUS_SUCCESS) - { - if (cmd_info_ptr->is_common_command) - { - processed = zb_zcl_handle_general_commands(param); - } - else - { - processed = zb_zcl_handle_specific_commands(param); - } - - if (!processed) - { - /* TODO: return correct status by zb_zcl_handle_general_commands() */ - TRACE_MSG(TRACE_ZCL1, "command is not processed", (FMT__0)); - /* ZCL8: CCB 2477: use UNSUP_COMMAND instead of any other Unsupported command status */ - if (zb_zcl_get_backward_compatible_statuses_mode() == ZB_ZCL_STATUSES_ZCL8_MODE) - { - status = ZB_ZCL_STATUS_UNSUP_CMD; - } - else - { - if (cmd_info_ptr->is_manuf_specific) - { - status = cmd_info_ptr->is_common_command ? - ZB_ZCL_STATUS_UNSUP_MANUF_GEN_CMD : ZB_ZCL_STATUS_UNSUP_MANUF_CLUST_CMD; - } - else - { - status = cmd_info_ptr->is_common_command ? - ZB_ZCL_STATUS_UNSUP_GEN_CMD : ZB_ZCL_STATUS_UNSUP_CLUST_CMD; - } - } - } - } /* zb_zcl_check_accept_command() */ - else - { -#if defined HA_CERTIFICATION - if (zb_zcl_rejected_command(param) ) - { - processed = ZB_TRUE; - } - else -#endif /* HA_CERTIFICATION */ - TRACE_MSG(TRACE_ZCL1, "skip command processing", (FMT__0)); - } - - if (processed) - { - status = ZB_ZCL_STATUS_SUCCESS; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_handle, ret %hd", (FMT__H, status)); - - return status; -} - -void zb_zcl_deinit() -{ - TRACE_MSG(TRACE_ZCL1, ">>zcl_deinit", (FMT__0)); - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_parse_header: param %hd h 0x%hx sz %hd, dst endp %hd", - (FMT__H_H_H_H, param, zb_buf_get_handle(param), zb_buf_len(param), ind->dst_endpoint)); - - /* buffer should have enough data for parsing command! */ - if (zb_buf_len(param) < zb_zcl_get_header_size(param)) - { - TRACE_MSG(TRACE_ERROR, "ERROR: buffer should have enough data for parsing command!", (FMT__0)); - return ZB_ZCL_STATUS_MALFORMED_CMD; - } - - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.addr_type = ZB_ZCL_ADDR_TYPE_SHORT; - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr = ind->src_addr; - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint = ind->src_endpoint; - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_addr = ind->dst_addr; - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint = ind->dst_endpoint; - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).fc = ind->fc; - -#if (defined ZB_ENABLE_SE) || (defined ZB_ZCL_SUPPORT_CLUSTER_WWAH) - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).aps_key_from_tc = ind->aps_key_from_tc; -#endif - - cmd_info->cluster_id = ind->clusterid; - cmd_info->profile_id = ind->profileid; - - zcl_header = zb_buf_begin(param); - - /* ZCL frame format */ - /* frame control 1b | manufacturer code 0/2b | TSN 1b | cmd id 1b | payload XXb */ - - /* frame control */ - /* frame type | manufacturer specific | direction | disable default resp */ - - /* Parse ZCL frame control */ - frame_type = ZB_ZCL_GET_FRAME_TYPE(*zcl_header); - cmd_info->is_common_command = (frame_type == ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC ) ? ZB_FALSE : ZB_TRUE; - if( frame_type != ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC && frame_type != ZB_ZCL_FRAME_TYPE_COMMON) - { - ret = ZB_ZCL_STATUS_INVALID_FIELD; - } - cmd_info->cmd_direction = ZB_ZCL_GET_DIRECTION(*zcl_header); - cmd_info->disable_default_response = (ZB_ZCL_GET_DISABLE_DEFAULT_RESPONSE(*zcl_header) != 0U )?(ZB_TRUE ):(ZB_FALSE ); - if (ZB_ZCL_GET_MANUF_SPECIFIC(*zcl_header) != 0U) - { - cmd_info->is_manuf_specific = ZB_TRUE; - zcl_header++; - ZB_ZCL_PACKET_GET_DATA16(&(cmd_info->manuf_specific), zcl_header); - } - else - { - /* there is no manufacturer specific sub field, get TSN field */ - cmd_info->is_manuf_specific = ZB_FALSE; - zcl_header++; - } - - /* Get TSN */ - cmd_info->seq_number = *zcl_header; - zcl_header++; - - /* Get command ID */ - cmd_info->cmd_id = *zcl_header; - - /* Note: there was cut of ZCL header here. Moved to zb_zcl_process_device_command() - the only caller of this routine. */ - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_parse_header ret = %hd", (FMT__H, ret)); - - return ret; -} - -zb_ret_t zb_zcl_add_cluster_handlers(zb_uint16_t cluster_id, - zb_uint8_t cluster_role, - zb_zcl_cluster_check_value_t cluster_check_value, - zb_zcl_cluster_write_attr_hook_t cluster_write_attr_hook, - zb_zcl_cluster_handler_t cluster_handler) -{ - zb_ret_t ret = RET_EMPTY; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_add_cluster_handlers cluster 0x%x role %hd", - (FMT__H_D, cluster_id, cluster_role)); - TRACE_MSG(TRACE_ZCL1, "check_value %p write_attr_hook %p handler %p", - (FMT__P_P_P, cluster_check_value, cluster_write_attr_hook, cluster_handler)); - if ((cluster_handler != NULL || cluster_check_value != NULL || cluster_write_attr_hook != NULL) - /*cstat !MISRAC2012-Rule-13.5 !MISRAC2012-Rule-13.6 */ - /* After some investigation, the following violations of Rule 13.5 and 13.6 seem to be false - * positives. There are no side effect to 'ZCL_CTX()'. This violation seems to be caused by - * the fact that 'ZCL_CTX()' is an external macro, which cannot be analyzed by C-STAT. */ - && ZCL_CTX().zcl_handlers_cnt < ZB_ARRAY_SIZE(ZCL_CTX().zcl_handlers)) - { - zb_uindex_t i = 0; - /* Search if we already have handler */ - while (i < ZCL_CTX().zcl_handlers_cnt) - { - if (ZCL_CTX().zcl_handlers[i].cluster_id == cluster_id - /*cstat !MISRAC2012-Rule-13.5 */ - /* After some investigation, the following violation of Rule 13.5 seems to be a false - * positive. There are no side effect to 'ZCL_CTX()'. This violation seems to be caused by - * the fact that 'ZCL_CTX()' is an external macro, which cannot be analyzed by C-STAT. */ - && ZCL_CTX().zcl_handlers[i].cluster_role == cluster_role) - { - break; - } - ++i; - } - if (i == ZCL_CTX().zcl_handlers_cnt) - { - /* add new entry */ - ZCL_CTX().zcl_handlers[i].cluster_id = cluster_id; - ZCL_CTX().zcl_handlers[i].cluster_role = cluster_role; - ZCL_CTX().zcl_handlers[i].cluster_handler = cluster_handler; - ZCL_CTX().zcl_handlers[i].cluster_check_value = cluster_check_value; - ZCL_CTX().zcl_handlers[i].cluster_write_attr_hook = cluster_write_attr_hook; - ++ZCL_CTX().zcl_handlers_cnt; - ret = RET_OK; - } - else - { - ret = RET_ALREADY_EXISTS; - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_add_cluster_handlers cluster ret %d", (FMT__D, ret)); - - return ret; -} - -zb_zcl_cluster_handler_t zb_zcl_get_cluster_handler(zb_uint16_t cluster_id, zb_uint8_t cluster_role) -{ - zb_uindex_t i = 0; - zb_zcl_cluster_handler_t ret = NULL; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_get_cluster_handler: cluster_id 0x%x cluster_role %hd", - (FMT__D_H, cluster_id, cluster_role)); - - /* Search if we already have handler */ - while (i < ZCL_CTX().zcl_handlers_cnt) - { - if (ZCL_CTX().zcl_handlers[i].cluster_id == cluster_id - /*cstat !MISRAC2012-Rule-13.5 */ - /* After some investigation, the following violation of Rule 13.5 seems to be a false - * positive. There are no side effect to 'ZCL_CTX()'. This violation seems to be caused by - * the fact that 'ZCL_CTX()' is an external macro, which cannot be analyzed by C-STAT. */ - && (ZCL_CTX().zcl_handlers[i].cluster_role == cluster_role - /* || ZCL_CTX().zcl_handlers[i].cluster_role == ZB_ZCL_CLUSTER_MIXED_ROLE */)) - { - ret = ZCL_CTX().zcl_handlers[i].cluster_handler; - break; - } - ++i; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_get_cluster_handler ret %p", (FMT__P, ret)); - - return ret; -} - -zb_zcl_cluster_check_value_t zb_zcl_get_cluster_check_value(zb_uint16_t cluster_id, zb_uint8_t cluster_role) -{ - zb_uindex_t i = 0; - ZVUNUSED(cluster_role); - - TRACE_MSG(TRACE_ERROR, "zb_zcl_get_cluster_check_value: cluster_id %d cluster_role %hd", - (FMT__D_H, cluster_id, cluster_role)); - - /* Search if we already have handler */ - while (i < ZCL_CTX().zcl_handlers_cnt) - { - if (ZCL_CTX().zcl_handlers[i].cluster_id == cluster_id - /*cstat !MISRAC2012-Rule-13.5 */ - /* After some investigation, the following violation of Rule 13.5 seems to be a false - * positive. There are no side effect to 'ZCL_CTX()'. This violation seems to be caused by - * the fact that 'ZCL_CTX()' is an external macro, which cannot be analyzed by C-STAT. */ - && ZCL_CTX().zcl_handlers[i].cluster_role == cluster_role) - { - return ZCL_CTX().zcl_handlers[i].cluster_check_value; - } - ++i; - } - return NULL; -} - -zb_zcl_cluster_write_attr_hook_t zb_zcl_get_cluster_write_attr_hook(zb_uint16_t cluster_id, zb_uint8_t cluster_role) -{ - zb_uindex_t i = 0; - ZVUNUSED(cluster_role); - - TRACE_MSG(TRACE_ERROR, "zb_zcl_get_cluster_write_attr_hook: cluster_id %d cluster_role %hd", - (FMT__D_H, cluster_id, cluster_role)); - - /* Search if we already have handler */ - while (i < ZCL_CTX().zcl_handlers_cnt) - { - if (ZCL_CTX().zcl_handlers[i].cluster_id == cluster_id - /*cstat !MISRAC2012-Rule-13.5 */ - /* After some investigation, the following violation of Rule 13.5 seems to be a false - * positive. There are no side effect to 'ZCL_CTX()'. This violation seems to be caused by - * the fact that 'ZCL_CTX()' is an external macro, which cannot be analyzed by C-STAT. */ - && ZCL_CTX().zcl_handlers[i].cluster_role == cluster_role) - { - return ZCL_CTX().zcl_handlers[i].cluster_write_attr_hook; - } - ++i; - } - return NULL; -} - -#ifdef ZB_CONTROL4_NETWORK_SUPPORT -zb_ret_t zb_zcl_add_control4_cluster_handlers(zb_uint16_t cluster_id, zb_uint8_t cluster_role, - zb_zcl_cluster_check_value_t cluster_check_value, - zb_zcl_cluster_write_attr_hook_t cluster_write_attr_hook, - zb_zcl_cluster_handler_t cluster_handler) -{ - zb_ret_t ret = RET_EMPTY; - - TRACE_MSG(TRACE_ZCL1, "zb_zcl_add_control4_cluster_handlers cluster 0x%x role %hd", - (FMT__H_D, cluster_id, cluster_role)); - - if (cluster_handler || cluster_check_value || cluster_write_attr_hook) - { - zb_uindex_t i = (cluster_role == ZB_ZCL_CLUSTER_SERVER_ROLE ? 0 : 1); - - /* add new entry */ - ZCL_CTX().control4_zcl_handlers[i].cluster_id = cluster_id; - ZCL_CTX().control4_zcl_handlers[i].cluster_role = cluster_role; - ZCL_CTX().control4_zcl_handlers[i].cluster_handler = cluster_handler; - ZCL_CTX().control4_zcl_handlers[i].cluster_check_value = cluster_check_value; - ZCL_CTX().control4_zcl_handlers[i].cluster_write_attr_hook = cluster_write_attr_hook; - ret = RET_OK; - } - - return ret; -} - -zb_zcl_cluster_handler_t zb_zcl_get_control4_cluster_handler(zb_uint16_t cluster_id, zb_uint8_t cluster_role) -{ - zb_uindex_t i = (cluster_role == ZB_ZCL_CLUSTER_SERVER_ROLE ? 0 : 1); - - TRACE_MSG(TRACE_ZCL1, "zb_zcl_get_control4_cluster_handler: cluster_id 0x%x cluster_role %hd", - (FMT__D_H, cluster_id, cluster_role)); - - /* Search if we already have handler */ - if (ZCL_CTX().control4_zcl_handlers[i].cluster_id == cluster_id && - ZCL_CTX().control4_zcl_handlers[i].cluster_role == cluster_role) - { - return ZCL_CTX().control4_zcl_handlers[i].cluster_handler; - } - - return NULL; -} - -zb_zcl_cluster_check_value_t zb_zcl_get_control4_cluster_check_value(zb_uint16_t cluster_id, zb_uint8_t cluster_role) -{ - zb_uindex_t i = (cluster_role == ZB_ZCL_CLUSTER_SERVER_ROLE ? 0 : 1); - - TRACE_MSG(TRACE_ERROR, "zb_zcl_get_control4_cluster_check_value: cluster_id %d cluster_role %hd", - (FMT__D_H, cluster_id, cluster_role)); - - /* Search if we already have handler */ - if (ZCL_CTX().control4_zcl_handlers[i].cluster_id == cluster_id - && ZCL_CTX().control4_zcl_handlers[i].cluster_role == cluster_role) - { - return ZCL_CTX().control4_zcl_handlers[i].cluster_check_value; - } - - return NULL; -} - -zb_zcl_cluster_write_attr_hook_t zb_zcl_get_control4_cluster_write_attr_hook(zb_uint16_t cluster_id, zb_uint8_t cluster_role) -{ - zb_uindex_t i = (cluster_role == ZB_ZCL_CLUSTER_SERVER_ROLE ? 0 : 1); - - TRACE_MSG(TRACE_ERROR, "zb_zcl_get_control4_cluster_write_attr_hook: cluster_id %d cluster_role %hd", - (FMT__D_H, cluster_id, cluster_role)); - - /* Search if we already have handler */ - if (ZCL_CTX().control4_zcl_handlers[i].cluster_id == cluster_id - && ZCL_CTX().control4_zcl_handlers[i].cluster_role == cluster_role) - { - return ZCL_CTX().control4_zcl_handlers[i].cluster_write_attr_hook; - } - - return NULL; -} - -static zb_bool_t zb_zcl_check_control4_cluster_handler(zb_uint8_t endpoint) -{ - zb_bool_t res = ZB_FALSE; - - ZVUNUSED(endpoint); - -#ifdef ZB_ED_FUNC - res = (zb_bool_t )(zb_control4_network_permitted() && endpoint == ZB_CONTROL4_NETWORK_ENDPOINT); -#endif /* ZB_ED_FUNC */ - - return res; -} -#endif /* ZB_CONTROL4_NETWORK_SUPPORT */ - -zb_zcl_cluster_handler_t zb_zcl_get_cluster_handler_internal(zb_uint8_t endpoint, zb_uint16_t cluster_id, zb_uint8_t cluster_role) -{ - zb_zcl_cluster_handler_t cluster_handler; - - ZVUNUSED(endpoint); - -#ifdef ZB_CONTROL4_NETWORK_SUPPORT - if (zb_zcl_check_control4_cluster_handler(endpoint)) - { - cluster_handler = zb_zcl_get_control4_cluster_handler(cluster_id, cluster_role); - } - else -#endif /* ZB_CONTROL4_NETWORK_SUPPORT */ - { - cluster_handler = zb_zcl_get_cluster_handler(cluster_id, cluster_role); - } - - return cluster_handler; -} - -zb_zcl_cluster_check_value_t zb_zcl_internal_get_cluster_check_value(zb_uint8_t endpoint, zb_uint16_t cluster_id, zb_uint8_t cluster_role) -{ - zb_zcl_cluster_check_value_t cluster_check_value; - - ZVUNUSED(endpoint); - -#ifdef ZB_CONTROL4_NETWORK_SUPPORT - if (zb_zcl_check_control4_cluster_handler(endpoint)) - { - cluster_check_value = zb_zcl_get_control4_cluster_check_value(cluster_id, cluster_role); - } - else -#endif /* ZB_CONTROL4_NETWORK_SUPPORT */ - { - cluster_check_value = zb_zcl_get_cluster_check_value(cluster_id, cluster_role); - } - - return cluster_check_value; -} - -zb_zcl_cluster_write_attr_hook_t zb_zcl_internal_get_cluster_write_attr_hook(zb_uint8_t endpoint, zb_uint16_t cluster_id, zb_uint8_t cluster_role) -{ - zb_zcl_cluster_write_attr_hook_t cluster_write_attr_hook; - - ZVUNUSED(endpoint); - -#ifdef ZB_CONTROL4_NETWORK_SUPPORT - if (zb_zcl_check_control4_cluster_handler(endpoint)) - { - cluster_write_attr_hook = zb_zcl_get_control4_cluster_write_attr_hook(cluster_id, cluster_role); - } - else -#endif /* ZB_CONTROL4_NETWORK_SUPPORT */ - { - cluster_write_attr_hook = zb_zcl_get_cluster_write_attr_hook(cluster_id, cluster_role); - } - - return cluster_write_attr_hook; -} - - -zb_bool_t zb_zcl_handle_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed; - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_handle_specific_commands param %hd", (FMT__H, param)); - - { - zb_zcl_cluster_handler_t cluster_handler; - - cluster_handler = zb_zcl_get_cluster_handler_internal(cmd_info->addr_data.common_data.dst_endpoint, - cmd_info->cluster_id, - cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV ? - ZB_ZCL_CLUSTER_SERVER_ROLE : - ZB_ZCL_CLUSTER_CLIENT_ROLE); - if (cluster_handler != NULL) - { - processed = cluster_handler(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "Cluster 0x%04x was not processed", (FMT__D, cmd_info->cluster_id)); - processed = ZB_FALSE; - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_handle_specific_commands processed %hd", (FMT__H, processed)); - return processed; -}/* zb_uint8_t zb_zcl_handle_specific_commands(zb_uint8_t param) */ - -#if defined HA_CERTIFICATION -/* During HA certification came out that for some commands which - * should not be handled (command with direction "to server" is sent - * to client for example) we need to send a response anyway, but with - * "empty" body */ -zb_bool_t zb_zcl_rejected_command(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_zcl_cluster_desc_t *cluster_desc; - zb_af_endpoint_desc_t *endpoint_desc; - zb_bool_t ret = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_rejected_command %hd", (FMT__H, param)); - - endpoint_desc = zb_af_get_endpoint_desc(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint); - cluster_desc = get_cluster_desc(ep_desc, cmd_info->cluster_id, - (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE); - - ZB_ZCL_DEBUG_DUMP_HEADER(cmd_info); - - /* if command is manufacturer specific - skip handling it by default */ - TRACE_MSG(TRACE_ZCL2, "manuf_spec %hd", (FMT__H, cmd_info->is_manuf_specific)); - if (cluster_desc && - !cmd_info->is_manuf_specific && - cmd_info->is_common_command) - { - switch(cmd_info->cmd_id) - { - case ZB_ZCL_CMD_DISCOVER_COMMANDS_RECEIVED: - case ZB_ZCL_CMD_DISCOVER_COMMANDS_GENERATED: - ret = zb_zcl_handle_general_commands(param); - break; - - case ZB_ZCL_CMD_DISCOVER_ATTR_EXT: - { - zb_uint8_t *resp_data; - resp_data = ZB_ZCL_START_PACKET(ZCL_CTX().runtime_buf); - - /* generate frame control taking into account manufacturer specific */ - ZB_ZCL_CONSTRUCT_GENERAL_COMMAND_RESP_FRAME_CONTROL_EXT( - resp_data, cmd_info->is_manuf_specific, ZB_ZCL_REVERT_DIRECTION(cmd_info->cmd_direction)); - /* Generate command header taking into account manufacturer specific */ - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_EXT( - resp_data, cmd_info->seq_number, cmd_info->is_manuf_specific, cmd_info->manuf_specific, - ZB_ZCL_CMD_DISCOVER_ATTR_EXT_RES); - /* There is the same beginning for both Discover Attr and Discover attr ext Resp */ - ZB_ZCL_PACKET_PUT_DATA8(resp_data, ZB_ZCL_DISC_COMPLETE); - - ZB_ZCL_FINISH_N_SEND_PACKET(ZCL_CTX().runtime_buf, resp_data, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - NULL); - - /* Use runtime buffer to send request, use received buffer with - * request data_buf as runtime buffer */ - ret = ZB_TRUE; - } - break; - - - case ZB_ZCL_CMD_DISCOVER_COMMANDS_RECEIVED_RES: - case ZB_ZCL_CMD_DISCOVER_COMMANDS_GENERATED_RES: - case ZB_ZCL_CMD_DISCOVER_ATTR_EXT_RES: - ret = ZB_FALSE; - break; - - default: - ret = ZB_FALSE; - break; - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_rejected_command %hd", (FMT__H, ret)); - return ret; -} -#endif /* HA_CERTIFICATION */ - - -void zb_zcl_send_cmd_tsn( - zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_zcl_frame_direction_t direction, - zb_uint8_t src_ep, - const void *payload, - zb_uint8_t payload_size, - zb_zcl_put_payload_cb_t put_payload, - zb_zcl_cluster_id_t cluster_id, - zb_zcl_disable_default_response_t def_resp, - zb_uint8_t cmd_id, - zb_uint8_t tsn, - zb_callback_t cb - ) -{ - zb_uint16_t profile_id = get_profile_id_by_endpoint(src_ep); - zb_uint32_t bytes_avail; -#ifdef APS_FRAGMENTATION - /* zb_uint16_t payload_out_cnt = 3; */ - /* It was static variable initially in SE code. Seems can use a runtime buffer for it. Hope no conflict here. */ - /* zb_uint8_t *payload_temp_out; */ -#endif - zb_uint8_t *cmd_ptr; - - TRACE_MSG(TRACE_ZCL2, "zb_zcl_send_cmd: param %hd (cluster_id 0x%x cmd_id %d)", (FMT__H_D_D, param, cluster_id, cmd_id)); - TRACE_MSG(TRACE_ZCL2, "payload size %hd", (FMT__H, payload_size)); - cmd_ptr = ZB_ZCL_START_PACKET(param); - ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL(*cmd_ptr, - ZB_ZCL_FRAME_TYPE_CLUSTER_SPECIFIC, - ZB_ZCL_NOT_MANUFACTURER_SPECIFIC, - direction, - def_resp); - cmd_ptr++; - ZB_ZCL_CONSTRUCT_COMMAND_HEADER(cmd_ptr, tsn, cmd_id); - -#ifdef APS_FRAGMENTATION - bytes_avail = (ZB_ASDU_MAX_FRAG_LEN - ZB_ZCL_GET_BYTES_WRITTEN(param, cmd_ptr)); -#else - bytes_avail = (ZB_ZCL_HI_MAX_PAYLOAD_SIZE - ZB_ZCL_GET_BYTES_WRITTEN(param, cmd_ptr)); -#endif - - if (bytes_avail < payload_size) - { - TRACE_MSG(TRACE_ERROR, "zb_zcl_send_cmd: ERROR, buffer is full (cluster_id %d cmd_id %d)", (FMT__D_D, cluster_id, cmd_id)); - zb_buf_free(param); - return; - } - else - { - TRACE_MSG(TRACE_ZCL3, "zb_zcl_send_cmd: buffer have enough space (bytes_avail = %hd)", (FMT__H, bytes_avail)); - } - if (put_payload != NULL && payload != NULL) - { - cmd_ptr = put_payload(cmd_ptr, payload); - } - else if (put_payload == NULL && payload != NULL) - { - ZB_MEMCPY(cmd_ptr, payload, payload_size); - cmd_ptr += payload_size; - } - else - { - /* MISRA rule 15.7 requires empty 'else' branch. */ - } - - TRACE_MSG(TRACE_ZCL3, "zb_zcl_send_cmd addr_type %d to " TRACE_FORMAT_64, - (FMT__D_A, dst_addr_mode, TRACE_ARG_64(dst_addr->addr_long))); - - ZB_ZCL_FINISH_N_SEND_PACKET(param, cmd_ptr, - *dst_addr, - dst_addr_mode, - dst_ep, - src_ep, - profile_id, - cluster_id, - cb); -} - -void zb_zcl_send_cmd( - zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_zcl_frame_direction_t direction, - zb_uint8_t src_ep, - const void *payload, - zb_uint8_t payload_size, - zb_zcl_put_payload_cb_t put_payload, - zb_zcl_cluster_id_t cluster_id, - zb_zcl_disable_default_response_t def_resp, - zb_uint8_t cmd_id, - zb_callback_t cb - ) -{ - zb_zcl_send_cmd_tsn(param, dst_addr, dst_addr_mode, dst_ep, direction, - src_ep, payload, payload_size, put_payload, cluster_id, def_resp, cmd_id, ZB_ZCL_GET_SEQ_NUM(), cb); -} - - -/* Helper for sending default responses */ -zb_bool_t zb_zcl_send_default_handler(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info, zb_zcl_status_t status) -{ - zb_bool_t ret; - - TRACE_MSG(TRACE_ZCL3, ">zb_zcl_send_default_handler param %hd, status: %hd", (FMT__H_H, param, status)); - - do - { - if (!ZB_ZCL_CHECK_IF_SEND_DEFAULT_RESP(*cmd_info, status)) - { - ret = ZB_FALSE; - break; - } - - ZB_ZCL_SEND_DEFAULT_RESP_DIRECTION( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - cmd_info->seq_number, - cmd_info->cmd_id, - status, - ZB_ZCL_REVERT_DIRECTION(cmd_info->cmd_direction)); - - param = 0; - ret = ZB_TRUE; - } while (0); - - if (param != 0u) - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL3, "profile_id, - (pcmd_info)->cluster_id, - (pcmd_info)->seq_number, - (pcmd_info)->cmd_id, - (status)); - } - else - { - TRACE_MSG( TRACE_ZCL3, "Default response disabled", (FMT__0)); - zb_buf_free(buffer); - } -} - -void zb_zcl_process_command_finish_new(zb_bufid_t buffer, zb_zcl_parsed_hdr_t *pcmd_info, zb_uint8_t status) -{ - if (ZB_ZCL_CHECK_IF_SEND_DEFAULT_RESP(*(pcmd_info), status)) - { - ZB_ZCL_SEND_DEFAULT_RESP_NEW( - (buffer), - ZB_ZCL_PARSED_HDR_SHORT_DATA((pcmd_info)).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA((pcmd_info)).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA((pcmd_info)).dst_endpoint, - (pcmd_info)->profile_id, - (pcmd_info)->cluster_id, - (pcmd_info)->seq_number, - (pcmd_info)->cmd_id, - (status), - ZB_APS_FC_IS_SECURE((pcmd_info)->addr_data.common_data.fc)); - } - else - { - TRACE_MSG( TRACE_ZCL3, "Default response disabled", (FMT__0)); - zb_buf_free(buffer); - } -} - -void zb_zcl_send_default_resp_ext(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info, zb_zcl_status_t status) -{ - if (ZB_ZCL_CHECK_IF_SEND_DEFAULT_RESP(*cmd_info, status)) - { - ZB_ZCL_SEND_DEFAULT_RESP_EXT( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - cmd_info->cluster_id, - cmd_info->seq_number, - cmd_info->cmd_id, - status, - ZB_ZCL_REVERT_DIRECTION(cmd_info->cmd_direction), - cmd_info->is_manuf_specific, - cmd_info->manuf_specific, - NULL); - } - else - { - zb_buf_free(param); - } -} - -#endif /* defined (ZB_ENABLE_ZCL) */ diff --git a/zboss/development/src/zcl/zcl_meter_identification.c b/zboss/development/src/zcl/zcl_meter_identification.c deleted file mode 100644 index 5a5424f052..0000000000 --- a/zboss/development/src/zcl/zcl_meter_identification.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#define ZB_TRACE_FILE_ID 93 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_METER_IDENTIFICATION) - -static zb_ret_t check_value_meter_identification_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_meter_identification_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_METER_IDENTIFICATION, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)check_value_meter_identification_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_meter_identification_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_METER_IDENTIFICATION, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -static zb_ret_t check_value_meter_identification_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_METER_IDENTIFICATION */ diff --git a/zboss/development/src/zcl/zcl_nvram.c b/zboss/development/src/zcl/zcl_nvram.c deleted file mode 100644 index d172a525e6..0000000000 --- a/zboss/development/src/zcl/zcl_nvram.c +++ /dev/null @@ -1,707 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL datasets functions -*/ - -#define ZB_TRACE_FILE_ID 2056 - -#include "zb_common.h" - -#if defined ZB_USE_NVRAM && defined ZB_ENABLE_ZCL - -#include "zb_zcl.h" - -#if defined ZB_ENABLE_HA -/** @brief Read HA data from NVRAM */ - -void zb_nvram_read_ha_dataset( - zb_uint8_t page, zb_uint32_t pos, zb_uint16_t len, zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver) -{ - zb_nvram_dataset_ha_t ds; - zb_ret_t ret; - - TRACE_MSG(TRACE_ZCL1, "> zb_nvram_read_ha_dataset %hd pos %ld, len %d, nvram_ver %d", - (FMT__H_L_D_D, page, pos, len, nvram_ver)); - - ZVUNUSED(len); - ZVUNUSED(nvram_ver); - ZVUNUSED(ds_ver); - - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_read_data(page, pos, (zb_uint8_t*)&ds, sizeof(ds)); - - if (ret == RET_OK) - { - zb_uint8_t endpoint; - zb_zcl_attr_t *attr_desc; - -#if !defined ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE || !defined ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL - ZVUNUSED(endpoint); - ZVUNUSED(attr_desc); -#endif /* !ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE || !ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL */ - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE - /********** IAS Zone Data set *************/ - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE); - TRACE_MSG(TRACE_ZCL1, "ias zone ep %hd", (FMT__H, endpoint)); - - if (endpoint) - { - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID); - ZB_ASSERT(attr_desc); - - ZB_IEEE_ADDR_COPY(attr_desc->data_p, ds.cie_address); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONESTATE_ID); - ZB_ASSERT(attr_desc); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.zone_state); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONEID_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.zone_id); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_EP); - - ZB_ASSERT(attr_desc); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.cie_ep); - - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_SHORT_ADDR); - ZB_ASSERT(attr_desc); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ds.cie_short_addr); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET); - ZB_ASSERT(attr_desc); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.cie_address_is_set); - - if (ZB_U2B(ds.cie_address_is_set)) - { - ret = zb_zcl_ias_zone_put_cie_address_to_binding_whitelist(endpoint); - if (ret != RET_OK) - { - TRACE_MSG(TRACE_ERROR, "Put CIE address to binding whitelist failed ret %hu", (FMT__D, ret)); - } - } - } -#endif -#ifdef ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL - /********** Poll control Data set *************/ - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE); - TRACE_MSG(TRACE_ZCL1, "poll control ep %hd", (FMT__H, endpoint)); - if (endpoint) - { - zb_zcl_poll_control_srv_cfg_data_t *addr_data; - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POLL_CONTROL_ADDR_DATA_ID); - ZB_ASSERT(attr_desc); - - addr_data = (zb_zcl_poll_control_srv_cfg_data_t*)attr_desc->data_p; - addr_data->poll_addr = ds.poll_ctrl_short_addr; - addr_data->poll_ep = ds.poll_ctrl_ep; - } -#endif - /********** Diagnostic Data set *************/ - /* Diagnostics counters were moved into the ZDO Diagnostics dataset, see zb_nvram_dataset_diagnostics_v1_t */ -#if 0 - - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_DIAGNOSTICS, ZB_ZCL_CLUSTER_SERVER_ROLE); - TRACE_MSG(TRACE_ZCL1, "Diagnostic ep %hd", (FMT__H, endpoint)); - if (endpoint) - { - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_DIAGNOSTICS, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_DIAGNOSTICS_NUMBER_OF_RESETS_ID); - ZB_ASSERT(attr_desc); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ds.number_of_resets); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_DIAGNOSTICS, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_DIAGNOSTICS_JOIN_INDICATION_ID); - ZB_ASSERT(attr_desc); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ds.join_indication); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_DIAGNOSTICS, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_DIAGNOSTICS_PACKET_BUFFER_ALLOCATE_FAILURES_ID); - ZB_ASSERT(attr_desc); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ds.packet_buffer_allocate_failures); - } - -#endif - } - - TRACE_MSG(TRACE_ZCL1, "< zb_nvram_read_ha_dataset", (FMT__0)); -} - - -/** @brief Write HA data to NVRAM */ -zb_ret_t zb_nvram_write_ha_dataset(zb_uint8_t page, zb_uint32_t pos) -{ - zb_nvram_dataset_ha_t ds; - zb_uint8_t endpoint; - zb_zcl_attr_t *attr_desc; - - TRACE_MSG(TRACE_ZCL1, "> zb_nvram_write_ha_dataset page %hd pos %ld", - (FMT__H_L, page, pos)); - - ZB_BZERO(&ds, sizeof(ds)); - -#if !defined ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE || !defined ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL - ZVUNUSED(endpoint); - ZVUNUSED(attr_desc); -#endif /* !ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE || !ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL */ - - /********** IAS Zone Data set *************/ -#ifdef ZB_ZCL_SUPPORT_CLUSTER_IAS_ZONE - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE); - TRACE_MSG(TRACE_ZCL1, "ias zone ep %hd", (FMT__H, endpoint)); - - if (endpoint) - { - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_IAS_CIE_ADDRESS_ID); - ZB_ASSERT(attr_desc); - - ZB_IEEE_ADDR_COPY(ds.cie_address, attr_desc->data_p); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONESTATE_ID); - ZB_ASSERT(attr_desc); - - ds.zone_state = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_EP); - ZB_ASSERT(attr_desc); - - ds.cie_ep = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_IAS_ZONE_ZONEID_ID); - if (attr_desc) - { - ds.zone_id = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - } - else - { - ds.zone_id = 0; - } - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_SHORT_ADDR); - ZB_ASSERT(attr_desc); - - ds.cie_short_addr = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_IAS_ZONE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_CUSTOM_CIE_ADDR_IS_SET); - ZB_ASSERT(attr_desc); - - ds.cie_address_is_set = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - } -#endif -#ifdef ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL - /********** Poll control Data set *************/ - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE); - TRACE_MSG(TRACE_ZCL1, "poll control ep %hd", (FMT__H, endpoint)); - - if (endpoint) - { - zb_zcl_poll_control_srv_cfg_data_t *addr_data; - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POLL_CONTROL_ADDR_DATA_ID); - ZB_ASSERT(attr_desc); - - addr_data = (zb_zcl_poll_control_srv_cfg_data_t*)attr_desc->data_p; - ds.poll_ctrl_short_addr = addr_data->poll_addr; - ds.poll_ctrl_ep = addr_data->poll_ep; - } -#endif - /********** Diagnostic Data set *************/ - /* Diagnostics counters were moved into the ZDO Diagnostics dataset, see zb_nvram_dataset_diagnostics_v1_t */ -#if 0 - - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_DIAGNOSTICS, ZB_ZCL_CLUSTER_SERVER_ROLE); - TRACE_MSG(TRACE_ZCL1, "Diagnostic ep %hd", (FMT__H, endpoint)); - if (endpoint) - { - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_DIAGNOSTICS, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_DIAGNOSTICS_NUMBER_OF_RESETS_ID); - ZB_ASSERT(attr_desc); - ds.number_of_resets = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_DIAGNOSTICS, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_DIAGNOSTICS_JOIN_INDICATION_ID); - ZB_ASSERT(attr_desc); - ds.join_indication = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_DIAGNOSTICS, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_DIAGNOSTICS_PACKET_BUFFER_ALLOCATE_FAILURES_ID); - ZB_ASSERT(attr_desc); - ds.packet_buffer_allocate_failures = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - } - -#endif - - TRACE_MSG(TRACE_ZCL1, "< zb_nvram_write_ha_dataset", (FMT__0)); - - return zb_nvram_write_data(page, pos, (zb_uint8_t*)&ds, sizeof(ds)); -} - -/** - * @} internal -*/ -#endif /* defined ZB_ENABLE_HA*/ - -#if !defined ZB_ZCL_DISABLE_REPORTING -zb_uint16_t zb_nvram_zcl_reporting_dataset_length(void) -{ - zb_uindex_t i, j; - zb_zcl_reporting_info_t *rep_info; - zb_uint16_t counter = 0; - - TRACE_MSG(TRACE_ZCL1, ">> zb_nvram_zcl_reporting_dataset_length", (FMT__0)); - - /* Iterate all reporting_info's */ - if (ZCL_CTX().device_ctx) - { - for (i = 0; i < ZCL_CTX().device_ctx->ep_count; i++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[i]->reporting_info) - { - rep_info = ZCL_CTX().device_ctx->ep_desc_list[i]->reporting_info; - for (j = 0; j < ZCL_CTX().device_ctx->ep_desc_list[i]->rep_info_count; j++) - { - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY)) - { - counter++; - } - rep_info++; - } - } - } - } - - counter *= sizeof(zb_zcl_reporting_info_nvram_t); - TRACE_MSG(TRACE_ZCL1, "<< zb_nvram_zcl_reporting_dataset_length %d", (FMT__D, counter)); - return counter; -} - - -void zb_nvram_read_zcl_reporting_dataset( - zb_uint8_t page, zb_uint32_t pos, zb_uint16_t length, zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver) -{ - zb_zcl_reporting_info_nvram_t rec; - zb_zcl_reporting_info_t *rep_info; - zb_uindex_t i, j, k, l, count; - zb_ret_t ret; - - TRACE_MSG(TRACE_ZCL1, "> zb_nvram_read_zcl_reporting_dataset %hd pos %ld length %d nvram_ver %d", - (FMT__H_L_D_D, page, pos, length, nvram_ver)); - - ZVUNUSED(nvram_ver); - ZVUNUSED(ds_ver); - - count = length / sizeof(rec); - - /* Erase reporting_info for every ep */ - for (k = 0; k < ZCL_CTX().device_ctx->ep_count; k++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[k]->reporting_info) - { - ZB_BZERO(ZCL_CTX().device_ctx->ep_desc_list[k]->reporting_info, - sizeof(zb_zcl_reporting_info_t) * - ZCL_CTX().device_ctx->ep_desc_list[k]->rep_info_count); - } - } - - for( i=0, j=0; iep_count; k++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[k]->reporting_info && - ZCL_CTX().device_ctx->ep_desc_list[k]->ep_id == rec.ep) - { - break; - } - } - if (k < ZCL_CTX().device_ctx->ep_count) - { - rep_info = ZCL_CTX().device_ctx->ep_desc_list[k]->reporting_info; - /* Skip BUSY slots */ - l = 0; - while (l < ZCL_CTX().device_ctx->ep_desc_list[k]->rep_info_count && - ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY)) - { - ++l; - ++rep_info; - } - - if (l < ZCL_CTX().device_ctx->ep_desc_list[k]->rep_info_count) - { - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY); - - TRACE_MSG(TRACE_ZCL3, "rec info flags %hx, ep %hd, cluster_id %d, attr_id %d", - (FMT__H_H_D_D, rec.flags, rec.ep, rec.cluster_id, rec.attr_id)); - - rep_info->direction = rec.direction; - rep_info->ep = rec.ep; - rep_info->cluster_id = rec.cluster_id; - rep_info->cluster_role = rec.cluster_role; - rep_info->attr_id = rec.attr_id; - rep_info->flags = rec.flags; - - if (rep_info->direction == ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT) - { - rep_info->u.send_info.min_interval = rec.min_interval; - rep_info->u.send_info.max_interval = rec.max_interval; - rep_info->u.send_info.delta.u48.low = rec.delta; - } - else - { - rep_info->u.recv_info.timeout = rec.min_interval; - } - rep_info->dst.short_addr = rec.short_addr_dest; - rep_info->dst.endpoint = rec.endpoint_dest; - rep_info->dst.profile_id = rec.profile_id_dest; - - /* Set reported_value to 0xff - it is most likely not the default value and not the first - change for the attribute. - Rationale: we do not have a flag to check is it first or non-first report. Furthermore, - we do reporting checks AFTER applying new value to attribute. Because of that, if first - attribute change is to the value equal to initial reported_value (it is 0), this change - will not be reportable. 0xff value is invalid for the most of attributes, so looks like - it is more safe to use. - */ - ZB_MEMSET(&rep_info->u.send_info.reported_value, -1, sizeof(union zb_zcl_attr_var_u)); - - TRACE_MSG(TRACE_ZCL3, "next rep info %p, flags %hx, ep %hd, cluster_id %d, attr_id %d", - (FMT__P_H_H_D_D, rep_info, rep_info->flags, rep_info->ep, rep_info->cluster_id, rep_info->attr_id)); - - zb_zcl_update_reporting_info(rep_info); -#if 0 /* obsolete? */ - /* Mark attr for reporting - we need to send first report with min interval. */ - zb_zcl_mark_attr_for_reporting(rep_info->ep, rep_info->cluster_id, rep_info->attr_id); - //rep_info++; -#endif - j++; - } - } - - if(j>0) // run timers - { - zb_zcl_adjust_reporting_timer(0); - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_nvram_read_zcl_reporting_dataset", (FMT__0)); -} - - -zb_ret_t zb_nvram_write_zcl_reporting_dataset(zb_uint8_t page, zb_uint32_t pos) -{ - zb_zcl_reporting_info_nvram_t rec; - zb_zcl_reporting_info_t *rep_info; - zb_zcl_reporting_info_nvram_t empty_rec; - zb_ret_t ret = RET_OK; - zb_uindex_t i, j; - zb_uint8_t n_entries = 0; - - TRACE_MSG(TRACE_ZCL1, "> zb_nvram_write_zcl_reporting_dataset %hd pos %ld", - (FMT__H_L, page, pos)); - - if (ZCL_CTX().device_ctx) - { - /* Calculate number of entries to store */ - for (j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) - { - rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; - for (i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) - { - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY)) - { - n_entries++; - } - rep_info++; - } - } - } - - TRACE_MSG(TRACE_ZCL3, "%hd entries to store", (FMT__H, n_entries)); - - if (!n_entries) - { - TRACE_MSG(TRACE_ZCL3, "store empty entry", (FMT__0)); - - ZB_BZERO(&empty_rec, sizeof(zb_zcl_reporting_info_nvram_t)); - - ret = zb_nvram_write_data(page, pos, (zb_uint8_t*)&empty_rec, sizeof(empty_rec)); - } - else - { - for (j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) - { - rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; - for (i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) - { - TRACE_MSG(TRACE_ZCL3, "next rep info %p, flags %hx, ep %hd, cluster_id %d, attr_id %d", - (FMT__P_H_H_D_D, rep_info, rep_info->flags, rep_info->ep, rep_info->cluster_id, rep_info->attr_id)); - - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY)) - { - TRACE_MSG(TRACE_ZCL1, "save %hd rec", (FMT__H, i)); - - ZB_BZERO(&rec, sizeof(rec)); - - rec.direction = rep_info->direction; - rec.ep = rep_info->ep; - rec.cluster_id = rep_info->cluster_id; - rec.cluster_role = rep_info->cluster_role; - rec.attr_id = rep_info->attr_id; - rec.flags = rep_info->flags; - - if (rep_info->direction == ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT) - { - rec.min_interval = rep_info->u.send_info.min_interval; - rec.max_interval = rep_info->u.send_info.max_interval; - rec.delta = rep_info->u.send_info.delta.u48.low; - } - else - { - rec.min_interval = rep_info->u.recv_info.timeout; - } - rec.short_addr_dest = rep_info->dst.short_addr; - rec.endpoint_dest = rep_info->dst.endpoint; - rec.profile_id_dest = rep_info->dst.profile_id; - - TRACE_MSG(TRACE_ZCL1, "rec info flags %hx, ep %hd, cluster_id %d, attr_id %d", - (FMT__H_H_D_D, rec.flags, rec.ep, rec.cluster_id, rec.attr_id)); - - ret = zb_nvram_write_data(page, pos, (zb_uint8_t*)&rec, sizeof(rec)); - pos += sizeof(rec); - } - - rep_info++; - } - } - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_nvram_write_zcl_reporting_dataset %hd", - (FMT__D, ret)); - - return ret; -} -#endif /* !defined ZB_ZCL_DISABLE_REPORTING */ - - -#if defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN -/** @brief Read POOL CONTROL data from NVRAM */ -void zb_nvram_read_poll_control_dataset( - zb_uint8_t page, zb_uint32_t pos, zb_uint16_t len, zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver) -{ - zb_nvram_dataset_poll_control_t ds; - zb_ret_t ret; - - ZVUNUSED(len); - ZVUNUSED(nvram_ver); - ZVUNUSED(ds_ver); - - TRACE_MSG(TRACE_ZCL1, "> zb_nvram_read_poll_control_dataset %d pos %ld len %d nvram_ver %d", - (FMT__H_L_D_D, page, pos, len, nvram_ver)); - - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_read_data(page, pos, (zb_uint8_t*)&ds, sizeof(ds)); - - if (ret == RET_OK) - { - zb_uint8_t endpoint; - zb_zcl_attr_t *attr_desc; - - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE); - ZB_ASSERT(endpoint); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, ds.checkin_interval); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, ds.long_poll_interval); - zb_zdo_pim_set_long_poll_interval(ZB_QUARTERECONDS_TO_MSEC(ds.long_poll_interval)); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ds.short_poll_interval); - zb_zdo_pim_set_fast_poll_interval(ZB_QUARTERECONDS_TO_MSEC(ds.short_poll_interval)); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_TIMEOUT_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ds.fast_poll_timeout); - zb_zdo_pim_set_fast_poll_timeout(ZB_QUARTERECONDS_TO_MSEC(ds.fast_poll_timeout)); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_MIN_CHECKIN_INTERVAL_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, ds.checkin_interval_min); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_MIN_INTERVAL_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, ds.long_poll_interval_min); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_MAX_TIMEOUT_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ds.fast_poll_timeout_max); - } - TRACE_MSG(TRACE_ZCL1, "< zb_nvram_read_poll_control_dataset", (FMT__0)); -} - - -/** @brief Write POOL CONTROL data to NVRAM */ -zb_ret_t zb_nvram_write_poll_control_dataset(zb_uint8_t page, zb_uint32_t pos) -{ - zb_nvram_dataset_poll_control_t ds; - zb_uint8_t endpoint; - zb_zcl_attr_t *attr_desc; - - TRACE_MSG(TRACE_ZCL1, "> zb_nvram_write_poll_control_dataset page %d pos %ld", - (FMT__H_L, page, pos)); - - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE); - ZB_ASSERT(endpoint); - - ZB_BZERO(&ds, sizeof(ds)); - - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID); - ZB_ASSERT(attr_desc); - ds.checkin_interval = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID); - ZB_ASSERT(attr_desc); - ds.long_poll_interval = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID); - ZB_ASSERT(attr_desc); - ds.short_poll_interval = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_TIMEOUT_ID); - ZB_ASSERT(attr_desc); - ds.fast_poll_timeout = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_MIN_CHECKIN_INTERVAL_ID); - ZB_ASSERT(attr_desc); - ds.checkin_interval_min = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_MIN_INTERVAL_ID); - ZB_ASSERT(attr_desc); - ds.long_poll_interval_min = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_MAX_TIMEOUT_ID); - ZB_ASSERT(attr_desc); - ds.fast_poll_timeout_max = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - TRACE_MSG(TRACE_ZCL1, "< zb_nvram_write_poll_control_dataset", (FMT__0)); - - return zb_nvram_write_data(page, pos, (zb_uint8_t*)&ds, sizeof(ds)); -} -#endif /* defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN */ - - -#endif /* defined ZB_USE_NVRAM && defined ZB_ENABLE_ZCL */ diff --git a/zboss/development/src/zcl/zcl_occupancy_sensing_commands.c b/zboss/development/src/zcl/zcl_occupancy_sensing_commands.c deleted file mode 100644 index 64e49261e1..0000000000 --- a/zboss/development/src/zcl/zcl_occupancy_sensing_commands.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Occupancy Sensing cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 6 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_OCCUPANCY_SENSING) - -#include "zcl/zb_zcl_occupancy_sensing.h" - -/** @internal - @{ -*/ - -zb_ret_t check_value_occupancy_sensing_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_occupancy_sensing_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_occupancy_sensing_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_occupancy_sensing_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_occupancy_sensing_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_ERROR; - - zb_uint16_t new_delay; - zb_uint16_t max_delay; - - zb_uint8_t min_threshold; - zb_uint8_t max_threshold; - - TRACE_MSG(TRACE_ZCL1, "> check_value_occupancy_sensing_server attr_id %d, ep %hd, val %hd", - (FMT__H_H_D, attr_id, endpoint, value)); - - if (value) - { - if (attr_id == ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_ID || - attr_id == ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_ID || - attr_id == ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_ID || - attr_id == ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_ID || - attr_id == ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_ID || - attr_id == ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_ID) - { - max_delay = ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_NO_REPORTING_VALUE; - switch (attr_id) - { - case ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_ID: - { - max_delay = ZB_ZCL_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_MAX_VALUE; - }break; - case ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_ID: - { - max_delay = ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_MAX_VALUE; - }break; - case ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_ID: - { - max_delay = ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_MAX_VALUE; - }break; - case ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_ID: - { - max_delay = ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_MAX_VALUE; - } - } - new_delay = ZB_ZCL_ATTR_GET16(value); - - if (new_delay > max_delay) - { - ret = RET_OUT_OF_RANGE; - } - else - { - ret = RET_OK; - } - } - else if (attr_id == ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_ID || - attr_id == ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID || - attr_id == ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID) - { - switch (attr_id) - { - case ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_ID: - { - min_threshold = ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_MIN_VALUE; - max_threshold = ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_MAX_VALUE; - }break; - case ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID: - { - min_threshold = ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_MIN_VALUE; - max_threshold = ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_MAX_VALUE; - }break; - case ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID: - { - min_threshold = ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_MIN_VALUE; - max_threshold = ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_MAX_VALUE; - }break; - default: - { - TRACE_MSG(TRACE_ERROR, "zcl_occ_sens_check_threshold_value: Unsupported attribute ID!", (FMT__0)); - ZB_ASSERT(0); /*Unsupported attribute*/ - }break; - } - - if (((*value) < min_threshold) || ((*value) > max_threshold)) - { - ret = RET_OUT_OF_RANGE; - } - else - { - ret = RET_OK; - } - } - } - else - { - TRACE_MSG(TRACE_ERROR, "check_value_occupancy_sensing_server: new value pointer is NULL!", (FMT__0)); - } - TRACE_MSG(TRACE_ZCL1, "< check_value_occupancy_sensing_server ret %hd", (FMT__H, ret)); - return ret; -} - -#endif diff --git a/zboss/development/src/zcl/zcl_on_off_commands.c b/zboss/development/src/zcl/zcl_on_off_commands.c deleted file mode 100644 index dfa211f30b..0000000000 --- a/zboss/development/src/zcl/zcl_on_off_commands.c +++ /dev/null @@ -1,975 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL On/Off cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2075 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_ON_OFF) - -#include "zb_zcl.h" -#include "zcl/zb_zcl_identify.h" -#include "zb_zdo.h" -#include "zb_aps.h" - -/* -CR:MAJOR Current implementation schedules timer multiple times with -0.1 sec timeout. Out timer and scheduler does NOT guarantee this -interval in real work, it guarantees that time interval is equal or -more. It mean in real total timeout maybe much more than specified by -command (x2 - x5). To solve this problem we need to check real timer -value in runtime. This functionality will be done by feature, called -Continuous Value Change, currently under development (DRI Kovtun) -TODO: redesign on/off operation with timer, using Continuous Value -Change feature, when it is ready. -*/ - -zb_uint8_t gs_on_off_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_ON_OFF_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_on_off_client_cmd_list = -{ - 0, NULL, - sizeof(gs_on_off_server_received_commands), gs_on_off_server_received_commands -}; - -zb_discover_cmd_list_t gs_on_off_server_cmd_list = -{ - sizeof(gs_on_off_server_received_commands), gs_on_off_server_received_commands, - 0, NULL -}; - -void zb_zcl_on_off_invoke_user_app(zb_uint8_t param); -static zb_ret_t zb_zcl_call_on_off_attr_device_cb(zb_uint8_t param, zb_uint8_t dst_ep, zb_uint8_t value); - -zb_ret_t check_value_on_off_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -zb_bool_t zb_zcl_process_on_off_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_on_off_specific_commands_cli(zb_uint8_t param); - -void zb_zcl_on_off_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ON_OFF, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_on_off_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_on_off_specific_commands_srv); -} - -void zb_zcl_on_off_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ON_OFF, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_on_off_specific_commands_cli); -} - -zb_ret_t check_value_on_off_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(endpoint); - ZVUNUSED(attr_id); - - switch (attr_id) - { - case ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID: case ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL: - { - return ( ZB_ZCL_CHECK_BOOL_VALUE(*value) )?(RET_OK):(RET_ERROR); - } - case ZB_ZCL_ATTR_ON_OFF_ON_TIME: case ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME: - { - return RET_OK; - } - case ZB_ZCL_ATTR_ON_OFF_START_UP_ON_OFF: - { - return ( (*value) == ZB_ZCL_ON_OFF_START_UP_ON_OFF_IS_OFF || - (*value) == ZB_ZCL_ON_OFF_START_UP_ON_OFF_IS_ON || - (*value) == ZB_ZCL_ON_OFF_START_UP_ON_OFF_IS_TOGGLE || - (*value) == ZB_ZCL_ON_OFF_START_UP_ON_OFF_IS_PREVIOUS ) ? RET_OK : RET_ERROR; - } - default: - { - return RET_ERROR; - } - } -} -/*! @internal Schedule command Inform User App about set On/Off attribute - * @param buffer - buffer for schedule, place data for User App and get result - * @param pcmd_info - pointer zb_zcl_parsed_hdr_t (see @ref zb_zcl_parsed_hdr_s ), use for - * contain ZCL data. Use for Send response to client app - * @param on_off - new value On/Off - * @param is_run_timer_ - if set True then after invoke User App will be schedule - * timer zb_zcl_on_off_timer_handler else run finish command "ZB_ZCL_PROCESS_COMMAND_FINISH". - * zb_zcl_on_off_timer_handler use for "On with timed off" command - * */ -void zb_on_off_schedule_user_app(zb_bufid_t buffer, zb_zcl_parsed_hdr_t *pcmd_info, zb_bool_t on_off, zb_bool_t is_run_timer_) -{ - zb_on_off_user_app_schedule_t* data = - ZB_BUF_GET_PARAM((buffer), zb_on_off_user_app_schedule_t); - ZB_MEMMOVE(&(data->cmd_info), (pcmd_info), sizeof(zb_zcl_parsed_hdr_t)); - data->new_value = (on_off); - data->is_run_timer = (zb_bool_t)(is_run_timer_); - ZB_SCHEDULE_CALLBACK(zb_zcl_on_off_invoke_user_app, (buffer)); -} - - -#define ZB_ZCL_ON_OFF_TIMER_INTERVAL 100 - -#define ZB_ZCL_ON_OFF_TIMER_BEACON_INTERVAL \ - ZB_MILLISECONDS_TO_BEACON_INTERVAL(ZB_ZCL_ON_OFF_TIMER_INTERVAL) - -#define ZB_ZCL_ON_OFF_TIMER_INTERVAL_REDUCED 90 - -#define ZB_ZCL_ON_OFF_TIMER_BEACON_INTERVAL_REDUCED \ - ZB_MILLISECONDS_TO_BEACON_INTERVAL(ZB_ZCL_ON_OFF_TIMER_INTERVAL_REDUCED) - -#define ZB_ZCL_ON_OFF_ZERO_TIMEOUT 0x0000 - -#define ZB_ZCL_ON_OFF_NON_LIMIT_TIMER 0xffff - -#define ZB_ZCL_ON_OFF_GLOBAL_SCENE_STORED ZB_FALSE - -#define ZB_ZCL_ON_OFF_GLOBAL_SCENE_NA ZB_TRUE - -/* Usage of this function. - * We need to set an alarm each tenth of second. - * Converting it to beacon interval we get the 15.36ms * 7 = 107.52ms - * It will increase the real time to 7,52 ms for every step - * The proposition is to switch alarm timer between 15.36ms * 7 = 107.52ms and 15.36ms * 6 = 92.16ms one by one. - * In that case the average time is equal to 99.84ms - */ -static zb_bool_t reduced_timer_counter = ZB_FALSE; - -static zb_bool_t get_reduced_timer_counter() -{ - reduced_timer_counter = !reduced_timer_counter; - return reduced_timer_counter; -} - -static zb_ret_t zb_zcl_call_on_off_attr_device_cb(zb_uint8_t param, zb_uint8_t dst_ep, zb_uint8_t value) -{ - zb_zcl_device_callback_param_t *user_app_invoke_data = - ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_call_on_off_attr_device_cb(), param %hd, dst_ep %hd, value %hd", - (FMT__H_H_H, param, dst_ep, value)); - - user_app_invoke_data->device_cb_id = ZB_ZCL_SET_ATTR_VALUE_CB_ID; - user_app_invoke_data->endpoint = dst_ep; - user_app_invoke_data->cb_param.set_attr_value_param.cluster_id = ZB_ZCL_CLUSTER_ID_ON_OFF; - user_app_invoke_data->cb_param.set_attr_value_param.attr_id = ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID; - user_app_invoke_data->cb_param.set_attr_value_param.values.data8 = value; - user_app_invoke_data->status = RET_OK; - - ZB_ASSERT(ZCL_CTX().device_cb != NULL); - (ZCL_CTX().device_cb)(param); - - TRACE_MSG(TRACE_ZCL1, "<status)); - return user_app_invoke_data->status; -} - -/* Timer for "On with timed off" command, see Spec 6.6.1.4.6.4 - * @param param - buffer - * - * If attr OnTime >0 then decrement OnTime and - * if OnTime stay =0 prepare to set OnOff = false - * else if attr OffWaitTime >0 then decrement OffWaitTime - * - * if prepare to set OnOff = false then invoke User App - * - * if OnTime or OffWaitTime >0 then schedule timer else send response command - * - * Timer period = 1/10 sec - * */ -void zb_zcl_on_off_timer_handler(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_uint8_t endpoint; - zb_uint16_t val; - zb_zcl_attr_t * attr_desc_on_off; - zb_zcl_attr_t * attr_desc_on_time; - zb_zcl_attr_t * attr_desc_off_wait_time; - zb_bool_t is_set_off = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_on_off_timer_handler %hd", (FMT__H, param)); - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - - attr_desc_on_off = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID); - attr_desc_on_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_TIME); - attr_desc_off_wait_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME); - - TRACE_MSG(TRACE_ZCL1, "dst_ep %hd", (FMT__H, endpoint)); - - ZB_ASSERT(attr_desc_on_off); - ZB_ASSERT(attr_desc_on_time); - ZB_ASSERT(attr_desc_off_wait_time); - - /* Update OnTime and OffWaitTime attributes and set flag "update OnOff", if need */ - if( ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_on_off)) - { - val = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_on_time); - if (val > 0) - { - --val; - } - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_on_time, val); - if (val == 0) - { - is_set_off = ZB_TRUE; - TRACE_MSG(TRACE_ZCL1, "OnTime is expired", (FMT__0)); - } - } - else - { - val = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_off_wait_time); - if (val > 0) - { - --val; - } - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_off_wait_time, val); - if (val == 0) - { - TRACE_MSG(TRACE_ZCL1, "OffWaitTime is expired", (FMT__0)); - return; - } - } - - if (val == 0) - { - if (is_set_off) // if need set OnOff - { - val = ZB_ZCL_ON_OFF_IS_OFF; - ZB_ZCL_SET_ATTRIBUTE(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - 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); - - if (ZCL_CTX().device_cb != NULL) - { - (void)zb_zcl_call_on_off_attr_device_cb( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - val); - } - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_off_wait_time, ZB_ZCL_ON_OFF_ZERO_TIMEOUT); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_on_off_timer_handler, ZB_ALARM_ANY_PARAM); - } - } - else - { - ZB_SCHEDULE_ALARM(zb_zcl_on_off_timer_handler, param, (get_reduced_timer_counter() ? - ZB_ZCL_ON_OFF_TIMER_BEACON_INTERVAL : ZB_ZCL_ON_OFF_TIMER_BEACON_INTERVAL_REDUCED)); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_on_off_timer_handler", (FMT__0)); -} - -void zb_zcl_on_off_send_default_resp(zb_uint8_t cb_param, zb_uint16_t user_param) -{ - if (!cb_param) - { - zb_buf_get_out_delayed_ext(zb_zcl_on_off_send_default_resp, user_param, 0); - } - else - { - zb_zcl_parsed_hdr_t *cmd_info; - cmd_info = ZB_BUF_GET_PARAM((zb_uint8_t)user_param, zb_zcl_parsed_hdr_t); - ZB_ZCL_PROCESS_COMMAND_FINISH(cb_param, cmd_info, ZB_ZCL_STATUS_SUCCESS); - } -} - -/* Process On command - * see Spec 3.8.2.3.2 - * */ -static zb_ret_t zb_zcl_process_on_off_on_handler(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc_on_off = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID); - zb_zcl_attr_t *attr_desc_on_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_TIME); - zb_zcl_attr_t *attr_desc_off_wait_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME); - zb_zcl_attr_t *attr_desc_global_scene = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL); - - zb_bool_t is_need_call_user_app = (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_on_off)==ZB_ZCL_ON_OFF_IS_OFF) ? ZB_TRUE : ZB_FALSE; - - ZB_ASSERT(attr_desc_on_off); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_on_off_on_handler param %hx", - (FMT__H, param)); - - if (attr_desc_on_time && attr_desc_off_wait_time) - { - if (ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_on_time) == ZB_ZCL_ON_OFF_ZERO_TIMEOUT) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_off_wait_time, ZB_ZCL_ON_OFF_ZERO_TIMEOUT); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_on_off_timer_handler, ZB_ALARM_ANY_PARAM); - } - } - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_SCENES - /* According to ZCL spec Revision 8. 3.8.2.2.2 GlobalSceneControl Attribute*/ - if (attr_desc_global_scene) - { - if( ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_global_scene) == - ZB_ZCL_ON_OFF_GLOBAL_SCENE_STORED ) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc_global_scene, - ZB_ZCL_ON_OFF_GLOBAL_SCENE_NA); - } - } -#endif - if(is_need_call_user_app) - { - zb_on_off_schedule_user_app(param, cmd_info, ZB_TRUE, ZB_FALSE); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_on_off_on_handler", (FMT__0)); - - return (is_need_call_user_app==ZB_TRUE) ? RET_BUSY : RET_OK; -} - -/* Process Off command - * see Spec 3.8.2.3.1 - * */ -static zb_ret_t zb_zcl_process_on_off_off_handler(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc_on_off = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID); - zb_zcl_attr_t *attr_desc_on_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_TIME); - - zb_bool_t is_need_call_user_app = (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_on_off)!=ZB_ZCL_ON_OFF_IS_OFF) ? ZB_TRUE : ZB_FALSE; - - ZB_ASSERT(attr_desc_on_off); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_on_off_off_handler param %hx", - (FMT__H, param)); - - if (attr_desc_on_time) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_on_time, ZB_ZCL_ON_OFF_ZERO_TIMEOUT); - } - if(is_need_call_user_app) - { - zb_on_off_schedule_user_app(param, cmd_info, ZB_FALSE, ZB_FALSE); - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_on_off_off_handler", (FMT__0)); - - return (is_need_call_user_app==ZB_TRUE) ? RET_BUSY : RET_OK; -} - -/* Process Toggle command - * see Spec 3.8.2.3.3 - * */ -static zb_ret_t zb_zcl_process_on_off_toggle_handler(zb_uint8_t param) -{ - zb_uint8_t new_val; - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc_on_off = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID); - zb_zcl_attr_t *attr_desc_on_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_TIME); - zb_zcl_attr_t *attr_desc_off_wait_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME); - zb_zcl_attr_t *attr_desc_global_scene = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_on_off_toggle_handler param %hx", - (FMT__H, param)); - - ZB_ASSERT(attr_desc_on_off); - - new_val = !ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_on_off); - - if (new_val) - { - if (attr_desc_on_time && attr_desc_off_wait_time) - { - if (ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_on_time) == ZB_ZCL_ON_OFF_ZERO_TIMEOUT) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_off_wait_time, ZB_ZCL_ON_OFF_ZERO_TIMEOUT); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_on_off_timer_handler, ZB_ALARM_ANY_PARAM); - } - } -#ifdef ZB_ZCL_SUPPORT_CLUSTER_SCENES - /* According to ZCL spec Revision 8. 3.8.2.2.2 GlobalSceneControl Attribute*/ - if (attr_desc_global_scene) - { - if( ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_global_scene) == - ZB_ZCL_ON_OFF_GLOBAL_SCENE_STORED ) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc_global_scene, - ZB_ZCL_ON_OFF_GLOBAL_SCENE_NA); - } - } -#endif - } - else - { - if (attr_desc_on_time) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_on_time, ZB_ZCL_ON_OFF_ZERO_TIMEOUT); - } - } - - zb_on_off_schedule_user_app(param, cmd_info, (zb_bool_t)new_val, ZB_FALSE); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_on_off_toggle_handler", (FMT__0)); - - return RET_BUSY; -} - -/* Invoke User App for "Off with effect" command - * - * Invoke User App with effect parameters : EffectId and EffectVariant - * if invoke result RET_OK then schedule invoke User App with attribute On/Off - * else send response command with error - */ -void zb_zcl_on_off_effect_invoke_user_app(zb_uint8_t param) -{ - zb_zcl_on_off_effect_user_app_schedule_t* invoke_data = ZB_BUF_GET_PARAM(param, zb_zcl_on_off_effect_user_app_schedule_t); - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t result; - zb_zcl_attr_t *attr_desc_on_time; - zb_uint8_t val = ZB_ZCL_ON_OFF_IS_OFF; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_on_off_effect_invoke_user_app param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, &(invoke_data->cmd_info), sizeof(zb_zcl_parsed_hdr_t)); - - if (ZCL_CTX().device_cb!=NULL) - { - - zb_zcl_device_callback_param_t *user_app_data = ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - ZB_MEMMOVE(&(user_app_data->cb_param.on_off_set_effect_value_param), - &(invoke_data->param), - sizeof(zb_zcl_on_off_set_effect_value_param_t)); - user_app_data->device_cb_id = ZB_ZCL_ON_OFF_WITH_EFFECT_VALUE_CB_ID; - user_app_data->endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - user_app_data->status = RET_OK; - (ZCL_CTX().device_cb)(param); - result = user_app_data->status; - /* TODO: check - free buffer after a call? */ - } - else - { - result = RET_NOT_IMPLEMENTED; - } - - if (result == RET_OK) - { -/* 2012-12-27 CR:MAJOR:DISCUSS Is this call really needed? - * zb_zcl_on_off_invoke_user_app() is called. - * A: YES. Spec 6.6.1.4.4.3 - both paragraf ended "...shall enter its off state - * and update the OnOff attribute accordingly." - * */ -/* 2013-01-09 CR:MAJOR:FIXED No need to call user application callback zb_zcl_on_off_invoke_user_app() - * here - need only set attribute value to Off and OnTime attribute - * to 0x0000 - * A: Not sure, but change*/ - - /* Use SET_ATTRIBUTE to report attribute change if needed. */ - ZB_ZCL_SET_ATTRIBUTE(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, - &val, - ZB_FALSE); - - attr_desc_on_time = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_TIME); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_on_time, 0x0000); - } - - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, zb_zcl_get_zcl_status_from_ret(result)); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_on_off_effect_invoke_user_app param", (FMT__0)); -} -/* Process Off with effect command - * see Spec 3.8.2.3.4 - * */ -static zb_ret_t zb_zcl_process_on_off_off_with_effect_handler(zb_uint8_t param) -{ - zb_zcl_on_off_off_with_effect_req_t off_with_effect_payload; - zb_zcl_parse_status_t status; - - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc_on_off = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID); - zb_zcl_attr_t *attr_desc_on_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_TIME); - zb_zcl_attr_t *attr_desc_global_scene = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL); - - zb_ret_t ret = RET_ERROR; - - ZB_ASSERT(attr_desc_on_off); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_on_off_off_with_effect_handler param %hx", - (FMT__H, param)); - - if (attr_desc_on_time && attr_desc_global_scene) - { - ZB_ZCL_ON_OFF_GET_OFF_WITH_EFFECT_REQ(&off_with_effect_payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_ON_OFF_GET_OFF_WITH_EFFECT_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_bool_t is_need_call_user_app = (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_on_off)!=ZB_ZCL_ON_OFF_IS_OFF) ? ZB_TRUE : ZB_FALSE; -#ifdef ZB_ZCL_SUPPORT_CLUSTER_SCENES - if (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_global_scene)== - ZB_ZCL_ON_OFF_GLOBAL_SCENE_NA) - { - zb_zcl_parsed_hdr_t cmd_info_copy; - zb_zcl_scenes_store_scene_req_t req; - - req.group_id = ZB_ZCL_SCENE_GLOBAL_SCENE_GROUP_ID; - req.scene_id = ZB_ZCL_SCENE_GLOBAL_SCENE_ID; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info_copy); - zb_zcl_scenes_process_store_scene(param, &req, &cmd_info_copy); - ZB_MEMCPY(cmd_info, &cmd_info_copy, sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc_global_scene, - ZB_ZCL_ON_OFF_GLOBAL_SCENE_STORED); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_on_time, ZB_ZCL_ON_OFF_ZERO_TIMEOUT); - } -#endif - if(is_need_call_user_app) - { - zb_on_off_schedule_user_app(param, cmd_info, ZB_FALSE, ZB_FALSE); - } - ret = (is_need_call_user_app==ZB_TRUE) ? RET_BUSY : RET_OK; - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_on_off_off_with_effect_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/* Process Off with effect command - * see Spec 3.8.2.3.5 - * */ -static zb_ret_t zb_zcl_process_on_off_on_with_recall_global_scene_handler(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc_on_off = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID); - zb_zcl_attr_t *attr_desc_on_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_TIME); - zb_zcl_attr_t *attr_desc_off_wait_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME); - zb_zcl_attr_t *attr_desc_global_scene = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL); - - zb_bool_t is_need_call_user_app = (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_on_off)==ZB_ZCL_ON_OFF_IS_OFF) ? ZB_TRUE : ZB_FALSE; - - /*According to ZCL On/Off Cluster Test Specification Test OO-TC-03S steps 3a and 6c, - the OnOff should response with success status in both cases (GlobalSceneControl attribute is equal to TRUE or FALSE) - */ - zb_ret_t ret = RET_OK; - - ZB_ASSERT(attr_desc_on_off); - - TRACE_MSG(TRACE_ZCL1, - "> zb_zcl_process_on_off_on_with_recall_global_scene_handler param %hx", - (FMT__H, param)); - - if (attr_desc_global_scene == NULL) - { - ret = RET_NOT_IMPLEMENTED; - } - else - { - if (attr_desc_on_time && attr_desc_off_wait_time) - { - if (ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_on_time) == ZB_ZCL_ON_OFF_ZERO_TIMEOUT) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_off_wait_time, ZB_ZCL_ON_OFF_ZERO_TIMEOUT); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_on_off_timer_handler, ZB_ALARM_ANY_PARAM); - } - } - -#ifdef ZB_ZCL_SUPPORT_CLUSTER_SCENES - /* Call User App - ON */ - if( ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_global_scene) == - ZB_ZCL_ON_OFF_GLOBAL_SCENE_STORED ) - { - zb_zcl_parsed_hdr_t cmd_info_copy; - zb_zcl_scenes_recall_scene_req_t req; - - req.group_id = ZB_ZCL_SCENE_GLOBAL_SCENE_GROUP_ID; - req.scene_id = ZB_ZCL_SCENE_GLOBAL_SCENE_ID; - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc_global_scene, - ZB_ZCL_ON_OFF_GLOBAL_SCENE_NA); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info_copy); - zb_zcl_scenes_process_recall_scene(param, &req, &cmd_info_copy); - ZB_MEMCPY(cmd_info, &cmd_info_copy, sizeof(zb_zcl_parsed_hdr_t)); - } - else -#endif - { - /* ZCL8, 3.8.2.3.5.1 - On receipt of the On With Recall Global Scene command, if the GlobalSceneControl attribute is equal to TRUE, the - application on the associated endpoint SHALL discard the command. - */ - } - } - - if (ret == RET_OK && is_need_call_user_app) - { - zb_on_off_schedule_user_app(param, cmd_info, ZB_TRUE, ZB_FALSE); - ret = RET_BUSY; - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_on_off_on_with_recall_global_scene_handler ret %d", - (FMT__H, ret)); - return ret; -} - -/* Process On with timed off command - * see Spec 3.8.2.3.6 - * */ -static zb_ret_t zb_zcl_process_on_off_on_with_timed_off_handler(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_ret_t ret = RET_ERROR; - - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc_on_off = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID); - zb_zcl_attr_t *attr_desc_on_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_ON_TIME); - zb_zcl_attr_t *attr_desc_off_wait_time = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME); - zb_bool_t is_need_timer; - zb_bool_t is_need_set_on = ZB_FALSE; - - zb_zcl_on_off_on_with_timed_off_req_t on_timed_off_payload; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_on_off_on_with_timed_off_handler param %hx", - (FMT__H, param)); - - ZB_ASSERT(attr_desc_on_off); - - if (attr_desc_on_time && attr_desc_off_wait_time) - { - ZB_ZCL_ON_OFF_GET_ON_WITH_TIMED_OFF_REQ(&on_timed_off_payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - ret = RET_INVALID_PARAMETER_1; - } - else - { - // if payload.on_off==1 and attribute On/Off == 0 then - // discarded - /* Condition is checked on the certification On/Off Cluster tests */ - if ( ((on_timed_off_payload.on_off & ZB_ZCL_ON_OFF_ACCEPT_ONLY_WHEN_ON) && ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_on_off)) || - !(on_timed_off_payload.on_off & ZB_ZCL_ON_OFF_ACCEPT_ONLY_WHEN_ON ) ) - { - // stop timer - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_on_off_timer_handler, ZB_ALARM_ANY_PARAM); - - // update attributes - /* We are in Delayed Off state. */ - if ( ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_off_wait_time) > ZB_ZCL_ON_OFF_ZERO_TIMEOUT && - !ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_on_off)) - { - // set minimum - if ( on_timed_off_payload.off_wait_time < - ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_off_wait_time) ) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_off_wait_time, - on_timed_off_payload.off_wait_time); - } - } - /* We are in other states */ - else - { - // set maximum - if ( on_timed_off_payload.on_time > - ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_on_time) ) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_on_time, - on_timed_off_payload.on_time); - } - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc_off_wait_time, - on_timed_off_payload.off_wait_time); - - is_need_set_on = ZB_TRUE; - } - - is_need_timer = (( ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_off_wait_time) < - ZB_ZCL_ON_OFF_NON_LIMIT_TIMER ) && - ( ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc_on_time) < - ZB_ZCL_ON_OFF_NON_LIMIT_TIMER)) ? ZB_TRUE : ZB_FALSE; - - if (is_need_set_on) - { - // schedule User App and next, if need, start timer - zb_on_off_schedule_user_app(param, cmd_info, ZB_TRUE, is_need_timer); - } - /* 2013-01-09 CR:MEDIUM:DISCUSS check, "else" clause is needed here or - * not. According to previous comment, "else" is not needed - * A: "else" run if this command working and client change timers delay */ - else if (is_need_timer) - { - //start timer - ZB_SCHEDULE_ALARM(zb_zcl_on_off_timer_handler, - param, - ZB_ZCL_ON_OFF_TIMER_BEACON_INTERVAL); - /* Server sends Default Response immediately after receiving the command*/ - zb_zcl_on_off_send_default_resp(0, param); - } - ret = RET_BUSY; - } -/*2019-04-10 In this case we have nothing to do, just send Default Response with "Success" status*/ - else - { - ret = RET_OK; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_on_off_on_with_timed_off_handler ret %hx", - (FMT__H, ret)); - return ret; -} - -/* - * Process specific command ZCL OnOff cluster - * See Spec 6.6.1 - */ -zb_bool_t zb_zcl_process_on_off_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t status = RET_OK; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_on_off_specific_commands: param %hd, cmd_info.cmd_id 0x%hx", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_ON_OFF == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - switch( cmd_info.cmd_id ) - { - case ZB_ZCL_CMD_ON_OFF_ON_ID: - status = zb_zcl_process_on_off_on_handler(param); - break; - case ZB_ZCL_CMD_ON_OFF_OFF_ID: - status = zb_zcl_process_on_off_off_handler(param); - break; - case ZB_ZCL_CMD_ON_OFF_TOGGLE_ID: - status = zb_zcl_process_on_off_toggle_handler(param); - break; - case ZB_ZCL_CMD_ON_OFF_OFF_WITH_EFFECT_ID: - status = zb_zcl_process_on_off_off_with_effect_handler(param); - break; - case ZB_ZCL_CMD_ON_OFF_ON_WITH_RECALL_GLOBAL_SCENE_ID: - status = zb_zcl_process_on_off_on_with_recall_global_scene_handler(param); - break; - case ZB_ZCL_CMD_ON_OFF_ON_WITH_TIMED_OFF_ID: - status = zb_zcl_process_on_off_on_with_timed_off_handler(param); - break; - - default: - processed = ZB_FALSE; - break; - } - - if( processed ) - { - if( cmd_info.disable_default_response && status == RET_OK) - { - TRACE_MSG( TRACE_ZCL3, - "Default response disabled", - (FMT__0)); - zb_buf_free(param); - } - else if (status == RET_NOT_IMPLEMENTED) /* case of absence global scene attribute instance for - * zb_zcl_process_on_off_on_with_recall_global_scene_handler - */ - { - ZB_ZCL_SEND_DEFAULT_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_ON_OFF, - cmd_info.seq_number, - cmd_info.cmd_id, - ZB_ZCL_STATUS_UNSUP_CMD); - } - else if (status != RET_BUSY) - { - ZB_ZCL_SEND_DEFAULT_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_ON_OFF, - cmd_info.seq_number, - cmd_info.cmd_id, - status==RET_OK ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_INVALID_FIELD); - } - } - - TRACE_MSG( TRACE_ZCL1, - "< zb_zcl_process_on_off_specific_commands: processed %d", - (FMT__D, processed)); - return processed; -} - - -zb_bool_t zb_zcl_process_on_off_specific_commands_srv(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_on_off_server_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_on_off_specific_commands(param); -} - -zb_bool_t zb_zcl_process_on_off_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_on_off_client_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_on_off_specific_commands(param); -} - -/* - * Invoke User App with On/Off attribute, set attribute and - * finish command or schedule on_off_timer. - * - * On_off_timer used "On with timed off" command. - */ -void zb_zcl_on_off_invoke_user_app(zb_uint8_t param) -{ - zb_on_off_user_app_schedule_t* invoke_data = - ZB_BUF_GET_PARAM(param, zb_on_off_user_app_schedule_t); - zb_uint8_t on_off = invoke_data->new_value; - zb_uint8_t is_run_timer = invoke_data->is_run_timer; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t result; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_on_off_invoke_user_app param %hx", - (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, &(invoke_data->cmd_info), sizeof(zb_zcl_parsed_hdr_t)); - - if (ZCL_CTX().device_cb != NULL) - { - result = zb_zcl_call_on_off_attr_device_cb( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - on_off); - } - else - { - result = RET_OK; - } - - /* Use SET_ATTRIBUTE to report attribute change if needed. */ - ZB_ZCL_SET_ATTRIBUTE(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_ON_OFF, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, - &on_off, - ZB_FALSE); - - if(is_run_timer) - { - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), &cmd_info, sizeof(cmd_info)); - ZB_SCHEDULE_ALARM(zb_zcl_on_off_timer_handler, param, ZB_ZCL_ON_OFF_TIMER_BEACON_INTERVAL); -/*2019-04-10 Now Server sends Default Response immediately after receiving the command*/ - if (result == RET_OK) - { - zb_zcl_on_off_send_default_resp(0, param); - } - } - else - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, zb_zcl_get_zcl_status_from_ret(result)); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_on_off_invoke_user_app", (FMT__0)); -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_ON_OFF */ diff --git a/zboss/development/src/zcl/zcl_on_off_switch_config.c b/zboss/development/src/zcl/zcl_on_off_switch_config.c deleted file mode 100644 index ef5d67616b..0000000000 --- a/zboss/development/src/zcl/zcl_on_off_switch_config.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#define ZB_TRACE_FILE_ID 80 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_ON_OFF_SWITCH_CONFIG) - -zb_ret_t check_value_on_off_switch_config_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_on_off_switch_config_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ON_OFF_SWITCH_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_on_off_switch_config_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_on_off_switch_config_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ON_OFF_SWITCH_CONFIG, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_on_off_switch_config_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - ZVUNUSED(endpoint); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_ID: - if( *value > ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_MAX_VALUE ) - { - ret = RET_ERROR; - } - break; - - case ZB_ZCL_ATTR_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_ID: - if( *value > ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_MAX_VALUE ) - { - ret = RET_ERROR; - } - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_on_off_switch_config ret %hd", (FMT__H, ret)); - return ret; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_ON_OFF_SWITCH_CONFIG */ diff --git a/zboss/development/src/zcl/zcl_ota_upgrade_commands.c b/zboss/development/src/zcl/zcl_ota_upgrade_commands.c deleted file mode 100644 index 201a1a65e1..0000000000 --- a/zboss/development/src/zcl/zcl_ota_upgrade_commands.c +++ /dev/null @@ -1,1795 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL OTA Upgrade cluster specific commands handling - Client role -*/ - -#define ZB_TRACE_FILE_ID 2076 - -#include "zb_common.h" - -/** @internal - @{ -*/ - -/* - To exclude OTA code linking when no OTA cluster declared in the app, OTA code divided into 4 files: - - zcl_ota_upgrade_commands.c (this file) - keep client code here. Linked if zb_zcl_ota_upgrade_init_cli is called from ZB_ZCL_CLUSTER_DESC() - zcl_ota_upgrade_srv_commands.c - server code - zcl_ota_upgrade_common.c - code common for client and server - zcl_ota_upgrade_minimal.c - functions called from ZBOSS ZCL kernel unconditionally. - - Also modified calls to zcl_ota_abort_and_set_tc() and zb_zcl_process_ota_upgrade_default_response_commands((). - First called via small adapter using non-standard command ZB_ZCL_CMD_OTA_UPGRADE_INTERNAL_ABORT_ID. - Second called from zb_zcl_handle_default_response_commands()->zb_zcl_handle_specific_commands(). - For both the idea is: if no cluster, does not call. - */ - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE) || defined DOXYGEN - -#if defined ZB_HA_ENABLE_OTA_UPGRADE_CLIENT || defined DOXYGEN - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_ota_upgrade.h" -#include "zb_zdo.h" -#include "zb_aps.h" -#include "zdo_wwah_stubs.h" - -static zb_uint8_t gs_ota_upgrade_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -static zb_uint8_t gs_ota_upgrade_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -static zb_discover_cmd_list_t gs_ota_upgrade_client_cmd_list = -{ - sizeof(gs_ota_upgrade_client_received_commands), gs_ota_upgrade_client_received_commands, - sizeof(gs_ota_upgrade_client_generated_commands), gs_ota_upgrade_client_generated_commands -}; - -static zb_bool_t zb_zcl_process_ota_upgrade_specific_commands_cli(zb_uint8_t param); -static zb_bool_t zb_zcl_process_ota_cli_upgrade_specific_commands(zb_uint8_t param); - -void zb_zcl_ota_upgrade_init_cli(void) -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - zb_zcl_check_value_ota_upgrade, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_ota_upgrade_specific_commands_cli); -} - - -static void schedule_resend_buffer(zb_uint8_t endpoint); - -static zb_zcl_ota_upgrade_client_variable_t * get_upgrade_client_variables(zb_uint8_t endpoint) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID); - ZB_ASSERT(attr_desc); - return (zb_zcl_ota_upgrade_client_variable_t*)attr_desc->data_p; -} - -/* public API */ -void zb_zcl_ota_set_file_size(zb_uint8_t endpoint, zb_uint32_t size) -{ - get_upgrade_client_variables(endpoint)->download_file_size = size; -} - - -static void zb_zcl_ota_upgrade_block_req_cb(zb_uint8_t param) -{ - zb_zcl_command_send_status_t *cmd_send_status = ZB_BUF_GET_PARAM(param, zb_zcl_command_send_status_t); - zb_zcl_ota_upgrade_client_variable_t *client_data = get_upgrade_client_variables(cmd_send_status->src_endpoint); - - client_data->img_block_req_sent = 0; - - if (client_data->pending_img_block_resp) - { - if (cmd_send_status->status == RET_OK) - { - /* Block_req is acknowledged, can process pending resp if exists */ - zb_zcl_process_ota_upgrade_specific_commands_cli(client_data->pending_img_block_resp); - } - else - { - /* Block_req is not acknowledged, drop pending img_block_resp */ - zb_buf_free(client_data->pending_img_block_resp); - } - } - - client_data->pending_img_block_resp = 0; - - zb_buf_free(param); -} - -/* Do not allow to do OTA upgrade too fast (even if it is configured by ZCL attr) - dups from OTA - * server should be filtered. */ -#define OTA_MIN_BLOCK_REQ_DELAY ZB_TIME_BEACON_INTERVAL_TO_MSEC( \ - ZB_N_APS_ACK_WAIT_DURATION_FROM_NON_SLEEPY * (ZB_N_APS_MAX_FRAME_RETRIES - 1) / ZB_APS_DUPS_TABLE_SIZE ) -#define OTA_BLOCK_REQ_DELAY(_delay) (((_delay > OTA_MIN_BLOCK_REQ_DELAY)) ? (_delay) : OTA_MIN_BLOCK_REQ_DELAY) - -static void zb_zcl_ota_upgrade_send_block_request(zb_uint8_t param, zb_uint64_t current_delay) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - zb_uint16_t manufacturer; - zb_uint16_t image_type; - zb_uint32_t file_version; - zb_uint32_t current_offset; - zb_zcl_ota_upgrade_client_variable_t *client_data; - zb_ieee_addr_t our_long_address = {0}; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_send_block_request param %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - manufacturer = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID); - image_type = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID); - file_version = zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID); - current_offset = zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID); - client_data = get_upgrade_client_variables(endpoint); - - TRACE_MSG(TRACE_ZCL2, "src ep %hd dst ep %hd", (FMT__H_H, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint)); - - /* Do not request block if offset is default (image downloading is not started) */ - ZB_ASSERT(current_offset != ZB_ZCL_OTA_UPGRADE_FILE_OFFSET_DEF_VALUE); - - zb_get_long_address(our_long_address); - ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_BLOCK_REQ(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - endpoint, - ZB_AF_HA_PROFILE_ID, ZB_FALSE, zb_zcl_ota_upgrade_block_req_cb, - ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_IEEE_PRESENT | - ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_DELAY_PRESENT, - manufacturer, - image_type, - file_version, - current_offset, - client_data->max_data_size, - our_long_address, - /* We are using attribute value directly as answer to server's request to slow down, - * but calculating real delay using OTA_BLOCK_DELAY, because we MAY behave this way according to spec: - * - ZCL 11.5.3 Rate Limiting - * The MinimumBlockPeriod attribute is a minimum delay. The client MAY request data slower than what the - * server specifies (i.e. with a longer delay). Sleeping end devices MAY do this normally to conserve battery - * power. - * - ZCL 11.13.6.2.8 MinimumBlockPeriod (optional) - * This attribute does not necessarily reflect the actual delay applied by the client between Image Block Re- - * quests, only the value set by the server on the client. */ - zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID), - OTA_BLOCK_REQ_DELAY(current_delay)); - client_data->img_block_req_sent = 1; - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_send_block_request", (FMT__0)); -} - -/****************** public function and its helper ****************/ - -static void zb_zcl_ota_upgrade_request_server_send(zb_uint8_t param, zb_uint16_t endpoint16) -{ - zb_uint8_t endpoint; - zb_uint16_t manufacturer; - zb_uint16_t image_type; - zb_uint32_t file_version; - zb_zcl_attr_t *attr_desc; - zb_uint16_t addr; - zb_uint8_t dst_endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_request_server_send param %hx ep %d", (FMT__H_D, - param, endpoint16)); - - endpoint = (zb_uint8_t)endpoint16; - - /* zb_zcl_ota_upgrade_request_server_send is called by delayed buffer alloc, - * so check for scheduling more than 1 zb_zcl_ota_upgrade_request_server_send - * when ZBOSS is in OOM state. */ - if (zb_zcl_ota_upgrade_get_ota_status(endpoint) == ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL) - { - manufacturer = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID); - image_type = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID); - file_version = zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_VERSION_ID ); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID); - ZB_ASSERT(attr_desc); - addr = *(zb_uint16_t *)attr_desc->data_p; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID); - ZB_ASSERT(attr_desc); - dst_endpoint = *(zb_uint8_t *)attr_desc->data_p; - - ZB_ZCL_OTA_UPGRADE_SEND_QUERY_NEXT_IMAGE_REQ(param, - addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - dst_endpoint, endpoint, ZB_AF_HA_PROFILE_ID, ZB_FALSE, NULL, - 0, - manufacturer, - image_type, - file_version, - 0, - ZB_FALSE); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_request_server_send", (FMT__0)); -} - - -static void zb_zcl_ota_upgrade_request_server(zb_uint8_t endpoint) -{ - zb_zcl_ota_upgrade_client_variable_t *client_data; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_request_server endpoint %d", (FMT__H, endpoint)); - - client_data = get_upgrade_client_variables(endpoint); - - (client_data->timer_counter)--; - - TRACE_MSG(TRACE_ZCL2, "timer_counter %d timer_query %d", (FMT__D_D, - client_data->timer_counter, client_data->timer_query)); - - if(client_data->timer_counter==0) - { - if (zb_zcl_ota_upgrade_get_ota_status(endpoint) == ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL) - { - zb_buf_get_out_delayed_ext(zb_zcl_ota_upgrade_request_server_send, endpoint, 0); - } -#ifdef ZB_ZCL_OTA_INCREMENTAL_QUERY_INTERVAL -/* TODO: implement correctly - handling timer_query, now it is - * re-calculated but not used as timeout */ - if ( (client_data->timer_query*=2) > ZB_ZCL_OTA_UPGRADE_MAX_INTERVAL ) - { - client_data->timer_query = ZB_ZCL_OTA_UPGRADE_MAX_INTERVAL; - } -#endif - client_data->timer_counter = client_data->timer_query; - } - - /* TODO: fix it - integer overflow for ZB_ZCL_OTA_UPGRADE_QUERY_TIMER_INTERVAL */ - ZB_SCHEDULE_ALARM(zb_zcl_ota_upgrade_request_server, endpoint, - ZB_ZCL_OTA_UPGRADE_QUERY_TIMER_INTERVAL); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_request_server", (FMT__0)); -} - -static void zb_zcl_ota_server_discovery_callback(zb_uint8_t param) -{ - zb_uint8_t *zdp_cmd = zb_buf_begin(param); - - zb_zdo_match_desc_resp_t *resp = (zb_zdo_match_desc_resp_t*)zdp_cmd; - zb_uint8_t *match_list = (zb_uint8_t*)(resp + 1); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_server_discovery_callback %hd", (FMT__H, resp->status)); - if (resp->status == ZB_ZDP_STATUS_SUCCESS && - /* See Use Trust Center for Cluster Command */ - ZB_ZDO_CHECK_CLUSTER_PERMISSION(resp->nwk_addr, ZB_ZCL_CLUSTER_ID_OTA_UPGRADE)) - { - /* The client shall use the first response received6. 6 CCB 1314. */ - if (!resp->match_len || - zb_zcl_ota_upgrade_start_client((*match_list), resp->nwk_addr) != RET_OK) - { - /* Notify an application that OTA Upgrade server not found */ - ZB_ZCL_OTA_UPGRADE_SERVER_NOT_FOUND_USER_APP(param); - } - } - else - { - /* Notify an application that OTA Upgrade server not found */ - ZB_ZCL_OTA_UPGRADE_SERVER_NOT_FOUND_USER_APP(param); - } - - zb_buf_free(param); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_server_discovery_callback", (FMT__0)); -} - -/* public API */ -void zb_zcl_ota_upgrade_init_client(zb_uint8_t param) -{ - zb_zdo_match_desc_param_t *req; - zb_uint16_t tc_addr; - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_init_client %hd", (FMT__H, param)); - - // start_ota_server_discovery - req = zb_buf_initial_alloc(param, sizeof(zb_zdo_match_desc_param_t) + sizeof(zb_uint16_t)); - - tc_addr = zb_aib_get_trust_center_short_address();; - /* If device is forced to use TC and we know TC addr then send request to TC or - * send broadcast request otherwise */ - req->nwk_addr = !IS_DISTRIBUTED_SECURITY() && - ZB_ZDO_CHECK_IF_FORCED_TO_USE_TC(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE) && - tc_addr != ZB_UNKNOWN_SHORT_ADDR ? - tc_addr : ZB_NWK_BROADCAST_RX_ON_WHEN_IDLE; - req->addr_of_interest = req->nwk_addr; - req->profile_id = ZB_AF_HA_PROFILE_ID; - req->num_in_clusters = 1; - req->num_out_clusters = 0; - req->cluster_list[0] = ZB_ZCL_CLUSTER_ID_OTA_UPGRADE; - - /* NK: Do not set initial value: upgrade could be started before Match Desc Request. - Silently fill variables in this case (zb_zcl_ota_upgrade_request_server() func already checks - if upgrade is started). */ - - if (zb_zdo_match_desc_req(param, zb_zcl_ota_server_discovery_callback) == ZB_ZDO_INVALID_TSN) - { - zb_zdo_match_desc_resp_t *resp; - - resp = zb_buf_initial_alloc(param, sizeof(zb_zdo_match_desc_resp_t)); - resp->tsn = ZB_ZDO_INVALID_TSN; - resp->status = ZB_ZDP_STATUS_INSUFFICIENT_SPACE; - TRACE_MSG(TRACE_ERROR, "no mem space for zb_zdo_match_desc_resp_t", (FMT__0)); - ZB_SCHEDULE_CALLBACK(zb_zcl_ota_server_discovery_callback, param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_init_client", (FMT__0)); -} - - -/* public API */ -zb_ret_t zb_zcl_ota_upgrade_start_client(zb_uint8_t server_ep, zb_uint16_t server_addr) -{ - zb_uint8_t endpoint; - zb_zcl_attr_t *attr_desc; - zb_ret_t ret = RET_ERROR; - - if (server_addr != ZB_ZCL_OTA_UPGRADE_SERVER_ADDR_DEF_VALUE && - server_ep != ZB_ZCL_OTA_UPGRADE_SERVER_ENDPOINT_DEF_VALUE) - { - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); - - /* update attribute */ - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ID); - ZB_ASSERT(attr_desc); - - zb_address_ieee_by_short(server_addr, (zb_uint8_t*)(attr_desc->data_p)); - TRACE_MSG(TRACE_ZCL2, "Server addr "TRACE_FORMAT_64" ", (FMT__A, TRACE_ARG_64((zb_uint8_t*)attr_desc->data_p))); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, server_addr); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, server_ep); - - /* Set timer_counter to 1 - to do first request after 1 min (minimal interval). */ - { - zb_zcl_ota_upgrade_client_variable_t *client_data = get_upgrade_client_variables(endpoint); - client_data->timer_counter = 1; - } - - /* start timer for Query Upgrade Server */ - /* Do delayed start - to do not upgrade during commissioning */ - ZB_SCHEDULE_ALARM(zb_zcl_ota_upgrade_request_server, endpoint, - ZB_ZCL_OTA_UPGRADE_QUERY_TIMER_INTERVAL); - - /* OTA Upgrade client is started */ - ret = RET_OK; - } - - return ret; -} - - -/* public API */ -void zb_zcl_ota_upgrade_stop_client(void) -{ - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_stop_client", (FMT__0)); - - /* Set OTA status to Normal - initial value for OTA */ - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); - if (endpoint) - { - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL); - } - - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_ota_upgrade_request_server, endpoint); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_stop_client", (FMT__0)); -} - - -/* public API */ -void zb_zcl_ota_upgrade_set_query_interval(zb_uint8_t endpoint, zb_uint16_t interval) -{ - - zb_zcl_ota_upgrade_client_variable_t *client_data; - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_set_query_interval ep %hd interval %d min", - (FMT__H_D, endpoint, interval)); - - client_data = get_upgrade_client_variables(endpoint); - - client_data->timer_query = interval; - if(client_data->timer_counter > interval) - { - client_data->timer_counter = interval; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_set_query_interval", (FMT__0)); -} - - -/* public API */ -void zb_zcl_ota_upgrade_file_upgraded(zb_uint8_t endpoint) -{ - zb_zcl_attr_t *attr_desc; - - TRACE_MSG( TRACE_ZCL1, "> zb_zcl_ota_upgrade_file_upgraded %hx", (FMT__H, endpoint)); - - // set attribute - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, 0xffffff); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, ZB_ZCL_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_DEF_VALUE); - - /* Restore attribute of request period from backup: - * 11.10.10 MinimumBlockPeriod Attribute - * This attribute SHALL reflect the minimum delay between Image Block Request commands generated by the - * client in milliseconds. The value of this attribute SHALL be updated when the rate is changed by the server, - * but SHOULD reflect the client default when an upgrade is not in progress or a server does not support this - * feature. */ - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ZCL_CTX().ota_cli.ota_period_backup); - - get_upgrade_client_variables(endpoint)->download_file_size = 0; - - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL); - - TRACE_MSG( TRACE_ZCL1, "< zb_zcl_ota_upgrade_file_upgraded", (FMT__0)); -} - - /*************************** Client handlers *************************/ - -/** @brief Image Notify command */ -static zb_ret_t image_notify_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - /* Compilers may complain here about maybe-uninitialized without {0} when optimization is enabled */ - zb_zcl_ota_upgrade_image_notify_t payload = {0}; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> image_notify_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_IMAGE_NOTIFY_REQ(&payload, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL2, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_IMAGE_NOTIFY_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - zb_bool_t is_agree_file = ZB_TRUE; -#ifdef ZB_ZCL_SUPPORT_CLUSTER_WWAH - if (zb_zcl_wwah_check_if_forced_to_use_tc(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE)) - { - is_agree_file = (cmd_info.addr_data.common_data.source.u.short_addr == - zb_aib_get_trust_center_short_address()); - } -#endif - TRACE_MSG(TRACE_ZCL2, "dst_addr 0x%x", (FMT__D, cmd_info.addr_data.common_data.dst_addr)); - if( ZB_NWK_IS_ADDRESS_BROADCAST(cmd_info.addr_data.common_data.dst_addr) ) - { - // note: no break this switch - // each value payload_type mean ALL low tests must be - switch(payload.payload_type) - { - case ZB_ZCL_OTA_UPGRADE_IMAGE_NOTIFY_PAYLOAD_JITTER_CODE_IMAGE_VER: - is_agree_file = is_agree_file && - ZB_ZCL_OTA_UPGRADE_VERSION_CMP(payload.file_version, - zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_VERSION_ID)); - /* FALLTHROUGH */ - case ZB_ZCL_OTA_UPGRADE_IMAGE_NOTIFY_PAYLOAD_JITTER_CODE_IMAGE: - is_agree_file = is_agree_file && - (payload.image_type==zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID)); - /* FALLTHROUGH */ - case ZB_ZCL_OTA_UPGRADE_IMAGE_NOTIFY_PAYLOAD_JITTER_CODE: - is_agree_file = is_agree_file && - (payload.manufacturer==zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID)); - } - if(is_agree_file) - { - zb_uint8_t my_jitter_rnd = ZB_RANDOM_JTR(ZB_ZCL_OTA_UPGRADE_QUERY_JITTER_MAX_VALUE) + 1; -#ifdef ZB_STACK_REGRESSION_TESTING_API - if (ZB_REGRESSION_TESTS_API().zcl_ota_custom_query_jitter) - { - my_jitter_rnd = ZB_REGRESSION_TESTS_API().zcl_ota_custom_query_jitter; - } -#endif /* ZB_STACK_REGRESSION_TESTING_API */ - TRACE_MSG(TRACE_ZCL2, "my_jitter_rnd %d", (FMT__H, my_jitter_rnd)); - is_agree_file = is_agree_file && (my_jitter_rnd <= payload.query_jitter); - } - } - else - { - is_agree_file = is_agree_file && - (cmd_info.addr_data.common_data.dst_addr == zb_get_short_address()); - } - - if (zb_zcl_ota_upgrade_get_ota_status(endpoint) != ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL) - { - /* NK:FIXME: WHY? It is not by spec! - Zigbee Document 095264r22, Zigbee Over-the-Air Upgrading Cluster, Revision 22, Version 1.1 - - 6.10.3.3: - However, payload type value of 0x03 has a slightly different effect. If the client device has all the - information matching those included in the command including the new file version, the device shall - then ignore the command. This indicates that the device has already gone through the upgrade process. - This is to prevent the device from downloading the same image version multiple times. This is only - true if the command is sent as broadcast/multicast. - - 6.10.3.4: - On receipt of a unicast Image Notify command, the device shall always send a Query Next Image - request back to the upgrade server. This provides a way for the server to force reinstallation of image - on the device. - ... - On receipt of a broadcast or multicast Image Notify command, the device shall keep examining each - field included in the payload with its own value. For each field, if the value matches its own, it shall - proceed to examine the next field. If values in all three fields (naming manufacturer code, image type - and new file version) match its own values, then it shall discard the command. The new file version in - the payload shall match either the devices current running file version or the downloaded file version - (on the additional memory space). - ... - For payload type value of 0x03, if - both manufacturer code and image type match the devices own values but the new file version is not a - match, the device shall proceed. In this case, the (new) file version may be lower or higher than the - devices file version to indicate a downgrade or an upgrade of the firmware respectively. - - TODO: Modify this behaviour: - <--- Drop it only if it is ZB_ZCL_OTA_UPGRADE_IMAGE_NOTIFY_PAYLOAD_JITTER_CODE_IMAGE_VER, - all checks (including file version) are ok and command is broadcast/multicast. If command - is unicast, proceed it even if all fields are equal (even if file version is the same) - - abort current download and begin new. - */ - TRACE_MSG(TRACE_ZCL2, "upgrade is in progress - skip image notify", (FMT__0)); - is_agree_file = ZB_FALSE; - } - - TRACE_MSG(TRACE_ZCL2, "is_agree_file %d", (FMT__H, is_agree_file)); - if(is_agree_file) - { - zb_uint16_t hw_ver = get_upgrade_client_variables(endpoint)->hw_version; - - /* For the case we didn't got it from the notify command */ - payload.image_type=zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID); - payload.manufacturer=zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID); - ZB_ZCL_OTA_UPGRADE_SEND_QUERY_NEXT_IMAGE_REQ(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_AF_HA_PROFILE_ID, ZB_FALSE, NULL, - ZB_ZCL_OTA_UPGRADE_QUERY_NEXT_IMAGE_HW_VERSION, - payload.manufacturer, - payload.image_type, - zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_VERSION_ID), - hw_ver, - (zb_bool_t)ZB_APS_FC_GET_SECURITY(cmd_info.addr_data.common_data.fc)); - - ret = RET_BUSY; - } - } - - TRACE_MSG(TRACE_ZCL1, "< image_notify_handler ret %hx", (FMT__H, ret)); - return ret; -} - -/** @brief Query Next Image Request command */ -static zb_ret_t query_next_image_resp_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ota_upgrade_query_next_image_res_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> query_next_image_resp_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_QUERY_NEXT_IMAGE_RES(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_QUERY_NEXT_IMAGE_RES", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - TRACE_MSG(TRACE_ZCL2, "payload.status %d", (FMT__H, payload.status)); - - switch(payload.status) - { - /* Server returned success if FW must be upgraded basing on file_version - * hw_version. It is up to application to decide which sub-element must be - * upgraded (see below) - */ - case ZB_ZCL_STATUS_SUCCESS: - { - zb_zcl_attr_t *attr_desc; - zb_uint16_t delay = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID); - zb_zcl_ota_upgrade_client_variable_t *client_data = get_upgrade_client_variables(endpoint); - zb_uint8_t app_status = ZB_ZCL_STATUS_SUCCESS; - - TRACE_MSG(TRACE_ZCL2, "SUCCESS found file", (FMT__0)); - - if (payload.file_version == - zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_VERSION_ID)) - { - /* ZCL8, 11.13.5.4 Effect on receipt: - If the file version contained in the Query Next Image Response is the same as the - CurrentFileVersion attribute (the current running version of software) or the - DownloadedFileVersion attribute for the specified Image Type, then the message SHOULD - be discarded and no further processing SHOULD be done. */ - TRACE_MSG(TRACE_ZCL2, "file version is equal to current running version, deny", (FMT__0)); - app_status = ZB_ZCL_OTA_UPGRADE_STATUS_ERROR; - } - else - { - /* Call user's callback to indicate upgrade process start. */ - ZB_ZCL_OTA_UPGRADE_START_USER_APP(param, payload.manufacturer, payload.image_type, - payload.file_version, payload.image_size, app_status); - } - - if (app_status == ZB_ZCL_OTA_UPGRADE_STATUS_OK) - { - // set attribute - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, 0); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, payload.file_version); - - client_data->download_file_size = payload.image_size; - - /* Backup period attribute */ - ZCL_CTX().ota_cli.ota_period_backup = delay; - - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DOWNLOADING); - - //send query block: offset 0 - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - /* In any case we need OTA file header. Then there can be variants (see - * multi-fw). Variants are to be implemented in the application. */ - zb_zcl_ota_upgrade_send_block_request(param, delay); - - ret = RET_BUSY; - /* Fill data for resend_buffer. FIXME: rewrite it */ - ZB_MEMCPY(&ZCL_CTX().ota_cli.cmd_info_2, &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - ZCL_CTX().ota_cli.payload_2.response.success.manufacturer = payload.manufacturer; - ZCL_CTX().ota_cli.payload_2.response.success.image_type = payload.image_type; - ZCL_CTX().ota_cli.payload_2.response.success.file_version = payload.file_version; - schedule_resend_buffer(endpoint); - } - } - break; - case ZB_ZCL_STATUS_NO_IMAGE_AVAILABLE: - default: - break; - } - } - - TRACE_MSG(TRACE_ZCL1, "< query_next_image_resp_handler ret %hx", (FMT__H, ret)); - return ret; -} - - -static void resend_buffer(zb_uint8_t param); - - -static void cancel_resend_buffer() -{ - ZCL_CTX().ota_cli.resend_retries = 0; - ZB_SCHEDULE_ALARM_CANCEL(resend_buffer, 0); -} - - -static void schedule_resend_buffer(zb_uint8_t endpoint) -{ - zb_uint16_t delay = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID); - - ZCL_CTX().ota_cli.resend_retries = 0; - ZB_SCHEDULE_ALARM_CANCEL(resend_buffer, 0); - /* Extend resend interval to exclude situation when we request new block and retransmit APS packet - * with old request. */ - ZB_SCHEDULE_ALARM(resend_buffer, 0, ZB_ZCL_OTA_UPGRADE_RESEND_BUFFER_DELAY + ZB_MILLISECONDS_TO_BEACON_INTERVAL(delay)); -} - - -/* public API */ -void zcl_ota_abort(zb_uint8_t endpoint, zb_uint8_t param) -{ - zb_uint8_t status = ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL; - zb_zcl_attr_t *attr_desc; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STATUS_ID); - if (attr_desc) - { - status = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - } - // set attribute - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL); - /* cancel resend */ - cancel_resend_buffer(); - - // set attribute - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, ZB_ZCL_OTA_UPGRADE_FILE_OFFSET_DEF_VALUE); - - // reset downloaded file version attribute - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, ZB_ZCL_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_DEF_VALUE); - - /* Restore attribute of request period from backup*/ - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ZCL_CTX().ota_cli.ota_period_backup); - - { - zb_zcl_ota_upgrade_client_variable_t *client_data = get_upgrade_client_variables(endpoint); - - client_data->img_block_req_sent = 0; - if (client_data->pending_img_block_resp) - { - zb_buf_free((client_data->pending_img_block_resp)); - client_data->pending_img_block_resp = 0; - } - } - - /* call User App */ - if (status != ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL) - { - if ((param > 0) && (param != ZB_UNDEFINED_BUFFER)) - { - ZB_ZCL_OTA_UPGRADE_ABORT_USER_APP(param); - } - else - { - zb_bufid_t send_buf = zb_buf_get_out(); - - ZB_ASSERT(send_buf); - ZB_ZCL_OTA_UPGRADE_ABORT_USER_APP(send_buf); - zb_buf_free(send_buf); - } - } -} - -/* FIXME: link problem. */ -#ifdef ZB_ZCL_SUPPORT_CLUSTER_WWAH -void schedule_init_client(zb_uint8_t param) -{ - TRACE_MSG(TRACE_APP1, "> schedule_init_client", (FMT__0)); - ZB_SCHEDULE_ALARM(zb_zcl_ota_upgrade_init_client, param, 2*ZB_TIME_ONE_SECOND); - TRACE_MSG(TRACE_APP1, "< schedule_init_client", (FMT__0)); -} - -/* This function performs: - * 1) Cancel any download that is in progress if OTA server is not a TC; - * 2) Set the value of the UpgradeServerID attribute to the apsTrustCenterAddress. - * This new UpgradeServerID value SHALL be persisted across reboots. - */ -#ifndef ZB_COORDINATOR_ONLY -static void zcl_ota_abort_and_set_tc_cli() -{ - zb_ieee_addr_t tc_long_address; - zb_uint8_t endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); - zb_zcl_attr_t *attr_desc; - if (endpoint) - { - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ID); - ZB_ASSERT(attr_desc); - zb_aib_get_trust_center_address(tc_long_address); - if (!IS_DISTRIBUTED_SECURITY() && - !ZB_IEEE_ADDR_IS_ZERO(tc_long_address) && - (ZB_MEMCMP(attr_desc->data_p, tc_long_address, sizeof(zb_ieee_addr_t)) != 0)) - { - if (zb_zcl_ota_upgrade_get_ota_status(endpoint) != ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL) - { - zcl_ota_abort(endpoint, 0); - } - zb_zcl_set_attr_val(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ID, - tc_long_address, - ZB_FALSE); - zb_buf_get_out_delayed(schedule_init_client); - } - } -} -#endif /* ZB_COORDINATOR_ONLY */ -#endif - -/* Helper routine to finish OTA Upgrade */ -static void zb_zcl_ota_upgrade_end(zb_uint8_t param, - zb_uint8_t status, - zb_zcl_parsed_hdr_t *cmd_info, - zb_zcl_ota_upgrade_image_block_res_t *payload) -{ - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - - TRACE_MSG(TRACE_OTA2, "OTA: send upgrade end request, status %hd", (FMT__H, status)); - - if (status != ZB_ZCL_STATUS_SUCCESS) - { - zcl_ota_abort(endpoint, param); - } - - /* send upgrade end request */ - ZB_ZCL_OTA_UPGRADE_SEND_UPGRADE_END_REQ(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_AF_HA_PROFILE_ID, ZB_FALSE, NULL, - status, - payload->response.success.manufacturer, - payload->response.success.image_type, - payload->response.success.file_version); -} - - -/* Note: resend_buffer is used by r20 ZBOSS apps. Seems now no need to call it from outside, so tet make it static. */ -// try resend req -static void resend_buffer(zb_uint8_t param) -{ - zb_ieee_addr_t our_long_address = {0}; - zb_bufid_t send_buf = 0; - zb_uint32_t current_offset; - zb_zcl_attr_t *attr_desc; - zb_uint8_t endpoint; - zb_uint16_t delay; - zb_zcl_ota_upgrade_client_variable_t *client_data; - - ZCL_CTX().ota_cli.ota_restart_after_rejoin = 0; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL3, "resend_buffer", (FMT__0)); - send_buf = zb_buf_get_out(); - if (send_buf) - { - zb_buf_reuse(send_buf); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&ZCL_CTX().ota_cli.cmd_info_2).dst_endpoint; - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STATUS_ID); - if (attr_desc - && ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DOWNLOADING == ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc)) - { - ZCL_CTX().ota_cli.resend_retries++; - if (ZCL_CTX().ota_cli.resend_retries < ZCL_OTA_MAX_RESEND_RETRIES) - { - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID); - ZB_ASSERT(attr_desc); - current_offset=ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - delay = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID); - client_data = get_upgrade_client_variables(endpoint); - - TRACE_MSG(TRACE_ZCL2, "OTA: re-sending UPGRADE_SEND_IMAGE_BLOCK_REQ delay %d", - (FMT__D, delay)); - zb_get_long_address(our_long_address); - ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_BLOCK_REQ(send_buf, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&ZCL_CTX().ota_cli.cmd_info_2).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&ZCL_CTX().ota_cli.cmd_info_2).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&ZCL_CTX().ota_cli.cmd_info_2).dst_endpoint, - ZB_AF_HA_PROFILE_ID, ZB_FALSE, zb_zcl_ota_upgrade_block_req_cb, - (ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_IEEE_PRESENT | - ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_DELAY_PRESENT), - ZCL_CTX().ota_cli.payload_2.response.success.manufacturer, - ZCL_CTX().ota_cli.payload_2.response.success.image_type, - ZCL_CTX().ota_cli.payload_2.response.success.file_version, - current_offset, - client_data->max_data_size, - our_long_address, - /* We are using attribute value directly as answer to server's request to slow down, - * but calculating real delay using OTA_BLOCK_DELAY, because we MAY behave this way according to spec: - * - ZCL 11.5.3 Rate Limiting - * The MinimumBlockPeriod attribute is a minimum delay. The client MAY request data slower than what the - * server specifies (i.e. with a longer delay). Sleeping end devices MAY do this normally to conserve battery - * power. - * - ZCL 11.13.6.2.8 MinimumBlockPeriod (optional) - * This attribute does not necessarily reflect the actual delay applied by the client between Image Block Re- - * quests, only the value set by the server on the client. */ - delay, OTA_BLOCK_REQ_DELAY(delay)); - client_data->img_block_req_sent = 1; - ZB_SCHEDULE_ALARM_CANCEL(resend_buffer, 0); - /* Extend resend interval to exclude situation when we request new block and retransmit APS packet - * with old request. */ - ZB_SCHEDULE_ALARM(resend_buffer, 0, ZB_ZCL_OTA_UPGRADE_RESEND_BUFFER_DELAY + ZB_MILLISECONDS_TO_BEACON_INTERVAL(delay)); - } - else - { - TRACE_MSG(TRACE_ZCL1, "OTA: out if IMAGE_BLOCK_REQ retries, abort upgrade", - (FMT__0)); - - zb_zcl_ota_upgrade_end(send_buf, - ZB_ZCL_STATUS_ABORT, - &(ZCL_CTX().ota_cli.cmd_info_2), - &(ZCL_CTX().ota_cli.payload_2)); - - /* zb_buf_free(send_buf); */ - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "OTA: resend_buffer while in the wrong state", - (FMT__0)); - zb_buf_free(send_buf); - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "OTA: no memory for resend_buffer. Retry via scheduler.", - (FMT__0)); - ZB_SCHEDULE_CALLBACK(resend_buffer, 0); - } -} - -/* Helper routine to get next image block */ -static void zb_zcl_ota_upgrade_get_next_image_block(zb_uint8_t param, - zb_zcl_parsed_hdr_t *cmd_info, - zb_zcl_ota_upgrade_image_block_res_t *payload) -{ - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - - TRACE_MSG(TRACE_OTA2, "OTA: send imageBlockReq", (FMT__0)); - - zb_zcl_ota_upgrade_send_block_request(param, zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID)); - - /* Schedule resend buffer if we don't get response */ - ZB_MEMCPY(&ZCL_CTX().ota_cli.cmd_info_2, cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - ZB_MEMCPY(&ZCL_CTX().ota_cli.payload_2, payload, sizeof(zb_zcl_ota_upgrade_image_block_res_t)); - schedule_resend_buffer(endpoint); -} - -/* Helper routine to process downloaded image */ -static void zb_zcl_ota_upgrade_process_downloaded_image(zb_uint8_t param, - zb_zcl_parsed_hdr_t *cmd_info, - zb_zcl_ota_upgrade_image_block_res_t *payload) -{ - zb_uint8_t endpoint; - zb_uint8_t upgrade_status; - - TRACE_MSG(TRACE_OTA2, "OTA: process downloaded image", (FMT__0)); - - /* reserve space for user callback parameters, it will be used later while - * calling this callback. When space is reserved, buffer data is moved to the left - - * it is better to do it here before any actions with pointers to data */ - (void)ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - - cancel_resend_buffer(); - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DOWNLOADED); - - ZB_ZCL_OTA_UPGRADE_CHECK_USER_APP(param, upgrade_status); - - if (upgrade_status != ZB_ZCL_OTA_UPGRADE_STATUS_BUSY) - { - /* Finish OTA process */ - zb_zcl_ota_upgrade_end(param, - (upgrade_status == ZB_ZCL_OTA_UPGRADE_STATUS_OK ? - ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_INVALID_IMAGE), - cmd_info, payload); - } - else - { - /* Application is busy, restore parameters and wait the signal to resume */ - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - } -} - -/* public API. Never called */ -/* Resume OTA Upgrade signal from application */ -void zb_zcl_ota_upgrade_resume_client(zb_uint8_t param, zb_uint8_t upgrade_status) -{ - zb_uint8_t endpoint; - zb_uint8_t ota_status; - zb_zcl_ota_upgrade_image_block_res_t payload = {0}; - zb_zcl_parsed_hdr_t cmd_info; - zb_zcl_parse_status_t status = ZB_ZCL_PARSE_STATUS_FAILURE; - - TRACE_MSG(TRACE_OTA2, "zb_zcl_ota_upgrade_resume_client param %hd", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_RES(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_OTA1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_RES", (FMT__0)); - zb_buf_free(param); - return; - } - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - ota_status = zb_zcl_ota_upgrade_get_ota_status(endpoint); - - if (ota_status == ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DOWNLOADING || - ota_status == ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_WAIT_FOR_MORE) - { - if (upgrade_status != ZB_ZCL_OTA_UPGRADE_STATUS_OK) - { - zb_zcl_ota_upgrade_end(param, ZB_ZCL_STATUS_INVALID_IMAGE, &cmd_info, &payload); - } - else - { - zb_uint32_t file_size; - zb_uint32_t current_offset; - zb_zcl_ota_upgrade_client_variable_t *client_data; - zb_zcl_attr_t *attr_desc = NULL; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID); - ZB_ASSERT(attr_desc); - - client_data = get_upgrade_client_variables(endpoint); - file_size = client_data->download_file_size; - current_offset = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - - if (file_size > current_offset) - { - zb_zcl_ota_upgrade_get_next_image_block(param, &cmd_info, &payload); - } - else - { - zb_zcl_ota_upgrade_process_downloaded_image(param, &cmd_info, &payload); - } - } - } - else if (ota_status == ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DOWNLOADED) - { - zb_zcl_ota_upgrade_end(param, - (upgrade_status == ZB_ZCL_OTA_UPGRADE_STATUS_OK ? - ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_INVALID_IMAGE), - &cmd_info, &payload); - } - else - { - TRACE_MSG(TRACE_OTA2, "Nothing to resume! Free buffer", (FMT__0)); - zb_buf_free(param); - } -} - -/* public API */ -void zb_zcl_ota_restart_after_rejoin(zb_uint8_t endpoint) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STATUS_ID); - TRACE_MSG(TRACE_OTA1, "zb_zcl_ota_restart_after_rejoin endpoint %hd", (FMT__H, endpoint)); - if ((attr_desc != NULL) - && ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DOWNLOADING == ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc)) - { - TRACE_MSG(TRACE_OTA1, "yes, restart OTA after getting sever descriptor", (FMT__0)); - ZCL_CTX().ota_cli.ota_restart_after_rejoin = 1; - - /* [MM]: Moved from zb_zcl_ota_server_discovery_callback */ - TRACE_MSG(TRACE_OTA1, "Restart after rejoin - schedule OTA buffer req resend", (FMT__0)); - /* Fill data for resend_buffer. */ - ZB_ZCL_PARSED_HDR_SHORT_DATA(&ZCL_CTX().ota_cli.cmd_info_2).dst_endpoint = endpoint; /* src ep (yes, src) */ - ZB_ZCL_PARSED_HDR_SHORT_DATA(&ZCL_CTX().ota_cli.cmd_info_2).source.u.short_addr = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID); - ZB_ZCL_PARSED_HDR_SHORT_DATA(&ZCL_CTX().ota_cli.cmd_info_2).src_endpoint = zb_zcl_ota_upgrade_get8(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID); /* dst ep (yes, dst) */ - ZCL_CTX().ota_cli.payload_2.response.success.manufacturer = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID); - ZCL_CTX().ota_cli.payload_2.response.success.image_type = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID);; - ZCL_CTX().ota_cli.payload_2.response.success.file_version = zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID); - - schedule_resend_buffer(endpoint); - } - else - { - if (attr_desc != NULL) - { - TRACE_MSG(TRACE_OTA1, "Upgrade status %hd - do not restart OTA", (FMT__H, ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc))); - } - else - { - TRACE_MSG(TRACE_ERROR, "Invalid Pointer attr_desc", (FMT__0)); - } - } -} - - -static void zb_zcl_ota_upgrade_finish_upgrade(zb_uint8_t param) -{ - zb_uint8_t user_ret; - zb_uint8_t endpoint = *ZB_BUF_GET_PARAM(param, zb_uint8_t); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_finish_upgrade param %hd ep %hd", (FMT__H_H, - param, endpoint)); - - ZB_ZCL_OTA_UPGRADE_FINISH_USER_APP(param, user_ret); - ZVUNUSED(user_ret); - - zb_buf_free(param); - - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_finish_upgrade param %hd ep %hd", (FMT__H_H, - param, endpoint)); -} - -/** @brief Image Block Response command */ -static zb_ret_t image_block_resp_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ota_upgrade_image_block_res_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> image_block_resp_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_RES(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_RES", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_zcl_ota_upgrade_client_variable_t *client_data = get_upgrade_client_variables(endpoint); - zb_zcl_attr_t *attr_desc; - zb_uint8_t ota_status = zb_zcl_ota_upgrade_get_ota_status(endpoint); - - /* If we are not downloading the image, do nothing */ - if (ota_status == ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL) - { - ret = RET_ERROR; - } - /* If fw is already downloaded, do not allow new Image Block Responses */ - else if (ota_status == ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DOWNLOADED || - ota_status == ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_WAITING_UPGRADE || - ota_status == ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_COUNT_DOWN) - { - /* Do not abort here - simply drop the packet (it may be retransmit etc). */ - TRACE_MSG(TRACE_ZCL2, "OTA: ImgBlockResp when already downloaded, drop pkt", (FMT__0)); - /* zcl_ota_abort(endpoint, param); */ - - /* ZB_ZCL_OTA_UPGRADE_SEND_UPGRADE_END_REQ(param, */ - /* ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, */ - /* ZB_APS_ADDR_MODE_16_ENDP_PRESENT, */ - /* ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, */ - /* ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, */ - /* ZB_AF_HA_PROFILE_ID, ZB_FALSE, NULL, */ - /* ZB_ZCL_STATUS_INVALID_IMAGE, */ - /* zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID), */ - /* zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID), */ - /* zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID)); */ - zb_buf_free(param); - ret = RET_BUSY; - } - else - /* According to ota_status, download is in progress. */ - { - switch(payload.status) - { - case ZB_ZCL_STATUS_SUCCESS: - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID); - ZB_ASSERT(attr_desc); - - /* clear delay before use - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, 0);*/ - - if(payload.response.success.manufacturer==zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID) && - payload.response.success.image_type==zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID) && - payload.response.success.file_version==zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID) ) - { - zb_uint32_t file_size = client_data->download_file_size; - zb_uint32_t current_offset; - zb_bool_t get_next_block = ZB_FALSE; - zb_uint_t upgrade_status = ZB_ZCL_STATUS_SUCCESS; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID); - ZB_ASSERT(attr_desc); - - current_offset=ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - - if (payload.response.success.file_offset==current_offset) - { - /* reserve space for user callback parameters, it will be used later while - * calling this callback. When space is reserved, buffer data is moved to the left - - * it is better to do it here before any actions with pointers to data */ - (void)ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - - /* Make sure that the image payload pointer is correct after making the reservation. */ - ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_RES(&payload, param, status); - - - /* Block with expected offset is received, cancel resending. */ - cancel_resend_buffer(); - // call User App - // NOTE file data place`s in buffer, payload saves pointer to data only! - - /* Move offset before user's callback in case user's callback move it */ - current_offset += payload.response.success.data_size; - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, current_offset); - - ZB_ZCL_OTA_UPGRADE_RECEIVE_USER_APP(param, payload.response.success.file_offset, - payload.response.success.data_size, payload.response.success.image_data, - upgrade_status); - - if (upgrade_status == ZB_ZCL_OTA_UPGRADE_STATUS_OK) - { - /* User's callback can change current_offset, so re-read it */ - current_offset = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - get_next_block = ZB_TRUE; - TRACE_MSG(TRACE_ZCL2, "OTA: recv offset == current offset %ld, send get next req", (FMT__L, current_offset)); - } - else if (upgrade_status == ZB_ZCL_OTA_UPGRADE_STATUS_BUSY) - { - TRACE_MSG(TRACE_ZCL2, "OTA: client is busy, suspend OTA and wait for the signal to resume", (FMT__0)); - /* restore parameters */ - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - ret = RET_BUSY; - break; - } - else - { - TRACE_MSG(TRACE_ZCL2, "User's OTA callback set upgrade status %d - sending upgrade end", (FMT__D, upgrade_status)); - - zb_zcl_ota_upgrade_end(param, ZB_ZCL_STATUS_INVALID_IMAGE, &cmd_info, &payload); - ret = RET_BUSY; - /* Prevent sending Upgrade End request twice when we downloaded entire file with some error. */ - break; - } - } - else - { - if (ZCL_CTX().ota_cli.ota_restart_after_rejoin) - { - /* ZC thinks we are doing OTA. If so, let's start just now */ - TRACE_MSG(TRACE_ZCL2, "This is OTA after reboot - start download immediately", (FMT__0)); - ZCL_CTX().ota_cli.ota_restart_after_rejoin = 0; - get_next_block = ZB_TRUE; - } - } - TRACE_MSG(TRACE_ZCL2, "file_size %ld current_offset %ld", (FMT__L_L, file_size, current_offset)); - if (file_size > current_offset) - { - TRACE_MSG(TRACE_ZCL2, "OTA: get_next_block %hd", (FMT__H, get_next_block)); - - if (get_next_block) - { - /* restore parameters */ - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - zb_zcl_ota_upgrade_get_next_image_block(param, &cmd_info, &payload); - - /* Mark buffer as BUSY - it will not be release */ - ret = RET_BUSY; - } - else - { - /* mark buffer is NOT BUSY - it will be released after returning from the func */ - TRACE_MSG(TRACE_ZCL2, "OTA: skip sending, free buf %hd", (FMT__H, param)); - } - } - else - { - zb_zcl_ota_upgrade_process_downloaded_image(param, &cmd_info, &payload); - - /* Mark buffer as BUSY - it will not be release */ - ret = RET_BUSY; - } - } - else - { - - TRACE_MSG(TRACE_ZCL1, "Error invalid command parameter: manufacturer %d/%d image type %d/%d file version %lx/%lx", - (FMT__D_D_D_D_L_L, - payload.response.success.manufacturer, zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID), - payload.response.success.image_type, zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID), - payload.response.success.file_version, zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID))); - ret = RET_INVALID_PARAMETER_1; - } - break; - case ZB_ZCL_STATUS_WAIT_FOR_DATA: - { - /* - zb_uint16_t manufacturer = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID); - zb_uint16_t image_type = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID); - zb_uint32_t file_version = zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID); - zb_uint32_t current_offset = zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID); - zb_zcl_ota_upgrade_client_variable_t *client_data = get_upgrade_client_variables(endpoint); - */ - zb_uint32_t delay32; - zb_uint64_t delay64; - - TRACE_MSG(TRACE_ZCL2, "set delay attr %d", - (FMT__D, payload.response.wait_for_data.delay)); - - /* TODO: implement attribute value check in zb_zcl_check_attr_value (0 - 0x258) - NOTE: it seems error in the spec, too low upper limit; - possibly it should be 6000? */ - - /* update attribute from server command: - * 11.10.10 MinimumBlockPeriod Attribute - * This attribute SHALL reflect the minimum delay between Image Block Request commands generated by the - * client in milliseconds. The value of this attribute SHALL be updated when the rate is changed by the server, - * but SHOULD reflect the client default when an upgrade is not in progress or a server does not support this - * feature. */ - ret = ((ZB_ZCL_STATUS_SUCCESS == zb_zcl_set_attr_val(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID, - (zb_uint8_t*)&payload.response.wait_for_data.delay, ZB_FALSE)) - ? RET_OK - : RET_ERROR); - - if (ret == RET_OK) - { - /* OTA spec 6.10.8.4 - if (request_time - current_time) == 0, use BlockRequestDelay value to wait */ - - delay32 = ZB_TIME32_SUBTRACT(payload.response.wait_for_data.request_time, - payload.response.wait_for_data.current_time); - - /* request/current time is sent in UTC (seconds), translate it to ms */ - delay64 = 1000ull * (delay32); - - if (delay64 == 0) - { - /* if time delta is zero, use BlockRequestDelay value */ - delay64 = payload.response.wait_for_data.delay; - } - - TRACE_MSG(TRACE_ZCL2, "OTA: delay32 %ds", (FMT__D, (zb_uint16_t)delay32)); - - /* re-send query next block */ - /* TODO: ImageBlockResp may also be received as a response - * to ImagePageReq, in this case ImagePageReq should be resent */ - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - zb_zcl_ota_upgrade_send_block_request(param, delay64); - - ret = RET_BUSY; - /* cancel resend */ - cancel_resend_buffer(); - } - } - break; - case ZB_ZCL_STATUS_ABORT: - zcl_ota_abort(endpoint, param); - break; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< image_block_resp_handler ret %hx", (FMT__H, ret)); - return ret; -} - - -/* public API */ -void zb_zcl_ota_upgrade_send_upgrade_end_req(zb_uint8_t param, zb_uint8_t upgrade_status) -{ - zb_zcl_ota_upgrade_image_block_res_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - ZB_BZERO(&payload, sizeof(payload)); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_send_upgrade_end_req param %hd, status %hd", - (FMT__H_H, param, upgrade_status)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_RES(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_RES", - (FMT__0)); - zb_buf_free(param); - } - else - { - /* Finish OTA process */ - zb_zcl_ota_upgrade_end(param, - (upgrade_status == ZB_ZCL_OTA_UPGRADE_STATUS_OK ? - ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_INVALID_IMAGE), - &cmd_info, &payload); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_send_upgrade_end_req", (FMT__0)); -} - -/** @brief Upgrade End Response command */ -static zb_ret_t upgrade_end_resp_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ota_upgrade_upgrade_end_res_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t user_ret; - - TRACE_MSG(TRACE_ZCL1, "> upgrade_end_resp_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_UPGRADE_END_RES(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_UPGRADE_END_RES", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - TRACE_MSG(TRACE_ZCL2, "payload parameter %ld %d %d", (FMT__L_D_D, - payload.file_version, payload.manufacturer, payload.image_type)); - TRACE_MSG(TRACE_ZCL2, "saved parameter %ld %d %d", (FMT__L_D_D, - zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID), - zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID))); - TRACE_MSG(TRACE_ZCL2, "time parameter %ld %ld", (FMT__L_L, - payload.current_time, payload.upgrade_time)); - - /* OTA spec 6.10.10.4: examine the manufacturer code, image - type and file version to verify that they match its own. If - the received values do not match its own values or they are - not wild card values, then it shall discard the command and - no further processing shall continue. - - TODO: make correct check - take into account wildcard values - */ - if(payload.manufacturer==zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID) && - payload.image_type==zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID) && - payload.file_version==zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID) && - (payload.current_time <= payload.upgrade_time || ZB_ZCL_OTA_UPGRADE_UPGRADE_TIME_DEF_VALUE==payload.upgrade_time)) - { - if(payload.upgrade_time == ZB_ZCL_OTA_UPGRADE_UPGRADE_TIME_DEF_VALUE) - { - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_WAITING_UPGRADE); - } - else - { - // call User App - ZB_ZCL_OTA_UPGRADE_APPLY_USER_APP(param, user_ret); - - switch (user_ret) - { - case ZB_ZCL_OTA_UPGRADE_STATUS_REQUIRE_MORE_IMAGE: - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_WAIT_FOR_MORE); - - // send - ZB_ZCL_OTA_UPGRADE_SEND_UPGRADE_END_REQ(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_AF_HA_PROFILE_ID, ZB_FALSE, NULL, - ZB_ZCL_STATUS_REQUIRE_MORE_IMAGE, - payload.manufacturer, - payload.image_type, - payload.file_version); - - ret = RET_BUSY; - break; - - case ZB_ZCL_OTA_UPGRADE_STATUS_OK: - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_COUNT_DOWN); - if(ZB_ZCL_OTA_UPGRADE_UPGRADE_TIME_DEF_VALUE==payload.upgrade_time) - { - ZB_ZCL_OTA_UPGRADE_FINISH_USER_APP(param, user_ret); - } - else - { - *ZB_BUF_GET_PARAM(param, zb_uint8_t) = endpoint; - - ZB_SCHEDULE_ALARM(zb_zcl_ota_upgrade_finish_upgrade, param, - (payload.upgrade_time - payload.current_time)*ZB_TIME_ONE_SECOND); - ret = RET_BUSY; - } - break; - - case ZB_ZCL_OTA_UPGRADE_STATUS_ERROR: - default: - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL); - break; - } - } - } - else - { - ret = RET_INVALID_PARAMETER_2; - } - } - - TRACE_MSG(TRACE_ZCL1, "< upgrade_end_resp_handler ret %hx", (FMT__H, ret)); - return ret; -} - -/** @brief Query Specific File Response command */ -static zb_ret_t query_specific_file_resp_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ota_upgrade_query_specific_file_res_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> query_specific_file_resp_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_QUERY_SPECIFIC_FILE_RES(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_QUERY_SPECIFIC_FILE_RES", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - switch(payload.status) - { - case ZB_ZCL_STATUS_SUCCESS: - if(payload.manufacturer==zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MANUFACTURE_ID) && - payload.image_type==zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_TYPE_ID) && - ZB_ZCL_OTA_UPGRADE_VERSION_CMP(payload.file_version, - zb_zcl_ota_upgrade_get32(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_VERSION_ID)) ) - { - zb_zcl_attr_t *attr_desc; - zb_uint16_t delay = zb_zcl_ota_upgrade_get16(endpoint, ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID); - zb_zcl_ota_upgrade_client_variable_t *client_data = get_upgrade_client_variables(endpoint); - - // set attribute - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_FILE_OFFSET_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, 0); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_DOWNLOADED_FILE_VERSION_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, payload.file_version); - - client_data->download_file_size = payload.image_size; - - /* Backup period attribute */ - ZCL_CTX().ota_cli.ota_period_backup = delay; - - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_DOWNLOADING); - - //send query block: offset 0 - ZB_MEMCPY(ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - zb_zcl_ota_upgrade_send_block_request(param, delay); - - ret = RET_BUSY; - } - break; - case ZB_ZCL_STATUS_NO_IMAGE_AVAILABLE: - break; - } - } - - TRACE_MSG(TRACE_ZCL1, "< query_specific_file_resp_handler ret %hx", (FMT__H, ret)); - return ret; -} - - -static zb_bool_t zb_zcl_process_ota_cli_upgrade_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t status = RET_OK; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_ota_upgrade_specific_commands: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE == cmd_info.cluster_id); - - switch( cmd_info.cmd_id ) - { - case ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_NOTIFY_ID: - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction); - status = image_notify_handler(param); - break; - - case ZB_ZCL_CMD_OTA_UPGRADE_QUERY_NEXT_IMAGE_RESP_ID: - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction); - status = query_next_image_resp_handler(param); - break; - - case ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_RESP_ID: - { - zb_zcl_ota_upgrade_client_variable_t *client_data = - get_upgrade_client_variables(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint); - - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction); - if (client_data->img_block_req_sent) - { - /* We have pending request, do not handle new block immediately */ - if (client_data->pending_img_block_resp) - { - /* Yes, we will skip this block. Another block is already pending. */ - zb_buf_free(param); - } - else - { - client_data->pending_img_block_resp = param; - } - return ZB_TRUE; /* Notify ZCL that command is processed */ - } - else - { - status = image_block_resp_handler(param); - } - } - break; - - case ZB_ZCL_CMD_OTA_UPGRADE_UPGRADE_END_RESP_ID: - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction); - status = upgrade_end_resp_handler(param); - break; - - case ZB_ZCL_CMD_OTA_UPGRADE_QUERY_SPECIFIC_FILE_RESP_ID: - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction); - status = query_specific_file_resp_handler(param); - break; - -#if defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && !defined ZB_COORDINATOR_ONLY - case ZB_ZCL_CMD_OTA_UPGRADE_INTERNAL_ABORT_ID: - zcl_ota_abort_and_set_tc_cli(); - break; -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_WWAH && !defined ZB_COORDINATOR_ONLY */ - - case ZB_ZCL_CMD_DEFAULT_RESP: - /* This is not a normall call to specific commands processing. - This is a replacement of direct call from zb_zcl_handle_default_response_commands(). - It made to exclude OTA code linking if OTA cluster is not declared by the app. - */ - return (zb_bool_t)zb_zcl_process_ota_upgrade_default_response_commands(param); - break; - - default: - processed = ZB_FALSE; - break; - } - - if( processed ) - { - if( (ZB_NWK_IS_ADDRESS_BROADCAST(cmd_info.addr_data.common_data.dst_addr) || - (cmd_info.disable_default_response)) && status == RET_OK) - { - TRACE_MSG( TRACE_ZCL3, "Default response disabled", (FMT__0)); - zb_buf_free(param); - } - /* Fixed according to CCB 2519, malformed command should be ignored, default response should - * not be sent, see ZCL8 spec subclause 11.13.3.5.1 */ - else if ((cmd_info.cmd_id == ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_NOTIFY_ID) && (ZB_NWK_IS_ADDRESS_BROADCAST(cmd_info.addr_data.common_data.dst_addr)) && (status == RET_INVALID_PARAMETER_1 || status == RET_INVALID_PARAMETER_2)) - { - TRACE_MSG(TRACE_ZCL3, "Got malformed packet, no further processing should be done", (FMT__0)); - zb_buf_free(param); - } - else if (status != RET_BUSY) - { - ZB_ZCL_SEND_DEFAULT_RESP_DIRECTION( param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, - cmd_info.seq_number, - cmd_info.cmd_id, - (status==RET_OK ? ZB_ZCL_STATUS_SUCCESS : - (status==RET_INVALID_PARAMETER_2 ? ZB_ZCL_STATUS_MALFORMED_CMD : - ZB_ZCL_STATUS_INVALID_FIELD)), - (ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction ? - ZB_ZCL_FRAME_DIRECTION_TO_SRV : - ZB_ZCL_FRAME_DIRECTION_TO_CLI)); - } - } - - TRACE_MSG( TRACE_ZCL1, - "< zb_zcl_process_ota_upgrade_specific_commands: processed %d", - (FMT__D, processed)); - return processed; -} - -static zb_bool_t zb_zcl_process_ota_upgrade_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_ota_upgrade_client_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_ota_cli_upgrade_specific_commands(param); -} - -/** - * @} internal -*/ - -#endif /* defined ZB_HA_ENABLE_OTA_UPGRADE_CLIENT || defined DOXYGEN */ - -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_ota_upgrade_common.c b/zboss/development/src/zcl/zcl_ota_upgrade_common.c deleted file mode 100644 index c2d9c811ff..0000000000 --- a/zboss/development/src/zcl/zcl_ota_upgrade_common.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL OTA Cluster - common part for Server and Client -*/ - -#define ZB_TRACE_FILE_ID 47 - -#include "zb_common.h" - -/** @internal - @{ -*/ - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE) || defined DOXYGEN - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_ota_upgrade.h" -#include "zb_zdo.h" -#include "zb_aps.h" -#include "zdo_wwah_stubs.h" -/* - That routines are linked if either Client or Server role is enabled. - */ - -zb_ret_t zb_zcl_check_value_ota_upgrade(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = ZB_TRUE; - ZVUNUSED(endpoint); - ZVUNUSED(value); - - TRACE_MSG(TRACE_ZCL1, "> check_value_ota_upgrade", (FMT__0)); - - switch( attr_id ) - { - /* remove for NTS certification - test 9.5.9 - * TH sends wrong value - 6000 (e.q. 25 minutes) */ -#ifdef NTS_HACK - case ZB_ZCL_ATTR_OTA_UPGRADE_MIN_BLOCK_REQUE_ID: - ret = 258 > *(zb_uint16_t*)value - ? RET_OK : RET_ERROR; - break; -#endif - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "< check_value_ota_upgrade ret %hd", (FMT__H, ret)); - return ret; -} -/*************************** Helper functions *************************/ -/** @brief Get 8bit attribute value from OTA Upgrade cluster - @param endpoint - endpoint - @param attr_id - attribute ID - @return attribute value -*/ -zb_uint8_t zb_zcl_ota_upgrade_get8(zb_uint8_t endpoint, zb_uint16_t attr_id) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, attr_id); - ZB_ASSERT(attr_desc); - return ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); -} - -/** @brief Get 16bit attribute value from OTA Upgrade cluster - @param endpoint - endpoint - @param attr_id - attribute ID - @return attribute value -*/ -zb_uint16_t zb_zcl_ota_upgrade_get16(zb_uint8_t endpoint, zb_uint16_t attr_id) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, attr_id); - ZB_ASSERT(attr_desc); - return ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); -} - -/** @brief Get 16bit attribute value from OTA Upgrade cluster - @param endpoint - endpoint - @param attr_id - attribute ID - @return attribute value -*/ -zb_uint32_t zb_zcl_ota_upgrade_get32(zb_uint8_t endpoint, zb_uint16_t attr_id) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, attr_id); - ZB_ASSERT(attr_desc); - return ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); -} - -void zb_zcl_ota_upgrade_set_ota_status(zb_uint8_t endpoint, zb_uint8_t status) -{ - zb_zcl_attr_t *attr_desc; - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_set_ota_status endpoint %hd status %hd", (FMT__H_H, endpoint, status)); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STATUS_ID); - ZB_ASSERT(attr_desc); - - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, status); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_set_ota_status", (FMT__0)); -} - -/** @brief Default Response command */ -zb_uint8_t zb_zcl_process_ota_upgrade_default_response_commands(zb_uint8_t param) -{ - zb_uint8_t ret = ZB_FALSE; - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_zcl_default_resp_payload_t* default_res; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_process_ota_upgrade_default_response_commands %hx", (FMT__H, param)); - - if( cmd_info -> cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_CLI && - cmd_info -> is_common_command && - cmd_info -> cmd_id == ZB_ZCL_CMD_DEFAULT_RESP) - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STATUS_ID); - ZB_ASSERT(attr_desc); - - default_res = ZB_ZCL_READ_DEFAULT_RESP(param); - TRACE_MSG(TRACE_ZCL2, "ZB_ZCL_CMD_DEFAULT_RESP: command_id 0x%hx, status: 0x%hx", - (FMT__H_H, default_res->command_id, default_res->status)); - - if(ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL != ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) && - ZB_ZCL_STATUS_ABORT== default_res->status) - { - // set attribute - zb_zcl_ota_upgrade_set_ota_status(endpoint, ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL); - - // call User App - ZB_ZCL_OTA_UPGRADE_ABORT_USER_APP(param); - } - - zb_buf_free(param); - - ret = ZB_TRUE; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_process_ota_upgrade_default_response_commands", (FMT__0)); - - return ret; -} - -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_ota_upgrade_minimal.c b/zboss/development/src/zcl/zcl_ota_upgrade_minimal.c deleted file mode 100644 index 92a3dcfc3c..0000000000 --- a/zboss/development/src/zcl/zcl_ota_upgrade_minimal.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL OTA Cluster - routines which always linked because called from the main ZCL logic. -*/ - -#define ZB_TRACE_FILE_ID 45 - -#include "zb_common.h" - -/** @internal - @{ -*/ - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE) || defined DOXYGEN - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_ota_upgrade.h" -#include "zb_zdo.h" -#include "zb_aps.h" -#include "zdo_wwah_stubs.h" - -/* That code may be called from zcl_poll_control_commands.c, so linked always.*/ -zb_uint8_t zb_zcl_ota_upgrade_get_ota_status(zb_uint8_t endpoint) -{ - zb_zcl_attr_t *attr_desc; - zb_uint8_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_get_ota_status endpoint %hd", (FMT__H, endpoint)); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_IMAGE_STATUS_ID); - ZB_ASSERT(attr_desc); - - status = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_get_ota_status %hd", (FMT__H, status)); - - return status; -} - - -void zcl_ota_abort_and_set_tc(zb_uint8_t param) -{ - zb_zcl_cluster_handler_t cluster_handler; - - cluster_handler = zb_zcl_get_cluster_handler(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, - ZB_ZCL_CLUSTER_CLIENT_ROLE); - if (cluster_handler) - { - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - cmd_info->disable_default_response = ZB_TRUE; - cmd_info->cluster_id = ZB_ZCL_CLUSTER_ID_OTA_UPGRADE; - cmd_info->cmd_id = ZB_ZCL_CMD_OTA_UPGRADE_INTERNAL_ABORT_ID; - cluster_handler(param); - } - else - { - zb_buf_free(param); - } -} - -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_ota_upgrade_srv_commands.c b/zboss/development/src/zcl/zcl_ota_upgrade_srv_commands.c deleted file mode 100644 index 149ba5df34..0000000000 --- a/zboss/development/src/zcl/zcl_ota_upgrade_srv_commands.c +++ /dev/null @@ -1,1047 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL OTA Upgrade cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 46 - -#include "zb_common.h" - -/** @internal - @{ -*/ - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE) || defined DOXYGEN - -#if defined ZB_HA_ENABLE_OTA_UPGRADE_SERVER || defined DOXYGEN - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_ota_upgrade.h" -#include "zb_zdo.h" -#include "zb_aps.h" -#include "zdo_wwah_stubs.h" - -static zb_uint8_t gs_ota_upgrade_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -static zb_uint8_t gs_ota_upgrade_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - - -static zb_discover_cmd_list_t gs_ota_upgrade_server_cmd_list = -{ - sizeof(gs_ota_upgrade_server_received_commands), gs_ota_upgrade_server_received_commands, - sizeof(gs_ota_upgrade_client_received_commands), gs_ota_upgrade_client_received_commands -}; - -static zb_bool_t zb_zcl_process_ota_upgrade_specific_commands_srv(zb_uint8_t param); - -void zb_zcl_ota_upgrade_init_srv() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_ota_upgrade_specific_commands_srv); -} - -static zb_ieee_addr_t zb_zcl_ota_upgrade_def_address = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -static zb_ret_t zcl_ota_upgrade_srv_query_img_invoke_user_app( - zb_uint8_t param, zb_zcl_addr_t *zcl_addr, - zb_uint16_t image_type, zb_uint16_t manufacturer_code, zb_uint32_t version, zb_uint8_t *table_idx); -static void zcl_ota_upgrade_srv_upgrade_started_invoke_user_app( - zb_uint8_t param, zb_zcl_addr_t *zcl_addr, - zb_uint16_t image_type, zb_uint32_t version); -static void zcl_ota_upgrade_srv_upgrade_aborted_invoke_user_app( - zb_uint8_t param, zb_zcl_addr_t *zcl_addr, - zb_uint16_t image_type, zb_uint32_t version); -static zb_ret_t zcl_ota_upgrade_srv_upgrade_end_invoke_user_app( - zb_uint8_t param, zb_zcl_addr_t *zcl_addr, zb_uint8_t status, - zb_uint16_t image_type, zb_uint32_t version, zb_uint32_t* upgrade_time); - -/******************************** Helper function ****************************************/ - -#define ZB_ZCL_OTA_FILE_DST_ADDR(header) \ - ( (((header)->fc) & ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_DEVICE_SPECIFIC) \ - ? (zb_uint8_t*)(header) + sizeof(zb_zcl_ota_upgrade_file_header_t) + \ - (( ((header)->fc) & ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_CREDENTIAL_VER) ? sizeof(zb_uint8_t): 0) \ - : zb_zcl_ota_upgrade_def_address) - -static zb_uint16_t zb_zcl_ota_file_min_hw_version(zb_zcl_ota_upgrade_file_header_t *header) -{ - zb_uint8_t *ptr = (zb_uint8_t*)header; - zb_uint16_t tmp_ptr_val = 0; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_file_min_hw_version %p", (FMT__P, header)); - - ZB_ASSIGN_UINT16(&tmp_ptr_val, ( ptr + sizeof(zb_zcl_ota_upgrade_file_header_t) - + ((header->fc & ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_CREDENTIAL_VER) ? sizeof(zb_uint8_t): 0) - + ((header->fc & ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_DEVICE_SPECIFIC) ? sizeof(zb_ieee_addr_t): 0))); - - return (header->fc & ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_HW_VER) - ? tmp_ptr_val - : 0; -} - -static zb_uint16_t zb_zcl_ota_file_max_hw_version(zb_zcl_ota_upgrade_file_header_t *header) -{ - zb_uint8_t *ptr = (zb_uint8_t*)header; - zb_uint16_t tmp_ptr_val = 0; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_file_max_hw_version %p", (FMT__P, header)); - - ZB_ASSIGN_UINT16(&tmp_ptr_val, ( ptr + sizeof(zb_zcl_ota_upgrade_file_header_t) - + ((header->fc & ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_CREDENTIAL_VER) ? sizeof(zb_uint8_t): 0) - + ((header->fc & ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_DEVICE_SPECIFIC) ? sizeof(zb_ieee_addr_t): 0) - + sizeof(zb_uint16_t))); - - return (header->fc & ZB_ZCL_OTA_UPGRADE_FILE_HEADER_FC_HW_VER) - ? tmp_ptr_val - : 0xffff; -} - -static zb_zcl_ota_upgrade_server_variable_t * get_upgrade_server_variables(zb_uint8_t endpoint) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_DATA_ID); - ZB_ASSERT(attr_desc); - return (zb_zcl_ota_upgrade_server_variable_t*)attr_desc->data_p; -} - -/******************************** App function ****************************************/ - -/* public API */ -void zb_zcl_ota_upgrade_init_server(zb_uint8_t endpoint, zb_zcl_ota_upgrade_next_data_ind_t next_data_ind_cb) -{ - zb_zcl_ota_upgrade_server_variable_t *vars; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_init_server %hx", (FMT__H, endpoint)); - - vars = get_upgrade_server_variables(endpoint); - - for(i=0; itable_length; i++) - { - vars->table[i].file_header = NULL; - } - - ZB_ASSERT(next_data_ind_cb); - - ZCL_CTX().ota_upgrade_next_data_ind_cb = next_data_ind_cb; - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_init_server", (FMT__0)); -} - -/* public API */ -zb_ret_t zb_zcl_ota_upgrade_insert_file(zb_uint8_t param) -{ - zb_zcl_ota_upgrade_server_insert_file_t* insert_data = - ZB_BUF_GET_PARAM(param, zb_zcl_ota_upgrade_server_insert_file_t); - zb_ret_t ret = RET_OK; - zb_zcl_ota_upgrade_server_variable_t *vars; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_insert_file %hx", (FMT__H, param)); - - endpoint = insert_data->endpoint; - - vars = get_upgrade_server_variables(endpoint); - - TRACE_MSG(TRACE_ZCL2, "index %hx", (FMT__H, insert_data->index)); - if(insert_data->index < vars->table_length) - { - zb_zcl_ota_upgrade_file_header_t *head = (zb_zcl_ota_upgrade_file_header_t*)insert_data->ota_file; - - // Fill table - vars->table[insert_data->index].file_header = head; - vars->table[insert_data->index].upgrade_time = insert_data->upgrade_time; - - TRACE_MSG(TRACE_ZCL2, "index = %d 0x%x", (FMT__H_P, insert_data->index, vars->table[insert_data->index].file_header)); - - if (insert_data->notify_on) - { - // Send Image Notify - if(ZB_ZCL_OTA_FILE_IS_FILE_SPECIFIC(head)) - { - zb_uint16_t dest_addr; - zb_ieee_addr_t dest_ieee; - - ZB_IEEE_ADDR_COPY(dest_ieee, ZB_ZCL_OTA_FILE_DST_ADDR(head)); - zb_inverse_bytes(dest_ieee,sizeof(zb_ieee_addr_t)); - - dest_addr = zb_address_short_by_ieee(dest_ieee); - - TRACE_MSG(TRACE_ZCL2, "short 0x%x long "TRACE_FORMAT_64"", (FMT__D_A, - dest_addr, TRACE_ARG_64(ZB_ZCL_OTA_FILE_DST_ADDR(head)))); - ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_NOTIFY_REQ(param, - dest_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, ZB_ZCL_BROADCAST_ENDPOINT, - endpoint, ZB_AF_HA_PROFILE_ID, ZB_TRUE, NULL, - ZB_ZCL_OTA_UPGRADE_IMAGE_NOTIFY_PAYLOAD_JITTER_CODE_IMAGE_VER, - *(vars->query_jitter), - head->manufacturer_code, - head->image_type, - head->file_version); - } - else // broadcast - { - zb_uint16_t short_addr = ZB_NWK_BROADCAST_ALL_DEVICES; - ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_NOTIFY_REQ(param, - short_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, ZB_ZCL_BROADCAST_ENDPOINT, - endpoint, ZB_AF_HA_PROFILE_ID, ZB_TRUE, NULL, - ZB_ZCL_OTA_UPGRADE_IMAGE_NOTIFY_PAYLOAD_JITTER_CODE_IMAGE_VER, - *(vars->query_jitter), - head->manufacturer_code, - head->image_type, - head->file_version); - } - } - else - { - zb_buf_free(param); - } - } - else - { - ret = RET_INVALID_PARAMETER_1; - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_insert_file ret %hx", (FMT__H, ret)); - - return ret; -} - -/* public API */ -zb_ret_t zb_zcl_ota_upgrade_remove_file(zb_uint8_t param) -{ - zb_zcl_ota_upgrade_server_remove_file_t* remove_data = - ZB_BUF_GET_PARAM(param, zb_zcl_ota_upgrade_server_remove_file_t); - zb_ret_t ret = RET_OK; - - zb_zcl_ota_upgrade_server_variable_t *vars = get_upgrade_server_variables(remove_data->endpoint); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_ota_upgrade_remove_file %hx", (FMT__H, param)); - - if(remove_data->index < vars->table_length) - { - vars->table[remove_data->index].file_header = 0; - } - else - { - ret = RET_INVALID_PARAMETER_1; - } - - zb_buf_free(param); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_ota_upgrade_remove_file ret %hx", (FMT__H, ret)); - - return ret; -} - -void zb_zcl_ota_upgrade_send_query_next_image_response(zb_zcl_parsed_hdr_t *zcl_parsed_hdr, zb_bool_t image_present, zb_uindex_t table_idx) -{ - zb_uint8_t endpoint; - zb_zcl_ota_upgrade_server_variable_t *vars; - zb_bufid_t param; - - TRACE_MSG(TRACE_ZCL1, - ">zb_zcl_ota_upgrade_send_query_next_image_response, image_presend %d, index %d", - (FMT__D_D, image_present, table_idx)); - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_parsed_hdr).dst_endpoint; - vars = get_upgrade_server_variables(endpoint); - - param = zb_buf_get_out(); - - if (param) - { - if (image_present) - { - if(table_idx < vars->table_length) - { - TRACE_MSG(TRACE_ZCL1, "Found OTA file ver 0x%x", - (FMT__L, vars->table[table_idx].file_header->file_version)); - - ZB_ZCL_OTA_UPGRADE_SEND_QUERY_NEXT_IMAGE_RES( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_parsed_hdr).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_parsed_hdr).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_parsed_hdr).dst_endpoint, - ZB_AF_HA_PROFILE_ID, zcl_parsed_hdr->seq_number, - ZB_ZCL_STATUS_SUCCESS, - vars->table[table_idx].file_header->manufacturer_code, - vars->table[table_idx].file_header->image_type, - vars->table[table_idx].file_header->file_version, - vars->table[table_idx].file_header->total_image_size); - } - else - { - TRACE_MSG(TRACE_ERROR, "incorrect table_idx: %d", (FMT__D, table_idx)); - } - } - else - { - ZB_ZCL_OTA_UPGRADE_SEND_QUERY_NEXT_IMAGE_RES( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_parsed_hdr).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_parsed_hdr).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_parsed_hdr).dst_endpoint, - ZB_AF_HA_PROFILE_ID, zcl_parsed_hdr->seq_number, - ZB_ZCL_STATUS_NO_IMAGE_AVAILABLE, - 0, 0, 0, 0); - } - } - else - { - TRACE_MSG(TRACE_ERROR, "failed to get out buf, response won't be sent", (FMT__0)); - } - - TRACE_MSG(TRACE_ZCL1, " query_next_image_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_QUERY_NEXT_IMAGE_REQ(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_QUERY_NEXT_IMAGE_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t i = 0U; - zb_uint8_t endpoint; - zb_zcl_ota_upgrade_server_variable_t *vars; - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - vars = get_upgrade_server_variables(endpoint); - ret = zcl_ota_upgrade_srv_query_img_invoke_user_app( - param, &ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source, - payload.image_type, payload.manufacturer, payload.file_version, &i); - - if (ret == RET_NOT_FOUND) - { - /* No user callback, try to search in table (old-style) */ - for(i=0; itable_length; i++) - { - if(vars->table[i].file_header) - { - TRACE_MSG(TRACE_ZCL2, "File %d %p", (FMT__H_P, i, vars->table[i].file_header)); - if( payload.manufacturer == vars->table[i].file_header->manufacturer_code && - payload.image_type == vars->table[i].file_header->image_type && - ZB_ZCL_OTA_UPGRADE_VERSION_CMP( - vars->table[i].file_header->file_version, payload.file_version) && - //ZB_ZCL_OTA_FILE_IS_FILE_SPECIFIC(vars->table[i].file_header)==ZB_FALSE && - // hw version - ( !(payload.fc & ZB_ZCL_OTA_UPGRADE_QUERY_NEXT_IMAGE_HW_VERSION) || - ( payload.hw_version >= zb_zcl_ota_file_min_hw_version(vars->table[i].file_header) && - payload.hw_version <= zb_zcl_ota_file_max_hw_version(vars->table[i].file_header) ) - ) ) - { - ret = RET_OK; - break; - } - } - } - } - - if (ret == RET_OK && i < vars->table_length) - { - TRACE_MSG(TRACE_ZCL1, "Found OTA file ver 0x%x", (FMT__L, vars->table[i].file_header->file_version)); - zb_zcl_ota_upgrade_send_query_next_image_response(&cmd_info, ZB_TRUE, i); - } - else if (ret == RET_BLOCKED) - { - TRACE_MSG(TRACE_ZCL1, "Application will call zb_zcl_upgrade_send_query_next_image_response later", - (FMT__0)); - } - else - { - zb_zcl_ota_upgrade_send_query_next_image_response(&cmd_info, ZB_FALSE, 0); - } - ret = RET_BUSY; - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< query_next_image_handler ret %hx", (FMT__H, ret)); - return ret; -} - -void zb_zcl_ota_upgrade_send_image_block_response(zb_zcl_parsed_hdr_t *zcl_header, zb_uindex_t table_idx, - zb_bool_t block_present, - zb_uint32_t offset, zb_uint8_t data_size, - const zb_uint8_t* data) -{ - zb_bufid_t param; - zb_uint8_t endpoint; - zb_zcl_ota_upgrade_server_variable_t *vars; - - - TRACE_MSG(TRACE_ZCL1, ">zb_zcl_ota_upgrade_send_image_block_response", (FMT__0)); - TRACE_MSG(TRACE_ZCL1, "table_idx %d, block_present %d, offset %d, data_size %d", - (FMT__D_D_D_D, table_idx, block_present, offset, data_size)); - - param = zb_buf_get_out(); - - if (param) - { - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_header).dst_endpoint; - vars = get_upgrade_server_variables(endpoint); - if (block_present) - { - ZB_ZCL_OTA_UPGRADE_SEND_IMAGE_BLOCK_SUCCESS_RES( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_header).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_header).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_header).dst_endpoint, - ZB_AF_HA_PROFILE_ID, zcl_header->seq_number, - vars->table[table_idx].file_header->manufacturer_code, - vars->table[table_idx].file_header->image_type, - vars->table[table_idx].file_header->file_version, - offset, - data_size, - data - ); - } - else - { - /* ZCL8 spec, 11.13.6.5.2 No Image Available - If either manufacturer code or image type or file version information in the request command is invalid or the OTA - upgrade file for the client for some reason has disappeared which result in the server no longer able to retrieve the file, - it SHALL send default response command with NO_IMAGE_AVAILABLE status to the client. - */ - ZB_ZCL_SEND_DEFAULT_RESP_DIRECTION( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_header).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_header).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(zcl_header).dst_endpoint, - zcl_header->profile_id, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, - zcl_header->seq_number, - zcl_header->cmd_id, - ZB_ZCL_STATUS_NO_IMAGE_AVAILABLE, - (ZB_ZCL_FRAME_DIRECTION_TO_CLI == zcl_header->cmd_direction ? - ZB_ZCL_FRAME_DIRECTION_TO_SRV : - ZB_ZCL_FRAME_DIRECTION_TO_CLI)); - } - } - else - { - TRACE_MSG(TRACE_ERROR, "Failed to get out buf, response won't be sent", (FMT__0)); - } - - TRACE_MSG(TRACE_ZCL1, " image_block_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, cmd_info_p, sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_REQ(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_IMAGE_BLOCK_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_zcl_ota_upgrade_server_variable_t *vars = get_upgrade_server_variables(endpoint); - zb_uindex_t i; - - for(i=0; itable_length; i++) - { - if(vars->table[i].file_header) - { - if( payload.manufacturer == vars->table[i].file_header->manufacturer_code && - payload.image_type == vars->table[i].file_header->image_type && - vars->table[i].file_header->file_version == payload.file_version ) - { - zb_uint32_t total_image_size = vars->table[i].file_header->total_image_size; - if( payload.file_offset < total_image_size) - { - zb_uint8_t *data = NULL; - zb_uint8_t data_size = - (payload.data_size_max <= ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_DATA_SIZE_MAX) ? - payload.data_size_max : - ZB_ZCL_OTA_UPGRADE_QUERY_IMAGE_BLOCK_DATA_SIZE_MAX; - - if(data_size > total_image_size - payload.file_offset) - { - data_size = total_image_size - payload.file_offset; - } - - ret = ZCL_CTX().ota_upgrade_next_data_ind_cb(i, cmd_info_p, payload.file_offset, data_size, &data); - - if (payload.file_offset == 0) - { - if (ret == RET_BLOCKED - || (ret == RET_OK && data) ) - { - /* Will hope RET_BLOCKED results means data will be sent later */ - zcl_ota_upgrade_srv_upgrade_started_invoke_user_app( - param, &ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source, - payload.image_type, payload.file_version); - } - } - - if (ret == RET_OK - && data) - { - zb_zcl_ota_upgrade_send_image_block_response(cmd_info_p, i, ZB_TRUE, payload.file_offset, - data_size, data); - zb_buf_free(param); - ret = RET_BUSY; - } - else if (ret == RET_BLOCKED) - { - TRACE_MSG(TRACE_ZCL1, "Application will call zb_zcl_ota_upgrade_send_image_block_response later", - (FMT__0)); - ret = RET_BUSY; - zb_buf_free(param); - } - } - break; - } - } - } - if (ret != RET_BUSY) - { - zcl_ota_upgrade_srv_upgrade_aborted_invoke_user_app( - param, &ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source, - payload.image_type, payload.file_version); - - zb_zcl_ota_upgrade_send_image_block_response(cmd_info_p, 0, ZB_FALSE, 0, 0, NULL); - zb_buf_free(param); - - ret = RET_BUSY; - } - } - - TRACE_MSG(TRACE_ZCL1, "< image_block_handler ret %hx", (FMT__H, ret)); - return ret; -} - -#if 0 -/** @brief Image Page Request command */ -static zb_ret_t image_page_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ota_upgrade_image_page_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> image_page_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_IMAGE_PAGE_REQ(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_IMAGE_PAGE_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_zcl_ota_upgrade_server_variable_t *vars = get_upgrade_server_variables(endpoint); - zb_uindex_t index; - - //todo - ret = RET_BUSY; - } - - TRACE_MSG(TRACE_ZCL1, "< image_page_handler ret %hx", (FMT__H, ret)); - return ret; -} -#endif /*0*/ - -/** @brief Upgrade End Request command */ -static zb_ret_t upgrade_end_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ota_upgrade_upgrade_end_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint32_t upgrade_time = ZB_ZCL_OTA_UPGRADE_UPGRADE_TIME_DEF_VALUE; - - TRACE_MSG(TRACE_ZCL1, "> upgrade_end_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_UPGRADE_END_REQ(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_UPGRADE_END_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_zcl_ota_upgrade_server_variable_t *vars = get_upgrade_server_variables(endpoint); - zb_uindex_t i = vars->table_length; - - if(payload.status==ZB_ZCL_STATUS_SUCCESS) - { - for(i=0; itable_length; i++) - { - if(vars->table[i].file_header) - { - if( payload.manufacturer == vars->table[i].file_header->manufacturer_code && - payload.image_type == vars->table[i].file_header->image_type && - vars->table[i].file_header->file_version == payload.file_version ) - { - upgrade_time = vars->table[i].upgrade_time; - break; - } - } - } - } - - /* pass the pointer to upgrade time field to give an application the means of setting upgrade time - FIXME: refactor this command and the whole cluster using IN/OUT params API */ - /*ret = */ - zcl_ota_upgrade_srv_upgrade_end_invoke_user_app( - param, &ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source, payload.status, - payload.image_type, payload.file_version, &upgrade_time); - - if(payload.status==ZB_ZCL_STATUS_SUCCESS) - { - if (i < vars->table_length) - { - vars->table[i].upgrade_time = upgrade_time; - } - else - { - ret = RET_ERROR; - } - } - - if (ret != RET_ERROR) - { - if (payload.status==ZB_ZCL_STATUS_SUCCESS) - { - ZB_ZCL_OTA_UPGRADE_SEND_UPGRADE_END_RES( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_AF_HA_PROFILE_ID, cmd_info.seq_number, - payload.manufacturer, - payload.image_type, - payload.file_version, - *(vars->current_time), - vars->table[i].upgrade_time); - } - else - { - ZB_ZCL_SEND_DEFAULT_RESP_DIRECTION( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, - cmd_info.seq_number, - cmd_info.cmd_id, - ZB_ZCL_STATUS_SUCCESS, - (ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction ? - ZB_ZCL_FRAME_DIRECTION_TO_SRV : - ZB_ZCL_FRAME_DIRECTION_TO_CLI)); - } - ret = RET_BUSY; - } - } - - TRACE_MSG(TRACE_ZCL1, "< upgrade_end_handler ret %hx", (FMT__H, ret)); - return ret; -} - -/** @brief Query Specific File command */ -static zb_ret_t query_specific_file_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_ota_upgrade_query_specific_file_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> query_specific_file_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_OTA_UPGRADE_GET_QUERY_SPECIFIC_FILE_REQ(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_OTA_UPGRADE_GET_QUERY_SPECIFIC_FILE_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else - { - zb_uint8_t endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - zb_zcl_ota_upgrade_server_variable_t *vars = get_upgrade_server_variables(endpoint); - zb_uindex_t i; - - for(i=0; itable_length; i++) - { - TRACE_MSG(TRACE_ZCL2, "index = %d", (FMT__H, i)); - if(vars->table[i].file_header) - { - TRACE_MSG(TRACE_ZCL2, "manuf %d long "TRACE_FORMAT_64"", (FMT__D_A, - vars->table[i].file_header->manufacturer_code, - TRACE_ARG_64(ZB_ZCL_OTA_FILE_DST_ADDR(vars->table[i].file_header)))); - - TRACE_MSG(TRACE_ZCL2, "if %d %d %d %d %d", (FMT__H_H_H_H_H, - ZB_IEEE_ADDR_CMP(ZB_ZCL_OTA_FILE_DST_ADDR(vars->table[i].file_header), payload.node_addr), - payload.manufacturer == vars->table[i].file_header->manufacturer_code, - payload.image_type == vars->table[i].file_header->image_type, - ZB_ZCL_OTA_UPGRADE_VERSION_CMP( - vars->table[i].file_header->file_version, payload.file_version), - payload.stack_version == vars->table[i].file_header->stack_version ) ); - - TRACE_MSG(TRACE_ZCL2, "file value "TRACE_FORMAT_64" payload value "TRACE_FORMAT_64"", (FMT__A_A, - TRACE_ARG_64(ZB_ZCL_OTA_FILE_DST_ADDR(vars->table[i].file_header)), TRACE_ARG_64(payload.node_addr))); - - if( ZB_IEEE_ADDR_CMP(ZB_ZCL_OTA_FILE_DST_ADDR(vars->table[i].file_header), payload.node_addr) && - payload.manufacturer == vars->table[i].file_header->manufacturer_code && - payload.image_type == vars->table[i].file_header->image_type && - ZB_ZCL_OTA_UPGRADE_VERSION_CMP( - vars->table[i].file_header->file_version, payload.file_version) && - payload.stack_version == vars->table[i].file_header->stack_version ) - { - ZB_ZCL_OTA_UPGRADE_SEND_QUERY_SPECIFIC_FILE_RES(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_AF_HA_PROFILE_ID, cmd_info.seq_number, - ZB_ZCL_STATUS_SUCCESS, - vars->table[i].file_header->manufacturer_code, - vars->table[i].file_header->image_type, - vars->table[i].file_header->file_version, - vars->table[i].file_header->total_image_size); - - ret = RET_BUSY; - break; - } - } - } - if(ret!=RET_BUSY) - { - ZB_ZCL_OTA_UPGRADE_SEND_QUERY_SPECIFIC_FILE_RES(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_AF_HA_PROFILE_ID, cmd_info.seq_number, - ZB_ZCL_STATUS_NO_IMAGE_AVAILABLE, - 0, 0, 0, 0); - - ret = RET_BUSY; - } - } - - TRACE_MSG(TRACE_ZCL1, "< query_specific_file_handler ret %hx", (FMT__H, ret)); - return ret; -} - - -static zb_ret_t zcl_ota_upgrade_srv_query_img_invoke_user_app( - zb_uint8_t param, zb_zcl_addr_t *zcl_addr, - zb_uint16_t image_type, zb_uint16_t manufacturer_code, zb_uint32_t version, zb_uint8_t *table_idx) -{ - zb_ret_t ret; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zcl_ota_upgrade_srv_query_img_invoke_user_app, param %hd", - (FMT__H, param)); - ret = RET_NOT_FOUND; - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - if (ZCL_CTX().device_cb) - { - zb_zcl_device_callback_param_t *user_app_data; - zb_zcl_ota_upgrade_srv_query_img_param_t *value; - - user_app_data = ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - value = &user_app_data->cb_param.ota_upgrade_srv_query_img_param; - value->zcl_addr = zcl_addr; - value->image_type = image_type; - value->manufacturer_code = manufacturer_code; - value->version = version; - value->table_idx = table_idx; - /* we need to save the ZCL header to send a response later using the same buffer */ - ZB_MEMCPY(&value->zcl_parsed_hdr, &cmd_info, sizeof(zb_zcl_parsed_hdr_t)); - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_SRV_QUERY_IMAGE_CB_ID; - user_app_data->endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_SERVER_ROLE); - user_app_data->status = RET_OK; - (ZCL_CTX().device_cb)(param); - ret = user_app_data->status; - } - TRACE_MSG(TRACE_ZCL1, "< zcl_ota_upgrade_srv_query_img_invoke_user_app, ret %hd", - (FMT__H, ret)); - return ret; -} - - -static void zcl_ota_upgrade_srv_upgrade_started_invoke_user_app( - zb_uint8_t param, zb_zcl_addr_t *zcl_addr, - zb_uint16_t image_type, zb_uint32_t version) -{ - TRACE_MSG(TRACE_ZCL1, "> zcl_ota_upgrade_srv_upgrade_started_invoke_user_app, param %hd", - (FMT__H, param)); - - if (ZCL_CTX().device_cb) - { - zb_zcl_device_callback_param_t *user_app_data; - zb_zcl_ota_upgrade_srv_upgrade_started_param_t *value; - - user_app_data = ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - value = &user_app_data->cb_param.ota_upgrade_srv_upgrade_started_param; - value->zcl_addr = zcl_addr; - value->image_type = image_type; - value->version = version; - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_SRV_UPGRADE_STARTED_CB_ID; - user_app_data->status = RET_OK; - (ZCL_CTX().device_cb)(param); - } - TRACE_MSG(TRACE_ZCL1, "< zcl_ota_upgrade_srv_upgrade_started_invoke_user_app", - (FMT__0)); -} - - -static void zcl_ota_upgrade_srv_upgrade_aborted_invoke_user_app( - zb_uint8_t param, zb_zcl_addr_t *zcl_addr, - zb_uint16_t image_type, zb_uint32_t version) -{ - TRACE_MSG(TRACE_ZCL1, "> zcl_ota_upgrade_srv_upgrade_aborted_invoke_user_app, param %hd", - (FMT__H, param)); - - if (ZCL_CTX().device_cb) - { - zb_zcl_device_callback_param_t *user_app_data; - zb_zcl_ota_upgrade_srv_upgrade_aborted_param_t *value; - - user_app_data = ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - value = &user_app_data->cb_param.ota_upgrade_srv_upgrade_aborted_param; - value->zcl_addr = zcl_addr; - value->image_type = image_type; - value->version = version; - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_SRV_UPGRADE_ABORTED_CB_ID; - user_app_data->status = RET_OK; - (ZCL_CTX().device_cb)(param); - } - TRACE_MSG(TRACE_ZCL1, "< zcl_ota_upgrade_srv_upgrade_aborted_invoke_user_app", - (FMT__0)); -} - -static zb_ret_t zcl_ota_upgrade_srv_upgrade_end_invoke_user_app( - zb_uint8_t param, zb_zcl_addr_t *zcl_addr, zb_uint8_t status, - zb_uint16_t image_type, zb_uint32_t version, zb_uint32_t *upgrade_time) -{ - zb_ret_t ret; - - TRACE_MSG(TRACE_ZCL1, "> zcl_ota_upgrade_srv_upgrade_end_invoke_user_app, param %hd", - (FMT__H, param)); - ret = RET_NOT_FOUND; - if (ZCL_CTX().device_cb) - { - zb_zcl_device_callback_param_t *user_app_data; - zb_zcl_ota_upgrade_srv_upgrade_end_param_t *value; - - user_app_data = ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - value = &user_app_data->cb_param.ota_upgrade_srv_upgrade_end_param; - value->zcl_addr = zcl_addr; - value->status = status; - value->image_type = image_type; - value->version = version; - value->upgrade_time = upgrade_time; - user_app_data->device_cb_id = ZB_ZCL_OTA_UPGRADE_SRV_UPGRADE_END_CB_ID; - user_app_data->endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, ZB_ZCL_CLUSTER_CLIENT_ROLE); - (ZCL_CTX().device_cb)(param); - ret = user_app_data->status; - } - TRACE_MSG(TRACE_ZCL1, "< zcl_ota_upgrade_srv_upgrade_end_invoke_user_app, ret %hd", - (FMT__H, ret)); - return ret; -} - - -static zb_bool_t zb_zcl_process_ota_srv_upgrade_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t status = RET_OK; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_ota_upgrade_specific_commands: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE == cmd_info.cluster_id); - - switch( cmd_info.cmd_id ) - { - case ZB_ZCL_CMD_OTA_UPGRADE_QUERY_NEXT_IMAGE_ID: - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - status = query_next_image_handler(param); - break; - - case ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_BLOCK_ID: - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - status = image_block_handler(param); - break; -/* // not release yet - case ZB_ZCL_CMD_OTA_UPGRADE_IMAGE_PAGE_ID: - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - status = image_page_handler(param); - break; -*/ - case ZB_ZCL_CMD_OTA_UPGRADE_UPGRADE_END_ID: - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - status = upgrade_end_handler(param); - break; - - case ZB_ZCL_CMD_OTA_UPGRADE_QUERY_SPECIFIC_FILE_ID: - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - status = query_specific_file_handler(param); - break; - - /* Called from zb_zcl_handle_default_response_commands->zb_zcl_process_ota_upgrade_default_response_commands->zb_zcl_handle_general_commands */ - case ZB_ZCL_CMD_DEFAULT_RESP: - /* This is not a normal call to specific commands processing. - This is a replacement of direct call from zb_zcl_handle_default_response_commands(). - It made to exclude OTA code linking if OTA cluster is not declared by the app. - */ - return (zb_bool_t)zb_zcl_process_ota_upgrade_default_response_commands(param); - break; - - default: - processed = ZB_FALSE; - break; - } - - if( processed ) - { - if( (ZB_NWK_IS_ADDRESS_BROADCAST(cmd_info.addr_data.common_data.dst_addr) || - (cmd_info.disable_default_response)) && status == RET_OK) - { - TRACE_MSG( TRACE_ZCL3, "Default response disabled", (FMT__0)); - zb_buf_free(param); - } - else if (status != RET_BUSY) - { - ZB_ZCL_SEND_DEFAULT_RESP_DIRECTION( param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_OTA_UPGRADE, - cmd_info.seq_number, - cmd_info.cmd_id, - (status==RET_OK ? ZB_ZCL_STATUS_SUCCESS : - (status==RET_INVALID_PARAMETER_2 ? ZB_ZCL_STATUS_MALFORMED_CMD : - ZB_ZCL_STATUS_INVALID_FIELD)), - (ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction ? - ZB_ZCL_FRAME_DIRECTION_TO_SRV : - ZB_ZCL_FRAME_DIRECTION_TO_CLI)); - } - } - - TRACE_MSG( TRACE_ZCL1, - "< zb_zcl_process_ota_upgrade_specific_commands: processed %d", - (FMT__D, processed)); - return processed; -} - -zb_bool_t zb_zcl_process_ota_upgrade_specific_commands_srv(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_ota_upgrade_server_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_ota_srv_upgrade_specific_commands(param); -} - -/** - * @} internal -*/ - -#endif /* defined ZB_HA_ENABLE_OTA_UPGRADE_SERVER || defined DOXYGEN */ - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE */ diff --git a/zboss/development/src/zcl/zcl_poll_control_client.c b/zboss/development/src/zcl/zcl_poll_control_client.c deleted file mode 100644 index da40f87d7b..0000000000 --- a/zboss/development/src/zcl/zcl_poll_control_client.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: poll control cluster implementation, client role -*/ - -#define ZB_TRACE_FILE_ID 2077 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL) - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_poll_control.h" - -zb_uint8_t gs_poll_control_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_POLL_CONTROL_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_poll_control_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_POLL_CONTROL_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_poll_control_client_cmd_list = -{ - sizeof(gs_poll_control_client_received_commands), gs_poll_control_client_received_commands, - sizeof(gs_poll_control_client_generated_commands), gs_poll_control_client_generated_commands -}; - -void zb_zcl_set_fast_poll_timeout(zb_uint8_t ep, zb_uint16_t fast_poll_timeout) -{ - zb_zcl_attr_t *attr_desc; - zb_zcl_poll_control_client_status_t *client_data; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_set_fast_poll_timeout ep %hd, timeout %d", - (FMT__H_D, ep, fast_poll_timeout)); - - attr_desc = zb_zcl_get_attr_desc_a( - ep, ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_STATUS_DATA_ID); - ZB_ASSERT(attr_desc); - client_data = (zb_zcl_poll_control_client_status_t*)attr_desc->data_p; - - client_data->fast_poll_timeout = fast_poll_timeout; - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_set_fast_poll_timeout", (FMT__0)); -} - -/** @brief Stop fast poll and schedule next Check-in command */ -static void zb_zcl_poll_control_stop_fast_poll_client(zb_uint8_t endpoint) -{ - zb_zcl_attr_t *attr_desc; - zb_zcl_poll_control_client_status_t *client_data; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_poll_control_stop_fast_poll_client %hx", (FMT__H, endpoint)); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_STATUS_DATA_ID); - ZB_ASSERT(attr_desc); - client_data = (zb_zcl_poll_control_client_status_t*)attr_desc->data_p; - - client_data->is_poll_mode = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_poll_control_stop_fast_poll_client", (FMT__0)); -} - -/** @brief Check-in command */ -static zb_ret_t check_in_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - zb_zcl_poll_control_client_status_t *client_data; - zb_zcl_attr_t *attr_desc; - zb_bool_t start_fast_poll; - zb_uint16_t timeout; - - TRACE_MSG(TRACE_ZCL1, "> check_in_handler param %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_CLIENT_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_STATUS_DATA_ID); - ZB_ASSERT(attr_desc); - client_data = (zb_zcl_poll_control_client_status_t*)attr_desc->data_p; - - /* If client in poll mode we won't start fast poll, else - ask user app */ - start_fast_poll = ZB_FALSE; - timeout = 0; - - if (!client_data->is_poll_mode) - { - zb_ret_t cb_result; - - ZB_ZCL_POLL_CONTROL_CLI_CALL_USER_APP( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - client_data->fast_poll_timeout, - cb_result); - - if (cb_result == RET_OK) - { - start_fast_poll = ZB_TRUE; - timeout = client_data->fast_poll_timeout; - } - } - - ZB_ZCL_POLL_CONTROL_SEND_CHECK_IN_RES( - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_FALSE, - NULL /*zb_zcl_poll_control_fast_pool_stop_scheduler*/, - start_fast_poll, - timeout); - - client_data->is_poll_mode = start_fast_poll; - - if (start_fast_poll) - { - /* Schedule fast poll stop */ - ZB_SCHEDULE_ALARM(zb_zcl_poll_control_stop_fast_poll_client, endpoint, - ZB_QUARTERECONDS_TO_BEACON_INTERVAL(client_data->fast_poll_timeout)); - } - - ret = RET_BUSY; /* not need send answer yet */ - - TRACE_MSG(TRACE_ZCL1, "< check_in_handler %hx", (FMT__H, ret)); - return ret; -} - -/* specific commands handling - client side */ -zb_bool_t zb_zcl_process_poll_control_specific_commands_cli(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t status = RET_OK; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_poll_control_client_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_poll_control_specific_commands_cli: param %hd, cmd %hd", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_POLL_CONTROL == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_CLI == cmd_info.cmd_direction); - - switch( cmd_info.cmd_id ) - { - case ZB_ZCL_CMD_POLL_CONTROL_CHECK_IN_ID: - status = check_in_handler(param); - break; - - default: - processed = ZB_FALSE; - break; - } - - if( processed ) - { - if( cmd_info.disable_default_response && status == RET_OK) - { - TRACE_MSG( TRACE_ZCL3, - "Default response disabled", - (FMT__0)); - zb_buf_free(param); - } - else if (status != RET_BUSY) - { - ZB_ZCL_SEND_DEFAULT_RESP( param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, - cmd_info.seq_number, - cmd_info.cmd_id, - status==RET_OK ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_INVALID_FIELD); - } - } - - TRACE_MSG( TRACE_ZCL1, - "< zb_zcl_process_poll_control_specific_commands_cli: processed %d", - (FMT__D, processed)); - return processed; -} - -void zb_zcl_poll_control_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_poll_control_specific_commands_cli); -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL*/ diff --git a/zboss/development/src/zcl/zcl_poll_control_commands.c b/zboss/development/src/zcl/zcl_poll_control_commands.c deleted file mode 100644 index ed6b42769c..0000000000 --- a/zboss/development/src/zcl/zcl_poll_control_commands.c +++ /dev/null @@ -1,1263 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Poll Control cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2078 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL) - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zb_aps.h" -#include "zb_watchdog.h" -#include "zcl/zb_zcl_poll_control.h" -#include "zdo_wwah_stubs.h" -/** @internal - @{ -*/ - -zb_uint8_t gs_poll_control_server_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_POLL_CONTROL_SERVER_ROLE_GENERATED_CMD_LIST -}; - -zb_uint8_t gs_poll_control_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_POLL_CONTROL_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_poll_control_server_cmd_list = -{ - sizeof(gs_poll_control_server_received_commands), gs_poll_control_server_received_commands, - sizeof(gs_poll_control_server_generated_commands), gs_poll_control_server_generated_commands -}; - -zb_ret_t check_value_poll_control_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -static void zb_zcl_poll_control_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -zb_bool_t zb_zcl_process_poll_control_specific_commands_srv(zb_uint8_t param); - -void zb_zcl_poll_control_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_poll_control_server, - zb_zcl_poll_control_write_attr_hook_server, - zb_zcl_process_poll_control_specific_commands_srv); -} - -zb_ret_t check_value_poll_control_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_bool_t ret = ZB_TRUE; - zb_ret_t ret_val = RET_ERROR; - zb_zcl_attr_t *attr_desc; - zb_uint32_t value32 = 0; - zb_uint16_t value16 = 0; - ZB_ASSIGN_UINT32(&value32, value); - ZB_ASSIGN_UINT16(&value16, value); - - TRACE_MSG(TRACE_ZCL1, "> check_value_poll_control_server", (FMT__0)); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID: - if (ZB_ZCL_POLL_CONTROL_CHECKIN_INTERVAL_NO_CHECK_IN_VALUE == value32) - { - TRACE_MSG(TRACE_ZCL2, "no Check-in value", (FMT__0)); - ret = ZB_TRUE; - } - else - { - ret = (value32 <= ZB_ZCL_POLL_CONTROL_CHECKIN_INTERVAL_MAX_VALUE) - ? ZB_TRUE : ZB_FALSE; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_MIN_CHECKIN_INTERVAL_ID); - if ( attr_desc != NULL ) - { - zb_uint32_t min_value = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - TRACE_MSG(TRACE_ZCL2, "min val %ld", (FMT__L, min_value)); - ret &= value32 >= min_value; - } - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID); - if ( attr_desc != NULL ) - { - zb_uint32_t long_poll = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - TRACE_MSG(TRACE_ZCL2, "long_poll %ld", (FMT__L, long_poll)); - ret &= value32 >= long_poll; - } - } - break; - - case ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID: - ret = (ZB_ZCL_POLL_CONTROL_LONG_POLL_INTERVAL_MIN_VALUE <= value32) && - (value32 <= ZB_ZCL_POLL_CONTROL_LONG_POLL_INTERVAL_MAX_VALUE) - ? ZB_TRUE : ZB_FALSE; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_MIN_INTERVAL_ID); - if ( attr_desc != NULL ) - { - zb_uint32_t poll_min = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - TRACE_MSG(TRACE_ZCL2, "min val %ld", (FMT__L, poll_min)); - ret &= poll_min <= value32; - } - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID); - if ( attr_desc != NULL ) - { - zb_uint32_t check_in_interval = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - TRACE_MSG(TRACE_ZCL2, "check_in_interval %ld", (FMT__L, check_in_interval)); - ret &= value32 <= check_in_interval; - } - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID); - if ( attr_desc != NULL ) - { - zb_uint16_t short_poll_interval = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - TRACE_MSG(TRACE_ZCL2, "short_poll_interval %ld", (FMT__L, short_poll_interval)); - ret &= short_poll_interval <= value32; - } - - break; - - case ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID: - ret = (ZB_ZCL_POLL_CONTROL_SHORT_POLL_INTERVAL_MIN_VALUE <= value16) - ? ZB_TRUE : ZB_FALSE; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID); - if ( attr_desc != NULL ) - { - zb_uint32_t long_poll = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - TRACE_MSG(TRACE_ZCL2, "long_poll %ld", (FMT__L, long_poll)); - ret &= value16 <= long_poll; - } - break; - - case ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_TIMEOUT_ID: - ret = (ZB_ZCL_POLL_CONTROL_FAST_POLL_TIMEOUT_MIN_VALUE <= value16) - ? ZB_TRUE : ZB_FALSE; - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_MAX_TIMEOUT_ID); - if ( attr_desc != NULL ) - { - zb_uint16_t poll_max = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - TRACE_MSG(TRACE_ZCL2, "val %d min val %d max val %d", (FMT__D_D_D, - value16, ZB_ZCL_POLL_CONTROL_FAST_POLL_TIMEOUT_MIN_VALUE, poll_max)); - /* According to CCB#1815: if FastPollTimeout > FastPollTimeoutMax server - * should return INVALID_VALUE. - * See url: old.Zigbee.org/en/members_area/CCB/list.asp?&NoLimit=true&NoLimit=true - * for more details. - */ - ret &= value16 <= poll_max; - } - TRACE_MSG(TRACE_ZCL2, "val %d", (FMT__D, value16)); - break; - - default: - break; - } - - if (ret) - { - ret_val = RET_OK; - } - TRACE_MSG(TRACE_ZCL1, "< check_value_poll_control_server ret %hd", (FMT__H, ret_val)); - return ret_val; -} - -#if defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN -#define ZB_CHECK_IN_NO_RESPONSE_INTERVAL_MS 7680 -#define ZB_CHECK_IN_NO_RESPONSE_INTERVAL ZB_MILLISECONDS_TO_BEACON_INTERVAL(ZB_CHECK_IN_NO_RESPONSE_INTERVAL_MS) - -// for devices with Poll control cluster and without OTA cluster -#ifndef ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL -#define ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL 0x00 -#endif - - -void zb_zcl_poll_control_check_in_non_response(zb_uint8_t endpoint); - -static void poll_control_check_binding(zb_bufid_t param, - zb_uint8_t src_endpoint, - zb_callback_t cb); - -void zb_zcl_poll_controll_register_cb(zb_callback_t cb) -{ - TRACE_MSG(TRACE_ZCL1, "zb_zcl_poll_controll_register_cb cb %p", (FMT__P, cb)); - - ZCL_CTX().checkin_cb = cb; -} - - -/** @brief Restart check-in cycle with passed interval - * @param param - buffer to be used, if 0, buffer will be acquired when needed - * @param new_checkin_interval_qsec - new checkin interval (in quarterseconds) to be applied */ -static void zb_zcl_poll_control_start_internal(zb_uint8_t param, zb_uint32_t new_checkin_interval_qsec) -{ - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_poll_control_start_internal param %hx new_interval %li", - (FMT__H_L, param, new_checkin_interval_qsec)); -#ifdef ZB_USE_CHECKIN_WATCHDOG - { - zb_uint32_t checkin_wd_interval = ZB_QUARTERECONDS_TO_BEACON_INTERVAL(new_checkin_interval_qsec)*3; - if (checkin_wd_interval < ZB_WD_CHECKIN_MIN_TO) - { - checkin_wd_interval = ZB_WD_CHECKIN_MIN_TO; - } - zb_add_watchdog(ZB_WD_CHECKIN, checkin_wd_interval); - } -#endif - - if (param != 0U) - { - zb_buf_free(param); - } - - /* Param is not reused here to prevent buffer blocking for pretty long check-in interval */ - ZB_SCHEDULE_ALARM(zb_zcl_poll_control_start_check_in, 0, ZB_QUARTERECONDS_TO_BEACON_INTERVAL(new_checkin_interval_qsec)); - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_poll_control_start_internal", (FMT__0)); -} - - -/** @brief Start check-ins cycle with interval taken from Poll Control Cluster - * @param param - buffer to be used for check-in command - * @param endpoint - endpoint on which check-ins should be started */ -void zb_zcl_poll_control_start(zb_uint8_t param, zb_uint8_t endpoint) -{ - zb_zcl_attr_t *attr_desc; - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_poll_control_start param %hx endpoint %hx", (FMT__H_H, param, endpoint)); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_POLL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID); - ZB_ASSERT(attr_desc); - - zb_zcl_poll_control_start_internal(param, ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc)); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_poll_control_start", (FMT__0)); -} - - -/** @brief Stop check-ins */ -zb_uint8_t zb_zcl_poll_control_stop(void) -{ - zb_uint8_t canceled_param = 0; - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_poll_control_stop", (FMT__0)); - ZB_SCHEDULE_ALARM_CANCEL_AND_GET_BUF( - zb_zcl_poll_control_start_check_in, ZB_ALARM_ANY_PARAM, &canceled_param); - -#ifdef ZB_USE_CHECKIN_WATCHDOG - zb_stop_watchdog(ZB_WD_CHECKIN); -#endif - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_poll_control_stop", (FMT__0)); - return canceled_param; -} - -/** @brief Hook on Write Check-in Interval attribute - * send Check-in if change Check-in interval & Check-in remain time > new check-in interval */ -void write_attr_check_in_interval_hook(zb_uint8_t endpoint, zb_uint8_t *new_value_ptr) -{ - zb_time_t time_alarm; - zb_time_t new_interval; - zb_uint32_t new_val; - zb_uint8_t canceled_param = 0; - zb_ret_t ret; - - ZVUNUSED(endpoint); - - TRACE_MSG(TRACE_ZCL1, "> write_attr_check_in_interval_hook endpoint %hx", - (FMT__H, endpoint)); - - ZB_MEMCPY(&new_val, new_value_ptr, sizeof(zb_uint32_t)); - new_interval = ZB_QUARTERECONDS_TO_BEACON_INTERVAL(new_val); - ZVUNUSED(new_interval); - - ret = ZB_SCHEDULE_GET_ALARM_TIME(zb_zcl_poll_control_start_check_in, ZB_ALARM_ANY_PARAM, &time_alarm); - - if (ret == RET_OK) - { - /* HA specification changed: re-start check-in unconditionally */ - - canceled_param = zb_zcl_poll_control_stop(); - TRACE_MSG(TRACE_APP1, "new check in value %ld", (FMT__L, new_val)); - /* If zero check-in interval is set - stop polling */ - if (new_val != ZB_ZCL_POLL_CONTROL_CHECKIN_INTERVAL_NO_CHECK_IN_VALUE) - { - /* re-use buffer specified by canceled_param */ - TRACE_MSG(TRACE_APP2, "call start_check_in with new interval", (FMT__0)); - zb_zcl_poll_control_start_internal(canceled_param, new_val); - } - else - { - /* free buffer - it is not re-used */ - TRACE_MSG(TRACE_APP2, "skip rescheduling check-in", (FMT__0)); - if (canceled_param) - { - TRACE_MSG(TRACE_APP2, "free canceled buffer %hd", (FMT__H, canceled_param)); - zb_buf_free(canceled_param); - } - } - } - else - { - TRACE_MSG(TRACE_ZCL2, "cant find alarm, skip", (FMT__0)); - } - - TRACE_MSG(TRACE_ZCL1, "< write_attr_check_in_interval_hook", (FMT__0)); -} - - -static void poll_control_send_default_response(zb_bufid_t param, - zb_zcl_parsed_hdr_t *cmd_info, - zb_zcl_status_t status) -{ - if (cmd_info->disable_default_response && status == ZB_ZCL_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL2, "Default response disabled", (FMT__0)); - zb_buf_free(param); - } - else - { - TRACE_MSG(TRACE_ZCL2, "Send DefaultResponse, status %xd", (FMT__D, status)); - ZB_ZCL_SEND_DEFAULT_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, - cmd_info->seq_number, - cmd_info->cmd_id, - status); - } -} - - -static zb_size_t get_aligned_size(zb_size_t size) -{ - return ((size + ZB_BUF_ALLOC_ALIGN - 1) / ZB_BUF_ALLOC_ALIGN) * ZB_BUF_ALLOC_ALIGN; -} - -static void check_in_res_handler_pack_params(zb_bufid_t param, - zb_zcl_poll_control_check_in_res_t *payload, - zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_size_t payload_size_aligned = get_aligned_size(sizeof(*payload)); - zb_size_t params_size = payload_size_aligned + sizeof(*cmd_info); - zb_uint8_t *ptr = NULL; - - ptr = zb_buf_initial_alloc(param, params_size); - - ZB_MEMCPY(ptr, payload, sizeof(*payload)); - ptr += payload_size_aligned; - - ZB_MEMCPY(ptr, cmd_info, sizeof(*cmd_info)); -} - - -static void check_in_res_handler_unpack_params(zb_bufid_t param, - zb_zcl_poll_control_check_in_res_t *payload, - zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_size_t payload_size_aligned = get_aligned_size(sizeof(*payload)); - zb_uint8_t *ptr = NULL; - - ptr = zb_buf_begin(param); - - ZB_MEMCPY(payload, ptr, sizeof(*payload)); - ptr += payload_size_aligned; - - ZB_MEMCPY(cmd_info, ptr, sizeof(*cmd_info)); -} - - -static void check_in_res_handler_check_binding_response_cb(zb_bufid_t param) -{ - zb_zcl_poll_control_check_in_res_t payload; - zb_zcl_parsed_hdr_t cmd_info = { 0 }; - zb_aps_check_binding_resp_t *check_binding_resp = NULL; - zb_zcl_status_t status = ZB_ZCL_STATUS_SUCCESS; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL2, ">> check_in_res_handler_check_binding_response_cb, param %d", - (FMT__D, param)); - - check_binding_resp = ZB_BUF_GET_PARAM(param, zb_aps_check_binding_resp_t); - - /* - ZCL8: If the Poll Control Server receives a Check-In Response from a client - for which there is no binding (unbound), it SHOULD respond with a Default Response - with a status value indicating FAILURE. - */ - if (!check_binding_resp->exists) - { - status = (zb_zcl_get_backward_compatible_statuses_mode() == ZB_ZCL_STATUSES_ZCL8_MODE) ? - ZB_ZCL_STATUS_FAIL : ZB_ZCL_STATUS_ACTION_DENIED; - } - - if (status == ZB_ZCL_STATUS_SUCCESS) - { - check_in_res_handler_unpack_params(param, &payload, &cmd_info); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - } - - /* - ZCL8: If the Poll Control Server receives a Check-In Response from a bound client - after temporary fast poll mode is completed it SHOULD respond with a Default Response - with a status value indicating FAILURE. - */ - if (status == ZB_ZCL_STATUS_SUCCESS) - { - zb_time_t tmp; - zb_ret_t ret; - - ret = ZB_SCHEDULE_GET_ALARM_TIME(zb_zcl_poll_control_check_in_non_response, endpoint, &tmp); - - if (ret != RET_OK) - { - status = ZB_ZCL_STATUS_FAIL; - } - } - - if (status == ZB_ZCL_STATUS_SUCCESS) - { - /* Cancel default Check-in loop (7.68 sec) */ - /* - [AV] This doesn't cancel default Check-in loop; next check-in stays scheduled! - FIXME: cancel start_check_in here? - */ - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_poll_control_check_in_non_response, endpoint); - - if(payload.is_start) - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_TIMEOUT_ID); - zb_time_t new_interval = ZB_QUARTERECONDS_TO_MSEC(payload.timeout); - - if (!new_interval) - { - ZB_ASSERT(attr_desc); - new_interval = ZB_QUARTERECONDS_TO_MSEC(ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc)); - } - zb_zdo_pim_stop_fast_poll(0); - zb_zdo_pim_set_fast_poll_timeout(new_interval); - zb_zdo_pim_start_fast_poll(0); - } - else - { - zb_zdo_pim_stop_fast_poll(0); - } - -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER - zb_zcl_wwah_bad_parent_recovery_signal(ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_OK); -#endif - } - - poll_control_send_default_response(param, &cmd_info, status); - - TRACE_MSG(TRACE_ZCL2, "<< check_in_res_handler_check_binding_response_cb", (FMT__0)); -} - - -/** @brief Check-in response command */ -static zb_ret_t check_in_res_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_poll_control_check_in_res_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - /* zb_zcl_poll_control_server_status_t *server_data; */ - - TRACE_MSG(TRACE_ZCL1, "> check_in_res_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - ZB_ZCL_POLL_CONTROL_GET_CHECK_IN_RES(&payload, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_POLL_CONTROL_GET_CHECK_IN_RES", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - - /* - ZCL8: If the Poll Control Server receives a Check-In Response from a client - for which there is no binding (unbound), it SHOULD respond with a Default Response - with a status value indicating FAILURE. - */ - if (ret == RET_OK) - { - check_in_res_handler_pack_params(param, &payload, &cmd_info); - poll_control_check_binding(param, - endpoint, - check_in_res_handler_check_binding_response_cb); - ret = RET_BUSY; - } - - - TRACE_MSG(TRACE_ZCL1, "< check_in_res_handler ret %hx", (FMT__H, ret)); - return ret; -} - - -#ifndef ZB_COORDINATOR_ONLY -static void fast_poll_stop_handler_send_default_response(zb_uint8_t param) -{ - /* ZCL8: Table 2-12. Enumerated Command Status Values: - * ACTION_DENIED is DEPRECATED: use FAILURE - */ - zb_zcl_status_t status = (zb_zcl_get_backward_compatible_statuses_mode() == ZB_ZCL_STATUSES_ZCL8_MODE) ? - ZB_ZCL_STATUS_FAIL : ZB_ZCL_STATUS_ACTION_DENIED; - zb_zdo_pim_stop_fast_poll_extended_resp_t *resp = ZB_BUF_GET_PARAM(param, zb_zdo_pim_stop_fast_poll_extended_resp_t); - zb_zcl_parsed_hdr_t *cmd_info = NULL; - - if (resp->stop_result == ZB_ZDO_PIM_STOP_FAST_POLL_RESULT_STOPPED) - { - status = ZB_ZCL_STATUS_SUCCESS; - } - - cmd_info = (zb_zcl_parsed_hdr_t*)zb_buf_begin(param); - poll_control_send_default_response(param, cmd_info, status); -} -#endif - - -static void fast_poll_stop_handler_check_binding_response_cb(zb_bufid_t param) -{ - zb_aps_check_binding_resp_t *check_binding_resp = NULL; - - TRACE_MSG(TRACE_ZCL2, ">> fast_poll_stop_handler_check_binding_response_cb, param %d", - (FMT__D, param)); - - check_binding_resp = ZB_BUF_GET_PARAM(param, zb_aps_check_binding_resp_t); - - if (check_binding_resp->exists) - { - /* - ZCL8: If the Poll Control Server is unable to stop fast - polling due to the fact that there is another bound client - which has requested that polling continue - it SHOULD respond with a Default Response with a status value - indicating FAILURE - */ - /* - So call stop_fast_poll anyway to decrement internal counter - and then recheck if we are still in fast poll and send - FAILURE in such case - */ - - zb_zdo_pim_stop_fast_poll_extended_req(param, fast_poll_stop_handler_send_default_response); - } - else - { - zb_zcl_parsed_hdr_t *cmd_info = NULL; - - cmd_info = (zb_zcl_parsed_hdr_t*)zb_buf_begin(param); - /* ZCL8: Table 2-12. Enumerated Command Status Values: - * ACTION_DENIED is DEPRECATED: use FAILURE - */ - poll_control_send_default_response(param, cmd_info, (zb_zcl_get_backward_compatible_statuses_mode() == ZB_ZCL_STATUSES_ZCL8_MODE) ? - ZB_ZCL_STATUS_FAIL : ZB_ZCL_STATUS_ACTION_DENIED); - } - - TRACE_MSG(TRACE_ZCL2, "<< fast_poll_stop_handler_check_binding_response_cb", (FMT__0)); -} - - -/** @brief fast_poll_stop command */ -static zb_ret_t fast_poll_stop_handler(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = NULL; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> fast_poll_stop_handler %hx", (FMT__H, param)); - - /* copy cmd_info so we can use it to send a response later */ - cmd_info = zb_buf_initial_alloc(param, sizeof(zb_zcl_parsed_hdr_t)); - ZB_MEMCPY(cmd_info, - ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), - sizeof(zb_zcl_parsed_hdr_t)); - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint; - - TRACE_MSG(TRACE_ZCL2, "call poll_control_check_binding", (FMT__0)); - poll_control_check_binding(param, endpoint, fast_poll_stop_handler_check_binding_response_cb); - - TRACE_MSG(TRACE_ZCL1, "< fast_poll_stop_handler", (FMT__0)); - - return RET_BUSY; -} - -/** @brief Set Long Poll Interval command */ -static zb_ret_t set_long_poll_interval_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_poll_control_set_long_poll_interval_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> set_long_poll_interval_handler param %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - ZB_ZCL_POLL_CONTROL_GET_SET_LONG_POLL_INTERVAL_REQ(&payload, param, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_POLL_CONTROL_GET_SET_LONG_POLL_INTERVAL_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if( /*!*/zb_zcl_check_attr_value(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, endpoint, - ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID, (zb_uint8_t*)(&payload.interval)) == RET_ERROR) - { - /* TODO: DO NOT send Default response here - do it in the - * zb_zcl_process_poll_control_specific_commands() */ - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - TRACE_MSG(TRACE_ZCL1, "set RET_BUSY", (FMT__0)); - } - else - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID); - ZB_ASSERT(attr_desc); - TRACE_MSG(TRACE_ZCL2, "payload.interval %hx", (FMT__L, payload.interval)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, payload.interval); - - zb_zdo_pim_set_long_poll_interval(ZB_QUARTERECONDS_TO_MSEC(payload.interval)); -#ifdef ZB_USE_NVRAM - ZB_SCHEDULE_CALLBACK(zb_zcl_poll_control_save_nvram, 0); -#endif - } - - TRACE_MSG(TRACE_ZCL1, "< set_long_poll_interval_handler ret %hx", (FMT__H, ret)); - return ret; -} - -/** @brief Set Short Poll Interval command */ -static zb_ret_t set_short_poll_interval_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_poll_control_set_short_poll_interval_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, "> set_short_poll_interval_handler param %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - - - ZB_ZCL_POLL_CONTROL_GET_SET_SHORT_POLL_INTERVAL_REQ(&payload, param, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_POLL_CONTROL_GET_SET_SHORT_POLL_INTERVAL_REQ", - (FMT__0)); - ret = RET_INVALID_PARAMETER_1; - } - else if( /*!*/zb_zcl_check_attr_value(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, endpoint, - ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID, (zb_uint8_t*)(&payload.interval)) == RET_ERROR) - { - ZB_ZCL_PROCESS_COMMAND_FINISH(param, &cmd_info, ZB_ZCL_STATUS_INVALID_VALUE); - ret = RET_BUSY; // not need send answer yet - } - else - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID); - ZB_ASSERT(attr_desc); - TRACE_MSG(TRACE_ZCL2, "payload.interval %hx", (FMT__D, payload.interval)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, payload.interval); - - zb_zdo_pim_set_fast_poll_interval(ZB_QUARTERECONDS_TO_MSEC(payload.interval)); -#ifdef ZB_USE_NVRAM - ZB_SCHEDULE_CALLBACK(zb_zcl_poll_control_save_nvram, 0); -#endif - } - - TRACE_MSG(TRACE_ZCL1, "< set_short_poll_interval_handler ret %hx", (FMT__H, ret)); - return ret; -} - -/* specific commands handling - server side */ -zb_bool_t zb_zcl_process_poll_control_specific_commands_srv(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t status = RET_OK; - zb_zcl_status_t resp_code; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_poll_control_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_poll_control_specific_commands_srv: param %hd, cmd %hd", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_POLL_CONTROL == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - switch( cmd_info.cmd_id ) - { - case ZB_ZCL_CMD_POLL_CONTROL_CHECK_IN_RESPONSE_ID: - status = check_in_res_handler(param); - break; - - case ZB_ZCL_CMD_POLL_CONTROL_FAST_POLL_STOP_ID: - status = fast_poll_stop_handler(param); - break; - - case ZB_ZCL_CMD_POLL_CONTROL_SET_LONG_POLL_INTERVAL_ID: - status = set_long_poll_interval_handler(param); - break; - - case ZB_ZCL_CMD_POLL_CONTROL_SET_SHORT_POLL_INTERVAL_ID: - status = set_short_poll_interval_handler(param); - break; - - default: - processed = ZB_FALSE; - break; - } - - if (processed && status != RET_BUSY) - { - switch (status) - { - case RET_OK: - resp_code = ZB_ZCL_STATUS_SUCCESS; - break; - - /* ZCL8: Table 2-12. Enumerated Command Status Values: - * ACTION_DENIED is DEPRECATED: use FAILURE - */ - case RET_INVALID_STATE: - resp_code = (zb_zcl_get_backward_compatible_statuses_mode() == ZB_ZCL_STATUSES_ZCL8_MODE) ? - ZB_ZCL_STATUS_FAIL : ZB_ZCL_STATUS_ACTION_DENIED; - break; - - case RET_TIMEOUT: - resp_code = ZB_ZCL_STATUS_TIMEOUT; - break; - - default: - resp_code = ZB_ZCL_STATUS_INVALID_FIELD; - break; - } - - poll_control_send_default_response(param, &cmd_info, resp_code); - } - - TRACE_MSG( TRACE_ZCL1, - "< zb_zcl_process_poll_control_specific_commands_srv: processed %d", - (FMT__D, processed)); - return processed; -} - - -/** @brief Run Check-in command if Check in Response not receive - * */ -void zb_zcl_poll_control_check_in_non_response(zb_uint8_t endpoint) -{ - ZVUNUSED(endpoint); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_poll_control_check_in_non_response endpoint %hd", (FMT__H, endpoint)); - - /* MA: return to Long Poll */ - zb_zdo_pim_stop_fast_poll(0); - -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER - zb_zcl_wwah_bad_parent_recovery_signal(ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED); -#endif - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_poll_control_check_in_non_response", (FMT__0)); -} - - -void zcl_poll_control_check_in_send_cb(zb_uint8_t param) -{ - zb_uint8_t endpoint; - zb_zcl_attr_t *attr_desc; - zb_zcl_poll_control_srv_cfg_data_t *addr_data; - zb_zcl_command_send_status_t *cmd_send_status = ZB_BUF_GET_PARAM(param, zb_zcl_command_send_status_t); - - - TRACE_MSG(TRACE_ZCL1, "> zcl_poll_control_check_in_send_cb", (FMT__0)); - - TRACE_MSG(TRACE_ZCL1, "check-in cmd send status %hd, param %hd", - (FMT__H_H, cmd_send_status->status, param)); - - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE); - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_ADDR_DATA_ID); - ZB_ASSERT(attr_desc); - addr_data = (zb_zcl_poll_control_srv_cfg_data_t*)attr_desc->data_p; - - if (cmd_send_status->status == 0) - { - /* Restart only in case of successful APS ACK reception */ - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_poll_control_check_in_non_response, endpoint); - /* Don't increment pkt number, it's been already done while - * sending - only move deadline */ - TRACE_MSG(TRACE_ZDO3, "Call zb_zdo_pim_start_turbo_poll_packets 0", (FMT__0)); - zb_zdo_pim_start_turbo_poll_packets(0); - ZB_SCHEDULE_ALARM(zb_zcl_poll_control_check_in_non_response, endpoint, ZB_CHECK_IN_NO_RESPONSE_INTERVAL); - } - - /* - sending_cmd cases: - sending_cmd == 0: no command is sending now - sending_cmd == 1: command sending is in progress - sending_cmd > 1: check-in timeout expired while trying to send - check-in command or somehow we were trying to send the next - check-in commang - */ - TRACE_MSG(TRACE_ZCL1, "sending_cmd %hd", (FMT__H, addr_data->sending_cmd)); - if (addr_data->sending_cmd > 1) - { - ZB_SCHEDULE_CALLBACK(zb_zcl_poll_control_start_check_in, param); - } - else - { - zb_buf_free(param); - } - addr_data->sending_cmd = 0; - - TRACE_MSG(TRACE_ZCL1, "< zcl_poll_control_check_in_send_cb", (FMT__0)); -} - - -static void check_in_handle_check_binding_confirm(zb_bufid_t param) -{ - zb_aps_check_binding_resp_t *check_binding_resp = NULL; - zb_uint8_t endpoint; - zb_uint32_t checkin_interval; - zb_zcl_attr_t *attr_desc; - - TRACE_MSG(TRACE_ZDO2, ">> check_in_handle_check_binding_confirm, param %d", (FMT__D, param)); - - check_binding_resp = ZB_BUF_GET_PARAM(param, zb_aps_check_binding_resp_t); - - /* FIXME: potential problem in the case of multi EP device */ - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE); - ZB_ASSERT(endpoint); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, ZB_ZCL_CLUSTER_ID_POLL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID); - ZB_ASSERT(attr_desc); - - checkin_interval = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - TRACE_MSG(TRACE_ZCL2, "checkin_interval %hd", (FMT__H, checkin_interval)); - - if (check_binding_resp->exists) - { - zb_zcl_poll_control_srv_cfg_data_t *addr_data; - - zb_uint16_t dst_addr = 0; - zb_uint8_t dst_ep = 0; - zb_uint8_t addr_mode; - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POLL_CONTROL_ADDR_DATA_ID); - ZB_ASSERT(attr_desc); - - addr_data = (zb_zcl_poll_control_srv_cfg_data_t*)attr_desc->data_p; - TRACE_MSG(TRACE_ZCL2, "poll addr %d, poll ep %hd", (FMT__D_H, addr_data->poll_addr, addr_data->poll_ep)); - - if (addr_data->poll_addr == ZB_ZCL_POLL_CTRL_INVALID_ADDR && addr_data->poll_ep == ZB_ZCL_POLL_INVALID_EP) - { - TRACE_MSG(TRACE_ZCL2, "sending using binding", (FMT__0)); - addr_mode = ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; - } - else - { - TRACE_MSG(TRACE_ZCL2, "sending using short addr", (FMT__0)); - dst_addr = addr_data->poll_addr; - dst_ep = addr_data->poll_ep; - addr_mode = ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - } - - ZB_ZCL_POLL_CONTROL_SEND_CHECK_IN_REQ( - param, - dst_addr, addr_mode, dst_ep, - endpoint, ZB_AF_HA_PROFILE_ID, - zcl_poll_control_check_in_send_cb); - - /* Set a flag - we are sending checkin command */ - addr_data->sending_cmd = 1; - - ZB_SCHEDULE_ALARM(zb_zcl_poll_control_check_in_non_response, endpoint, ZB_CHECK_IN_NO_RESPONSE_INTERVAL); - - zb_zdo_pim_set_fast_poll_timeout(ZB_CHECK_IN_NO_RESPONSE_INTERVAL_MS); - zb_zdo_pim_start_fast_poll(0); - -#ifdef ZB_USE_CHECKIN_WATCHDOG - ZB_KICK_WATCHDOG(ZB_WD_CHECKIN); -#endif - - /* Go fast polling until check-in response comes or timeout fires - * ZB_CHECK_IN_NO_RESPONSE_INTERVAL */ - - if (ZCL_CTX().checkin_cb != NULL) - { - /* Call user callback during checking-in */ - ZB_SCHEDULE_CALLBACK(ZCL_CTX().checkin_cb, 0); - } - } - else - { - TRACE_MSG(TRACE_ZCL2, "skip and reschedule check in - no binding", (FMT__0)); - - /* param is not reused intentionally to prevent buffer blocking - * during whole check-in alarm interval */ - zb_buf_free(param); - } - - /* Schedule next Check-in command */ - ZB_SCHEDULE_ALARM(zb_zcl_poll_control_start_check_in, 0, ZB_QUARTERECONDS_TO_BEACON_INTERVAL(checkin_interval)); - - TRACE_MSG(TRACE_ZDO2, "<< check_in_handle_check_binding_confirm", (FMT__0)); -} - - -static void poll_control_check_binding(zb_bufid_t param, - zb_uint8_t src_endpoint, - zb_callback_t cb) -{ - zb_aps_check_binding_req_t *check_binding_req = NULL; - TRACE_MSG(TRACE_ZCL2, ">> poll_control_check_binding, param %d, src ep %d, cb %p", - (FMT__D_D_P, param, src_endpoint, cb)); - - check_binding_req = ZB_BUF_GET_PARAM(param, zb_aps_check_binding_req_t); - ZB_BZERO(check_binding_req, sizeof(*check_binding_req)); - - check_binding_req->src_endpoint = src_endpoint; - check_binding_req->cluster_id = ZB_ZCL_CLUSTER_ID_POLL_CONTROL; - check_binding_req->response_cb = cb; - - zb_aps_check_binding_request(param); - - TRACE_MSG(TRACE_ZCL2, "<< poll_control_check_binding", (FMT__0)); -} - - -/** @brief Start Check-in command - * Get buffer - * Get endpoint for Poll Control Cluster - * Send Check-in command - * Schedule default next Check-in (7.68 sec) - * */ -void zb_zcl_poll_control_start_check_in(zb_uint8_t param) -{ - zb_zcl_attr_t *attr_desc; - zb_uint8_t endpoint; - zb_uint32_t checkin_interval; - zb_zcl_poll_control_srv_cfg_data_t *addr_data; -#ifdef ZB_ZCL_NO_CHECKINS_DURING_OTA - zb_uint8_t ota_status = ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL; -#endif - zb_bool_t skip_check_in = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_poll_control_start_check_in, param %hd", (FMT__H, param)); - - /* FIXME: potential problem in the case of multi EP device */ - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE); - ZB_ASSERT(endpoint); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, ZB_ZCL_CLUSTER_ID_POLL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID); - ZB_ASSERT(attr_desc); - - checkin_interval = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - TRACE_MSG(TRACE_ZCL1, "checkin_interval %hd", (FMT__H, checkin_interval)); - - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POLL_CONTROL_ADDR_DATA_ID); - ZB_ASSERT(attr_desc); - addr_data = (zb_zcl_poll_control_srv_cfg_data_t*)attr_desc->data_p; - -#ifdef ZB_ZCL_NO_CHECKINS_DURING_OTA -#ifdef ZB_ZCL_SUPPORT_CLUSTER_OTA_UPGRADE - { - zb_uint8_t endpoint_ota; - - endpoint_ota = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_OTA_UPGRADE); - if (endpoint_ota != 0) - { - /* OTA link problem! Forcing OTA code link always */ - ota_status = zb_zcl_ota_upgrade_get_ota_status(endpoint_ota); - } - else - { - ota_status = ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL; - } - } -#endif - - TRACE_MSG(TRACE_ZCL1, "ota_status %hd checkin_interval %hd", - (FMT__H_H, ota_status, checkin_interval)); -#endif - - if (checkin_interval == ZB_ZCL_POLL_CONTROL_CHECKIN_INTERVAL_NO_CHECK_IN_VALUE) - { - TRACE_MSG(TRACE_ZCL1, "skip check in - zero interval", (FMT__0)); - skip_check_in = ZB_TRUE; - } -#ifdef ZB_ZCL_NO_CHECKINS_DURING_OTA - else if (ota_status != ZB_ZCL_OTA_UPGRADE_IMAGE_STATUS_NORMAL) - { - TRACE_MSG(TRACE_ZCL1, "skip check in - OTA is in progress", (FMT__0)); - skip_check_in = ZB_TRUE; - /* reschedule the next check-in iteration, otherwise it will stop */ - ZB_SCHEDULE_ALARM(zb_zcl_poll_control_start_check_in, 0, - ZB_QUARTERECONDS_TO_BEACON_INTERVAL(checkin_interval)); - } -#endif - else - { - TRACE_MSG(TRACE_ZCL1, "continue... sending_cmd %hd", (FMT__H, addr_data->sending_cmd)); - /* check flag, it is non-zero if check-in command is being sent now */ - if (addr_data->sending_cmd > 0) - { - TRACE_MSG(TRACE_ZCL1, "Currently sending Check-in cmd, skip", (FMT__0)); - if (addr_data->sending_cmd < 2) - { - addr_data->sending_cmd++; - } - skip_check_in = ZB_TRUE; - } - } - - if (skip_check_in == ZB_FALSE && param == 0) - { - TRACE_MSG(TRACE_ZCL2, "will call zb_get_out_buf_delayed", (FMT__0)); - zb_buf_get_out_delayed(zb_zcl_poll_control_start_check_in); - } - else if (skip_check_in == ZB_FALSE) - { - TRACE_MSG(TRACE_ZCL2, "call poll_control_check_binding", (FMT__0)); - poll_control_check_binding(param, - ZB_ZCL_BROADCAST_ENDPOINT, - check_in_handle_check_binding_confirm); - } - else - { - TRACE_MSG(TRACE_ZCL2, "skip check in...", (FMT__0)); - if (param != 0) - { - TRACE_MSG(TRACE_ZCL2, "free buf %hd", (FMT__H, param)); - zb_buf_free(param); - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_poll_control_start_check_in", (FMT__0)); -} - -#endif /* defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN */ - - -/** @brief Save NVRAM by write attribute - */ -#ifdef ZB_USE_NVRAM -void zb_zcl_poll_control_save_nvram(zb_uint8_t param) -{ - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_poll_control_save_nvram", (FMT__0)); - /* If we fail, trace is given and assertion is triggered */ - (void)zb_nvram_write_dataset(ZB_NVRAM_HA_POLL_CONTROL_DATA); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_poll_control_save_nvram", (FMT__0)); -} -#endif /* ZB_USE_NVRAM */ - -/** @brief Hook on Write attribute - * send Check-in if change Check-in interval & Check-in remain time > new check-in interval */ -static void zb_zcl_poll_control_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value) -{ - zb_uint32_t new_val = 0; -/* 07/08/2019 EE CR:MAJOR LE/BE conversion? Is there a problem of local/remote attr write? */ - ZB_MEMCPY(&new_val, new_value, sizeof(zb_uint32_t)); - - (void)endpoint; - (void)attr_id; - (void)new_value; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_poll_control_write_attr_hook endpoint %hx attr_id %d", - (FMT__H_D, endpoint, attr_id)); - -#if defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN - if(attr_id==ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID) - { - write_attr_check_in_interval_hook(endpoint, new_value); - } - else if (attr_id==ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID) - { - zb_zdo_pim_set_long_poll_interval(ZB_QUARTERECONDS_TO_MSEC(new_val)); - } - else if (attr_id==ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID) - { - zb_zdo_pim_set_fast_poll_interval(ZB_QUARTERECONDS_TO_MSEC(new_val)); - } -#ifdef ZB_USE_NVRAM - TRACE_MSG(TRACE_ZCL1, "check if nvram save is needed", (FMT__0)); - if(attr_id==ZB_ZCL_ATTR_POLL_CONTROL_CHECKIN_INTERVAL_ID - || attr_id==ZB_ZCL_ATTR_POLL_CONTROL_LONG_POLL_INTERVAL_ID - || attr_id==ZB_ZCL_ATTR_POLL_CONTROL_SHORT_POLL_INTERVAL_ID - || attr_id==ZB_ZCL_ATTR_POLL_CONTROL_FAST_POLL_TIMEOUT_ID) - { - TRACE_MSG(TRACE_ZCL1, "schedule nvram save", (FMT__0)); - ZB_SCHEDULE_CALLBACK(zb_zcl_poll_control_save_nvram, 0); - } -#endif /* ZB_USE_NVRAM */ -#endif /* defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN */ - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_poll_control_write_attr_hook", (FMT__0)); -} - - -#if defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN -zb_ret_t zb_zcl_poll_control_set_client_addr(zb_uint8_t local_ep, zb_uint16_t addr, zb_uint8_t ep) -{ - zb_zcl_attr_t *attr_desc; - zb_zcl_poll_control_srv_cfg_data_t *addr_data; - zb_ret_t ret; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_poll_control_set_client_addr local_ep %hd, addr %d, endpoint %hd", - (FMT__H_D_H, local_ep, addr, ep)); - /* See Use Trust Center for Cluster Command */ - if (ZB_ZDO_CHECK_CLUSTER_PERMISSION(addr, ZB_ZCL_CLUSTER_ID_POLL_CONTROL)) - { - attr_desc = zb_zcl_get_attr_desc_a( - local_ep, - ZB_ZCL_CLUSTER_ID_POLL_CONTROL, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_POLL_CONTROL_ADDR_DATA_ID); - ZB_ASSERT(attr_desc); - addr_data = (zb_zcl_poll_control_srv_cfg_data_t*)attr_desc->data_p; - - addr_data->poll_addr = addr; - addr_data->poll_ep = ep; - ret = RET_OK; - } - else - { - ret = RET_ERROR; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_poll_control_set_client_addr", (FMT__0)); - return ret; -} -#endif /* defined ZB_HA_ENABLE_POLL_CONTROL_SERVER || defined DOXYGEN */ - -/** - * @} internal -*/ - -#if defined ZB_ENABLE_HA -/* -static zb_uint8_t gs_poll_control_cmd_list_srv[] = -{ - ZB_ZCL_CMD_POLL_CONTROL_CHECK_IN_ID -}; - -static zb_uint8_t gs_poll_control_cmd_list_cli[] = -{ - ZB_ZCL_CMD_POLL_CONTROL_CHECK_IN_RESPONSE_ID, - ZB_ZCL_CMD_POLL_CONTROL_FAST_POLL_STOP_ID, - ZB_ZCL_CMD_POLL_CONTROL_SET_LONG_POLL_INTERVAL_ID, - ZB_ZCL_CMD_POLL_CONTROL_SET_SHORT_POLL_INTERVAL_ID -}; -*/ -/* Returns supported commands list for receiving or generating */ -/* -zb_uint8_t zb_zcl_get_cmd_list_poll_control(zb_bool_t is_client_generated, zb_uint8_t **cmd_list) -{ - zb_uint8_t ret = 0; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_get_cmd_list_poll_control is_client_generated %hd", (FMT__H, is_client_generated)); - - if (is_client_generated) - { - *cmd_list = gs_poll_control_cmd_list_cli; - ret = sizeof(gs_poll_control_cmd_list_cli); - } - else - { - *cmd_list = gs_poll_control_cmd_list_srv; - ret = sizeof(gs_poll_control_cmd_list_srv); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_get_cmd_list_poll_control ret %hd", (FMT__H, ret)); - return ret; -} -*/ -#endif /* defined ZB_ENABLE_HA */ - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_POLL_CONTROL */ diff --git a/zboss/development/src/zcl/zcl_power_config_commands.c b/zboss/development/src/zcl/zcl_power_config_commands.c deleted file mode 100644 index 928167ae1d..0000000000 --- a/zboss/development/src/zcl/zcl_power_config_commands.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Power Configuration cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2079 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_POWER_CONFIG) - -#include "zb_time.h" -#include "zb_zdo.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_power_config.h" -#include "zcl/zb_zcl_alarms.h" - -/** @internal - @{ -*/ - -zb_ret_t check_value_power_config_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -void zb_zcl_power_config_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -void zb_zcl_power_config_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_power_config_server, - zb_zcl_power_config_write_attr_hook_server, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_power_config_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_power_config_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} - -/*Subtrahend to cast battery voltage attribute IDs to the simplified calculation view*/ -#define ZB_ZCL_POWER_CONFIG_BATTERY_VOLTAGE_ATTR_SUBTRAHEND 0x20 -/*Subtrahend to cast battery percentage remaining attribute IDs to the simplified calculation view*/ -#define ZB_ZCL_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ATTR_SUBTRAHEND 0x21 -/*The addend is needed for calculation alarm value from normalized attribute Id*/ -#define ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODES_ADDEND 0x20 - -/*Alarm State attribute shifts (ZCL spec Rev 7 3.3.2.2.4.11)*/ -#define ZB_ZCL_POWER_CONFIG_ALARM_STATE_ATTR_BATTERY_SOURCE_LSHIFT 0 -#define ZB_ZCL_POWER_CONFIG_ALARM_STATE_ATTR_BATTERY_SOURCE_2_LSHIFT 10 -#define ZB_ZCL_POWER_CONFIG_ALARM_STATE_ATTR_BATTERY_SOURCE_3_LSHIFT 20 - -/*The minuend for getting alarm mask value from normalized attribute ID*/ -#define ZB_ZCL_POWER_CONFIG_ALARM_MASKS_MINUEND 16 - -#define ZB_ZCL_CHECK_THRESHOLD_EXISTENCE(ep, attr_set, is_percentage) \ -{ \ - zb_zcl_attr_t *attr_desc_local; \ - attr_desc_local = zb_zcl_get_attr_desc_a( \ - ep, \ - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - (is_percentage) ? \ - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_MIN_THRESHOLD_ID): \ - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_MIN_THRESHOLD_ID)); \ - if (!attr_desc_local) \ - { \ - val &= ~ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_MIN_THRESHOLD; \ - } \ - attr_desc_local = zb_zcl_get_attr_desc_a( \ - ep, \ - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - (is_percentage) ? \ - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD1_ID): \ - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD1_ID)); \ - if (!attr_desc_local) \ - { \ - val &= ~ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE1; \ - } \ - attr_desc_local = zb_zcl_get_attr_desc_a( \ - ep, \ - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - (is_percentage) ? \ - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD2_ID): \ - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD2_ID)); \ - if (!attr_desc_local) \ - { \ - val &= ~ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE2; \ - } \ - attr_desc_local = zb_zcl_get_attr_desc_a( \ - ep, \ - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, \ - ZB_ZCL_CLUSTER_SERVER_ROLE, \ - (is_percentage) ? \ - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD3_ID): \ - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD3_ID)); \ - if (!attr_desc_local) \ - { \ - val &= ~ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE3; \ - } \ -} - -void fill_alarm_mask_bitmap(zb_uint8_t ep, enum zb_zcl_power_config_battery_alarm_state_e value, - zb_zcl_attr_t *attr_desc, zb_uint16_t attr_set, zb_bool_t is_percentage) -{ - if (attr_desc) - { - zb_uint8_t val = ZB_ZCL_POWER_CONFIG_ALARM_MASKS_MINUEND - value; - ZB_ZCL_CHECK_THRESHOLD_EXISTENCE(ep, attr_set, is_percentage); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, val); - } -} - -void fill_alarm_state_bitmap(zb_uint8_t ep, enum zb_zcl_power_config_battery_alarm_state_e value, - zb_zcl_attr_t *attr_desc, zb_uint16_t attr_set, zb_bool_t is_percentage) -{ - if (attr_desc) - { - zb_uint32_t attr_val = 0; - zb_uint8_t val = ZB_ZCL_POWER_CONFIG_ALARM_MASKS_MINUEND - value; - ZB_ZCL_CHECK_THRESHOLD_EXISTENCE(ep, attr_set, is_percentage); - if (attr_set == ZB_ZCL_POWER_CONFIG_BATTERY_ATTRIBUTE_SET) - { - attr_val = (zb_uint32_t)val << ZB_ZCL_POWER_CONFIG_ALARM_STATE_ATTR_BATTERY_SOURCE_LSHIFT; - } - else if (attr_set == ZB_ZCL_POWER_CONFIG_BATTERY_SOURCE_2_ATTRIBUTE_SET) - { - attr_val = (zb_uint32_t)val << ZB_ZCL_POWER_CONFIG_ALARM_STATE_ATTR_BATTERY_SOURCE_2_LSHIFT; - } - else if (attr_set == ZB_ZCL_POWER_CONFIG_BATTERY_SOURCE_3_ATTRIBUTE_SET) - { - attr_val = (zb_uint32_t)val << ZB_ZCL_POWER_CONFIG_ALARM_STATE_ATTR_BATTERY_SOURCE_3_LSHIFT; - } - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, attr_val); - } -} - -/* performs comparison taking into account hysteresis. Returns TRUE - * if voltage value goes lower then threshold */ -zb_bool_t zcl_pwr_value_under_threshold(zb_uint8_t voltage, zb_uint8_t threshold) -{ - zb_bool_t ret = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, "> zcl_pwr_value_under_threshold voltage %hd threshold %hd", - (FMT__H_H, voltage, threshold)); - - /* TODO: implement comparison taking into account hysteresis */ - if ((voltage < threshold) && (threshold != 0xff)) - { - ret = ZB_TRUE; - } - - TRACE_MSG(TRACE_ZCL1, "< zcl_pwr_value_under_threshold ret %hd", - (FMT__H, ret)); - return ret; -} - -void send_alarm(zb_uint8_t param) -{ - zb_bool_t ret = ZB_TRUE; - zb_uint16_t addr = 0; - zb_uint16_t *user_param = ZB_BUF_GET_PARAM(param, zb_uint16_t); - zb_uint8_t ep = *user_param; - zb_uint8_t alarm_code = *user_param >> 8; - - /* AN: For Mains Voltage it needs to check current value just before alarm sending one more time. - * Maybe Voltage has come back to the [Min Threshold; Max Threshold] range - */ - if ((alarm_code == ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD_ALARM_CODE) || - (alarm_code == ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD_ALARM_CODE)) - { - zb_zcl_attr_t *attr_desc; - zb_uint16_t val,threshold; - attr_desc = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_ID); - val = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - attr_desc = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (alarm_code == ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD_ALARM_CODE) ? - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD : - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD); - threshold = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - if (((alarm_code == ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD_ALARM_CODE) && (val >= threshold)) || - ((alarm_code == ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD_ALARM_CODE) && (val <= threshold)) || - (threshold == ZB_ZCL_POWER_CONFIG_THRESHOLD_ALARM_OMISSION_VALUE)) - { - ret = ZB_FALSE; - } - } - - if (ret) - { - ZB_ZCL_ALARMS_SEND_ALARM_RES( - param, - addr, - ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT, - 0, - ep, - ZB_AF_HA_PROFILE_ID, - NULL, alarm_code, ZB_ZCL_CLUSTER_ID_POWER_CONFIG); - } - else - { - zb_buf_free(param); - } -} - -void get_send_alarm_buf(zb_uint8_t param, zb_uint16_t user_param) -{ - if (!param) - { - zb_buf_get_out_delayed_ext(get_send_alarm_buf, user_param, 0); - } - else - { - zb_uint16_t dwell_period = 0; - zb_uint16_t *u_param = ZB_BUF_GET_PARAM(param, zb_uint16_t); - zb_zcl_attr_t *attr_desc = NULL; - *u_param = user_param; - attr_desc = zb_zcl_get_attr_desc_a( - (zb_uint8_t)user_param, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_DWELL_TRIP_POINT); - if (attr_desc && ((user_param >> 8 == ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD_ALARM_CODE) || - (user_param >> 8 == ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD_ALARM_CODE))) - { - dwell_period = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - } - zb_schedule_alarm(send_alarm, param, ZB_TIME_ONE_SECOND*dwell_period); - } -} - -void zcl_pwr_cfg_check_mains_voltage(zb_uint8_t ep, zb_uint16_t val) -{ - zb_bool_t ret = ZB_FALSE; - zb_zcl_attr_t *attr_desc; - zb_zcl_attr_t *attr_desc_mask; - zb_uint16_t threshold; - - attr_desc_mask = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_ALARM_MASK_ID); - - TRACE_MSG(TRACE_ZCL1, "> zcl_pwr_cfg_check_mains_voltage_value ep %hd, val %d", (FMT__H_D, ep, val)); - - if (attr_desc_mask) - { - attr_desc = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MIN_THRESHOLD); - if (attr_desc) - { - threshold = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - if (val < threshold && threshold != ZB_ZCL_POWER_CONFIG_THRESHOLD_ALARM_OMISSION_VALUE) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc_mask, ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_ALARM_CODE_MIN_THRESHOLD); - ret = ZB_TRUE; - } - } - if (!ret) - { - attr_desc = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_MAX_THRESHOLD); - if (attr_desc) - { - threshold = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - if (val > threshold && threshold != ZB_ZCL_POWER_CONFIG_THRESHOLD_ALARM_OMISSION_VALUE) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc_mask, ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_ALARM_CODE_MAX_THRESHOLD); - ret = ZB_TRUE; - } - } - } - if (ret) - { - zb_af_endpoint_desc_t* endpoint_desc = zb_af_get_endpoint_desc(ep); - zb_zcl_cluster_desc_t *cluster_desc = get_cluster_desc(endpoint_desc, ZB_ZCL_CLUSTER_ID_ALARMS, ZB_ZCL_CLUSTER_SERVER_ROLE); - if (cluster_desc) - { - zb_uint8_t alarm_mask = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_mask); - zb_uint16_t u_param = ( ((alarm_mask & ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_ALARM_CODE_MAX_THRESHOLD) ? - ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_ALARM_CODE_MAX_THRESHOLD : - ZB_ZCL_POWER_CONFIG_MAINS_VOLTAGE_ALARM_CODE_MIN_THRESHOLD)<< 8) | ep; - zb_buf_get_out_delayed_ext(get_send_alarm_buf, u_param, 0); - } - } - } -} - /* HA version of Power Configuration declares 3 sets of - * BatteryInformation and BatterySettings attr sets. This function - * is used to check new BATTERY_VOLTAGE attribute or BATTERY_PERCENTAGE_REMAINING - * value in attribute set defined by attr_set value and set BatteryAlarmState - * if any alarm appears (BatteryVoltageMinThreshold or other threshold check) - */ -void zcl_pwr_cfg_check_battery_voltage_or_percentage_value(zb_uint8_t ep, zb_uint8_t val, - zb_uint16_t attr_set, zb_bool_t is_percentage) -{ - zb_bool_t ret = ZB_FALSE; - zb_zcl_attr_t *attr_desc; - zb_zcl_attr_t *attr_desc_state; - zb_zcl_attr_t *attr_desc_mask; - zb_uint8_t threshold; - - TRACE_MSG(TRACE_ZCL1, "> zcl_pwr_cfg_check_val_value ep %hd, val %hd, attr_set %d", - (FMT__H_H_D, ep, val, attr_set)); - - attr_desc_state = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_ALARM_STATE_ID)); - - attr_desc_mask = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_ALARM_MASK_ID)); - - if (attr_desc_state) - { - /*** Check Min threshold value ***/ - attr_desc = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (is_percentage) ? - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_MIN_THRESHOLD_ID): - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_MIN_THRESHOLD_ID)); - if(attr_desc) - { - threshold = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - if (zcl_pwr_value_under_threshold(val, threshold)) - { - fill_alarm_state_bitmap(ep, ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_MIN_THRESHOLD, attr_desc_mask, attr_set, is_percentage); - if (attr_desc_mask) - { - fill_alarm_mask_bitmap(ep, ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_MIN_THRESHOLD, attr_desc_mask, attr_set, is_percentage); - } - ret = ZB_TRUE; - } - } - - /*** Check Threshold1 value ***/ - if (!ret) - { - attr_desc = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (is_percentage) ? - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD1_ID): - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD1_ID)); - if(attr_desc) - { - threshold = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - if (zcl_pwr_value_under_threshold(val, threshold)) - { - fill_alarm_state_bitmap(ep, ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE1, attr_desc_mask, attr_set, is_percentage); - if (attr_desc_mask) - { - fill_alarm_mask_bitmap(ep, ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE1, attr_desc_mask, attr_set, is_percentage); - } - ret = ZB_TRUE; - } - } - } - /*** Check Threshold2 value ***/ - if (!ret) - { - attr_desc = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (is_percentage) ? - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD2_ID): - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD2_ID)); - if(attr_desc) - { - threshold = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - if (zcl_pwr_value_under_threshold(val, threshold)) - { - fill_alarm_state_bitmap(ep, ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE2, attr_desc_mask, attr_set, is_percentage); - if (attr_desc_mask) - { - fill_alarm_mask_bitmap(ep, ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE2, attr_desc_mask, attr_set, is_percentage); - } - ret = ZB_TRUE; - } - } - } - - /*** Check Threshold3 value ***/ - if (!ret) - { - attr_desc = zb_zcl_get_attr_desc_a( - ep, - ZB_ZCL_CLUSTER_ID_POWER_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (is_percentage) ? - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_THRESHOLD3_ID): - (zb_uint16_t)(attr_set+ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_THRESHOLD3_ID)); - if(attr_desc) - { - threshold = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - if (zcl_pwr_value_under_threshold(val, threshold)) - { - fill_alarm_state_bitmap(ep, ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE3, attr_desc_mask, attr_set, is_percentage); - if (attr_desc_mask) - { - fill_alarm_mask_bitmap(ep, ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE3, attr_desc_mask, attr_set, is_percentage); - } - ret = ZB_TRUE; - } - } - } - if (ret) - { - if (attr_desc_mask) - { - zb_af_endpoint_desc_t* endpoint_desc = zb_af_get_endpoint_desc(ep); - zb_zcl_cluster_desc_t *cluster_desc = get_cluster_desc(endpoint_desc, ZB_ZCL_CLUSTER_ID_ALARMS, ZB_ZCL_CLUSTER_SERVER_ROLE); - if (cluster_desc) - { - zb_uint8_t alarm_mask = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_mask); - /* AN: Looks like, that we can send only one "the most significant" alarm. - * ZCL spec strongly requires (p. 3.3.2.2.4.8 BatteryVoltageThreshold 1-3 Attributes) - * that BatteryVoltageThresholdN+1 has to be higher than the BatteryVoltageThresholdN. - * - * ms-alarm - subtrahend with range [0;4]. It is needed for Alarm code "threshold" nibble (10*[0,1,2] + 4 - ms_alarm) - */ - zb_uint8_t ms_alarm = (alarm_mask & ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_MIN_THRESHOLD) ? 4 : ( - (alarm_mask & ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE1) ? 3 : ( - (alarm_mask & ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE2) ? 2 : ( - (alarm_mask & ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_STATE_SOURCE1_VOLTAGE3) ? 1 : 0 ))); - zb_uint16_t u_param = (((attr_set+ZB_ZCL_POWER_CONFIG_BATTERY_ALARM_CODES_ADDEND)/2 + (4-ms_alarm)) << 8) | ep; - zb_buf_get_out_delayed_ext(get_send_alarm_buf, u_param, 0); - } - } - } - - } - TRACE_MSG(TRACE_ZCL1, "< zcl_pwr_cfg_check_val_value ret %hd", (FMT__H, ret)); -} - -void zb_zcl_power_config_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_power_config_write_attr_hook endpoint %hx attr_id %d", - (FMT__H_D, endpoint, attr_id)); - - if (attr_id == ZB_ZCL_ATTR_POWER_CONFIG_MAINS_VOLTAGE_ID) - { - zb_uint16_t new_value_16 = ZB_ZCL_ATTR_GET16(new_value); - zcl_pwr_cfg_check_mains_voltage(endpoint, new_value_16); - } - if (attr_id == ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_ID || - attr_id == ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_VOLTAGE_ID || - attr_id == ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_VOLTAGE_ID) - { - zcl_pwr_cfg_check_battery_voltage_or_percentage_value(endpoint, *new_value, - attr_id-ZB_ZCL_POWER_CONFIG_BATTERY_VOLTAGE_ATTR_SUBTRAHEND, ZB_FALSE); - } - else if (attr_id == ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID || - attr_id == ZB_ZCL_ATTR_POWER_CONFIG_BATTERY2_PERCENTAGE_REMAINING_ID || - attr_id == ZB_ZCL_ATTR_POWER_CONFIG_BATTERY3_PERCENTAGE_REMAINING_ID) - { - zcl_pwr_cfg_check_battery_voltage_or_percentage_value(endpoint, *new_value, - attr_id-ZB_ZCL_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ATTR_SUBTRAHEND, ZB_TRUE); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_power_config_write_attr_hook", (FMT__0)); -} - -/** - * @} internal -*/ - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_POWER_CONFIG */ diff --git a/zboss/development/src/zcl/zcl_pressure_measurement.c b/zboss/development/src/zcl/zcl_pressure_measurement.c deleted file mode 100644 index 9ae22c719f..0000000000 --- a/zboss/development/src/zcl/zcl_pressure_measurement.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL: implements attribute values check -*/ - -#define ZB_TRACE_FILE_ID 5696 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_PRESSURE_MEASUREMENT) - -#include "zb_zcl.h" -#include "zb_aps.h" -#include "zcl/zb_zcl_common.h" - -zb_ret_t check_value_pressure_measurement_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -void zb_zcl_pressure_measurement_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -void zb_zcl_pressure_measurement_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_pressure_measurement_server, - zb_zcl_pressure_measurement_write_attr_hook_server, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_pressure_measurement_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_pressure_measurement_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - zb_int16_t val = ZB_ZCL_ATTR_GETS16(value); - - TRACE_MSG(TRACE_ZCL1, "> check_value_pressure_measurement, attr_id %d, val %d", - (FMT__D_D, attr_id, val)); - - switch (attr_id) - { - case ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID: - if (ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_UNKNOWN == val) - { - ret = RET_OK; - } - else - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_ID); - ZB_ASSERT(attr_desc); - - ret = (ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) == ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_INVALID || - ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) <= val) - ? RET_OK : RET_ERROR; - - if (ret) - { - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_ID); - ZB_ASSERT(attr_desc); - - ret = ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) == ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_INVALID || - val <= ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) - ? RET_OK : RET_ERROR; - } - } - break; - - case ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_ID: - ret = ((ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_MIN_VALUE <= val) && - (val <= ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_MAX_VALUE)) || - (ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_INVALID == val) - ? RET_OK : RET_ERROR; - break; - - case ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_ID: - ret = ((ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_MIN_VALUE <= val -#if ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_MAX_VALUE != 0x7fff - && val <= ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_MAX_VALUE -#endif - ) || (ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_INVALID == val)) - ? RET_OK : RET_ERROR; - break; - - /* TODO: Tolerance attrib and scaled attrib */ - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "< check_value_pressure_measurement ret %hd", (FMT__H, ret)); - return ret; -} - -void zb_zcl_pressure_measurement_write_attr_hook_server( - zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value) -{ - ZVUNUSED(new_value); - ZVUNUSED(endpoint); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_pressure_measurement_write_attr_hook endpoint %hd, attr_id %d", - (FMT__H_D, endpoint, attr_id)); - - /* All attributes in this cluster are read-only. Do nothing */ - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_pressure_measurement_write_attr_hook", (FMT__0)); -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_PRESSURE_MEASUREMENT */ diff --git a/zboss/development/src/zcl/zcl_rel_humidity.c b/zboss/development/src/zcl/zcl_rel_humidity.c deleted file mode 100644 index bee88dea48..0000000000 --- a/zboss/development/src/zcl/zcl_rel_humidity.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#define ZB_TRACE_FILE_ID 82 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_REL_HUMIDITY_MEASUREMENT) - -zb_ret_t check_value_rel_humidity_measurement_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_rel_humidity_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_rel_humidity_measurement_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_rel_humidity_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_rel_humidity_measurement_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> check_value_rel_humidity_measurement", (FMT__0)); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID: - if( ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_UNKNOWN == ZB_ZCL_ATTR_GET16(value) ) - { - ret = RET_OK; - } - else - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_ID); - - ZB_ASSERT(attr_desc); - - ret = (ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) == - ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_UNDEFINED - || ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) <= ZB_ZCL_ATTR_GET16(value)) - ? RET_OK : RET_ERROR; - - if(ret) - { - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID); - - ZB_ASSERT(attr_desc); - - ret = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) == ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_UNDEFINED || - ZB_ZCL_ATTR_GET16(value) <= ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) - ? RET_OK : RET_ERROR; - } - } - break; - - case ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_ID: - ret = ( -#if ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_MIN_VALUE != 0 - ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_MIN_VALUE <= ZB_ZCL_ATTR_GET16(value) && -#endif - (ZB_ZCL_ATTR_GET16(value) <= ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MIN_VALUE_MAX_VALUE) ) - ? RET_OK : RET_ERROR; - break; - - case ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID: - ret = ( (ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_MIN_VALUE <= ZB_ZCL_ATTR_GET16(value)) && - (ZB_ZCL_ATTR_GET16(value) <= ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_MAX_VALUE) ) - ? RET_OK : RET_ERROR; - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "< check_value_rel_humidity_measurement ret %hd", (FMT__H, ret)); - return ret; -} -#endif /* if defined (ZB_ZCL_SUPPORT_CLUSTER_REL_HUMIDITY_MEASUREMENT) */ diff --git a/zboss/development/src/zcl/zcl_reporting.c b/zboss/development/src/zcl/zcl_reporting.c deleted file mode 100644 index c816865d20..0000000000 --- a/zboss/development/src/zcl/zcl_reporting.c +++ /dev/null @@ -1,1607 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL, reporting functions implementation -*/ - -#define ZB_TRACE_FILE_ID 2080 - -#include "zb_common.h" - -#if defined(ZB_ENABLE_ZCL) && !(defined ZB_ZCL_DISABLE_REPORTING) - -#include "zb_zcl.h" -#include "zb_aps.h" -#include "zb_zdo.h" -#include "zcl/zb_zcl_common.h" -#include "zcl/zb_zcl_reporting.h" -#include "zb_nvram.h" - -#ifdef SWITCH_OFF_SOME_ZCL_TRACE -/* temporary switch trace off here */ -#undef TRACE_ZCL1 -#define TRACE_ZCL1 TRACE_MEM1 -#undef TRACE_ZCL2 -#define TRACE_ZCL2 TRACE_MEM2 -#undef TRACE_ZCL3 -#define TRACE_ZCL3 TRACE_MEM3 -#endif - -static zb_zcl_reporting_info_t* get_new_reporting_info(zb_uint8_t endpoint_id); - -#ifdef EXCLUDED_FROM_BUILD -static zb_uint8_t zb_zcl_mark_all_for_reporting(zb_uint8_t flag); -#endif - -static zb_bool_t check_delta_value(zb_zcl_reporting_info_t *rep_info); -static void start_wait_reporting_timer(zb_zcl_reporting_info_t *rep_info); -void zb_zcl_wait_reporting_timeout(zb_uint8_t param); -void zb_zcl_update_reporting_info(zb_zcl_reporting_info_t *rep_info); -void zb_zcl_adjust_reporting_timer(zb_uint8_t param); -void zb_zcl_reporting_timer_handler(zb_uint8_t param); -void zb_zcl_report_attr(zb_uint8_t param); - -/* - Reporting timeouts. - - Start 2 timers: - - start_reporting timer - it will mark all attributes - for reporting with max_interval timeout - - allow_reporting timer - it will mark all attributes as allowed for - reporting with min_interval timeout - - "allow_reporting" makes sense only for reporting caused by attribute - value change and it is not taken into account for periodic reporting. - - Note: it is possible that some attribute is reported because of its - value change and right after it - reported because of periodic - reporting. Suppose, it is not very often occasion and network will - not be overloaded because of it. - - - Timeout for getting report. - Functionality: check that some attribute is reported by remote with - some timeout period; if attribute report for specific attribute is - not received during , application is informed via - user callback no_reporting_cb. - On receiving attribute report, ZCL reporting logic is informed about - it and in wait_reporting_timer is restarted. To inform about report - receiving application should call zb_zcl_report_received(), it is - also called from default report attribute handler zb_zcl_report_attr_cmd_handler() - - - Sending reports - To prevent ZB stack overloading with packets to send, use the - following logic for sending reports: - - send 1 report at a time - - wait, until reporting command is sent (successfully or with error - doesn't metter), zb_zcl_reporting_cb() is called from - zb_apsde_data_acknowledged() - - when command send is confirmed, send another command - - to send next report, check reporting_info, find the first - attribute that should be reported and send report for it - - */ - - -/** @internal @brief Init reporting context - cancels all alarms and - * initializes timeouts */ -void zb_zcl_init_reporting_ctx() -{ - /* Allocate new buffer here... */ - zb_bufid_t buf; - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_init_reporting_ctx", (FMT__0)); - - ZB_BZERO(&ZCL_CTX().reporting_ctx, sizeof(zb_zcl_reporting_ctx_t)); - - /* FIXME: Do not lock the buf if we do not need to report anything... */ - buf = zb_buf_get_any(); - if (buf) - { - TRACE_MSG(TRACE_ZCL1, "Use %hd buffer for reporting", (FMT__H, buf)); - - ZCL_CTX().reporting_ctx.buf_ref = buf; - } - else - { - /* Empty buffer*/ - TRACE_MSG(TRACE_ERROR, "no free buf for reporting", (FMT__0)); - ZB_ASSERT(0); - } - - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_reporting_timer_handler, ZB_ALARM_ALL_CB); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_wait_reporting_timeout, ZB_ALARM_ALL_CB); - - TRACE_MSG(TRACE_ZCL1, "<>zb_zcl_reset_reporting_ctx", (FMT__0)); - - old_buf_ref = ZCL_CTX().reporting_ctx.buf_ref; - ZB_BZERO(&ZCL_CTX().reporting_ctx, sizeof(zb_zcl_reporting_ctx_t)); - ZCL_CTX().reporting_ctx.buf_ref = old_buf_ref; - - TRACE_MSG(TRACE_ZCL1, "Use old %hd buf_ref for reporting", (FMT__H, old_buf_ref)); - - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_reporting_timer_handler, ZB_ALARM_ALL_CB); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_wait_reporting_timeout, ZB_ALARM_ALL_CB); - - TRACE_MSG(TRACE_ZCL1, "<ep_count; i++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[i]->reporting_info) - { - ZB_BZERO(ZCL_CTX().device_ctx->ep_desc_list[i]->reporting_info, - sizeof(zb_zcl_reporting_info_t) * ZCL_CTX().device_ctx->ep_desc_list[i]->rep_info_count); - } - } - } -} - -zb_ret_t zb_zcl_put_reporting_info(zb_zcl_reporting_info_t* rep_info_ptr, zb_bool_t override) -{ - zb_zcl_reporting_info_t *rep_info; -/* 05/28/15 NK:CR {*/ - zb_af_endpoint_desc_t *ep_desc; - zb_zcl_cluster_desc_t *cluster_desc; - zb_zcl_attr_t *attr_desc; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_put_reporting_info", (FMT__0)); - - /* NK: Check if we support this attribute */ - ep_desc = zb_af_get_endpoint_desc(rep_info_ptr->ep); - /* TRICKY: If role is not set, assume server by default. */ - if (!rep_info_ptr->cluster_role) - { - rep_info_ptr->cluster_role = ZB_ZCL_CLUSTER_SERVER_ROLE; - } - cluster_desc = get_cluster_desc(ep_desc, rep_info_ptr->cluster_id, - rep_info_ptr->cluster_role); - attr_desc = zb_zcl_get_attr_desc(cluster_desc, rep_info_ptr->attr_id); - - if (attr_desc) - { - /* search for already registered configure reporting record */ - rep_info = zb_zcl_find_reporting_info( - rep_info_ptr->ep, - rep_info_ptr->cluster_id, - rep_info_ptr->cluster_role, - rep_info_ptr->attr_id); - - /* New reporting configuration may overrule an existing reporting configuration (probably - * configured by a peer). Check if overriding is allowed. */ - if (rep_info && !override) - { - /* not allowed - reporting already configured */ - return RET_ALREADY_EXISTS; - } - - if (!rep_info) - { - rep_info = get_new_reporting_info(rep_info_ptr->ep); - } - - if (rep_info) - { - if (rep_info->u.send_info.def_max_interval != 0 && - rep_info->u.send_info.def_max_interval < rep_info->u.send_info.def_min_interval) - { - return RET_INVALID_PARAMETER_1; - } - - ZB_MEMCPY(rep_info, rep_info_ptr, sizeof(zb_zcl_reporting_info_t)); - ZB_ZCL_CLR_ALL_REPORTING_FLAGS(rep_info); - - rep_info->u.send_info.min_interval = rep_info->u.send_info.def_min_interval; - rep_info->u.send_info.max_interval = rep_info->u.send_info.def_max_interval; - - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY); - - /* Set reported_value to 0xff - it is most likely not the default value and not the first change - for the attribute. - Rationale: we do not have a flag to check is it first or non-first report. Furthermore, we - do reporting checks AFTER applying new value to attribute. Because of that, if first - attribute change is to the value equal to initial reported_value (it is 0), this change - will not be reportable. - 0xff value is invalid for the most of attributes, so looks like it is more safe to use. - */ - ZB_MEMSET(&rep_info->u.send_info.reported_value, -1, sizeof(union zb_zcl_attr_var_u)); - - if (rep_info->direction == ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT) - { - if (rep_info->u.send_info.max_interval == ZB_ZCL_REPORTING_NOT_NEEDED) - { - TRACE_MSG(TRACE_ZCL3, "clear reporting info", (FMT__0)); - - /* Remember that we don't send reports by default */ - ZB_ZCL_CLR_ALL_REPORTING_FLAGS(rep_info); - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY); - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP); - } -#ifdef ZB_USE_NVRAM - /* WARNING: This function may be called from zb_zcl_put_default_reporting_info_for_cluster() - * BEFORE NVRAM init, in such case we do not need to write anything to NVRAM. - * This is default reporting configuration inited every startup, so it is ok NOT to store - * it in NVRAM. - * Note that it WILL be stored (or overwritten and stored) if application (locally or - * remotely via ZCL API) will configure the reporting (this will be done AFTER NVRAM - * init). This is also ok - default reporting will be CONFIGURED to defaults here (before - * NVRAM init) and than OVERWRITTEN by NVRAM loading procedure. */ - if (ZB_NVRAM().inited) - { - /* If we fail, trace is given and assertion is triggered */ - (void)zb_nvram_write_dataset(ZB_NVRAM_ZCL_REPORTING_DATA); - } -#endif - if (!ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP)) - { - zb_zcl_update_reporting_info(rep_info); - zb_zcl_adjust_reporting_timer(0); - /* Mark attr for reporting - we need to send first report with min interval. */ - /* [AN] 3/3/2020 maybe we should report only in case, when maximum interval is non-zero*/ - if (rep_info->u.send_info.max_interval) - { - zb_zcl_mark_attr_for_reporting(rep_info->ep, rep_info->cluster_id, rep_info->cluster_role, rep_info->attr_id); - } - } - } - else - { - TRACE_MSG(TRACE_ZCL3, "accept wait reporting timeout %d", (FMT__D, rep_info->u.recv_info.timeout)); - start_wait_reporting_timer(rep_info); - - if (rep_info->u.recv_info.timeout == ZB_ZCL_TIMEOUT_ZERO) - { - TRACE_MSG(TRACE_ZCL3, "cancel wait reporting", (FMT__0)); - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY); - } - } - } - else - { - TRACE_MSG(TRACE_ERROR, "Error, no free slots for reporting info", (FMT__0)); - return RET_NO_MEMORY/* no memory */; - } - } - else - { - TRACE_MSG(TRACE_ERROR, "Error, attribute not found", (FMT__0)); - return RET_NOT_FOUND; - } -/* 05/28/15 NK:CR }*/ - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_put_reporting_info", (FMT__0)); - return RET_OK /* success */; -} - -void zb_zcl_put_default_reporting_info_for_cluster(zb_uint8_t endpoint, zb_uint16_t profile_id, struct zb_zcl_cluster_desc_s *cluster_desc) -{ - zb_zcl_reporting_info_t rep_info; - zb_zcl_attr_t *attr_desc; - zb_uint16_t i = 0; - - ZB_ASSERT(cluster_desc); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_put_default_reporting_info_for_cluster cluster_id 0x%x", (FMT__D, cluster_desc->cluster_id)); - - attr_desc = cluster_desc->attr_desc_list; - - if (attr_desc) - { - ZB_BZERO(&rep_info, sizeof(rep_info)); - - rep_info.direction = ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT; - rep_info.ep = endpoint; - rep_info.cluster_id = cluster_desc->cluster_id; - rep_info.cluster_role = cluster_desc->role_mask; - rep_info.dst.profile_id = profile_id; - - rep_info.u.send_info.def_min_interval = ZB_ZCL_MIN_REPORTING_INTERVAL_DEFAULT; - rep_info.u.send_info.def_max_interval = ZB_ZCL_MAX_REPORTING_INTERVAL_DEFAULT; - - ZB_BZERO(&rep_info.u.send_info.delta, sizeof(union zb_zcl_attr_var_u)); - - while (attr_desc) - { - if (attr_desc->access & ZB_ZCL_ATTR_ACCESS_REPORTING) - { - TRACE_MSG(TRACE_ZCL3, "Attribute with id: 0x%x supports reporting, configure...", - (FMT__D, attr_desc->id)); - - rep_info.attr_id = attr_desc->id; - - if (zb_zcl_is_analog_data_type(attr_desc->type)) - { - ZB_BZERO(&rep_info.u.send_info.delta, - zb_zcl_get_analog_attribute_size(attr_desc->type)); - } - - zb_zcl_put_reporting_info(&rep_info, ZB_FALSE); - } - - i++; - attr_desc++; - if (i >= cluster_desc->attr_count) - { - attr_desc = NULL; - break; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_put_default_reporting_info_for_cluster", (FMT__0)); -} - -/** @internal @brief Put reporting information to device contexts - @param cmd_info - command information - @param config_rep_req - configure reporting command - @return RET_OK on success, error code otherwise -*/ - -zb_ret_t zb_zcl_put_reporting_info_from_req(zb_zcl_configure_reporting_req_t *config_rep_req, - zb_zcl_attr_addr_info_t* attr_addr_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_reporting_info_t *rep_info; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_put_reporting_info_from_req config_rep_req %p", - (FMT__P, config_rep_req)); - - ZB_ASSERT(config_rep_req); - ZB_ASSERT(attr_addr_info); - - /* search for already registered configure reporting record */ - rep_info = zb_zcl_find_reporting_info( - attr_addr_info->src_ep, - attr_addr_info->cluster_id, - attr_addr_info->cluster_role, - config_rep_req->attr_id); - - if (!rep_info) - { - /* get free slot to store configure reporting record */ - rep_info = get_new_reporting_info(attr_addr_info->src_ep); - if (rep_info) - { - ZB_BZERO(rep_info, sizeof(zb_zcl_reporting_info_t)); - } - } - - TRACE_MSG(TRACE_ZCL3, "rep_info %p", (FMT__P, rep_info)); - if (rep_info) - { - /* Clear old reporting flags (if any) */ - ZB_ZCL_CLR_ALL_REPORTING_FLAGS(rep_info); - - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY); - /* We can't use 0xff as reported value, it can be default value for reportable attribute. - E.g RMSVoltage attribute of Electrical measurement cluster - So, let's use ZB_ZCL_REPORT_IS_FIRST flag for this purpose - */ - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_FIRST); - rep_info->direction = config_rep_req->direction; - rep_info->ep = attr_addr_info->src_ep; - TRACE_MSG(TRACE_ZCL3, "put_reporting_info ep %i", (FMT__H, rep_info->ep)); - rep_info->cluster_id = attr_addr_info->cluster_id; - rep_info->cluster_role = attr_addr_info->cluster_role; - rep_info->attr_id = config_rep_req->attr_id; - - rep_info->dst.short_addr = attr_addr_info->dst_short_addr; - rep_info->dst.endpoint = attr_addr_info->dst_ep; - rep_info->dst.profile_id = attr_addr_info->profile_id; - - TRACE_MSG(TRACE_ZCL3, "direction %hd", (FMT__H, rep_info->direction)); - if (rep_info->direction == ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT) - { - /* - ZCL 6.0 2.5.7.1.6: Maximum Reporting Interval Field - If this value is set to 0x0000 and the minimum reporting interval field equals 0xffff, - then the device SHALL revert back to its default reporting configuration. - The reportable change field, if present, SHALL be set to zero. - */ - /* - Report records are not deleted now, when report is not needed, - REPORT_STOP is set instead to save default configuration; - that's why we suppose default configs to be actual here - */ - if (config_rep_req->u.clnt.min_interval == ZB_ZCL_REPORTING_NOT_NEEDED - && config_rep_req->u.clnt.max_interval == ZB_ZCL_TIMEOUT_ZERO) - { - TRACE_MSG(TRACE_ZCL3, "restore default reporting config", (FMT__0)); - - rep_info->u.send_info.min_interval = rep_info->u.send_info.def_min_interval; - rep_info->u.send_info.max_interval = rep_info->u.send_info.def_max_interval; - - if (zb_zcl_is_analog_data_type(config_rep_req->u.clnt.attr_type)) - { - ZB_BZERO(&rep_info->u.send_info.delta, - zb_zcl_get_analog_attribute_size(config_rep_req->u.clnt.attr_type)); - } - - TRACE_MSG(TRACE_ZCL3, "min interval %d max interval %d", (FMT__D_D, rep_info->u.send_info.def_min_interval, rep_info->u.send_info.def_max_interval)); - } - else - { - rep_info->u.send_info.min_interval = config_rep_req->u.clnt.min_interval; - rep_info->u.send_info.max_interval = config_rep_req->u.clnt.max_interval; - - if (zb_zcl_is_analog_data_type(config_rep_req->u.clnt.attr_type)) - { - ZB_MEMCPY(&rep_info->u.send_info.delta, config_rep_req->u.clnt.delta, - zb_zcl_get_analog_attribute_size(config_rep_req->u.clnt.attr_type)); - } - } - - - if (rep_info->u.send_info.max_interval == ZB_ZCL_REPORTING_NOT_NEEDED) - { - TRACE_MSG(TRACE_ZCL3, "clear reporting info", (FMT__0)); - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP); - } - else - { - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP); - zb_zcl_update_reporting_info(rep_info); - zb_zcl_adjust_reporting_timer(0); - /* Mark attr for reporting - we need to send first report with min interval. */ - /* [AN] 3/3/2020 maybe we should report only in case, when maximum interval is non-zero*/ - if (rep_info->u.send_info.max_interval) - { - zb_zcl_mark_attr_for_reporting(rep_info->ep, rep_info->cluster_id, rep_info->cluster_role, rep_info->attr_id); - } - } -#ifdef ZB_USE_NVRAM - /* If we fail, trace is given and assertion is triggered */ - (void)zb_nvram_write_dataset(ZB_NVRAM_ZCL_REPORTING_DATA); -#endif - } - else - { - TRACE_MSG(TRACE_ZCL3, "accept wait reporting timeout %d", (FMT__D, rep_info->u.recv_info.timeout)); - rep_info->u.recv_info.timeout = config_rep_req->u.srv.timeout; - start_wait_reporting_timer(rep_info); - - if (config_rep_req->u.srv.timeout == ZB_ZCL_TIMEOUT_ZERO) - { - TRACE_MSG(TRACE_ZCL3, "cancel wait reporting", (FMT__0)); - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY); - } - } - /* NK: TODO: Call reporting_cb here - configure some parameters on device if needed. */ - } - else - { - TRACE_MSG(TRACE_ERROR, "Error, no free slots for reporting info", (FMT__0)); - ret = RET_NO_MEMORY; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_put_reporting_info_from_req ret %hd", (FMT__H, ret)); - return ret; -} - -/*! Returns slot number of the reporting info */ -zb_uint8_t zb_zcl_reporting_slot_number(zb_zcl_reporting_info_t *rep_info) -{ - /* assign maxuint to return ZB_ZCL_UNDEFINED_REPORTING_SLOT if no ctx/arg */ - zb_uindex_t i = (zb_uindex_t)~0; - zb_uint8_t slot_num = 0; - - if (rep_info && ZCL_CTX().device_ctx) - { - for (i = 0; i < ZCL_CTX().device_ctx->ep_count; i++) - { - if (rep_info->ep != ZCL_CTX().device_ctx->ep_desc_list[i]->ep_id) - { - slot_num += ZB_ZCL_MAX_REPORTING_SLOTS_BY_EP; /* ZCL_CTX().device_ctx->ep_desc_list[i]->rep_info_count */ - } - else - { - slot_num += rep_info - ZCL_CTX().device_ctx->ep_desc_list[i]->reporting_info; - break; - } - } - } - - return (i < ZCL_CTX().device_ctx->ep_count) ? slot_num : ZB_ZCL_UNDEFINED_REPORTING_SLOT; -} - -/*! Returns reporting info that is stored in slot with specified number */ -zb_zcl_reporting_info_t *zb_zcl_get_reporting_info(zb_uint8_t slot_number) -{ - zb_uindex_t i; - - if (slot_number != ZB_ZCL_UNDEFINED_REPORTING_SLOT && ZCL_CTX().device_ctx) - { - for (i = 0; i < ZCL_CTX().device_ctx->ep_count; i++) - { - if (slot_number >= ZB_ZCL_MAX_REPORTING_SLOTS_BY_EP) - { - slot_number -= ZB_ZCL_MAX_REPORTING_SLOTS_BY_EP; - } - else - { - return (zb_zcl_reporting_info_t *)(ZCL_CTX().device_ctx->ep_desc_list[i]->reporting_info + slot_number); - } - } - } - - return NULL; -} - -static void start_wait_reporting_timer(zb_zcl_reporting_info_t *rep_info) -{ - TRACE_MSG(TRACE_ZCL1, "start_wait_reporting_timer %p, timeout %d", - (FMT__P_D, rep_info, rep_info->u.recv_info.timeout)); - - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_wait_reporting_timeout, zb_zcl_reporting_slot_number(rep_info)); - - if (rep_info->u.recv_info.timeout != ZB_ZCL_TIMEOUT_ZERO) - { - ZB_SCHEDULE_ALARM(zb_zcl_wait_reporting_timeout, zb_zcl_reporting_slot_number(rep_info), - rep_info->u.recv_info.timeout * ZB_TIME_ONE_SECOND); - } -} - -void zb_zcl_update_reporting_info(zb_zcl_reporting_info_t *rep_info) -{ - zb_uint16_t delay_time = ZB_ZCL_INVALID_TIMEOUT; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_update_reporting_info rep_info %p, min_interval %d, max_interval %d ep %hd", - (FMT__P_D_D_H, rep_info, rep_info->u.send_info.min_interval, rep_info->u.send_info.max_interval, rep_info->ep)); - - /* Firstly, check minimal interval */ - if (rep_info->u.send_info.min_interval != ZB_ZCL_TIMEOUT_ZERO) - { - TRACE_MSG(TRACE_ZCL2, "delay for min_interval", (FMT__0)); - delay_time = rep_info->u.send_info.min_interval; - } - else - { - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_ALLOWED); - - /* Check ZB_ZCL_REPORT_ATTR flag -> it may be already set - * while waiting for reporting buffer freeing */ - if (!ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR)) - { - if (rep_info->u.send_info.max_interval != ZB_ZCL_TIMEOUT_ZERO) - { - TRACE_MSG(TRACE_ZCL2, "delay for max_interval", (FMT__0)); - delay_time = rep_info->u.send_info.max_interval; - } - else - { - /* Non-periodic reporting - do nothing */ - TRACE_MSG(TRACE_ZCL2, "Non-periodic rep_info", (FMT__0)); - } - } - else - { - /* Do not reschedule zb_zcl_report_attr() - it'll be rescheduled - * in zb_zcl_reporting_cb */ - TRACE_MSG(TRACE_ZCL2, "Non-periodic rep_info", (FMT__0)); - } - } - - TRACE_MSG(TRACE_ZCL1, "delay for %d seconds", (FMT__D, delay_time)); - if (delay_time != ZB_ZCL_INVALID_TIMEOUT) - { - zb_time_t t; - - t = ZB_TIMER_GET(); - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED); - rep_info->run_time = ZB_TIME_ADD(t, delay_time*ZB_TIME_ONE_SECOND); - TRACE_MSG(TRACE_ZCL1, "rep_info->run_time %ld", (FMT__L, rep_info->run_time)); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_update_reporting_info", (FMT__0)); -} - -void zb_zcl_adjust_reporting_timer(zb_uint8_t param) -{ - zb_bool_t reschedule = ZB_FALSE; - zb_zcl_reporting_info_t *rep_info = NULL; - zb_time_t next_event_time = 0; - zb_uindex_t i, j; - - ZVUNUSED(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_adjust_reporting_timer", (FMT__0)); - - for (j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) - { - rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; - for (i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) - { - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY) && - !ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP) && - ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED)) - { - if (!reschedule) - { - /* The easiest way to find first entry */ - next_event_time = rep_info->run_time; - reschedule = ZB_TRUE; - } - - /* Find the minimal schedule-time */ - if (ZB_TIME_GE(next_event_time, rep_info->run_time)) - { - next_event_time = rep_info->run_time; - } - } - rep_info++; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "reschedule %hd, next_event_time %ld", (FMT__H_L, reschedule, next_event_time)); - - if (reschedule) - { - zb_time_t t; - - t = ZB_TIMER_GET(); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_reporting_timer_handler, ZB_ALARM_ALL_CB); - /* If next_event_time is in the past, run immediately. */ - if (ZB_TIME_GE(t, next_event_time)) - { - ZB_SCHEDULE_CALLBACK(zb_zcl_reporting_timer_handler, 0); - } - else - { - ZB_SCHEDULE_ALARM(zb_zcl_reporting_timer_handler, 0, ZB_TIME_SUBTRACT(next_event_time, t)); - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_adjust_reporting_timer", (FMT__0)); -} - -void zb_zcl_reporting_timer_handler(zb_uint8_t param) -{ - zb_zcl_reporting_info_t *rep_info = NULL; - zb_time_t t; - zb_uint8_t rep_count = 0; - zb_uindex_t i, j; - - ZVUNUSED(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_reporting_timer_handler", (FMT__0)); - - t = ZB_TIMER_GET(); - - /* We're here because some event has been occurred. Need to analyse it */ - for (j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) - { - rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; - for (i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) - { - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY) && - !ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP) && - ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED) && - ZB_TIME_GE(t, rep_info->run_time)) - { - /* Get the reason */ - if (!ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_ALLOWED)) - { - /* Minimal interval expired - mark attribute as allowed to - * be reported */ - TRACE_MSG(TRACE_ZCL1, "min_interval expired rep_info %p", (FMT__P)); - - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_ALLOWED); - - /* If pending attributes exists, mark to report and do not schedule - * max_interval event */ - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR)) - { - TRACE_MSG(TRACE_ZCL1, "handle pending report", (FMT__0)); - rep_count++; - } - else - { - if (rep_info->u.send_info.max_interval != ZB_ZCL_TIMEOUT_ZERO) - { - zb_uint16_t delay_time; - - delay_time = rep_info->u.send_info.max_interval - rep_info->u.send_info.min_interval; - rep_info->run_time = ZB_TIME_ADD(t, delay_time*ZB_TIME_ONE_SECOND); - TRACE_MSG(TRACE_ZCL1, "Schedule max_interval timer, delay %d seconds, run_time %ld", - (FMT__D_L, delay_time, rep_info->run_time)); - } - else - { - /* Clear timed callback - reporting flag */ - /* TODO: DEBUG: when minimum interval is expired BEFORE binding, this record will - * NEVER be reported! */ - TRACE_MSG(TRACE_ZCL1, "Zero max_interval time, skip", (FMT__0)); - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED); - } - } - } - else - { - /* Maximum interval expired - mark attribute to be reported */ - TRACE_MSG(TRACE_ZCL1, "max_interval expired rep_info %p", (FMT__P)); - - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR); - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED); - - rep_count++; - } - } - - rep_info++; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "%hd entries to report", (FMT__H, rep_count)); - if (rep_count) - { - TRACE_MSG(TRACE_ZCL1, "Schedule next report attribute rep_count %hd", (FMT__H, rep_count)); - ZB_SCHEDULE_CALLBACK(zb_zcl_report_attr, 0); - } - - zb_zcl_adjust_reporting_timer(0); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_reporting_timer_handler", (FMT__0)); -} - -/** - Returns reporting info for specified attribute - */ -zb_zcl_reporting_info_t* zb_zcl_find_reporting_info( zb_uint8_t ep, - zb_uint16_t cluster_id, - zb_uint8_t cluster_role, - zb_uint16_t attr_id) -{ - zb_zcl_reporting_info_t *rep_info = NULL; - zb_uindex_t i, j; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_find_reporting_info, ep %hd, cluster %d, attr_id %d", - (FMT__H_D_D, ep, cluster_id, attr_id)); - if (ZCL_CTX().device_ctx) - { - for (j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) - { - TRACE_MSG(TRACE_ZCL1, ">> ZCL_CTX().device_ctx->rep_info_count = %d", - (FMT__D, ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count)); - rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; - TRACE_MSG(TRACE_ZCL1, ">> rep_info = %p",(FMT__P, rep_info)); - for (i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) - { - TRACE_MSG(TRACE_ZCL1, ">> rep_info->ep = %d rep_info->cluster_id = %d rep_info->attr_id = %d rep_flags %i)", - (FMT__D_D_D_H, rep_info->ep,rep_info->cluster_id,rep_info->attr_id,rep_info->flags)); - TRACE_MSG(TRACE_ZCL1, " max_interval %d min_interval %d",(FMT__D_D, rep_info->u.send_info.max_interval, - rep_info->u.send_info.min_interval)); - - if ((rep_info->ep == ep) && - (rep_info->cluster_id == cluster_id) && - (rep_info->cluster_role == cluster_role) && - (rep_info->attr_id == attr_id) && - ZB_ZCL_GET_REPORTING_FLAG(rep_info,ZB_ZCL_REPORTING_SLOT_BUSY)) - { - break; - } - rep_info++; - } - if (i >= ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count) - { - TRACE_MSG(TRACE_ZCL2, ">> if (i >= ZCL_CTX().device_ctx->rep_info_count)", - (FMT__0)); - rep_info = NULL; - } - /* If rep_info was successfully found, break outer loop to return from the function. */ - else - { - break; - } - } - } - } - - TRACE_MSG(TRACE_ZCL2, "<< zb_zcl_find_reporting_info %p", (FMT__P, rep_info)); - return rep_info; -} - - -static zb_zcl_reporting_info_t* get_new_reporting_info(zb_uint8_t endpoint_id) -{ - zb_zcl_reporting_info_t *rep_info = NULL; - zb_uindex_t i, j; - - TRACE_MSG(TRACE_ZCL1, ">> get_new_reporting_info",(FMT__0)); - if (ZCL_CTX().device_ctx) - { - for (j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[j]->ep_id == endpoint_id && - ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) - { - rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; - for (i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) - { - if (!(rep_info->flags & ZB_ZCL_REPORTING_SLOT_BUSY)) - { - break; - } - rep_info++; - } - if (i >= ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count) - { - rep_info = NULL; - } - } - } - } - - TRACE_MSG(TRACE_ZCL1, "<< get_new_reporting_info %p", (FMT__P, rep_info)); - return rep_info; -} - - -void zb_zcl_report_attr(zb_uint8_t param) -{ - zb_uindex_t i, j; - zb_bool_t report_sent = ZB_FALSE; - zb_zcl_reporting_info_t *rep_info; - - ZVUNUSED(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_report_attr buf_ref %hd", (FMT__H, ZCL_CTX().reporting_ctx.buf_ref)); - - if (ZCL_CTX().device_ctx) - { - for (j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) - { - rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; - for (i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) - { - TRACE_MSG(TRACE_ZCL1, "rep_info %p, flags %hx", (FMT__P_H, rep_info, rep_info->flags)); - - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR) && - ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_ALLOWED) && - !ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP)) - { - if (ZCL_CTX().reporting_ctx.buf_ref != ZB_UNDEFINED_BUFFER) - { - TRACE_MSG(TRACE_ZCL1, "buffer is free, send report", (FMT__0)); - - /* Moved to zb_zcl_send_report_attr_command() - to properly reset flags for each - rep_info independently (if there are 2 attributes to report in one cluster). */ - /* ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR); */ - /* ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_ALLOWED); */ - /* ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED); */ - /* ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_SENT); */ - - zb_zcl_send_report_attr_command(rep_info, ZCL_CTX().reporting_ctx.buf_ref); - ZCL_CTX().reporting_ctx.buf_ref = ZB_UNDEFINED_BUFFER; - - report_sent = ZB_TRUE; - - break; - } - else - { - /* Report buffer is in use. Retry sending on cb */ - TRACE_MSG(TRACE_ZCL1, "buffer is in use, skip", (FMT__0)); - } - } - rep_info++; - } - } - } - } - - if (!report_sent) - { - TRACE_MSG(TRACE_ZCL1, "report is not sent, skip", (FMT__0)); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_report_attr", (FMT__0)); -} - - -/* @internal @brief Function returns next reporting info that should be reported. - * - * Criteria: it should be sent to the same device and to the same cluster, as specified by - * @ref rep_info_init - */ -zb_zcl_reporting_info_t* zb_zcl_get_next_reporting_info(zb_zcl_reporting_info_t *rep_info_init, zb_uint8_t is_manuf_spec) -{ - zb_zcl_reporting_info_t *rep_info = NULL; - zb_zcl_attr_t *attr_desc; - zb_uint8_t attr_manuf_spec; - zb_uindex_t i, j; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_get_next_reporting_info, rep_info_init %p, is_manuf_spec %hd", - (FMT__P_D, rep_info_init, is_manuf_spec)); - - if (ZCL_CTX().device_ctx) - { - /* Should look here only on the same endpoint */ - j = 0; - while (j < ZCL_CTX().device_ctx->ep_count - && ZCL_CTX().device_ctx->ep_desc_list[j]->ep_id != rep_info_init->ep) - { - ++j; - } - ZB_ASSERT(j < ZCL_CTX().device_ctx->ep_count); - - if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) - { - rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; - - for (i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) - { - TRACE_MSG(TRACE_ZCL3, "check next rep info %p", (FMT__P, rep_info)); - - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY)) - { - - attr_desc = - zb_zcl_get_attr_desc_a(rep_info->ep, rep_info->cluster_id, rep_info->cluster_role, rep_info->attr_id); - attr_manuf_spec = !!ZB_ZCL_IS_ATTR_MANUF_SPEC(attr_desc); - - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR) && - ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_ALLOWED) && - !ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP) && - rep_info->dst.short_addr == rep_info_init->dst.short_addr && - rep_info->dst.endpoint == rep_info_init->dst.endpoint && - rep_info->dst.profile_id == rep_info_init->dst.profile_id && - rep_info->ep == rep_info_init->ep && - rep_info->cluster_id == rep_info_init->cluster_id && - !(attr_manuf_spec ^ is_manuf_spec)) - { - TRACE_MSG(TRACE_ZCL3, "found new %p", (FMT__P, rep_info)); - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR); - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_ALLOWED); - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_SENT); - - break; - } - } - rep_info++; - } - if (i >= ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count) - { - rep_info = NULL; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_get_next_reporting_info, ret %p", (FMT__P, rep_info)); - return rep_info; -} - -void zb_zcl_mark_report_not_sent(zb_zcl_reporting_info_t *rep_info) -{ - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_mark_report_not_sent, rep_info %p", (FMT__P, rep_info)); - - if (rep_info) - { - /* Restore reporting flags - try to the attribute them next time */ - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR); - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_ALLOWED); - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_SENT); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_mark_report_not_sent", (FMT__0)); -} - -void zb_zcl_wait_reporting_timeout(zb_uint8_t param) -{ - zb_zcl_reporting_info_t *rep_info = zb_zcl_get_reporting_info(param); - - TRACE_MSG(TRACE_ZCL1, "zb_zcl_wait_reporting_timeout param %hd, rep_info %p", - (FMT__H_P, param, rep_info)); - - if (ZCL_CTX().no_reporting_cb) - { - TRACE_MSG(TRACE_ZCL3, "inform application - no report cb %p", (FMT__P, ZCL_CTX().no_reporting_cb)); - (*ZCL_CTX().no_reporting_cb)(rep_info->dst.endpoint, rep_info->cluster_id, rep_info->attr_id); - } - - if (ZCL_CTX().reporting_ctx.min_interval != ZB_ZCL_TIMEOUT_ZERO) - { - TRACE_MSG(TRACE_ZCL3, "start wait reporting again", (FMT__0)); - ZB_SCHEDULE_ALARM(zb_zcl_wait_reporting_timeout, param, - rep_info->u.recv_info.timeout * ZB_TIME_ONE_SECOND); - } -} - - -/** @internal @brief Function should be called by application on receiving attribute - report to inform ZCL that report is received. - @param ep - endpoint number - @param cluster_id - cluster ID - @param attr_id - attribute ID - */ -void zb_zcl_report_received(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id) -{ - zb_zcl_reporting_info_t *rep_info; - - TRACE_MSG(TRACE_ZCL1, "zb_zcl_report_received ep %hd, cluster_id %d, attr_id %d", - (FMT__H_D_D, ep, cluster_id, attr_id)); - rep_info = zb_zcl_find_reporting_info(ep, cluster_id, cluster_role, attr_id); - if (rep_info) - { - TRACE_MSG(TRACE_ZCL3, "restart wait report timer", (FMT__0)); - start_wait_reporting_timer(rep_info); - } -} - - -#ifdef EXCLUDED_FROM_BUILD -/* Function sets flags: report-is-needed or report-is-allowed for all - * active reporting info records */ -static zb_uint8_t zb_zcl_mark_all_for_reporting(zb_uint8_t flag) -{ - zb_uindex_t i; - zb_zcl_reporting_info_t *rep_info; - zb_uint8_t counter = 0; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_mark_all_for_reporting, flag %hx", (FMT__H, flag)); - - if (ZCL_CTX().device_ctx && ZCL_CTX().device_ctx->reporting_info) - { - rep_info = ZCL_CTX().device_ctx->reporting_info; - for (i = 0; i < ZCL_CTX().device_ctx->rep_info_count; i++) - { - TRACE_MSG(TRACE_ZCL3, "next rep info %p, flags %hx", (FMT__P_H, rep_info, rep_info->flags)); - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY)) - { - /* DO NOT check for min_interval here, check it only when - * setting report-is-needed because of attr value change */ - - TRACE_MSG(TRACE_ZCL3, "set flag value", (FMT__0)); - ZB_ZCL_SET_REPORTING_FLAG(rep_info, flag); - counter++; - } - rep_info++; - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_mark_all_for_reporting ret %hd", (FMT__H, counter)); - return counter; -} -#endif - - -void zb_zcl_save_reported_value(zb_zcl_reporting_info_t *rep_info, zb_zcl_attr_t* attr_desc) -{ - zb_ushort_t attr_size; - - TRACE_MSG(TRACE_ZCL1, ">> save_reported_value rep_info %p, attr_desc %p", - (FMT__P_P, rep_info, attr_desc)); - - TRACE_MSG(TRACE_ZCL1, "attr type %hd", (FMT__H, attr_desc->type)); - - if (zb_zcl_is_analog_data_type(attr_desc->type)) - { - switch (attr_desc->type) - { - case ZB_ZCL_ATTR_TYPE_U8: - case ZB_ZCL_ATTR_TYPE_S8: - { - rep_info->u.send_info.reported_value.u8 = *(zb_uint8_t*)attr_desc->data_p; - TRACE_MSG(TRACE_ZCL3, "reported U8 %hd", (FMT__H, rep_info->u.send_info.reported_value.u8)); - break; - } - - case ZB_ZCL_ATTR_TYPE_U16: - { - rep_info->u.send_info.reported_value.u16 = *(zb_uint16_t*)attr_desc->data_p; - TRACE_MSG(TRACE_ZCL3, "reported U16 %d", (FMT__H, rep_info->u.send_info.reported_value.u16)); - break; - } - - case ZB_ZCL_ATTR_TYPE_S16: - { - rep_info->u.send_info.reported_value.s16 = *(zb_int16_t*)attr_desc->data_p; - TRACE_MSG(TRACE_ZCL3, "reported S16 %d", (FMT__H, rep_info->u.send_info.reported_value.s16)); - break; - } - - case ZB_ZCL_ATTR_TYPE_U24: - { - rep_info->u.send_info.reported_value.u24 = *(zb_uint24_t*)attr_desc->data_p; - TRACE_MSG(TRACE_ZCL3, "reported U24 %d %d", (FMT__D_D, rep_info->u.send_info.reported_value.u24.high, rep_info->u.send_info.reported_value.u24.low)); - break; - } - - case ZB_ZCL_ATTR_TYPE_S24: - { - rep_info->u.send_info.reported_value.s24 = *(zb_int24_t*)attr_desc->data_p; - TRACE_MSG(TRACE_ZCL3, "reported S24 %d %d", (FMT__D_D, rep_info->u.send_info.reported_value.s24.high, rep_info->u.send_info.reported_value.s24.low)); - break; - } - - case ZB_ZCL_ATTR_TYPE_U32: - { - rep_info->u.send_info.reported_value.u32 = *(zb_uint32_t*)attr_desc->data_p; - TRACE_MSG(TRACE_ZCL3, "reported U32 [%hd %hd %hd %hd]", - (FMT__H_H_H_H, - rep_info->u.send_info.reported_value.data_buf[0], rep_info->u.send_info.reported_value.data_buf[1], - rep_info->u.send_info.reported_value.data_buf[2], rep_info->u.send_info.reported_value.data_buf[3])); - break; - } - - case ZB_ZCL_ATTR_TYPE_S32: - { - rep_info->u.send_info.reported_value.s32 = *(zb_int32_t*)attr_desc->data_p; - TRACE_MSG(TRACE_ZCL3, "reported S32 [%hd %hd %hd %hd]", - (FMT__H_H_H_H, - rep_info->u.send_info.reported_value.data_buf[0], rep_info->u.send_info.reported_value.data_buf[1], - rep_info->u.send_info.reported_value.data_buf[2], rep_info->u.send_info.reported_value.data_buf[3])); - break; - } - - case ZB_ZCL_ATTR_TYPE_U48: - { - rep_info->u.send_info.reported_value.u48 = *(zb_uint48_t*)attr_desc->data_p; - TRACE_MSG(TRACE_ZCL3, "reported U48 %d %d", (FMT__D_D, rep_info->u.send_info.reported_value.u48.high, rep_info->u.send_info.reported_value.u48.low)); - break; - } - - default: - break; - } - } /* is analog type */ - else - { - TRACE_MSG(TRACE_ZCL3, "descrete attr type", (FMT__0)); - attr_size = zb_zcl_get_attribute_size(attr_desc->type, attr_desc->data_p); - rep_info->u.send_info.reported_value.data_buf_crc32 = zb_crc32(attr_desc->data_p, attr_size); - TRACE_MSG(TRACE_ZCL3, "reported attr size %hd, data crc32 = 0x%08x", - (FMT__H_D, attr_size, rep_info->u.send_info.reported_value.data_buf_crc32)); - } - - TRACE_MSG(TRACE_ZCL1, "<< save_reported_value", (FMT__0)); -} - -static zb_bool_t check_delta_value(zb_zcl_reporting_info_t *rep_info) -{ - zb_zcl_attr_t* attr_desc; - zb_ret_t ret = RET_EMPTY; - zb_ushort_t attr_size; - - TRACE_MSG(TRACE_ZCL1, ">> check_delta_value %p", (FMT__P, rep_info)); - - attr_desc = zb_zcl_get_attr_desc_a(rep_info->ep, rep_info->cluster_id, rep_info->cluster_role, rep_info->attr_id); - if (attr_desc) - { - if (zb_zcl_is_analog_data_type(attr_desc->type)) - { - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_FIRST)) - { - /* Special reported_value indicates that it is first check_delta_value() call - report any - * value first time. */ - TRACE_MSG(TRACE_ZCL3, "First report!", (FMT__0)); - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_FIRST); - ret = RET_OK; - } - else - { - switch (attr_desc->type) - { - case ZB_ZCL_ATTR_TYPE_U8: - case ZB_ZCL_ATTR_TYPE_S8: - { - zb_uint8_t delta; - - delta = ZB_ABS((zb_int16_t)*(zb_uint8_t*)(attr_desc->data_p) - rep_info->u.send_info.reported_value.u8); - - TRACE_MSG(TRACE_ZCL3, "U8 delta %hd, min delta %hd", (FMT__H_H, delta, rep_info->u.send_info.delta.u8)); - ret = (delta >= rep_info->u.send_info.delta.u8)?(RET_OK ):(RET_IGNORE ); - break; - } - - case ZB_ZCL_ATTR_TYPE_U16: - { - zb_uint16_t delta; - - delta = (zb_uint16_t)ZB_ABS((zb_int32_t)(*(zb_uint16_t*)(attr_desc->data_p)) - rep_info->u.send_info.reported_value.u16); - - TRACE_MSG(TRACE_ZCL3, "U16 delta %d, min delta %d", (FMT__D_D, delta, rep_info->u.send_info.delta.u16)); - ret = (delta >= rep_info->u.send_info.delta.u16)?(RET_OK ):(RET_IGNORE ); - break; - } - - case ZB_ZCL_ATTR_TYPE_S16: - { - zb_int16_t delta; - - delta = ZB_ABS(*(zb_int16_t*)(attr_desc->data_p) - rep_info->u.send_info.reported_value.s16); - - TRACE_MSG(TRACE_ZCL3, "S16 delta %d, min delta %d", (FMT__D_D, delta, rep_info->u.send_info.delta.s16)); - ret = (delta >= rep_info->u.send_info.delta.s16)?(RET_OK ):(RET_IGNORE ); - break; - } - - case ZB_ZCL_ATTR_TYPE_U24: - { - zb_uint32_t delta = 0, - delta_u24 = ZB_GET_UINT32_FROM_UINT24(rep_info->u.send_info.delta.u24); - zb_uint32_t n1 = ZB_GET_UINT32_FROM_UINT24(*(zb_uint24_t*)(attr_desc->data_p)), - n2 = ZB_GET_UINT32_FROM_UINT24(rep_info->u.send_info.reported_value.u24); - - delta = (n1 > n2) ? (n1 - n2) : (n2 - n1); - - TRACE_MSG(TRACE_ZCL3, "U24 delta %ld, min delta %ld", - (FMT__L_L, delta, delta_u24)); - ret = (delta >= delta_u24) ? (RET_OK ):(RET_IGNORE ); - break; - } - - case ZB_ZCL_ATTR_TYPE_S24: - { - zb_int32_t delta = - ZB_ABS(ZB_GET_INT32_FROM_INT24(*(zb_int24_t*)(attr_desc->data_p)) - - ZB_GET_INT32_FROM_INT24(rep_info->u.send_info.reported_value.s24)); - - TRACE_MSG(TRACE_ZCL3, "S24 delta %ld, min delta %ld", - (FMT__L_L, delta, ZB_GET_INT32_FROM_INT24(rep_info->u.send_info.delta.s24))); - ret = (delta >= ZB_GET_INT32_FROM_INT24(rep_info->u.send_info.delta.s24)) ? (RET_OK ):(RET_IGNORE ); - break; - } - - case ZB_ZCL_ATTR_TYPE_U32: - { - zb_uint32_t delta; - - if (*(zb_uint32_t*)(attr_desc->data_p) > rep_info->u.send_info.reported_value.u32) - { - delta = *(zb_uint32_t*)(attr_desc->data_p) - rep_info->u.send_info.reported_value.u32; - } - else - { - delta = rep_info->u.send_info.reported_value.u32 - *(zb_uint32_t*)(attr_desc->data_p); - } - - TRACE_MSG(TRACE_ZCL3, "reported U32 [%hd %hd %hd %hd]", - (FMT__H_H_H_H, - rep_info->u.send_info.reported_value.data_buf[0], rep_info->u.send_info.reported_value.data_buf[1], - rep_info->u.send_info.reported_value.data_buf[2], rep_info->u.send_info.reported_value.data_buf[3])); - ret = (delta >= rep_info->u.send_info.delta.u32)?(RET_OK ):(RET_IGNORE ); - break; - } - - case ZB_ZCL_ATTR_TYPE_S32: - { - zb_int32_t delta = ZB_ABS(*(zb_int32_t*)(attr_desc->data_p) - - rep_info->u.send_info.reported_value.s32); - - TRACE_MSG(TRACE_ZCL3, "reported S32 [%hd %hd %hd %hd]", - (FMT__H_H_H_H, - rep_info->u.send_info.reported_value.data_buf[0], rep_info->u.send_info.reported_value.data_buf[1], - rep_info->u.send_info.reported_value.data_buf[2], rep_info->u.send_info.reported_value.data_buf[3])); - ret = (delta >= rep_info->u.send_info.delta.s32)?(RET_OK ):(RET_IGNORE ); - break; - } - - - case ZB_ZCL_ATTR_TYPE_U48: - { - zb_uint48_t delta = *(zb_uint48_t*)(attr_desc->data_p); /* initial value */ - - TRACE_MSG(TRACE_ZCL3, "delta_cur %x %lx", (FMT__D_L, delta.high, delta.low)); - - ZB_UINT48_SUB(delta, rep_info->u.send_info.reported_value.u48); - - TRACE_MSG(TRACE_ZCL3, "delta_cur %x %lx, delta_u48 %x %lx", (FMT__D_L_L_D, delta.high, delta.low, rep_info->u.send_info.delta.u48.high, rep_info->u.send_info.delta.u48.low)); - - ret = ZB_UINT48_IS_GREAT_OR_EQUAL(delta, rep_info->u.send_info.delta.u48)?(RET_OK ):(RET_IGNORE ); - break; - } - - default: - break; - } - } - } /* is analog type */ - - /* Allow to work with unknown analog data types as with discrete - report any change if we can not - * check the delta. */ - if (ret == RET_EMPTY) - { - TRACE_MSG(TRACE_ZCL3, "discrete/unknown analog attr type, check if value was changed or not", (FMT__0)); - attr_size = zb_zcl_get_attribute_size(attr_desc->type, attr_desc->data_p); - if(rep_info->u.send_info.reported_value.data_buf_crc32 != zb_crc32(attr_desc->data_p, attr_size)) - { - TRACE_MSG(TRACE_ZCL1, "Value was changed, report it", (FMT__0)); - ret = RET_OK; - } - } - } - TRACE_MSG(TRACE_ZCL1, "<< check_delta_value ret %hd", (FMT__H, ret)); - return (ret == RET_OK) ? (ZB_TRUE) : (ZB_FALSE); -} - -/* marks attribute for reporting, after its value was changed */ -void zb_zcl_mark_attr_for_reporting(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id) -{ - zb_zcl_reporting_info_t *rep_info; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_mark_attr_for_reporting, ep %hd, cluster_id %d, attr_id %d", - (FMT__H_D_D, ep, cluster_id, attr_id)); - - rep_info = zb_zcl_find_reporting_info(ep, cluster_id, cluster_role, attr_id); - if (rep_info) - { - TRACE_MSG(TRACE_ZCL3, "min_inerval %hd, flags %hd", - (FMT__H_H, rep_info->u.send_info.min_interval, rep_info->flags)); - - /* Check for delta value */ - if (check_delta_value(rep_info)) - { - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_ALLOWED)) - { - TRACE_MSG(TRACE_ZCL3, "set reporting is needed", (FMT__0)); - - /* Debug if needed, but in current circumstances it works incorrectly: if - * max_interval expired before bind, we will have ZB_ZCL_REPORT_ATTR flag and NEVER run - * zb_zcl_report_attr(). - * Note that zb_zcl_report_attr() has its own checks for free buffer. - */ - if (1/* !ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR) */) - { - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR); - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED); - - TRACE_MSG(TRACE_ZCL3, "schedule reporting", (FMT__0)); - ZB_SCHEDULE_CALLBACK(zb_zcl_report_attr, 0); - - zb_zcl_adjust_reporting_timer(0); - } - else - { - /* Attribute is waiting for free buffer to be reported. No need - * to retrigger zb_zcl_reporting_attr() function */ - TRACE_MSG(TRACE_ZCL3, "Already pending and waiting for free buffer", (FMT__0)); - } - } - else - { - TRACE_MSG(TRACE_ZCL3, "set reporting is pending", (FMT__0)); - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_ATTR); - } - } - } - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_mark_attr_for_reporting", (FMT__0)); -} - -/* stop attribute for reporting */ -zb_ret_t zb_zcl_stop_attr_reporting(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id) -{ - zb_ret_t ret = RET_OK; - zb_zcl_reporting_info_t *rep_info; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_stop_attr_for_reporting, ep %hd, cluster_id %d, attr_id %d", - (FMT__H_D_D, ep, cluster_id, attr_id)); - - rep_info = zb_zcl_find_reporting_info(ep, cluster_id, cluster_role, attr_id); - if (rep_info) - { - ZB_ZCL_SET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP); - } - else - { - ret = RET_NOT_FOUND; - } - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_stop_attr_for_reporting %d", (FMT__H, ret)); - return ret; -} - -/* start attribute for reporting */ -zb_ret_t zb_zcl_start_attr_reporting(zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id) -{ - zb_ret_t ret = RET_OK; - zb_zcl_reporting_info_t *rep_info; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_start_attr_for_reporting, ep %hd, cluster_id %d, attr_id %d", - (FMT__H_D_D, ep, cluster_id, attr_id)); - - rep_info = zb_zcl_find_reporting_info(ep, cluster_id, cluster_role, attr_id); - if (rep_info) - { - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP); - } - else - { - ret = RET_NOT_FOUND; - } - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_start_attr_for_reporting %d", (FMT__H, ret)); - return ret; -} - -/** Reporting command send callback - - Reports are sent 1-by-1, zb_zcl_reporting_cb() is called when previous report is sent - */ -void zb_zcl_reporting_cb(zb_uint8_t param) -{ - zb_uindex_t i, j; - zb_zcl_reporting_info_t *rep_info; - zb_zcl_command_send_status_t *cmd_send_status = - ZB_BUF_GET_PARAM(param, zb_zcl_command_send_status_t); - - ZVUNUSED(cmd_send_status); - TRACE_MSG(TRACE_ZCL1, "zb_zcl_reporting_cb param %hd, send status %hx", - (FMT__H_H, param, cmd_send_status->status)); - - for (j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) - { - if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) - { - rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; - for (i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) - { - if (ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_SLOT_BUSY) && - ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_SENT) && - !ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORTING_STOP)) - { - ZB_ZCL_CLR_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_IS_SENT); - zb_zcl_update_reporting_info(rep_info); - } - rep_info++; - } - } - } - - zb_zcl_adjust_reporting_timer(0); - - /* Send next reporting info */ - zb_buf_reuse(param); - ZCL_CTX().reporting_ctx.buf_ref = param; - ZB_SCHEDULE_CALLBACK(zb_zcl_report_attr, 0); -} - -zb_bool_t zcl_is_attr_reported( - zb_uint8_t ep, zb_uint16_t cluster_id, zb_uint8_t cluster_role, zb_uint16_t attr_id) -{ - zb_bool_t ret; - zb_zcl_reporting_info_t *rep_info; - - TRACE_MSG(TRACE_ZCL1, ">> zcl_is_attr_reported", (FMT__0)); - - rep_info = zb_zcl_find_reporting_info(ep, cluster_id, cluster_role, attr_id); - ret = (zb_bool_t)!!rep_info; - - TRACE_MSG(TRACE_ZCL1, "<< zcl_is_attr_reported ret %hd", (FMT__H, ret)); - return ret; -} - -#ifdef ZB_ZCL_ENABLE_DEFAULT_REPORT_ATTR_PROCESSING -/** - Default report attribute command handler - @param cmd_buf - pointer to received buffer with command - @param cmd_info - pointer to a parsed command header - */ -void zb_zcl_report_attr_cmd_handler(zb_uint8_t param) -{ - zb_zcl_report_attr_req_t *rep_attr_req; - zb_zcl_parsed_hdr_t cmd_info; - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_report_attr_cmd_handler %hd", - (FMT__H, param)); - - do - { - ZB_ZCL_GENERAL_GET_NEXT_REPORT_ATTR_REQ(param, rep_attr_req); - TRACE_MSG(TRACE_ZCL3, "rep_attr_req %p", (FMT__P, rep_attr_req)); - if (rep_attr_req) - { - TRACE_MSG(TRACE_ZCL3, "attr dump: attr id %hd, type %hd", - (FMT__H_H, rep_attr_req->attr_id, rep_attr_req->attr_type)); - - /* inform ZCL that report is received to prevent timeout alarm */ - zb_zcl_report_received( - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - cmd_info.cluster_id, - (cmd_info.cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV) ? - ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE, - rep_attr_req->attr_id); - - if (ZCL_CTX().report_attr_cb) - { - TRACE_MSG(TRACE_ZCL3, "inform user about reporting", (FMT__0)); - - (*ZCL_CTX().report_attr_cb)(&ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - cmd_info.cluster_id, - rep_attr_req->attr_id, - rep_attr_req->attr_type, - rep_attr_req->attr_value); - } - } - } - while(rep_attr_req); - - if (!cmd_info.disable_default_response) - { - ZB_ZCL_SEND_DEFAULT_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - cmd_info.cluster_id, - cmd_info.seq_number, - cmd_info.cmd_id, - ZB_ZCL_STATUS_SUCCESS); - } - else - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_report_attr_cmd_handler", (FMT__0)); -} -#endif /* ZB_ZCL_ENABLE_DEFAULT_REPORT_ATTR_PROCESSING */ - -#endif /* defined(ZB_ENABLE_ZCL) && !(defined ZB_ZCL_DISABLE_REPORTING) */ diff --git a/zboss/development/src/zcl/zcl_s_daily_schedule.c b/zboss/development/src/zcl/zcl_s_daily_schedule.c deleted file mode 100644 index ee880feeb0..0000000000 --- a/zboss/development/src/zcl/zcl_s_daily_schedule.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: SERVER: Daily Schedule Cluster -*/ - -#define ZB_TRACE_FILE_ID 13 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_DAILY_SCHEDULE) || defined DOXYGEN - -#include "zcl/zb_zcl_daily_schedule.h" -/******************************************************************************/ -/* Common definitions */ - -zb_uint8_t gs_daily_schedule_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_daily_schedule_server_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE_SERVER_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_daily_schedule_server_cmd_list = -{ - sizeof(gs_daily_schedule_server_received_commands), gs_daily_schedule_server_received_commands, - sizeof(gs_daily_schedule_server_generated_commands), gs_daily_schedule_server_generated_commands -}; - -/* FIXME: Some commands are sent via follow macros. But we usually use ZB_APS_ADDR_MODE_64_ENDP_PRESENT address mode*/ -/** Helper for sending cluster commands - * @param _fn - sending cluster command function - * @param _param - user parameter - * @param _cmd_info - command info - * @param _payload - sending payload. Corresponds to sending command. - * @param _cb - Callback which should be called when the ZCL stack receives - * APS ack. - */ -#define ZB_ZCL_DAILY_SCHEDULE_SEND_CMD_HELPER(_fn, _param, _cmd_info, _payload, _cb) \ - _fn((_param), \ - (zb_addr_u *) &ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).source, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).src_endpoint, \ - ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).dst_endpoint, \ - (_payload), (_cb) \ - ) - -zb_bool_t zb_zcl_process_s_daily_schedule_specific_commands(zb_uint8_t param); - -static zb_ret_t check_value_daily_schedule(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - - -void zb_zcl_daily_schedule_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)check_value_daily_schedule, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_s_daily_schedule_specific_commands); -} - - -static zb_ret_t check_value_daily_schedule(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} - - -#define PUT_PL_FUN(type) type ## _put_payload -#define PUT_PL_START(type, pl_var) \ -static zb_uint8_t *PUT_PL_FUN(type)(zb_uint8_t *data, const void *pl_arg) \ -{ \ - const type *pl_var = pl_arg; \ - ZB_ASSERT(pl_arg); \ - ZB_ASSERT(data); - -#define PUT_PL_END() return data; } - -PUT_PL_START(zb_zcl_daily_schedule_publish_schedule_payload_t, pl) - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->provider_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->issuer_event_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->schedule_id); - ZB_ZCL_PACKET_PUT_DATA16(data, &pl->day_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->start_time); - ZB_ZCL_PACKET_PUT_DATA8 (data, pl->schedule_type); - ZB_ZCL_PACKET_PUT_DATA8 (data, pl->schedule_time_reference); - TRACE_MSG(TRACE_ZCL1, "schedule_name size %hd", (FMT__H, pl->schedule_name[0])); - ZB_ZCL_PACKET_PUT_DATA8 (data, pl->schedule_name[0]); - ZB_ZCL_PACKET_PUT_DATA_N(data, pl->schedule_name+1, pl->schedule_name[0]); -PUT_PL_END() - -PUT_PL_START(zb_zcl_daily_schedule_cancel_schedule_payload_t, pl) - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->provider_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->schedule_id); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->schedule_type); -PUT_PL_END() - -PUT_PL_START(zb_zcl_daily_schedule_publish_day_profile_payload_t, pl) - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->provider_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->issuer_event_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->schedule_id); - ZB_ZCL_PACKET_PUT_DATA8 (data, pl->total_number_of_schedule_entries); - ZB_ZCL_PACKET_PUT_DATA8 (data, pl->command_index); - ZB_ZCL_PACKET_PUT_DATA8 (data, pl->total_number_of_commands); - ZB_ZCL_PACKET_PUT_DATA8 (data, pl->schedule_type); - switch (pl->schedule_type) - { - case ZB_ZCL_DAILY_SCHEDULE_TYPE_LINKY_SCHEDULE: - { - zb_uint8_t i; - for (i = 0; i < pl->number_of_entries_in_this_command; i++) - { - ZB_ZCL_PACKET_PUT_DATA16(data, &pl->day_schedule_entries[i].linky_schedule_entry.start_time); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->day_schedule_entries[i].linky_schedule_entry.price_tier); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->day_schedule_entries[i].linky_schedule_entry.auxiliary_load_switch_state); - } - - break; - } - default: - /* none */ - break; - } -PUT_PL_END() - -#undef PUT_PL_START -#undef PUT_PL_END - -void zb_zcl_daily_schedule_send_cmd_publish_schedule(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_daily_schedule_publish_schedule_payload_t *pl, - zb_callback_t cb -) -{ - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, pl, sizeof(*pl), - PUT_PL_FUN(zb_zcl_daily_schedule_publish_schedule_payload_t), - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_SCHEDULE, - cb); -} - - -void zb_zcl_daily_schedule_send_cmd_publish_day_profile(zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_daily_schedule_publish_day_profile_payload_t *pl, - zb_callback_t cb -) -{ - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, pl, sizeof(*pl), - PUT_PL_FUN(zb_zcl_daily_schedule_publish_day_profile_payload_t), - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_PUBLISH_DAY_PROFILE, - cb); -} - -void zb_zcl_daily_schedule_send_cmd_cancel_schedule(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_daily_schedule_cancel_schedule_payload_t *pl, - zb_callback_t cb -) -{ - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, pl, sizeof(*pl), - PUT_PL_FUN(zb_zcl_daily_schedule_cancel_schedule_payload_t), - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_SCHEDULE, - cb); -} - -void zb_zcl_daily_schedule_send_cmd_cancel_all_schedules(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - zb_callback_t cb -) -{ - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, NULL, 0, - NULL, - ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DAILY_SCHEDULE_SRV_CMD_CANCEL_ALL_SCHEDULES, - cb); -} -/******************************************************************************/ -/* Server definitions */ - -static ZB_INLINE const zb_uint8_t *zb_zcl_daily_schedule_get_schedule_parse_payload( - zb_zcl_daily_schedule_get_schedule_payload_t *pl, zb_uint8_t param) -{ - zb_uint8_t *data = (zb_uint8_t *)zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - ZB_ASSERT(data); - - if (!ZB_ZCL_DAILY_SCHEDULE_GET_SCHEDULE_PL_SIZE_IS_VALID(data_size)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl->provider_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->earliest_start_time, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->min_issuer_event_id, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->number_of_schedules, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->schedule_type, data); - - return data; -} - -static const zb_uint8_t *zb_zcl_daily_schedule_get_day_profile_parse_payload( - zb_zcl_daily_schedule_get_day_profile_payload_t *pl, zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_daily_schedule_get_day_profile_parse_payload", (FMT__0)); - - if (!ZB_ZCL_DAILY_SCHEDULE_GET_DAY_PROFILE_PL_SIZE_IS_VALID(data_size)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl->provider_id, data); - ZB_ZCL_PACKET_GET_DATA16(&pl->day_id, data); - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_daily_schedule_process_get_schedule", (FMT__0)); - - if (!zb_zcl_daily_schedule_get_schedule_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DAILY_SCHEDULE_GET_SCHEDULE_CB_ID, RET_NOT_FOUND, cmd_info, &pl_in, &pl_out); - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - zb_buf_free(param); - } - else - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_daily_schedule_process_get_schedule", (FMT__0)); - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_daily_schedule_process_get_day_profile(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_daily_schedule_get_day_profile_payload_t pl_in = ZB_ZCL_DAILY_SCHEDULE_GET_DAY_PROFILE_PL_INIT; - zb_zcl_daily_schedule_publish_day_profile_payload_t pl_out = ZB_ZCL_DAILY_SCHEDULE_PUBLISH_DAY_PROFILE_PL_INIT; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_daily_schedule_process_get_day_profile", (FMT__0)); - - if (!zb_zcl_daily_schedule_get_day_profile_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DAILY_SCHEDULE_GET_DAY_PROFILE_CB_ID, - RET_NOT_FOUND, cmd_info, &pl_in, &pl_out); - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - ZB_ZCL_DAILY_SCHEDULE_SEND_CMD_HELPER(zb_zcl_daily_schedule_send_cmd_publish_day_profile, param, cmd_info, &pl_out, NULL); - } - else - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_daily_schedule_process_get_day_profile", (FMT__0)); - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_daily_schedule_process_get_schedule_cancellation(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_daily_schedule_cancel_schedule_payload_t pl_out = ZB_ZCL_DAILY_SCHEDULE_CANCEL_SCHEDULE_PL_INIT; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_daily_schedule_process_get_schedule_cancellation", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DAILY_SCHEDULE_GET_SCHEDULE_CANCELLATION_CB_ID, - RET_NOT_FOUND, cmd_info, NULL, &pl_out); - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { -#ifdef ZB_ZCL_DAILY_SCHEDULE_CANCEL_PARTICULAR_SCHEDULE - ZB_ZCL_DAILY_SCHEDULE_SEND_CMD_HELPER(zb_zcl_daily_schedule_send_cmd_cancel_schedule, param, cmd_info, &pl_out, NULL); -#else - zb_zcl_daily_schedule_send_cmd_cancel_all_schedules(param, - (zb_addr_u *) &ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - NULL); -#endif - } - else - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_daily_schedule_process_get_schedule_cancellation", (FMT__0)); - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_process_daily_schedule_srv_cmd(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_bool_t processed = ZB_FALSE; - - switch((zb_zcl_daily_schedule_cli_cmd_t) cmd_info->cmd_id) - { - case ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE: - processed = zb_zcl_daily_schedule_process_get_schedule(param, cmd_info); - break; - case ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_DAY_PROFILE: - processed = zb_zcl_daily_schedule_process_get_day_profile(param, cmd_info); - break; - case ZB_ZCL_DAILY_SCHEDULE_CLI_CMD_GET_SCHEDULE_CANCELLATION: - processed = zb_zcl_daily_schedule_process_get_schedule_cancellation(param, cmd_info); - break; -#ifdef WIP - default: - break; -#endif - /* FIXME: add default case */ - } - - return processed; -} - -/******************************************************************************/ -/* Handler definition */ -zb_bool_t zb_zcl_process_s_daily_schedule_specific_commands(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t processed = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_s_daily_schedule_specific_commands, " - "param=%hd", (FMT__H, param)); - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_daily_schedule_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - /* ZB_ASSERT(cmd_info.profile_id == ZB_AF_SE_PROFILE_ID); */ - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_DAILY_SCHEDULE); - - if (ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction) - { - processed = zb_zcl_process_daily_schedule_srv_cmd(param, &cmd_info); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_s_daily_schedule_specific_commands (cmd_id=%hd, ret=%hd)", - (FMT__H_H, cmd_info.cmd_id, processed)); - - return processed; -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_DAILY_SCHEDULE || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_s_drlc.c b/zboss/development/src/zcl/zcl_s_drlc.c deleted file mode 100644 index 8b1ee2d73a..0000000000 --- a/zboss/development/src/zcl/zcl_s_drlc.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: SERVER: Demand Response and Load Control cluster definitions - -*/ - -#define ZB_TRACE_FILE_ID 24549 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_DRLC) || defined DOXYGEN - -#include "zcl/zb_zcl_drlc.h" - -/* Init 'zb_addr_u' from 'zb_zcl_parsed_hdr_t.src_addr' field */ -#define ZB_ADDR_INIT_FROM_CMD_INFO(_cmd_info) \ - { \ - .addr_short = ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).source.u.short_addr \ - } - -zb_uint8_t gs_drlc_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_DRLC_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_drlc_server_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_DRLC_SERVER_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_drlc_server_cmd_list = -{ - sizeof(gs_drlc_server_received_commands), gs_drlc_server_received_commands, - sizeof(gs_drlc_server_generated_commands), gs_drlc_server_generated_commands -}; - -zb_bool_t zb_zcl_process_s_drlc_specific_commands(zb_uint8_t param); - -void zb_zcl_drlc_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_DRLC, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_s_drlc_specific_commands); -} - -/** - * Server - * - * No Attributes - * - * 3 mandatory commands generated - * 2 mandatory commands handled - * - */ - -void zb_drlc_server_send_load_control_event(zb_uint8_t param, - zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_zcl_drlc_lce_payload_t *payload, zb_callback_t cb) -{ - zb_zcl_drlc_lce_payload_t pl; - zb_uint8_t *data = (zb_uint8_t *) &pl; - - TRACE_MSG(TRACE_ZCL1, ">> zb_drlc_server_send_load_control_event", (FMT__0)); - - ZB_BZERO(&pl, sizeof(pl)); - - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->issuer_event_id); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->device_class); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->utility_enrollment_group); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->start_time); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->duration_in_minutes); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->criticality_level); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->cooling_temperature_offset); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->heating_temperature_offset); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->cooling_temperature_set_point); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->heating_temperature_set_point); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->average_load_adjustment_percentage); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->duty_cycle); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->event_control); - - zb_zcl_send_cmd( - param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, - &pl, sizeof(pl), NULL, - ZB_ZCL_CLUSTER_ID_DRLC, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DRLC_SRV_CMD_LOAD_CONTROL_EVENT, - cb - ); - - TRACE_MSG(TRACE_ZCL1, "<< zb_drlc_server_send_load_control_event", (FMT__0)); -} - -void zb_drlc_server_send_cancel_load_control_event(zb_uint8_t param, - zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_zcl_drlc_cancel_lce_payload_t *payload, zb_callback_t cb) -{ - zb_zcl_drlc_cancel_lce_payload_t pl; - zb_uint8_t *data = (zb_uint8_t *) &pl; - - TRACE_MSG(TRACE_ZCL1, ">> zb_drlc_server_send_cancel_load_control_event", (FMT__0)); - - ZB_BZERO(&pl, sizeof(pl)); - - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->issuer_event_id); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->device_class); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->utility_enrollment_group); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->cancel_control); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->effective_time); - - zb_zcl_send_cmd( - param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, - &pl, sizeof(pl), NULL, - ZB_ZCL_CLUSTER_ID_DRLC, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DRLC_SRV_CMD_CANCEL_LOAD_CONTROL_EVENT, - cb - ); - - TRACE_MSG(TRACE_ZCL1, "<< zb_drlc_server_send_cancel_load_control_event", (FMT__0)); -} - -void zb_drlc_server_send_cancel_all_load_control_events(zb_uint8_t param, - zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, zb_uint8_t *payload, zb_callback_t cb) -{ - - TRACE_MSG(TRACE_ZCL1, ">> zb_drlc_server_send_cancel_all_load_control_events", (FMT__0)); - - zb_zcl_send_cmd( - param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, - payload, 1, NULL, - ZB_ZCL_CLUSTER_ID_DRLC, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_DRLC_SRV_CMD_CANCEL_ALL_LOAD_CONTROL_EVENTS, - cb - ); - - TRACE_MSG(TRACE_ZCL1, "<< zb_drlc_server_send_cancel_all_load_control_events", (FMT__0)); -} - -zb_ret_t zb_drlc_server_handle_report_event_status(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_drlc_report_event_status_payload_t pl = ZB_ZCL_DRLC_REPORT_EVENT_STATUS_PAYLOAD_INIT; - zb_uint8_t *data = zb_buf_begin(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_drlc_server_handle_report_event_status", (FMT__0)); - - if (!ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS_IS_VALID(zb_buf_len(param))) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet len (%hd).", (FMT__H, zb_buf_len(param))); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return RET_INVALID_FORMAT; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl.issuer_event_id, data); - ZB_ZCL_PACKET_GET_DATA8(&pl.event_status, data); - ZB_ZCL_PACKET_GET_DATA32(&pl.event_status_time, data); - ZB_ZCL_PACKET_GET_DATA8(&pl.criticality_level_applied, data); - ZB_ZCL_PACKET_GET_DATA16(&pl.cooling_temperature_set_point_applied, data); - ZB_ZCL_PACKET_GET_DATA16(&pl.heating_temperature_set_point_applied, data); - ZB_ZCL_PACKET_GET_DATA8(&pl.average_load_adjustment_percentage_applied, data); - ZB_ZCL_PACKET_GET_DATA8(&pl.duty_cycle_applied, data); - ZB_ZCL_PACKET_GET_DATA8(&pl.event_control, data); - ZB_ZCL_PACKET_GET_DATA8(&pl.signature_type, data); - ZB_ZCL_PACKET_GET_DATA_N(&pl.signature, data, sizeof(pl.signature)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DRLC_REPORT_EVENT_STATUS_CB_ID, RET_OK, cmd_info, &pl, NULL); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_drlc_server_handle_report_event_status", (FMT__0)); - - zb_zcl_send_default_handler(param, cmd_info, - (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); - - return RET_OK; -} - -zb_ret_t zb_drlc_server_handle_get_scheduled_events(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_drlc_lce_payload_t pl_out = ZB_ZCL_DRLC_LCE_PAYLOAD_INIT; - zb_zcl_drlc_get_scheduled_events_payload_t pl_in = ZB_ZCL_DRLC_CMD_GET_SCHEDULED_EVENTS_PAYLOAD_INIT; - zb_addr_u dst_addr = ZB_ADDR_INIT_FROM_CMD_INFO(cmd_info); - zb_uint8_t *data = zb_buf_begin(param); - - zb_int32_t data_remaining = 0; - - TRACE_MSG(TRACE_ZCL1, ">> zb_drlc_server_handle_get_scheduled_events", (FMT__0)); - - data_remaining = zb_buf_len(param); - - if (!ZB_ZCL_DRLC_GET_SCHEDULED_EVENTS_PAYLOAD_SIZE_IS_VALID((zb_uint8_t)data_remaining)) - { - TRACE_MSG(TRACE_ZCL1, "zb_drlc_server_handle_get_scheduled_events: " - "ERROR: invalid payload len (%d)", - (FMT__D, data_remaining)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return RET_INVALID_FORMAT; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl_in.start_time, data); data_remaining -= 4; - ZB_ZCL_PACKET_GET_DATA8(&pl_in.number_of_events, data); data_remaining --; - - if (data_remaining>0) - { - ZB_ZCL_PACKET_GET_DATA32(&pl_in.issuer_event_id, data); data_remaining -= 4; - } - - - if (data_remaining<0) - { - TRACE_MSG(TRACE_ZCL1, "zb_drlc_server_handle_get_scheduled_events: " - "ERROR: invalid issuer event id field length.", - (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return RET_INVALID_FORMAT; - } - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_DRLC_GET_SCHEDULED_EVENTS_CB_ID, RET_ERROR, cmd_info, &pl_in, &pl_out); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - if (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) - { - zb_drlc_server_send_load_control_event(param, - &dst_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - &pl_out, - NULL); - } - else - { - TRACE_MSG(TRACE_ZCL1, "<< error in user cb call:%d", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - return RET_ERROR; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_drlc_server_handle_get_scheduled_events", (FMT__0)); - - return RET_OK; -} - - -static zb_bool_t zb_zcl_process_drlc_server_commands(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_uint8_t processed = ZB_FALSE; - zb_ret_t result = RET_ERROR; - /* ZCL8: CCB 2477: use UNSUP_COMMAND instead of any other Unsupported command status */ - zb_zcl_status_t status = ZB_ZCL_STATUS_UNSUP_CMD; - - switch ((zb_zcl_drlc_cli_cmd_t) cmd_info->cmd_id) - { - case ZB_ZCL_DRLC_CLI_CMD_REPORT_EVENT_STATUS: - result = zb_drlc_server_handle_report_event_status(param, cmd_info); - if ( RET_OK == result ) - { - status = ZB_ZCL_STATUS_SUCCESS; - } - else if (RET_INVALID_FORMAT == result) - { - status = ZB_ZCL_STATUS_INVALID_FIELD; - } - else - { - status = ZB_ZCL_STATUS_FAIL; - } - processed = ZB_TRUE; - break; - case ZB_ZCL_DRLC_CLI_CMD_GET_SCHEDULED_EVENTS: - result = zb_drlc_server_handle_get_scheduled_events(param, cmd_info); - if ( RET_OK == result ) - { - processed = ZB_TRUE; - status = ZB_ZCL_STATUS_SUCCESS; - } - else if (RET_INVALID_FORMAT == result) - { - processed = ZB_TRUE; - status = ZB_ZCL_STATUS_INVALID_FIELD; - } - else - { - status = ZB_ZCL_STATUS_NOT_FOUND; - } - break; - default: - break; - } - - if (!processed) - { - zb_zcl_send_default_handler(param, cmd_info, (zb_zcl_status_t) status); - } - - return ZB_TRUE; -} - - -/** - * - */ - - -zb_bool_t zb_zcl_process_s_drlc_specific_commands(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_drlc_specific_commands", (FMT__0)); - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_drlc_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - /* ZB_ASSERT(cmd_info.profile_id == ZB_AF_SE_PROFILE_ID); */ - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_DRLC); - - if (ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction) - { - return zb_zcl_process_drlc_server_commands(param, &cmd_info); - } - - return ZB_FALSE; - -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_DRLC || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_s_messaging.c b/zboss/development/src/zcl/zcl_s_messaging.c deleted file mode 100644 index be5fe04b14..0000000000 --- a/zboss/development/src/zcl/zcl_s_messaging.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: SERVER: Messaging cluster handlers -*/ - -#define ZB_TRACE_FILE_ID 68 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_MESSAGING) || defined DOXYGEN - -#include "zboss_api.h" -#include "zcl/zb_zcl_messaging.h" - -zb_uint8_t gs_messaging_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_MESSAGING_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_messaging_server_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_MESSAGING_SERVER_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_messaging_server_cmd_list = -{ - sizeof(gs_messaging_server_received_commands), gs_messaging_server_received_commands, - sizeof(gs_messaging_server_generated_commands), gs_messaging_server_generated_commands -}; - - -typedef zb_uint8_t *(zb_zcl_messaging_put_payload_cb_t)(zb_uint8_t *, const void *); - - -static zb_uint8_t *zb_zcl_messaging_display_msg_put_payload( - zb_uint8_t *data, const void *_payload) -{ - const zb_zcl_messaging_display_message_payload_t *payload = _payload; - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->message_id); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->message_control); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->start_time); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->duration_in_minutes); - ZB_ZCL_PACKET_PUT_DATA8(data, payload->message_len); - ZB_MEMCPY(data, payload->message, payload->message_len); - data+=payload->message_len; - ZB_ZCL_PACKET_PUT_DATA8(data, payload->extended_message_control); - - return data; -} - -static zb_uint8_t *zb_zcl_messaging_cancel_msg_put_payload( - zb_uint8_t *data, const void *_payload) -{ - const zb_zcl_messaging_cancel_message_payload_t *payload = _payload; - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->message_id); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->message_control); - return data; -} - -void zb_zcl_messaging_send_cancel_msg(zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_messaging_cancel_message_payload_t *payload, - zb_callback_t cb) -{ - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_messaging_send_cancel_msg", (FMT__0)); - - zb_zcl_send_cmd(param, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, - payload, sizeof(*payload), zb_zcl_messaging_cancel_msg_put_payload, - ZB_ZCL_CLUSTER_ID_MESSAGING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_MESSAGING_SRV_CMD_CANCEL_MESSAGE, - cb - ); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_messaging_send_cancel_msg", (FMT__0)); -} - -/* -Any message that needs truncation shall truncate on a UTF-8 character boundary. -The SE secure payload is 59 bytes for the Message field in a non-fragmented, non-source routed -Display Message packet (11 bytes for other Display Message fields). -Devices using fragmentation can send a message larger than this. -Reserving bytes for source route will reduce this. -*/ -void zb_zcl_messaging_send_display_msg(zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_messaging_display_message_payload_t *payload, - zb_callback_t cb) -{ - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_messaging_send_display_msg", (FMT__0)); - - zb_zcl_send_cmd(param, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, - payload, 0, zb_zcl_messaging_display_msg_put_payload, - ZB_ZCL_CLUSTER_ID_MESSAGING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_MESSAGING_SRV_CMD_DISPLAY_MESSAGE, - cb - ); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_messaging_send_display_msg", (FMT__0)); -} - - -static void zb_zcl_messaging_server_handle_message_confirmation(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_int32_t data_remaining = 0; - zb_zcl_messaging_message_confirm_payload_t pl = ZB_ZCL_MESSAGING_MSG_CONFIRM_PAYLOAD_INIT; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_messaging_server_handle_message_confirmation", (FMT__0)); - - data_remaining = zb_buf_len(param); - - if (!ZB_ZCL_MESSAGING_MSG_CONFIRM_PAYLOAD_SIZE_IS_VALID((zb_uint8_t)data_remaining)) - { - TRACE_MSG(TRACE_ZCL1, "zb_zcl_messaging_server_handle_message_confirmation: " - "ERROR: invalid payload len (%d)", - (FMT__D, data_remaining)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl.message_id, data); data_remaining -= 4; - ZB_ZCL_PACKET_GET_DATA32(&pl.confirmation_time, data); data_remaining -= 4; - if (data_remaining>0) - { - ZB_ZCL_PACKET_GET_DATA8(&pl.message_confirmation_control, data); data_remaining -= 1; - } - if (data_remaining>0) - { - ZB_ZCL_PACKET_GET_STATIC_STRING(pl.message_confirmation_response, data); - data_remaining -= pl.message_confirmation_response[0]; - } - - if (data_remaining<0) - { - /* Send INVALID_FIELD status if message has invalid length. */ - TRACE_MSG(TRACE_ZCL1, "zb_zcl_messaging_server_handle_message_confirmation: " - "ERROR: invalid msg confirmation response field length.", - (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_MESSAGING_MSG_CONFIRMATION_CB_ID, RET_OK, cmd_info, &pl, NULL); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - zb_zcl_send_default_handler(param, cmd_info, - (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK) ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_messaging_server_handle_message_confirmation", (FMT__0)); -} - -static void zb_zcl_messaging_server_handle_get_last_message(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_messaging_get_last_message_response_t resp = ZB_ZCL_MESSAGING_GET_LAST_MESSAGE_RESPONSE_INIT; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_messaging_server_handle_get_last_message", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_MESSAGING_GET_LAST_MSG_CB_ID, RET_OK, cmd_info, NULL, &resp); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - /*check ret status of application callback. In protected case we send not_found default response. */ - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - switch (resp.resp_type) - { - case ZB_ZCL_MESSAGING_RESPONSE_TYPE_NORMAL: - zb_zcl_messaging_send_display_msg(param, - (zb_addr_u *) &(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr), - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - &resp.resp.display_message, - NULL); - break; - case ZB_ZCL_MESSAGING_RESPONSE_TYPE_PROTECTED: - /*NOTE: DisplayProtectedMessage command is unsupported(optional)*/ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - break; - } - break; - case RET_NOT_FOUND: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - break; - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_messaging_server_handle_get_last_message", (FMT__0)); -} - - -static zb_bool_t zb_zcl_messaging_server_side_process_commands(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_bool_t processed = ZB_FALSE; - - switch ((zb_zcl_messaging_cli_cmd_t) cmd_info->cmd_id) - { - case ZB_ZCL_MESSAGING_CLI_CMD_GET_LAST_MESSAGE: - (void) zb_zcl_messaging_server_handle_get_last_message(param, cmd_info); - processed = ZB_TRUE; - break; - case ZB_ZCL_MESSAGING_CLI_CMD_MESSAGE_CONFIRMATION: - (void) zb_zcl_messaging_server_handle_message_confirmation(param, cmd_info); - processed = ZB_TRUE; - break; - default: - break; - } - - return processed; -} - - -zb_bool_t zb_zcl_process_s_messaging_specific_command(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t res = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_s_messaging_specific_command param %hd", (FMT__H, param)); - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_messaging_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - /* ZB_ASSERT(cmd_info.profile_id == ZB_AF_SE_PROFILE_ID); */ - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_MESSAGING); - - if (ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction) - { - /* process commands sent by clients */ - res = zb_zcl_messaging_server_side_process_commands(param, &cmd_info); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_s_messaging_specific_command", (FMT__0)); - return res; -} - -void zb_zcl_messaging_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_MESSAGING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_s_messaging_specific_command); -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_MESSAGING || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_s_metering.c b/zboss/development/src/zcl/zcl_s_metering.c deleted file mode 100644 index a2e5be6f59..0000000000 --- a/zboss/development/src/zcl/zcl_s_metering.c +++ /dev/null @@ -1,949 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: SERVER: Metering Cluster -*/ - -#define ZB_TRACE_FILE_ID 1802 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_METERING) || defined DOXYGEN - -#include "zcl/zb_zcl_metering.h" - -zb_uint8_t gs_metering_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_METERING_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_metering_server_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_METERING_SERVER_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_metering_server_cmd_list = -{ - sizeof(gs_metering_server_received_commands), gs_metering_server_received_commands, - sizeof(gs_metering_server_generated_commands), gs_metering_server_generated_commands -}; - -zb_bool_t zb_zcl_process_s_metering_specific_commands(zb_uint8_t param); - -static zb_ret_t check_value_metering(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_metering_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)check_value_metering, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)zb_zcl_process_s_metering_specific_commands); -} - -static zb_ret_t check_value_metering(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} - -#define ZB_ZCL_METERING_SEND_CMD_HELPER(_fn, _param, _cmd_info, _payload, _payload_size, _cb) \ - _fn((_param), \ - (zb_addr_u *) &ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).source.u.short_addr, \ - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, \ - ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).src_endpoint, \ - ZB_ZCL_PARSED_HDR_SHORT_DATA(_cmd_info).dst_endpoint, \ - (_payload), (_payload_size), (_cmd_info)->seq_number, (_cb)) - - -static zb_uint8_t *zb_zcl_metering_put_get_profile_response(zb_uint8_t *data, const void *pl_arg) -{ - - const zb_zcl_metering_get_profile_response_payload_t *pl = pl_arg; - - zb_uindex_t i; - - ZB_ASSERT(pl_arg); - ZB_ASSERT(data); - - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->end_time); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->status); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->profile_interval_period); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->number_of_periods_delivered); - - for (i = 0; i < pl->number_of_periods_delivered; i++) - { - ZB_ZCL_PACKET_PUT_DATA24(data, (pl->intervals + i)); - } - - return data; -} - - -static zb_uint8_t *zb_zcl_metering_put_get_sampled_data_response(zb_uint8_t *data, const void *pl_arg) -{ - - const zb_zcl_metering_get_sampled_data_response_payload_t *pl = pl_arg; - - zb_uindex_t i; - - ZB_ASSERT(pl_arg); - ZB_ASSERT(data); - - ZB_ZCL_PACKET_PUT_DATA16(data, &pl->sample_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->sample_start_time); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->sample_type); - ZB_ZCL_PACKET_PUT_DATA16(data, &pl->sample_request_interval); - ZB_ZCL_PACKET_PUT_DATA16(data, &pl->number_of_samples); - - for (i = 0; i < pl->number_of_samples; i++) - { - ZB_ZCL_PACKET_PUT_DATA24(data, (pl->samples + i)); - } - - return data; -} - - -static zb_uint8_t *zb_zcl_metering_put_publish_snapshot(zb_uint8_t *data, const void *pl_arg) -{ - - const zb_zcl_metering_publish_snapshot_payload_t *pl = pl_arg; - - zb_uindex_t i; - - ZB_ASSERT(pl_arg); - ZB_ASSERT(data); - - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->snapshot_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->snapshot_time); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->total_snapshots_found); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->command_index); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->total_number_of_commands); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->snapshot_cause); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->snapshot_payload_type); - - switch (pl->snapshot_payload_type) - { - case ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS: - { - const zb_zcl_metering_tou_delivered_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_delivered); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_time_stamp_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_time_stamp_delivered); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->bill_delivered_trailing_digit); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - } - break; - case ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS: - { - const zb_zcl_metering_tou_received_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_received); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS", (FMT__0)); - - - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_time_stamp_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_time_stamp_received); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->bill_received_trailing_digit); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_DELIVERED: - { - const zb_zcl_metering_block_delivered_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_delivered); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_DELIVERED", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_time_stamp_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_delivered); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_time_stamp_delivered); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->bill_delivered_trailing_digit); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_and_block_thresholds_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_and_block_thresholds_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_block_summation + i)); - } - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_RECEIVED: - { - const zb_zcl_metering_block_received_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_received); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_RECEIVED", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->bill_to_date_time_stamp_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_received); - ZB_ZCL_PACKET_PUT_DATA32(data, &sub_payload->projected_bill_time_stamp_received); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->bill_received_trailing_digit); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - - for (i = 0; i < sub_payload->number_of_tiers_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_and_block_thresholds_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_and_block_thresholds_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_block_summation + i)); - } - } - break; - case ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING: - { - const zb_zcl_metering_tou_delivered_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_delivered_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_delivered); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - } - break; - case ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING: - { - const zb_zcl_metering_tou_received_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_received_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_received); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING: - { - const zb_zcl_metering_block_tier_delivered_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_tier_delivered_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_delivered); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_and_block_thresholds_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_and_block_thresholds_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_block_summation + i)); - } - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING: - { - const zb_zcl_metering_block_tier_received_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_tier_received_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING", (FMT__0)); - - ZB_ZCL_PACKET_PUT_DATA48(data, &sub_payload->current_summation_received); - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_summation + i)); - } - - ZB_ZCL_PACKET_PUT_DATA8(data, sub_payload->number_of_tiers_and_block_thresholds_in_use); - - for (i = 0; i < sub_payload->number_of_tiers_and_block_thresholds_in_use; i++) - { - ZB_ZCL_PACKET_PUT_DATA48(data, (sub_payload->tier_block_summation + i)); - } - } - break; - case ZB_ZCL_METERING_DATA_UNAVAILABLE: - /*NOTE: from SE spec: The data for this snapshot is currently unavailable; - * if used, there is currently no subsequent snapshot data. - */ - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_DATA_UNAVAILABLE", (FMT__0)); - break; - default: - TRACE_MSG(TRACE_ZCL1, "Malformed packet: unsupported snapshot payload type", (FMT__0)); - break; - } - - return data; -} - - -static zb_int16_t zb_zcl_metering_calculate_publish_snapshot_payload_size(const zb_zcl_metering_publish_snapshot_payload_t *pl) -{ - - zb_int16_t pl_size = 0; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_calculate_publish_snapshot_payload_size", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_publish_snapshot_payload_t, snapshot_sub_payload); - - switch (pl->snapshot_payload_type) - { - case ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS: - { - const zb_zcl_metering_tou_delivered_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_delivered); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_DELIVERED_REGISTERS", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_tou_delivered_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS: - { - const zb_zcl_metering_tou_received_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_received); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_RECEIVED_REGISTERS", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_tou_received_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_DELIVERED: - { - const zb_zcl_metering_block_delivered_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_delivered); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_DELIVERED", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_block_delivered_payload_t, tier_summation); - pl_size += (sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE); - pl_size += 1; /* 1 byte for number_of_tiers_and_block_thresholds_in_use */ - pl_size += sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_RECEIVED: - { - const zb_zcl_metering_block_received_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_received); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_RECEIVED", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_block_received_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - pl_size += 1; /* 1 byte for number_of_tiers_and_block_thresholds_in_use */ - pl_size += sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING: - { - const zb_zcl_metering_tou_delivered_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_delivered_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_DELIVERED_NO_BILLING", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_tou_delivered_no_billing_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING: - { - const zb_zcl_metering_tou_received_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.tou_received_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_TOU_RECEIVED_NO_BILLING", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_tou_received_no_billing_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING: - { - const zb_zcl_metering_block_tier_delivered_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_tier_delivered_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_DELIVERED_NO_BILLING", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_block_tier_delivered_no_billing_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - pl_size += 1; /*1 byte for number_of_tiers_and_block_thresholds_in_use*/ - pl_size += sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING: - { - const zb_zcl_metering_block_tier_received_no_billing_payload_t *sub_payload = &(pl->snapshot_sub_payload.block_tier_received_no_billing); - - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_BLOCK_TIER_RECEIVED_NO_BILLING", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_metering_block_tier_received_no_billing_payload_t, tier_summation); - pl_size += sub_payload->number_of_tiers_in_use * ZB_48BIT_SIZE; - pl_size += 1; /*1 byte for number_of_tiers_and_block_thresholds_in_use*/ - pl_size += sub_payload->number_of_tiers_and_block_thresholds_in_use * ZB_48BIT_SIZE; - } - break; - case ZB_ZCL_METERING_DATA_UNAVAILABLE: - /*NOTE: from SE spec: The data for this snapshot is currently unavailable; - * if used, there is currently no subsequent snapshot data. - */ - TRACE_MSG(TRACE_ZCL1, "Snapshot payload type is ZB_ZCL_METERING_DATA_UNAVAILABLE", (FMT__0)); - break; - default: - TRACE_MSG(TRACE_ZCL1, "Malformed packet: unsupported snapshot payload type", (FMT__0)); - pl_size = -1; - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_calculate_publish_snapshot_payload_size", (FMT__0)); - - return pl_size; -} - - -void zb_zcl_metering_send_cmd_publish_snapshot(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_metering_publish_snapshot_payload_t *pl, - zb_callback_t cb) -{ - - zb_int16_t pl_size; - - pl_size = zb_zcl_metering_calculate_publish_snapshot_payload_size(pl); - - if ((pl_size <= 255)&& (pl_size > 0)) - { - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, pl, - (zb_uint8_t)pl_size, - zb_zcl_metering_put_publish_snapshot, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_SRV_CMD_PUBLISH_SNAPSHOT, - cb); - } - else - { - TRACE_MSG(TRACE_ERROR, "zb_zcl_metering_send_cmd_publish_snapshot: invalid payload", (FMT__0)); - ZB_ZCL_SCHEDULE_STATUS_ABORT(param, (zb_addr_u *)dst_addr, dst_addr_mode, dst_ep, src_ep, cb); - } -} - - -void zb_zcl_metering_send_cmd_request_fast_poll_mode_response(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_metering_request_fast_poll_mode_response_payload_t *pl, - zb_uint8_t pl_size, zb_uint8_t tsn, - zb_callback_t cb) -{ - - zb_zcl_metering_request_fast_poll_mode_response_payload_t payload; - zb_uint8_t *data = (zb_uint8_t *) &payload; - - ZB_BZERO(&payload, sizeof(payload)); - - ZB_ZCL_PACKET_PUT_DATA8(data, pl->applied_update_period_in_seconds); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->fast_poll_mode_end_time); - - if (0 == pl_size) - { - pl_size = sizeof(payload); - } - - zb_zcl_send_cmd_tsn(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, &payload, pl_size, - NULL, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_SRV_CMD_REQUEST_FAST_POLL_MODE_RESPONSE, - tsn, - cb); - -} - - -void zb_zcl_metering_send_cmd_get_profile_response(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, const zb_zcl_metering_get_profile_response_payload_t *pl, - zb_uint8_t pl_size, zb_uint8_t tsn, zb_callback_t cb) -{ - if (0 == pl_size) - { - pl_size = sizeof(zb_zcl_metering_get_profile_response_payload_t) - sizeof(void *) + ZB_24BIT_SIZE * pl->number_of_periods_delivered; - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_send_cmd_get_profile_response: " - "passed 0, calculated size = %d", (FMT__D, pl_size)); - } - - zb_zcl_send_cmd_tsn(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, pl, pl_size, - zb_zcl_metering_put_get_profile_response, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_SRV_CMD_GET_PROFILE_RESPONSE, - tsn, - cb); - -} - - -void zb_zcl_metering_send_cmd_get_sampled_data_response(zb_uint8_t param, const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_metering_get_sampled_data_response_payload_t *pl, - zb_uint8_t pl_size, zb_uint8_t tsn, zb_callback_t cb) -{ - if (0 == pl_size) - { - pl_size = ZB_OFFSETOF(zb_zcl_metering_get_sampled_data_response_payload_t, samples) + ZB_24BIT_SIZE * pl->number_of_samples; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_send_cmd_get_sampled_data_response: " - "passed 0, calculated size = %d", (FMT__D, pl_size)); - } - - - zb_zcl_send_cmd_tsn(param, dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, pl, pl_size, - zb_zcl_metering_put_get_sampled_data_response, - ZB_ZCL_CLUSTER_ID_METERING, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_METERING_SRV_CMD_GET_SAMPLED_DATA_RESPONSE, - tsn, - cb); -} - - -static const zb_uint8_t *zb_zcl_metering_get_snapshot_data_parse_payload(zb_zcl_metering_get_snapshot_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_get_snapshot_data_parse_payload", (FMT__0)); - - if (data_size < sizeof(zb_zcl_metering_get_snapshot_payload_t)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA32(&pl->earliest_start_time, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->latest_end_time, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->snapshot_offset, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->snapshot_cause, data); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_get_snapshot_data_parse_payload", (FMT__0)); - - return data; -} - - -static const zb_uint8_t *zb_zcl_metering_request_fast_poll_mode_parse_payload( - zb_zcl_metering_request_fast_poll_mode_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_request_fast_poll_mode_parse_payload", (FMT__0)); - - if (data_size < sizeof(zb_zcl_metering_request_fast_poll_mode_payload_t)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA8(&pl->fast_poll_update_period, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->duration_in_minutes, data); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_request_fast_poll_mode_parse_payload", (FMT__0)); - - return data; -} - - -static const zb_uint8_t *zb_zcl_metering_get_sampled_data_parse_payload(zb_zcl_metering_get_sampled_data_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_get_sampled_data_parse_payload", (FMT__0)); - - if (data_size < sizeof(zb_zcl_metering_get_sampled_data_payload_t)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA16(&pl->sample_id, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->earliest_sample_time, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->sample_type, data); - ZB_ZCL_PACKET_GET_DATA16(&pl->number_of_samples, data); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_get_sampled_data_parse_payload", (FMT__0)); - - return data; -} - - -static const zb_uint8_t *zb_zcl_metering_get_profile_parse_payload(zb_zcl_metering_get_profile_payload_t *pl, - zb_uint8_t param) -{ - zb_uint8_t *data = zb_buf_begin(param); - zb_uint8_t data_size = zb_buf_len(param); - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_metering_get_profile_parse_payload", (FMT__0)); - - /* NOTE: User must check whether the number_of_periods is greater than MaxNumberOfPeriodsDelivered. */ - if (!ZB_ZCL_METERING_GET_PROFILE_PAYLOAD_SIZE_IS_VALID(data_size)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid payload size %hd", (FMT__H, data_size)); - return NULL; - } - - ZB_ZCL_PACKET_GET_DATA8(&pl->interval_channel, data); - ZB_ZCL_PACKET_GET_DATA32(&pl->end_time, data); - ZB_ZCL_PACKET_GET_DATA8(&pl->number_of_periods, data); - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_metering_process_request_fast_poll_mode", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_REQUEST_FAST_POLL_MODE_CB_ID, - RET_ERROR, cmd_info, &pl_in, &pl_out); - - if (!zb_zcl_metering_request_fast_poll_mode_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid request_fast_poll_mode payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - ZB_ZCL_METERING_SEND_CMD_HELPER(zb_zcl_metering_send_cmd_request_fast_poll_mode_response, - param, cmd_info, &pl_out, 0, NULL); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_request_fast_poll_mode", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_metering_process_get_snapshot(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_metering_get_snapshot_payload_t pl_in ; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_process_get_snapshot", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_GET_SNAPSHOT_CB_ID, - RET_NOT_FOUND, cmd_info, &pl_in, NULL); - - if (!zb_zcl_metering_get_snapshot_data_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid get_snapshot payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - /*We don't send a PublishSnapshot command. Application must send reply - * for this command. - */ - zb_buf_free(param); - break; - case RET_NOT_FOUND: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_get_snapshot", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_metering_process_get_sampled_data(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_metering_get_sampled_data_payload_t pl_in ; - zb_zcl_metering_get_sampled_data_response_payload_t pl_out = { 0 }; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_process_get_sampled_data", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_GET_SAMPLED_DATA_CB_ID, - RET_NOT_FOUND, cmd_info, &pl_in, &pl_out); - - if (!zb_zcl_metering_get_sampled_data_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid get_sampled_data payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - ZB_ZCL_METERING_SEND_CMD_HELPER(zb_zcl_metering_send_cmd_get_sampled_data_response, - param, cmd_info, &pl_out, 0, NULL); - break; - case RET_NOT_FOUND: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_get_sampled_data", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_metering_process_get_profile(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_metering_get_profile_payload_t pl_in; - zb_zcl_metering_get_profile_response_payload_t pl_out = { 0 }; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_metering_process_get_profile", (FMT__0)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_METERING_GET_PROFILE_CB_ID, - RET_ERROR, cmd_info, &pl_in, &pl_out); - - if (!zb_zcl_metering_get_profile_parse_payload(&pl_in, param)) - { - TRACE_MSG(TRACE_ZCL1, "Invalid get_profile payload", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - ZB_ZCL_METERING_SEND_CMD_HELPER(zb_zcl_metering_send_cmd_get_profile_response, - param, cmd_info, &pl_out, 0, NULL); - break; - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_metering_process_get_profile", (FMT__0)); - - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_process_metering_server_commands(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_bool_t processed = ZB_FALSE; - - switch ((zb_zcl_metering_cli_cmd_t)cmd_info->cmd_id) - { - case ZB_ZCL_METERING_CLI_CMD_GET_PROFILE: - processed = zb_zcl_metering_process_get_profile(param, cmd_info); - break; - case ZB_ZCL_METERING_CLI_CMD_REQUEST_FAST_POLL_MODE: - processed = zb_zcl_metering_process_request_fast_poll_mode(param, cmd_info); - break; - case ZB_ZCL_METERING_CLI_CMD_GET_SNAPSHOT: - processed = zb_zcl_metering_process_get_snapshot(param, cmd_info); - break; - case ZB_ZCL_METERING_CLI_CMD_GET_SAMPLED_DATA: - processed = zb_zcl_metering_process_get_sampled_data(param, cmd_info); - break; - default: - break; - } - - return processed; -} - - -zb_bool_t zb_zcl_process_s_metering_specific_commands(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t processed = ZB_FALSE; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_metering_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_s_metering_specific_commands, " - "param=%hd, cmd_id=%hd", (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_METERING); - - if (ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction) - { - processed = zb_zcl_process_metering_server_commands(param, &cmd_info); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_s_metering_specific_commands (ret=%hd)", - (FMT__H, processed)); - - return processed; -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_METERING || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_s_price.c b/zboss/development/src/zcl/zcl_s_price.c deleted file mode 100644 index 5e72d418e9..0000000000 --- a/zboss/development/src/zcl/zcl_s_price.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: SERVER: Smart Energy Price Cluster -*/ - -#define ZB_TRACE_FILE_ID 3999 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_PRICE) || defined DOXYGEN - -#include "zcl/zb_zcl_price.h" - -zb_uint8_t gs_price_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_PRICE_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_price_server_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_PRICE_SERVER_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_price_server_cmd_list = -{ - sizeof(gs_price_server_received_commands), gs_price_server_received_commands, - sizeof(gs_price_server_generated_commands), gs_price_server_generated_commands -}; - -typedef zb_uint8_t *(*zb_price_put_payload_cb_t)(zb_uint8_t *, const void *); - -zb_bool_t zb_zcl_process_s_price_specific_commands(zb_uint8_t param); - -static zb_ret_t check_value_price(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_price_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_PRICE, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (zb_zcl_cluster_check_value_t)check_value_price, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_s_price_specific_commands); -} - -static zb_ret_t check_value_price(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for mandatory attributes are allowed, extra check for - * optional attributes is needed */ - - return RET_OK; -} -/* convert payload into raw data */ -static zb_uint8_t *zb_zcl_price_publish_price_put_payload( - zb_uint8_t *data, const void *_payload) -{ - const zb_zcl_price_publish_price_payload_t *payload = _payload; - - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->provider_id); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->rate_label[0]); - ZB_ZCL_PACKET_PUT_DATA_N(data, &payload->rate_label[1], - payload->rate_label[0]); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->issuer_event_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->current_time); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->unit_of_measure); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->currency); - ZB_ZCL_PACKET_PUT_DATA8 (data, - ZB_UINT4x2_TO_UINT8(payload->price_trailing_digit, - payload->price_tier)); - ZB_ZCL_PACKET_PUT_DATA8 (data, - ZB_UINT4x2_TO_UINT8(payload->number_of_price_tiers, - payload->register_tier)); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->start_time); - ZB_ZCL_PACKET_PUT_DATA16(data, &payload->duration_in_minutes); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->price); - - /* NK:CR Remove optional fields. */ - /* IA:CR: These fields must be presented in the packet. - * See SE spec, D.4.2.4.1.1: - * "Note: M = Mandatory field, O = Optional field. - * All fields must be present in the payload. - * Optional fields will be marked with specific values to - * indicate they are not being used." - */ - - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->price_ratio); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->generation_price); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->generation_price_ratio); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->alternate_cost_delivered); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->alternate_cost_unit); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->alternate_cost_trailing_digit); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->number_of_block_thresholds); - - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->price_control); - - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->number_of_generation_tiers); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->generation_tier); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->extended_number_of_price_tiers); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->extended_price_tier); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->extended_register_tier); - - return data; -} - -/* convert payload into raw data */ -static zb_uint8_t *zb_zcl_price_ack_put_payload( - zb_uint8_t *data, const void *_payload) -{ - const zb_zcl_price_ack_payload_t *payload = _payload; - - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->provider_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->issuer_event_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &payload->current_time); - ZB_ZCL_PACKET_PUT_DATA8 (data, payload->price_control); - return data; -} - -static inline const zb_uint8_t *zb_zcl_get_scheduled_prices_get_payload_from_data( - zb_zcl_price_get_scheduled_prices_payload_t *payload, const zb_uint8_t *data) -{ - ZB_ZCL_PACKET_GET_DATA32(&payload->start_time, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->number_of_events, data); - - return data; -} - - -static inline const zb_uint8_t *zb_zcl_get_tier_labels_get_payload_from_data( - zb_zcl_price_get_tier_labels_payload_t *payload, - const zb_uint8_t *data) -{ - ZB_ZCL_PACKET_GET_DATA32(&payload->issuer_tariff_id, data); - - return data; -} - - -static inline const zb_uint8_t *zb_zcl_price_ack_get_payload_from_data( - zb_zcl_price_ack_payload_t *payload, const zb_uint8_t *data) -{ - ZB_ZCL_PACKET_GET_DATA32(&payload->provider_id, data); - ZB_ZCL_PACKET_GET_DATA32(&payload->issuer_event_id, data); - ZB_ZCL_PACKET_GET_DATA32(&payload->current_time, data); - ZB_ZCL_PACKET_GET_DATA8 (&payload->price_control, data); - return data; -} - -void zb_zcl_price_send_cmd_price_ack( - zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_price_ack_payload_t *payload, - zb_callback_t cb -) -{ - zb_zcl_send_cmd(param, - dst_addr, - dst_addr_mode, - dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, - payload, - sizeof(*payload), - zb_zcl_price_ack_put_payload, - ZB_ZCL_CLUSTER_ID_PRICE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_PRICE_CLI_CMD_PRICE_ACK, - cb - ); -} - -void zb_zcl_price_send_cmd_get_current_price( - zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - zb_uint8_t rx_on_when_idle, - zb_callback_t cb -) -{ - zb_zcl_price_get_current_price_payload_t payload = ZB_ZCL_PRICE_GET_CURRENT_PRICE_PAYLOAD_INIT; - - if (rx_on_when_idle) - { - ZB_ZCL_PRICE_SET_REQUESTOR_RX_ON_WHEN_IDLE(&payload.command_options); - } - - zb_zcl_send_cmd(param, - dst_addr, - dst_addr_mode, - dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, - &payload, - sizeof(zb_zcl_price_get_current_price_payload_t), - NULL, - ZB_ZCL_CLUSTER_ID_PRICE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_PRICE_CLI_CMD_GET_CURRENT_PRICE, - cb - ); -} - -void zb_zcl_price_send_cmd_get_scheduled_prices(zb_uint8_t param, - const zb_addr_u *dst_addr, zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, zb_uint8_t src_ep, - const zb_zcl_price_get_scheduled_prices_payload_t *payload, - zb_callback_t cb -) -{ - zb_zcl_send_cmd(param, - dst_addr, - dst_addr_mode, - dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_SRV, - src_ep, - payload, - sizeof(*payload), - NULL, - ZB_ZCL_CLUSTER_ID_PRICE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_PRICE_CLI_CMD_GET_SCHEDULED_PRICES, - cb - ); -} - -void zb_zcl_price_send_cmd_publish_price( - zb_uint8_t param, - const zb_addr_u *dst_addr, - zb_aps_addr_mode_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t src_ep, - const zb_zcl_price_publish_price_payload_t *payload, - zb_callback_t cb -) -{ - zb_zcl_send_cmd(param, - dst_addr, - dst_addr_mode, - dst_ep, - ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, - payload, - sizeof(*payload), - zb_zcl_price_publish_price_put_payload, - ZB_ZCL_CLUSTER_ID_PRICE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_PRICE, - cb - ); -} - - -static zb_uint8_t *zb_zcl_price_put_publish_tier_labels(zb_uint8_t *data, const void *pl_arg) -{ - const zb_zcl_price_publish_tier_labels_payload_t *pl = pl_arg; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_price_put_publish_tier_labels", (FMT__0)); - - ZB_ASSERT(pl_arg); - ZB_ASSERT(data); - - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->provider_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->issuer_event_id); - ZB_ZCL_PACKET_PUT_DATA32(data, &pl->issuer_tariff_id); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->command_index); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->total_number_of_commands); - ZB_ZCL_PACKET_PUT_DATA8(data, pl->number_of_labels); - - for (i = 0; i < pl->number_of_labels; i++) - { - ZB_ZCL_PACKET_PUT_DATA8(data, (pl->tier_labels + i)->tier_id); - ZB_ZCL_PACKET_PUT_DATA_N(data, (pl->tier_labels + i)->tier_label, 1 + (pl->tier_labels + i)->tier_label[0]); - } - - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_price_put_publish_tier_labels", (FMT__0)); - return data; -} - - -static zb_uint8_t zb_zcl_price_calculate_publish_tier_labels_payload_size(zb_zcl_price_publish_tier_labels_payload_t *pl) -{ - zb_uint8_t pl_size = 0; - zb_uint8_t i; - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_price_calculate_publish_tier_labels_payload_size", (FMT__0)); - - pl_size += ZB_OFFSETOF(zb_zcl_price_publish_tier_labels_payload_t, tier_labels); - - for (i = 0; i <= pl->number_of_labels - 1; i++) - { - pl_size += ZB_OFFSETOF(zb_zcl_price_publish_tier_labels_sub_payload_t, tier_label); - pl_size += 1 + (pl->tier_labels + i)->tier_label[0]; /* the first byte + string length */ - } - - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_price_send_cmd_publish_tier_labels", (FMT__0)); - - zb_zcl_send_cmd(param, dst_addr, dst_addr_mode, - dst_ep, ZB_ZCL_FRAME_DIRECTION_TO_CLI, - src_ep, payload, - zb_zcl_price_calculate_publish_tier_labels_payload_size(payload), - zb_zcl_price_put_publish_tier_labels, - ZB_ZCL_CLUSTER_ID_PRICE, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE, - ZB_ZCL_PRICE_SRV_CMD_PUBLISH_TIER_LABELS, - cb); - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_price_send_cmd_publish_tier_labels", (FMT__0)); -} - -static zb_bool_t zb_price_publish_price_payload_is_valid( - zb_zcl_price_publish_price_payload_t *payload) -{ - /* NOTE: SE spec, D.4.2.4.1.1: - * "Rate Label (mandatory): A ZCL Octet String field capable of - * storing a 12 character string (the first Octet indicates length) ..." - */ - if (payload->rate_label[0] >= sizeof(payload->rate_label)) - { - TRACE_MSG(TRACE_ZCL1, "ERROR: " - "Invalid length of PublishPrice.RateLabel string" - " payload %hd size %hd", - (FMT__H_H, payload->rate_label[0], sizeof(payload->rate_label))); - return ZB_FALSE; - } - - return ZB_TRUE; -} - -/* Notify user about PriceAck command. */ -static zb_bool_t zb_zcl_price_process_price_ack(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_price_ack_payload_t pl_in = ZB_ZCL_PRICE_ACK_PAYLOAD_INIT; - zb_bool_t processed = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_price_process_price_ack", (FMT__0)); - - if (!ZB_ZCL_PRICE_ACK_PAYLOAD_SIZE_IS_VALID(zb_buf_len(param))) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet len (%hd).", (FMT__H, zb_buf_len(param))); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - (void) zb_zcl_price_ack_get_payload_from_data(&pl_in, zb_buf_begin(param)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_PRICE_PRICE_ACK_CB_ID, RET_ERROR, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb) - { - TRACE_MSG(TRACE_ZCL1, "Attempt to get price param from user app", (FMT__0)); - - (ZCL_CTX().device_cb)(param); - - processed = (zb_bool_t) (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK); - - if (!processed) - { - TRACE_MSG(TRACE_ZCL1, "ERROR: " - "Unable to get price_ack params from user app, err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - if (processed) - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_SUCCESS); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_price_process_price_ack", (FMT__0)); - return processed; -} - - -static zb_bool_t zb_zcl_price_process_get_scheduled_prices(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_price_get_scheduled_prices_payload_t pl_in = ZB_ZCL_PRICE_GET_SCHEDULED_PRICES_PAYLOAD_INIT; - zb_bool_t processed = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_price_process_get_scheduled_prices", (FMT__0)); - - if (!ZB_ZCL_PRICE_GET_SCHEDULED_PRICES_PAYLOAD_SIZE_IS_VALID(zb_buf_len(param))) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet len (%hd).", (FMT__H, zb_buf_len(param))); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - (void) zb_zcl_get_scheduled_prices_get_payload_from_data(&pl_in, zb_buf_begin(param)); - - /* value 0x00000000 will be replaced with the current time stamp. */ - if (pl_in.start_time == 0) - { - pl_in.start_time = zb_get_utc_time(); - } - - TRACE_MSG(TRACE_ZCL1, "Got GetScheduledPrices packet with %hd events, %d time stamp.", - (FMT__H_D, pl_in.number_of_events, pl_in.start_time)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_PRICE_GET_SCHEDULED_PRICES_CB_ID, - RET_NOT_FOUND, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - processed = (zb_bool_t)(ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK); - } - - if (!processed) - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - } - else - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_price_process_get_scheduled_prices", (FMT__0)); - return ZB_TRUE; -} - - -static zb_bool_t zb_zcl_price_process_get_tier_labels(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_price_get_tier_labels_payload_t pl_in; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_price_process_get_tier_labels", (FMT__0)); - - if (!ZB_ZCL_PRICE_GET_TIER_LABELS_PAYLOAD_SIZE_IS_VALID(zb_buf_len(param))) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet len (%hd).", (FMT__H, zb_buf_len(param))); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - if (!zb_zcl_get_tier_labels_get_payload_from_data(&pl_in, zb_buf_begin(param))) - { - TRACE_MSG(TRACE_ZCL1, "Malformed packet", (FMT__0)); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return ZB_TRUE; - } - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_PRICE_GET_TIER_LABELS_CB_ID, - RET_NOT_FOUND, cmd_info, &pl_in, NULL); - - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - /*We don't send a PublishTierLabels command. Application must send reply - * for this command. - */ - zb_buf_free(param); - return ZB_TRUE; - case RET_NOT_FOUND: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - break; - case RET_ERROR: - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_price_process_get_tier_labels", (FMT__0)); - return ZB_TRUE; -} - - -/* Get payload information from user and send PublishPrice to the client. */ -static void zb_zcl_price_process_get_current_price(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_bool_t price_data_is_available = ZB_FALSE; - zb_zcl_price_get_current_price_payload_t pl_in = ZB_ZCL_PRICE_GET_CURRENT_PRICE_PAYLOAD_INIT; - zb_zcl_price_publish_price_payload_t pl_out = ZB_ZCL_PRICE_PUBLISH_PRICE_PAYLOAD_INIT; - zb_uint8_t *data = zb_buf_begin(param); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_price_process_get_current_price", (FMT__0)); - - if (!ZB_ZCL_PRICE_GET_CURRENT_PRICE_PAYLOAD_SIZE_IS_VALID(zb_buf_len(param))) - { - TRACE_MSG(TRACE_ZCL1, "Invalid packet len (%hd).", (FMT__H, zb_buf_len(param))); - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - /* Input payload: get Command Options (see D.4.2.3.2.1.1).*/ - ZB_ZCL_PACKET_GET_DATA8(&pl_in.command_options, data); - - /* 0. Allocate params and fill it with default values */ - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_PRICE_GET_CURRENT_PRICE_CB_ID, RET_NOT_FOUND, cmd_info, &pl_in, &pl_out); - ZB_ZCL_DEVICE_CMD_PARAM_OUT_GET(param, zb_zcl_price_publish_price_payload_t)->current_time = zb_get_utc_time(); - - /* 1. Get params from user */ - if (ZCL_CTX().device_cb) - { - TRACE_MSG(TRACE_ZCL1, "Attempt to get price param from user app", (FMT__0)); - - (ZCL_CTX().device_cb)(param); - - price_data_is_available = (zb_bool_t)(ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK); - - if (!price_data_is_available) - { - TRACE_MSG(TRACE_ZCL1, "ERROR: " - "Unable to get publish_price params from user app, err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "User app callback isn't defined.", (FMT__0)); - } - - /* 2. Validate payload */ - if (price_data_is_available) - { - price_data_is_available = zb_price_publish_price_payload_is_valid(&pl_out); - } - - /* 3. Send result */ - if (price_data_is_available) - { - ZB_ZCL_PRICE_SEND_CMD_PUBLISH_PRICE(param, - (zb_addr_u *) &ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - &pl_out); - } - else - { - /* If the server don't have any information about price, - * it should send default response with NOT_FOUND status to the client. - * See SE spec, subclause D.4.2.3.1. - */ - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_NOT_FOUND); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_price_process_get_current_price", (FMT__0)); -} - -static zb_bool_t zb_zcl_process_price_server_commands(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_bool_t processed = ZB_FALSE; - - switch ((zb_zcl_price_client_cmd_t) cmd_info->cmd_id) - { - case ZB_ZCL_PRICE_CLI_CMD_GET_CURRENT_PRICE: - zb_zcl_price_process_get_current_price(param, cmd_info); - processed = ZB_TRUE; - break; - case ZB_ZCL_PRICE_CLI_CMD_GET_SCHEDULED_PRICES: - processed = zb_zcl_price_process_get_scheduled_prices(param, cmd_info); - break; - case ZB_ZCL_PRICE_CLI_CMD_PRICE_ACK: - processed = zb_zcl_price_process_price_ack(param, cmd_info); - break; - case ZB_ZCL_PRICE_CLI_CMD_GET_TIER_LABELS: - processed = zb_zcl_price_process_get_tier_labels(param, cmd_info); - break; - default: - break; - } - - return processed; -} - -zb_bool_t zb_zcl_process_s_price_specific_commands(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_bool_t processed = ZB_FALSE; - - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_price_server_cmd_list; - return ZB_TRUE; - } - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_process_s_price_specific_commands, " - "param=%hd, cmd_id=%hd", (FMT__H_H, param, cmd_info.cmd_id)); - - /* ZB_ASSERT(cmd_info.profile_id == ZB_AF_SE_PROFILE_ID); */ - ZB_ASSERT(cmd_info.cluster_id == ZB_ZCL_CLUSTER_ID_PRICE); - - if (ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction) - { - processed = zb_zcl_process_price_server_commands(param, &cmd_info); - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_process_s_price_specific_commands (ret=%hd)", - (FMT__H, processed)); - - return processed; -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_PRICE || defined DOXYGEN */ diff --git a/zboss/development/src/zcl/zcl_s_wwah.c b/zboss/development/src/zcl/zcl_s_wwah.c deleted file mode 100644 index a847f90e34..0000000000 --- a/zboss/development/src/zcl/zcl_s_wwah.c +++ /dev/null @@ -1,3054 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL WWAH cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 12084 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_WWAH) - -#include "zb_zcl.h" -#include "zcl/zb_zcl_wwah.h" -#include "zdo_wwah_survey_beacons.h" -#include "zdo_wwah_parent_classification.h" -#include "zb_bdb_internal.h" -#include "zdo_hubs.h" -#include "zb_error_indication.h" - -/* #include "zb_mac_globals.h" */ -/* #include "mac_internal.h" */ -#include "zb_aps.h" -#include "zcl/zb_zcl_keep_alive.h" - -#ifdef ZB_ZCL_ENABLE_WWAH_SERVER - -zb_zcl_wwah_attr_t wwah_attr; - -void zb_zcl_wwah_periodic_checkin_countdown(zb_uint8_t param); -void zb_zcl_wwah_recounter_checkin(void); -void zb_zcl_wwah_periodic_checkin_timeout(zb_uint8_t param); - -static const zb_uint8_t gs_wwah_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_WWAH_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -static const zb_uint8_t gs_wwah_server_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_WWAH_SERVER_ROLE_GENERATED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_wwah_server_cmd_list = -{ - sizeof(gs_wwah_server_received_commands), (zb_uint8_t *)gs_wwah_server_received_commands, - sizeof(gs_wwah_server_generated_commands), (zb_uint8_t *)gs_wwah_server_generated_commands -}; - -zb_ret_t check_value_wwah(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -zb_bool_t zb_zcl_process_wwah_specific_commands_srv(zb_uint8_t param); - -zb_uint8_t wwah_endpoint = 0; - -void get_pib_max_frame_retries_confirm(zb_uint8_t param) -{ - zb_mlme_get_confirm_t *conf = (zb_mlme_get_confirm_t *)zb_buf_begin(param); - zb_uint8_t *ptr = ((zb_uint8_t *)conf) + sizeof(zb_mlme_get_confirm_t); - zb_uint8_t zero = 0; - TRACE_MSG(TRACE_ZCL1, "get_pib_max_frame_confirm status %hd value %hd", (FMT__H_H, conf->status, *ptr)); - - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_MAC_RETRY_COUNT_ID, - conf->status == MAC_SUCCESS ? ptr: &zero, - ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - (void)zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - zb_buf_free(param); -} - -void get_pib_max_frame_retries(zb_uint8_t param) -{ - zb_mlme_get_request_t *req = NULL; - - req = zb_buf_initial_alloc(param, sizeof(zb_mlme_get_request_t)); - req->pib_attr = ZB_PIB_ATTRIBUTE_MAX_FRAME_RETRIES; - req->confirm_cb_u.cb = get_pib_max_frame_retries_confirm; - req->iface_id = ZB_PIBCACHE_PRIMARY_IFACE(); - - zb_multimac_mlme_get_request_proxy(param); -} - -static zb_bool_t wwah_handle_read_attr_resp(zb_bufid_t param) -{ - zb_bool_t processed = ZB_FALSE; - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - - if (zb_zcl_wwah_periodic_checkin_block_zcl_cmd(cmd_info)) - { - processed = zb_zcl_wwah_periodic_checkin_read_attr_handle(param); - } - - return processed; -} - -void zb_zcl_wwah_init_server(void) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_init_server", (FMT__0)); - if (zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_wwah, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_wwah_specific_commands_srv) == RET_OK - /* If we are here - we show wwah behavior */ -#if 0 - && WWAH_CTX().wwah_behavior -#endif - ) - { - wwah_endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_WWAH, ZB_ZCL_CLUSTER_SERVER_ROLE); - WWAH_CTX().periodic_checkins.poll_method = ZB_ZCL_WWAH_PERIODIC_CHECKINS_NOT_SUPPORTED; - WWAH_CTX().periodic_checkins.tsn = ZB_ZDO_INVALID_TSN; - - WWAH_CTX().wwah_hub_endpoint = 0; /* Will set it after matching */ - WWAH_CTX().wwah_hub_address = 0x0000; /*zb_address_short_by_ieee(ZB_AIB().trust_center_address) */ - WWAH_CTX().time_server_addr = 0; - WWAH_CTX().time_server_endpoint = 0; - - ZB_ASSERT(ZB_ZCL_WWAH_APS_ACK_EXEMPT_TABLE_SIZE > 0 && - ZB_ZCL_WWAH_APS_ACK_EXEMPT_TABLE_SIZE <= 0xFF); - - ZB_MEMSET(WWAH_CTX().aps_ack_exempt_table, (zb_uint8_t)ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD, - sizeof(WWAH_CTX().aps_ack_exempt_table)); - WWAH_CTX().aps_ack_exempt_table_cnt = 0; - - ZB_ASSERT(ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_TABLE_SIZE > 0 && - ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_TABLE_SIZE <= 0xFF); - - ZB_MEMSET(WWAH_CTX().aps_link_key_authorization_table, (zb_uint8_t)ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD, - sizeof(WWAH_CTX().aps_link_key_authorization_table)); - WWAH_CTX().aps_link_key_authorization_table_cnt = 0; - - WWAH_CTX().aps_link_key_enabled_by_default = ZB_FALSE; - - ZB_ASSERT(ZB_ZCL_WWAH_USE_TRUST_CENTER_FOR_CLUSTER_TABLE_SIZE == 4); - - ZB_MEMSET(WWAH_CTX().use_trust_center_for_cluster_table, (zb_uint8_t)ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD, sizeof(WWAH_CTX().use_trust_center_for_cluster_table)); - WWAH_CTX().use_trust_center_for_cluster_table_cnt = 0; - - ZCL_SELECTOR().block_zcl_cmd = zb_zcl_wwah_periodic_checkin_block_zcl_cmd; - ZCL_SELECTOR().read_attr_resp_handler = wwah_handle_read_attr_resp; - - /* TODO: Place f&b checking for endpoint*/ - } -} - -void zb_zcl_wwah_init_server_attr(void) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_init_server_attr", (FMT__0)); - - wwah_attr.cluster_revision = ZB_ZCL_WWAH_CLUSTER_REVISION_MIN_VALUE; - wwah_attr.disable_ota_downgrades = ZB_FALSE; - wwah_attr.mgmt_leave_without_rejoin_enabled = ZB_ZCL_WWAH_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED_DEFAULT_VALUE; - wwah_attr.nwk_retry_count = ZB_NWKC_UNICAST_RETRIES; - zb_buf_get_out_delayed(get_pib_max_frame_retries); /* fetch and update */ - wwah_attr.router_check_in_enabled = ZB_ZCL_WWAH_ROUTER_CHECK_IN_ENABLED_DEFAULT_VALUE; - wwah_attr.touchlink_interpan_enabled = ZB_TRUE; - wwah_attr.wwah_parent_classification_enabled = ZB_ZCL_WWAH_WWAH_PARENT_CLASSIFICATION_ENABLED_DEFAULT_VALUE; - wwah_attr.wwah_app_event_retry_enabled = ZB_ZCL_WWAH_WWAH_APP_EVENT_RETRY_ENABLED_DEFAULT_VALUE; - wwah_attr.wwah_app_event_retry_queue_size = ZB_ZCL_WWAH_WWAH_APP_EVENT_RETRY_QUEUE_SIZE_DEFAULT_VALUE; - wwah_attr.wwah_rejoin_enabled = ZB_ZCL_WWAH_WWAH_REJOIN_ENABLED_DEFAULT_VALUE; - wwah_attr.mac_poll_failure_wait_time = ZB_ZCL_WWAH_MAC_POLL_FAILURE_WAIT_TIME_DEFAULT_VALUE; - wwah_attr.configuration_mode_enabled = ZB_ZCL_WWAH_CONFIGURATION_MODE_ENABLED_DEFAULT_VALUE; - wwah_attr.current_debug_report_id = 0; - wwah_attr.tc_security_on_nwk_key_rotation_enabled = ZB_ZCL_WWAH_TC_SECURITY_ON_NWK_KEY_ROTATION_ENABLED_DEFAULT_VALUE; - wwah_attr.wwah_bad_parent_recovery_enabled = ZB_ZCL_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_DEFAULT_VALUE; - wwah_attr.pending_network_update_channel = ZB_ZCL_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_DEFAULT_VALUE; - wwah_attr.pending_network_update_panid = ZB_ZCL_WWAH_PENDING_NETWORK_UPDATE_PANID_DEFAULT_VALUE; - wwah_attr.ota_max_offline_duration = 0; - - zb_zcl_wwah_stop_periodic_checkin(); - zb_zcl_wwah_stop_bad_parent_recovery(); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_init_server_attr", (FMT__0)); -} - -zb_ret_t check_value_wwah(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - ZVUNUSED(attr_id); - ZVUNUSED(value); - ZVUNUSED(endpoint); - - /* All values for attributes are allowed */ - - return RET_OK; -} -/* - * Invoke User App with WWAH command. - */ -void zb_zcl_wwah_invoke_user_app(zb_uint8_t param, zb_uint16_t endpoint16) -{ - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_invoke_user_app %hx endpoint %d", - (FMT__H_D, param, endpoint16)); - zb_buf_free(param); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_invoke_user_app", (FMT__0)); -} - -/* - * Check new channel in ZDO MGMT Network Update command - * @return ZB_TRUE if new channel is allowed - * ZB_FALSE otherwise - */ - -zb_bool_t zb_zcl_wwah_check_new_channel(zb_uint32_t new_channel_mask) -{ - zb_zcl_attr_t *attr_desc; - zb_bool_t ret = ZB_TRUE; - if (zb_is_wwah_server()) - { - attr_desc = zb_zcl_get_attr_desc_a(wwah_endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_ID); - ZB_ASSERT(attr_desc); - if ((zb_bool_t)(ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) != 0xFF)) - { - ret = (zb_bool_t)(1u << ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) == new_channel_mask); - } - } - return ret; -} - -/* - * Check new PANID in NLME Network Update req command - * @return ZB_TRUE if new PANID is allowed - */ - -zb_bool_t zb_zcl_wwah_check_new_panid(zb_uint16_t new_panid) -{ - zb_zcl_attr_t *attr_desc; - zb_bool_t ret = ZB_TRUE; - if (zb_is_wwah_server()) - { - attr_desc = zb_zcl_get_attr_desc_a(wwah_endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_PANID_ID); - ZB_ASSERT(attr_desc); - if ((zb_bool_t)(ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) != 0xFFFF)) - { - ret = (zb_bool_t)(ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc) == new_panid); - }; - } - return ret; -} - -/* - * Check if Zigbee non-Green Power Inter-pan messages supported - * @return ZB_TRUE interpan message allowed - * ZB_FALSE otherwise - */ - -zb_bool_t zb_zcl_wwah_check_if_interpan_supported(void) -{ - zb_zcl_attr_t *attr_desc; - zb_bool_t ret = ZB_TRUE; - - if (zb_is_wwah_server()) - { - attr_desc = zb_zcl_get_attr_desc_a(wwah_endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_TOUCHLINK_INTERPAN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ret = (zb_bool_t)ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - } - return ret; -} - - -/* - * Check if OTA Downgrade disabled - * @return ZB_TRUE Disabled - * ZB_FALSE Enabled - */ - -zb_bool_t zb_zcl_wwah_check_if_downgrade_disabled(void) -{ - zb_zcl_attr_t *attr_desc; - zb_bool_t ret = ZB_FALSE; - if (zb_is_wwah_server()) - { - attr_desc = zb_zcl_get_attr_desc_a(wwah_endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_DISABLE_OTA_DOWNGRADES_ID); - ZB_ASSERT(attr_desc); - ret = (zb_bool_t)ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - } - return ret; -} - -/* - * Check if specific WWAH Router Check-Ins mechanism is enabled. - * @return ZB_TRUE mechanism enabled - * ZB_FALSE otherwise - */ - -zb_bool_t zb_zcl_wwah_check_if_periodic_router_check_ins_enabled(void) -{ - zb_zcl_attr_t *attr_desc; - zb_bool_t ret = ZB_TRUE; - - if (zb_is_wwah_server()) - { - attr_desc = zb_zcl_get_attr_desc_a(wwah_endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ret = (zb_bool_t)ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - } - return ret; -} - -zb_bool_t zb_zcl_wwah_check_src_addr_for_cluster(zb_uint16_t short_addr, zb_uint16_t cluster_id) -{ - zb_bool_t ret = ZB_TRUE; - - if (zb_is_wwah_server()) - { - /* 17-01067-015 WWAH ZCL Cluster definition, Server Dependencies - * The device SHALL reject all packets regarding this cluster if they are not sourced from the - * hub/coordinator and not encrypted by the TC Link Key with error code NOT_AUTHORIZED - * (0x7e). To check if the command is from the coordinator, the device could check that the - * source network address is 0x0000. - */ - if (cluster_id == ZB_ZCL_CLUSTER_ID_WWAH && short_addr != 0) - { - ret = ZB_FALSE; - } - } - return ret; -} - -/* - * Get additional retries count for mac poll - * @return ZB_ZCL_WWAH_MAC_POLL_RETRY_COUNT if WWAH behavior is enabled - * @return 0 otherwise - */ - -zb_uint8_t zb_zcl_wwah_mac_poll_cca_retry_count(void) -{ - zb_uint8_t ret = 0; - if (zb_is_wwah_server()) - { - ret = ZB_ZCL_WWAH_MAC_POLL_RETRY_COUNT; - } - return ret; -} - -/* - * Get MACPollFailureWaitTime in beacon intervals - * @return MACPollFailureWaitTime in beacon intervals - */ - -zb_time_t zb_zcl_wwah_mac_poll_failure_wait_time(void) -{ - zb_zcl_attr_t *attr_desc; - zb_time_t ret = 0; - if (zb_is_wwah_server()) - { - attr_desc = zb_zcl_get_attr_desc_a(wwah_endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_MAC_POLL_FAILURE_WAIT_TIME_ID); - ZB_ASSERT(attr_desc); - ret = ZB_MILLISECONDS_TO_BEACON_INTERVAL(ZB_SECONDS_TO_MILLISECONDS(ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc))); - } - return ret; -} - -/* - * Check if APS ACK requirement needed for given cluster. - */ -zb_bool_t zb_zcl_wwah_check_if_aps_ack_needed(zb_uint16_t cluster_id) -{ - zb_uindex_t i; - zb_bool_t ret = ZB_TRUE; - TRACE_MSG(TRACE_ZCL1, "check_if_aps_ack_needed (cnt %hd)", (FMT__H, WWAH_CTX().aps_ack_exempt_table_cnt)); - if (zb_is_wwah_server()) - { - for (i = 0; i < WWAH_CTX().aps_ack_exempt_table_cnt; ++i) - { - if (cluster_id == WWAH_CTX().aps_ack_exempt_table[i]) - { - ret = ZB_FALSE; - break; - } - } - } - return ret; -} - -/* - * Check if requiring APS level security needed for given cluster. - */ -zb_bool_t zb_zcl_wwah_check_if_aps_link_key_authorization_needed(zb_uint16_t cluster_id) -{ - zb_uindex_t i; - zb_bool_t ret = WWAH_CTX().aps_link_key_enabled_by_default; - - //return ZB_FALSE; /* Uncomment to temporary disable APS Security in WWAH.*/ - TRACE_MSG(TRACE_ZCL1, ">> check_if_aps_link_key_authorization_needed cluster_id 0x%x", (FMT__D, cluster_id)); - - if (cluster_id == ZB_ZCL_CLUSTER_ID_WWAH) - { - ret = ZB_TRUE; - } - else if (zb_is_wwah_server()) - { - for (i = 0; i < WWAH_CTX().aps_link_key_authorization_table_cnt; ++i) - { - if (cluster_id == WWAH_CTX().aps_link_key_authorization_table[i]) - { - /* Inverted policy: see WWAH_CTX().aps_link_key_enabled_by_default description */ - ret = (zb_bool_t)!ret; - break; - } - } - } - - TRACE_MSG(TRACE_ZCL1, "<< check_if_aps_link_key_authorization_needed ret %hd", (FMT__H, ret)); - return ret; -} - -/* - * Check if given cluster forced to use the Trust Center. - * @retval ZB_TRUE - cluster is forced to use only Trust Center - * @retval ZB_FALSE - otherwise - */ -zb_bool_t zb_zcl_wwah_check_if_forced_to_use_tc(zb_uint16_t cluster_id) -{ - zb_uindex_t i; - zb_bool_t ret = ZB_FALSE; - if (zb_is_wwah_server()) - { - for (i = 0; i < WWAH_CTX().use_trust_center_for_cluster_table_cnt; ++i) - { - if (cluster_id == WWAH_CTX().use_trust_center_for_cluster_table[i]) - { - ret = ZB_TRUE; - break; - } - } - } - return ret; -} - -/* - * This function is used to check cluster permissions based on "Use TC for Cluster" command - * @param nwk_addr address of remote device - * @param cluster_id given cluster - * @retval ZB_TRUE frame is OK when: Given cluster is forced to use TC and nwk_addr belongs to TC - * or WWAH behaviour is switched off - * or Distributed security is switched on - * @retval ZB_FALSE otherwise - */ -zb_bool_t zb_zcl_wwah_check_cluster_permission(zb_uint16_t nwk_addr, zb_uint16_t cluster_id) -{ - zb_bool_t ret = ZB_TRUE; - if (!IS_DISTRIBUTED_SECURITY() && zb_zcl_wwah_check_if_forced_to_use_tc(cluster_id)) - { - ret = (zb_bool_t)(nwk_addr == zb_aib_get_trust_center_short_address()); - } - return ret; -} - - -zb_bool_t zb_zcl_wwah_check_if_wwah_rejoin_enabled(void) -{ - zb_zcl_attr_t *attr_desc; - zb_bool_t ret = ZB_FALSE; - - if (zb_is_wwah_server()) - { - attr_desc = zb_zcl_get_attr_desc_a(wwah_endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_REJOIN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ret = (zb_bool_t)ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - } - TRACE_MSG(TRACE_NWK1, "zb_zcl_wwah_check_if_wwah_rejoin_enabled: %hd", (FMT__H, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_enable_aps_link_key_authorization_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_wwah_cluster_list_t payload = { 0 }; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_enable_aps_link_key_authorization_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_WWAH_GET_CLUSTER_LIST_CMD(param, &payload, status); - if (status == ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - if (payload.number_of_clusters > ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_TABLE_SIZE) - { - status = ZB_ZCL_PARSE_STATUS_FAILURE; - } - } - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_ENABLE_APS_LINK_KEY_AUTHORIZATION_HANDLER", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - /* This command enforces that all cluster commands for the cluster have APS level security. */ - ZB_MEMSET(WWAH_CTX().aps_link_key_authorization_table, (zb_uint8_t)ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD, - sizeof(WWAH_CTX().aps_link_key_authorization_table)); - WWAH_CTX().aps_link_key_authorization_table_cnt = 0; - - for(i = 0; i < payload.number_of_clusters; ++i) - { - if (payload.cluster_id[i] != ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD && - /* The device SHALL ignore any cluster IDs in the list for clusters not supported by the device. */ - is_cluster_present(payload.cluster_id[i])) - { - TRACE_MSG(TRACE_ZCL1, "add cluster %hd to aps_link_key_authorization_table (idx %hd)", (FMT__D_H, payload.cluster_id[i], WWAH_CTX().aps_link_key_authorization_table_cnt)); - WWAH_CTX().aps_link_key_authorization_table[WWAH_CTX().aps_link_key_authorization_table_cnt++] = payload.cluster_id[i]; - } - } - WWAH_CTX().aps_link_key_enabled_by_default = ZB_TRUE; - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_enable_aps_link_key_authorization_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_disable_aps_link_key_authorization_handler(zb_uint8_t param){ - zb_ret_t ret = RET_OK; - zb_zcl_wwah_cluster_list_t payload = { 0 }; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_disable_aps_link_key_authorization_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_WWAH_GET_CLUSTER_LIST_CMD(param, &payload, status); - if (status == ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - if (payload.number_of_clusters > ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_TABLE_SIZE) - { - status = ZB_ZCL_PARSE_STATUS_FAILURE; - } - } - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_DISABLE_APS_LINK_KEY_AUTHORIZATION_HANDLER", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - /* This command removes the enforcement of APS level security on cluster commands. */ - ZB_MEMSET(WWAH_CTX().aps_link_key_authorization_table, (zb_uint8_t)ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD, - sizeof(WWAH_CTX().aps_link_key_authorization_table)); - WWAH_CTX().aps_link_key_authorization_table_cnt = 0; - for(i = 0; i < payload.number_of_clusters; ++i) - { - if (payload.cluster_id[i] != ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD && - /* The device SHALL ignore any cluster IDs in the list for clusters not supported by the device. */ - is_cluster_present(payload.cluster_id[i])) - { - WWAH_CTX().aps_link_key_authorization_table[WWAH_CTX().aps_link_key_authorization_table_cnt++] = payload.cluster_id[i]; - } - } - WWAH_CTX().aps_link_key_enabled_by_default = ZB_FALSE; - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_disable_aps_link_key_authorization_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_aps_link_key_authorization_query_handler(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t cmd_info; - zb_zcl_parse_status_t status; - zb_ret_t ret; - zb_uint16_t cluster_id; - zb_bool_t allowed; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_aps_link_key_authorization_query_handler %hd", (FMT__H, param)); - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - ZB_ZCL_WWAH_GET_APS_LINK_KEY_AUTHORIZATION_QUERY(param, cluster_id, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - /* The device SHALL respond with value of FALSE for any cluster IDs in the list for clusters - * not supported by the device.*/ - allowed = is_cluster_present(cluster_id) ? - zb_zcl_wwah_check_if_aps_link_key_authorization_needed(cluster_id) : ZB_FALSE; - ZB_ZCL_WWAH_SEND_APS_LINK_KEY_AUTHORIZATION_QUERY_RESPONSE(param, - cmd_info.seq_number, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - NULL, - &cluster_id, - allowed); - ret = RET_BUSY; - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_aps_link_key_authorization_query_handler", (FMT__0)); - return ret; -} - -#ifdef ZB_JOIN_CLIENT -void zb_zcl_wwah_request_key(zb_uint8_t param) -{ - zb_apsme_request_key_req_t *req = ZB_BUF_GET_PARAM(param, zb_apsme_request_key_req_t); - TRACE_MSG(TRACE_ZCL1, "Scheduling apsme request key", (FMT__0)); - zb_aib_get_trust_center_address(req->dest_address); - /* 17-01067-015 WWAH ZCL cluster definition, p.14: - On receipt of this command, a device SHALL request a new Trust Center Link Key from the - Trust Center. */ - req->key_type = ZB_TC_LINK_KEY; //ZB_APP_LINK_KEY; - ZB_SCHEDULE_CALLBACK(zb_secur_apsme_request_key, param); -} - -zb_ret_t zb_zcl_wwah_request_new_aps_link_key_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_request_new_aps_link_key_handler %hd", (FMT__H, param)); - - zb_buf_get_out_delayed(zb_zcl_wwah_request_key); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_request_new_aps_link_key_handler", (FMT__0)); - return ret; -} -zb_ret_t zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t enable_bool = ZB_TRUE; - zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_handler %hx", (FMT__H, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - ZB_ZCL_WWAH_GET_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM(param, payload, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_HANDLER", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - if (!payload.first_backoff_time_in_seconds || - !payload.backoff_sequence_common_ratio || - payload.max_backoff_time_in_seconds <= payload.first_backoff_time_in_seconds || - payload.max_backoff_time_in_seconds > 86400 || - !payload.max_re_delivery_attempts) - { - TRACE_MSG(TRACE_ZCL1, "payload of ZB_ZCL_WWAH_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_HANDLER is out of range", (FMT__0)); - ret = RET_OUT_OF_RANGE; - } - else - { - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_ENABLED_ID, - (zb_uint8_t *)&enable_bool, - ZB_FALSE); - } - if (ret == RET_OK) - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_WWAH_ENABLE_APP_EVENT_RETRY_ALGORITHM_CB_ID, RET_NOT_FOUND, &cmd_info, &payload, NULL); - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - ret = ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param); - } - else - { - ret = RET_NOT_FOUND; - } - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_handler", (FMT__0)); - return ret; -} - -zb_ret_t zb_zcl_wwah_disable_wwah_app_event_retry_algorithm_handler(zb_uint8_t param) -{ - zb_ret_t ret; - zb_bool_t disable_bool = ZB_FALSE; - zb_zcl_parsed_hdr_t cmd_info; - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_disable_wwah_app_event_retry_algorithm_handler %hd", (FMT__H, param)); - - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_ENABLED_ID, - (zb_uint8_t *)&disable_bool, - ZB_FALSE); - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_WWAH_DISABLE_APP_EVENT_RETRY_ALGORITHM_CB_ID, RET_NOT_FOUND, &cmd_info, NULL, NULL); - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - ret = ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param); - } - else - { - ret = RET_NOT_FOUND; - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_disable_wwah_app_event_retry_algorithm_handler", (FMT__0)); - return ret; -} - -void zb_zcl_wwah_send_request_time(zb_uint8_t param) -{ - zb_uint8_t *cmd_ptr; - zb_ret_t ret = WWAH_CTX().time_server_endpoint == 0 ? RET_ERROR : RET_OK; - zb_uint8_t time_client_endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_TIME, ZB_ZCL_CLUSTER_CLIENT_ROLE); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_send_request_time param %hd", (FMT__H, param)); - if (ret == RET_OK) - { - if (!param) - { - ret = zb_buf_get_out_delayed(zb_zcl_wwah_send_request_time); - if (ret != RET_OK) - { - TRACE_MSG(TRACE_ERROR, "Failed zb_buf_get_out_delayed [%d]", (FMT__D, ret)); - } - } - else - { - ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ(param, cmd_ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); - ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, ZB_ZCL_ATTR_TIME_TIME_STATUS_ID); - ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, ZB_ZCL_ATTR_TIME_TIME_ID); - ZB_ZCL_GENERAL_SEND_READ_ATTR_REQ(param, - cmd_ptr, - WWAH_CTX().time_server_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - WWAH_CTX().time_server_endpoint, - time_client_endpoint, - ZB_AF_HA_PROFILE_ID, - ZB_ZCL_CLUSTER_ID_TIME, - NULL); - } - } - else if (param) - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_send_request_time", (FMT__0)); -} - -static void zb_zcl_wwah_match_desc_time_cb(zb_uint8_t param) -{ - zb_bufid_t buf = param; - zb_uint8_t *zdp_cmd = zb_buf_begin(buf); - zb_zdo_match_desc_resp_t *resp = (zb_zdo_match_desc_resp_t*)zdp_cmd; - - if (resp->status == ZB_ZDP_STATUS_SUCCESS && resp->match_len == 1) - { - WWAH_CTX().time_server_addr = resp->nwk_addr; - WWAH_CTX().time_server_endpoint = *((zb_uint8_t*)(resp + 1)); - ZB_SCHEDULE_CALLBACK(zb_zcl_wwah_send_request_time, param); - } - else - { - zb_buf_free(buf); - } -} - -static void zb_zcl_wwah_match_desc_time(zb_uint8_t param) -{ - if (!param) - { - zb_buf_get_out_delayed(zb_zcl_wwah_match_desc_time); - } - else - { - zb_bufid_t buf = param; - zb_zdo_match_desc_param_t *req; - - TRACE_MSG(TRACE_APP1, "send_wwah_match_desc", (FMT__0)); - - req = zb_buf_initial_alloc(buf, sizeof(zb_zdo_match_desc_param_t) + 1 * sizeof(zb_uint16_t)); - - req->nwk_addr = zb_aib_get_trust_center_short_address(); - req->addr_of_interest = req->nwk_addr; - req->profile_id = ZB_AF_HA_PROFILE_ID; - req->num_in_clusters = 1; - req->num_out_clusters = 0; - req->cluster_list[0] = ZB_ZCL_CLUSTER_ID_TIME; - - zb_zdo_match_desc_req(param, zb_zcl_wwah_match_desc_time_cb); - - } -} - -zb_ret_t zb_zcl_wwah_update_time(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_update_time", (FMT__0)); - - if (WWAH_CTX().time_server_endpoint) - { - ret = zb_schedule_alarm(zb_zcl_wwah_send_request_time, param, ZB_MILLISECONDS_TO_BEACON_INTERVAL(200)); - } - else - { - /* If we do not have Time Server Endpoint, need to discover it first */ - zb_buf_get_out_delayed(zb_zcl_wwah_match_desc_time); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_update_time", (FMT__0)); - return ret; -} - -zb_ret_t zb_zcl_wwah_request_time_handler(zb_uint8_t param) -{ - zb_ret_t ret; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_request_time_handler %hd", (FMT__H, param)); - - ret = zb_zcl_wwah_update_time(0); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_request_time_handler", (FMT__0)); - return ret; -} - -zb_ret_t zb_zcl_wwah_enable_wwah_rejoin_algorithm_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_wwah_enable_wwah_rejoin_algorithm_t payload; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_enable_wwah_rejoin_algorithm_handler %hd", (FMT__H, param)); - - ZB_ZCL_WWAH_GET_ENABLE_WWAH_REJOIN_ALGORITHM(param, payload, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_ENABLE_WWAH_REJOIN_ALGORITHM", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - zb_bool_t enable_bool = ZB_TRUE; - - ZB_MEMCPY(&WWAH_CTX().rejoin_alg, &payload, sizeof(zb_zcl_wwah_enable_wwah_rejoin_algorithm_t)); - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_REJOIN_ENABLED_ID, - (zb_uint8_t *)&enable_bool, - ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - if (RET_OK != ret) - { - TRACE_MSG(TRACE_ERROR, "failed to write into nvram", (FMT__0)); - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_enable_wwah_rejoin_algorithm_handler, ret %d", (FMT__D, ret)); - return ret; -} - - -zb_ret_t zb_zcl_wwah_disable_wwah_rejoin_algorithm_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t enable_bool = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_disable_wwah_rejoin_algorithm_handler %hd", (FMT__H, param)); - - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_REJOIN_ENABLED_ID, - (zb_uint8_t *)&enable_bool, - ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - if (RET_OK != ret) - { - TRACE_MSG(TRACE_ERROR, "failed to write into nvram", (FMT__0)); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_disable_wwah_rejoin_algorithm_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_get_rejoin_tmo(zb_uint16_t attempt, zb_time_t *tmo) -{ - zb_ret_t ret = RET_OK; - zb_uint16_t fast_rejoin_attempts = 1; - zb_uint16_t is_fast_rejoin_attempt = 0; - zb_uint16_t backoff_attempt; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_wwah_get_rejoin_tmo: attempt %d", (FMT__D, attempt)); - - if (wwah_attr.wwah_rejoin_enabled) - { - ZB_ASSERT(WWAH_CTX().rejoin_alg.duration_between_each_rejoin_in_seconds); - fast_rejoin_attempts = (WWAH_CTX().rejoin_alg.fast_rejoin_timeout_in_seconds / WWAH_CTX().rejoin_alg.duration_between_each_rejoin_in_seconds) + 1; - } - - backoff_attempt = ((attempt - 1) / fast_rejoin_attempts); - TRACE_MSG(TRACE_ZCL1, "backoff_attempt %d", (FMT__D, backoff_attempt)); - TRACE_MSG(TRACE_ZCL1, "fast_rejoin_attempts %d", (FMT__D, fast_rejoin_attempts)); - - if (!wwah_attr.wwah_rejoin_enabled) - { - /* Wait for next Rejoin cycle */ - ret = RET_EXIT; - *tmo = ZB_ZCL_WWAH_REJOIN_SLEEPY_ED_TIMEOUT; - } - else - { - is_fast_rejoin_attempt = (attempt % fast_rejoin_attempts); - TRACE_MSG(TRACE_ZCL1, "is_fast_rejoin_attempt %d", (FMT__D, is_fast_rejoin_attempt)); - if (is_fast_rejoin_attempt) - { - *tmo = WWAH_CTX().rejoin_alg.duration_between_each_rejoin_in_seconds * ZB_TIME_ONE_SECOND; - } - else - { - /* A value of 0x00 means do not perform any Fast Rejoins after the Fast Rejoin Time In Seconds - * (eg. no backoff/retry). - * FIXME: Not very clear what does it mean. Let's wait for next Rejoin cycle in that case. - */ - if (!WWAH_CTX().rejoin_alg.fast_rejoin_first_backoff_in_seconds) - { - /* Wait for next Rejoin cycle */ - ret = RET_EXIT; - *tmo = ZB_ZCL_WWAH_REJOIN_SLEEPY_ED_TIMEOUT; - } - else - { - /* A value of 0x00 means do not reset the backoff duration */ - if (WWAH_CTX().rejoin_alg.max_backoff_iterations - && backoff_attempt >= WWAH_CTX().rejoin_alg.max_backoff_iterations) - { - backoff_attempt %= WWAH_CTX().rejoin_alg.max_backoff_iterations; - } - - *tmo = (WWAH_CTX().rejoin_alg.fast_rejoin_first_backoff_in_seconds * (1l << backoff_attempt)); - if (*tmo > WWAH_CTX().rejoin_alg.rejoin_max_backoff_time_in_seconds) - { - *tmo = WWAH_CTX().rejoin_alg.rejoin_max_backoff_time_in_seconds; - } - *tmo *= ZB_TIME_ONE_SECOND; - } - } - } - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_wwah_get_rejoin_tmo: ret %hd tmo %ld sec", (FMT__H_L, ret, *tmo / ZB_TIME_ONE_SECOND)); - return ret; -} - -#endif /* ZB_JOIN_CLIENT */ - -zb_ret_t zb_zcl_wwah_set_ias_zone_enrollment_method_handler(zb_uint8_t param) -{ - zb_uint8_t enrollment_method; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_set_ias_zone_enrollment_method_handler %hd", (FMT__H, param)); - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - ZB_ZCL_WWAH_GET_SET_IAS_ZONE_ENROLLMENT_METHOD(param, enrollment_method, status); - - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_SET_IAS_ZONE_ENROLLMENT_METHOD", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - if (ZCL_CTX().device_cb) - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_WWAH_SET_IAS_ZONE_ENROLLMENT_METHOD_CB_ID, RET_NOT_FOUND, &cmd_info, &enrollment_method, NULL); - ZCL_CTX().device_cb(param); - ret = ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param); - } - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_set_ias_zone_enrollment_method_handler", (FMT__0)); - return ret; -} - -zb_ret_t zb_zcl_wwah_clear_binding_table_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_clear_binding_table_handler %hd", (FMT__H, param)); - - apsme_forget_device(); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_clear_binding_table_handler", (FMT__0)); - return ret; -} - -zb_ret_t zb_zcl_wwah_enable_periodic_router_check_ins_handler(zb_uint8_t param){ - zb_ret_t ret = RET_OK; - zb_uint16_t payload; - zb_zcl_parse_status_t status; - zb_bool_t enable_bool = ZB_TRUE; - zb_zcl_attr_t *attr_desc; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_enable_periodic_router_check_ins_handler %hd", (FMT__H, param)); - ZB_ZCL_WWAH_GET_ENABLE_PERIODIC_ROUTER_CHECK_INS(param, payload, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS || payload == 0) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_ENABLE_PERIODIC_ROUTER_CHECK_INS_HANDLER", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - /* On receipt of this command, a router or non-sleepy end device SHALL enable the Periodic - * Router Check-in WWAH functionality */ - if (!zb_get_rx_on_when_idle()) - { - TRACE_MSG(TRACE_ZCL1, "RX-OFF: ignore command", (FMT__0)); - ret = RET_IGNORE; - } - else - { - TRACE_MSG(TRACE_ZCL1, "RX-ON: set attribute, start periodic checkins", (FMT__0)); - attr_desc = zb_zcl_get_attr_desc_a(wwah_endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID); - ZB_ASSERT(attr_desc); - /* Check it was not started before */ - if (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) == ZB_FALSE) - { - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID, - (zb_uint8_t *)&enable_bool, - ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - WWAH_CTX().periodic_checkins.keepalive_base = payload; - WWAH_CTX().periodic_checkins.keepalive_jitter = 0; - zb_zcl_wwah_start_periodic_checkin(); - } - } - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_enable_periodic_router_check_ins_handler ret %hd", (FMT__H, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_disable_periodic_router_check_ins_handler(zb_uint8_t param) -{ - zb_ret_t ret; - zb_bool_t disable_bool = ZB_FALSE; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_disable_periodic_router_check_ins_handler %hd", (FMT__H, param)); - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID, - (zb_uint8_t *)&disable_bool, - ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - zb_zcl_wwah_stop_periodic_checkin(); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_disable_periodic_router_check_ins_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_set_mac_poll_cca_wait_time_handler(zb_uint8_t param){ - zb_ret_t ret = RET_OK; - zb_uint8_t payload; - zb_zcl_parse_status_t status; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_set_mac_poll_cca_wait_time_handler %hd", (FMT__H, param)); - ZB_ZCL_WWAH_GET_SET_MAC_POLL_CCA_WAIT_TIME(param, payload, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_SET_MAC_POLL_CCA_WAIT_TIME_HANDLER", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_MAC_POLL_FAILURE_WAIT_TIME_ID, - &payload, - ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_set_mac_poll_cca_wait_time_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_set_pending_network_update_handler(zb_uint8_t param){ - zb_ret_t ret = RET_OK; - zb_zcl_wwah_set_pending_network_update_t payload; - zb_zcl_parse_status_t status; - zb_uint8_t channel; - zb_uint16_t pan_id; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_set_pending_network_update_handler %hd", (FMT__H, param)); - - ZB_ZCL_WWAH_GET_SET_PENDING_NETWORK_UPDATE(param, payload, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_SET_PENDING_NETWORK_UPDATE_HANDLER", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - channel = payload.channel; - pan_id = payload.pan_id; - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_ID, - &channel, - ZB_FALSE); - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_PANID_ID, - (zb_uint8_t *)&pan_id, - ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_set_pending_network_update_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_require_aps_acks_on_unicasts_handler(zb_uint8_t param){ - zb_ret_t ret = RET_OK; - zb_zcl_wwah_cluster_list_t payload = { 0 }; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_require_aps_acks_on_unicasts_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_WWAH_GET_CLUSTER_LIST_CMD(param, &payload, status); - if (status == ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - if (payload.number_of_clusters > ZB_ZCL_WWAH_APS_ACK_EXEMPT_TABLE_SIZE) - { - status = ZB_ZCL_PARSE_STATUS_FAILURE; - } - } - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_REQUIRE_APS_ACKS_ON_UNICASTS_HANDLER", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - /* This command enforces that all unicast commands have APS ACKs enabled. */ - ZB_MEMSET(WWAH_CTX().aps_ack_exempt_table, (zb_uint8_t)ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD, - sizeof(WWAH_CTX().aps_ack_exempt_table)); - WWAH_CTX().aps_ack_exempt_table_cnt = 0; - for(i = 0; i < payload.number_of_clusters; ++i) - { - if (payload.cluster_id[i] != ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD && - /* The device SHALL ignore any cluster IDs in the list for clusters not supported by the device.*/ - is_cluster_present(payload.cluster_id[i])) - { - WWAH_CTX().aps_ack_exempt_table[WWAH_CTX().aps_ack_exempt_table_cnt++] = payload.cluster_id[i]; - } - } - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - } - return ret; -} - -zb_ret_t zb_zcl_wwah_remove_aps_acks_on_unicasts_requirement_handler(zb_uint8_t param) -{ - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_remove_aps_acks_on_unicasts_requirement_handler %hd", (FMT__H, param)); - ZB_MEMSET(WWAH_CTX().aps_ack_exempt_table, (zb_uint8_t)ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD, - sizeof(WWAH_CTX().aps_ack_exempt_table)); - WWAH_CTX().aps_ack_exempt_table_cnt = 0; - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_remove_aps_acks_on_unicasts_requirement_handler", (FMT__0)); - return RET_OK; -} - -zb_ret_t zb_zcl_wwah_aps_ack_requirement_query_handler(zb_uint8_t param) -{ - zb_uint8_t *resp_data; - zb_zcl_parsed_hdr_t cmd_info; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_aps_ack_requirement_query_handler %hd", (FMT__H, param)); - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - ZB_ZCL_WWAH_SEND_APS_ACK_REQUIREMENT_QUERY_RESPONSE_START(param, cmd_info.seq_number, WWAH_CTX().aps_ack_exempt_table_cnt, resp_data); - for(i = 0; i < WWAH_CTX().aps_ack_exempt_table_cnt; ++i) - { - ZB_ZCL_WWAH_SEND_APS_ACK_REQUIREMENT_QUERY_RESPONSE_ADD(resp_data, &WWAH_CTX().aps_ack_exempt_table[i]); - } - ZB_ZCL_WWAH_SEND_APS_ACK_REQUIREMENT_QUERY_RESPONSE_END( - resp_data, - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_aps_ack_requirement_query_handler", (FMT__0)); - return RET_BUSY; -} - -zb_ret_t zb_zcl_wwah_debug_report_query_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_uint8_t payload; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_zcl_wwah_debug_report_t *out; - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_debug_report_query_handler %hd", (FMT__H, param)); - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - ZB_ZCL_WWAH_GET_DEBUG_REPORT_QUERY(param, payload, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_GET_DEBUG_REPORT_QUERY", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, ZB_ZCL_WWAH_DEBUG_REPORT_QUERY_CB_ID, RET_NOT_FOUND, &cmd_info, &payload, NULL); - if (ZCL_CTX().device_cb) - { - ZCL_CTX().device_cb(param); - ret = ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param); - if (ret == RET_OK) - { - out = ZB_ZCL_DEVICE_CMD_PARAM_OUT_GET(param, zb_zcl_wwah_debug_report_t); - ZB_ASSERT(out); - ZB_ZCL_WWAH_SEND_DEBUG_REPORT_QUERY_RESPONSE(param, - cmd_info.seq_number, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - NULL, - out->report_id, - out->report, - out->report_size); - ret = RET_BUSY; - } - } - else - { - ret = RET_NOT_FOUND; - } - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_debug_report_query_handler", (FMT__0)); - return ret; -} - - -zb_ret_t zb_zcl_wwah_survey_beacons_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t need_standard_beacons; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_wwah_survey_beacons_handler", (FMT__0)); - -#if !(defined ZB_BEACON_SURVEY && defined ZB_ZCL_ENABLE_WWAH_SERVER) - TRACE_MSG(TRACE_ZCL1, "beacon survey is disabled", (FMT__0)); - ret = RET_ERROR; -#else - if (WWAH_CTX().survey_beacons_in_progress) - { - ret = RET_BUSY; - zb_buf_free(param); - } - - if (ZB_IS_DEVICE_ZR()) - { - ret = RET_IGNORE; - } - - if (RET_OK == ret) - { - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - ZB_ZCL_WWAH_GET_SURVEY_BEACONS(param, need_standard_beacons, status); - - if (ZB_ZCL_PARSE_STATUS_FAILURE == status) - { - TRACE_MSG(TRACE_ZCL1, "beacons survey parsing is failed", (FMT__0)); - ret = RET_ERROR; - } - } - - if (RET_OK == ret) - { - zb_zdo_beacon_survey_configuration_t *conf = - ZB_BUF_GET_PARAM(param, zb_zdo_beacon_survey_configuration_t); - - conf->params.channel_page = zb_get_current_page(); - conf->params.channel_mask = (1l << zb_get_current_channel()); - conf->params.scan_type = (zb_uint8_t)(((zb_uint8_t)need_standard_beacons) ? ACTIVE_SCAN : ENHANCED_ACTIVE_SCAN); - - ret = zdo_wwah_start_survey_beacons(param); - - if (RET_OK == ret) - { - WWAH_CTX().survey_beacons_seq_number = cmd_info.seq_number; - WWAH_CTX().survey_beacons_in_progress = 1; - ret = RET_BUSY; - TRACE_MSG(TRACE_ZDO1, "survey beacons started, seq_number %hd", (FMT__H, cmd_info.seq_number)); - } - } -#endif /* ZB_BEACON_SURVEY */ - - TRACE_MSG(TRACE_ZCL1, "<> zb_zcl_wwah_send_survey_beacons_response, buf %hd, obuf %hd, beacons_number %hd", - (FMT__H_H_H, buf, obuf, resp_params->parents.count_potential_parents)); - - ZB_ZCL_WWAH_SEND_SURVEY_BEACONS_RESPONSE_ADD_ALL( - ptr, - resp_params->parents.parents_info_ptr, - resp_params->parents.count_potential_parents); - - ZB_ZCL_WWAH_SEND_SURVEY_BEACONS_RESPONSE_END( - ptr, - obuf, - WWAH_CTX().wwah_hub_address, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - WWAH_CTX().wwah_hub_endpoint, - src_endpoint, - get_profile_id_by_endpoint(src_endpoint)); - - WWAH_CTX().survey_beacons_in_progress = 0; - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_wwah_send_survey_beacons_response", (FMT__0)); - } -} -#endif - -zb_ret_t zb_zcl_wwah_disable_ota_downgrades_handler(zb_uint8_t param) -{ - zb_ret_t ret; - zb_bool_t disable_bool = ZB_TRUE; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_disable_ota_downgrades_handler %hd", (FMT__H, param)); - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_DISABLE_OTA_DOWNGRADES_ID, - (zb_uint8_t *)&disable_bool, - ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_disable_ota_downgrades_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_disable_mgmt_leave_without_rejoin_handler(zb_uint8_t param) -{ - zb_ret_t ret; - zb_bool_t disable_bool = ZB_FALSE; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_disable_mgmt_leave_without_rejoin_handler %hd", (FMT__H, param)); - - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED_ID, - (zb_uint8_t *)&disable_bool, - ZB_FALSE); - zb_wwah_set_leave_without_rejoin_allowed(disable_bool); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_disable_mgmt_leave_without_rejoin_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_disable_touchlink_interpan_message_support_handler(zb_uint8_t param) -{ - zb_ret_t ret; - zb_bool_t disable_bool = ZB_FALSE; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_disable_touchlink_interpan_message_support_handler %hd", (FMT__H, param)); - - /* can be enabled but not disabled */ - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_TOUCHLINK_INTERPAN_ENABLED_ID, - (zb_uint8_t *)&disable_bool, - ZB_FALSE); - zb_wwah_set_interpan_supported(disable_bool); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_disable_touchlink_interpan_message_support_handler, ret %d", (FMT__D, ret)); - return ret; -} - -/** - * @brief Set value for the 'WWAH Parent Classification is enabled' attribute - * - * @param is_enabled - new attribute value - */ -static zb_ret_t zdo_wwah_set_parent_classification_state(zb_bool_t is_enabled) -{ - zb_ret_t ret = RET_OK; - zb_bool_t current_state; - zb_uint8_t endpoint; - zb_zcl_attr_t *attr_desc_parent_classification = NULL; - - TRACE_MSG(TRACE_ZDO1, ">>zdo_wwah_set_parent_classification_state, is_enabled %d", (FMT__D, is_enabled)); - - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_WWAH, ZB_ZCL_CLUSTER_SERVER_ROLE); - - if (0x00 == endpoint || 0xFF == endpoint) - { - ret = RET_ERROR; - TRACE_MSG(TRACE_ZCL2, "invalid endpoint", (FMT__0)); - } - - if (RET_OK == ret) - { - attr_desc_parent_classification = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_PARENT_CLASSIFICATION_ENABLED_ID); - } - - if (!attr_desc_parent_classification) - { - ret = RET_ERROR; - TRACE_MSG(TRACE_ZCL2, "invalid attribute descriptor", (FMT__0)); - } - - if (RET_OK == ret) - { - current_state = *(zb_bool_t*)attr_desc_parent_classification->data_p; - - TRACE_MSG(TRACE_ZCL2, "current state %d, new state %d", (FMT__D_D, current_state, is_enabled)); - - if (current_state != is_enabled) - { - /* sync with ZDO Hubs ctx */ - zdo_wwah_parent_classification_set(is_enabled); - ZB_ZCL_SET_ATTRIBUTE(endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_PARENT_CLASSIFICATION_ENABLED_ID, - (zb_uint8_t*)&is_enabled, - ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - } - } - - TRACE_MSG(TRACE_ZDO1, "< zb_zcl_wwah_enable_wwah_parent_classification_handler %hd", (FMT__H, param)); - - ret = zdo_wwah_set_parent_classification_state(ZB_TRUE); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_enable_wwah_parent_classification_handler", (FMT__0)); - return ret; -} - -zb_ret_t zb_zcl_wwah_disable_wwah_parent_classification_handler(zb_uint8_t param) -{ - zb_ret_t ret; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_disable_wwah_parent_classification_handler %hd", (FMT__H, param)); - - ret = zdo_wwah_set_parent_classification_state(ZB_FALSE); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_disable_wwah_parent_classification_handler", (FMT__0)); - return ret; -} - -zb_ret_t zb_zcl_wwah_enable_tc_security_on_nwk_key_rotation_handler(zb_uint8_t param) -{ - zb_ret_t ret; - zb_bool_t enable_bool = ZB_TRUE; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_enable_tc_security_on_nwk_key_rotation_handler %hd", (FMT__H, param)); - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_TC_SECURITY_ON_NWK_KEY_ROTATION_ENABLED_ID, - (zb_uint8_t *)&enable_bool, - ZB_FALSE); - - /* WWAH ZCL Cluster Definition: - * If TCSecurityOnNwkKeyRotationEnabled Attribute is set to TRUE, - * the node SHALL only process network key rotation commands, - * specifically APS Transport Key (command identifier 0x05), - * which are sent via unicast and are encrypted by the Trust Center Link Key. */ - zb_wwah_set_nwk_key_commands_broadcast_allowed(ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_enable_tc_security_on_nwk_key_rotation_handler, ret %d", (FMT__D, ret)); - return ret; -} - -/* ----------------------- BAD PARENT RECOVERY ----------------------- */ - -void zb_zcl_wwah_bad_parent_recovery_tmo(zb_zcl_wwah_bad_parent_recovery_signal_t sig); - -void zb_zcl_wwah_restart_bad_parent_recovery(zb_zcl_wwah_bad_parent_recovery_signal_t sig) -{ - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_wwah_restart_bad_parent_recovery: sig %hd", (FMT__H, sig)); - - if (WWAH_CTX().bad_parent_recovery.started) - { - if (sig == ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED) - { - WWAH_CTX().bad_parent_recovery.poll_control_checkin_failed_cnt = 0; - } - else - { - ZB_SCHEDULE_ALARM_CANCEL((zb_callback_t)zb_zcl_wwah_bad_parent_recovery_tmo, sig); - ZB_SCHEDULE_ALARM((zb_callback_t)zb_zcl_wwah_bad_parent_recovery_tmo, sig, ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_TIMEOUT); - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_wwah_restart_bad_parent_recovery", (FMT__0)); -} - -void zb_zcl_wwah_bad_parent_recovery_signal(zb_zcl_wwah_bad_parent_recovery_signal_t sig) -{ - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_wwah_bad_parent_recovery_signal sig %hd", (FMT__H, sig)); - - if (WWAH_CTX().bad_parent_recovery.started) - { - switch (sig) - { - case ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_RSSI_WITH_PARENT_OK: - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_RSSI_WITH_PARENT_OK", (FMT__0)); - zb_zcl_wwah_restart_bad_parent_recovery(ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_RSSI_WITH_PARENT_BAD); - break; - case ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_APS_ACK_OK: - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_APS_ACK_OK", (FMT__0)); - zb_zcl_wwah_restart_bad_parent_recovery(ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_APS_ACK_FAILED); - break; - case ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_OK: - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_OK", (FMT__0)); - zb_zcl_wwah_restart_bad_parent_recovery(ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED); - break; - case ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED: - TRACE_MSG(TRACE_ZCL1, "ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED", (FMT__0)); - ++WWAH_CTX().bad_parent_recovery.poll_control_checkin_failed_cnt; - if (WWAH_CTX().bad_parent_recovery.poll_control_checkin_failed_cnt == ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED_CNT) - { - zb_zcl_wwah_bad_parent_recovery_tmo(ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED); - } - break; - default: - TRACE_MSG(TRACE_ZCL1, "sig %hd, ignore", (FMT__H, sig)); - break; - } - } - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_wwah_bad_parent_recovery_signal", (FMT__0)); -} - -void zb_zcl_wwah_stop_bad_parent_recovery(void) -{ - ZB_SCHEDULE_ALARM_CANCEL((zb_callback_t)zb_zcl_wwah_bad_parent_recovery_tmo, ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_RSSI_WITH_PARENT_BAD); - ZB_SCHEDULE_ALARM_CANCEL((zb_callback_t)zb_zcl_wwah_bad_parent_recovery_tmo, ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_APS_ACK_FAILED); - WWAH_CTX().bad_parent_recovery.poll_control_checkin_failed_cnt = 0; - WWAH_CTX().bad_parent_recovery.started = ZB_FALSE; -} - -void zb_zcl_wwah_start_bad_parent_recovery(void) -{ - zb_zcl_attr_t *attr_desc; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_wwah_start_bad_parent_recovery", (FMT__0)); - - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_WWAH, ZB_ZCL_CLUSTER_SERVER_ROLE); - if (endpoint) - { - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_ID); - ZB_ASSERT(attr_desc); - - if (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) == ZB_TRUE && - !ZB_IS_DEVICE_ZC()) - { - WWAH_CTX().bad_parent_recovery.started = ZB_TRUE; - - zb_zcl_wwah_restart_bad_parent_recovery(ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_RSSI_WITH_PARENT_BAD); - zb_zcl_wwah_restart_bad_parent_recovery(ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_APS_ACK_FAILED); - zb_zcl_wwah_restart_bad_parent_recovery(ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED); - } - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_wwah_start_bad_parent_recovery", (FMT__0)); -} - -void zb_zcl_wwah_bad_parent_recovery_tmo(zb_zcl_wwah_bad_parent_recovery_signal_t sig) -{ - TRACE_MSG(TRACE_ZCL1, "zb_zcl_wwah_start_bad_parent_recovery_tmo: sig %hd", (FMT__H, sig)); - zb_zcl_wwah_stop_bad_parent_recovery(); - bdb_start_rejoin_recovery( - 0, - (sig == ZB_ZCL_WWAH_BAD_PARENT_RECOVERY_POLL_CONTROL_CHECK_IN_FAILED) ? - BDB_COMM_REJOIN_REASON_POLL_CONTROL_CHECK_IN : - BDB_COMM_REJOIN_REASON_UNSPECIFIED); -} - -zb_ret_t zb_zcl_wwah_enable_wwah_bad_parent_recovery_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t enable_bool = ZB_TRUE; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_enable_wwah_bad_parent_recovery_handler %hd", (FMT__H, param)); - - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_ID, - (zb_uint8_t *)&enable_bool, - ZB_FALSE); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - zb_zcl_wwah_start_bad_parent_recovery(); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_enable_wwah_bad_parent_recovery_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_disable_wwah_bad_parent_recovery_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t enable_bool = ZB_FALSE; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_disable_wwah_bad_parent_recovery_handler %hd", (FMT__H, param)); - - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_ID, - (zb_uint8_t *)&enable_bool, - ZB_FALSE); - if (RET_OK != zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA)) - { - TRACE_MSG(TRACE_ERROR, "failed to write into nvram", (FMT__0)); - } - zb_zcl_wwah_stop_bad_parent_recovery(); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_disable_wwah_bad_parent_recovery_handler", (FMT__0)); - return ret; -} - -zb_ret_t zb_zcl_wwah_enable_configuration_mode_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t enable_bool = ZB_TRUE; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_enable_configuration_mode_handler %hd", (FMT__H, param)); - - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_CONFIGURATION_MODE_ENABLED_ID, - (zb_uint8_t *)&enable_bool, - ZB_FALSE); - zb_wwah_set_configuration_mode(enable_bool); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_enable_configuration_mode_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_disable_configuration_mode_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_bool_t disable_bool = ZB_FALSE; - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_disable_configuration_mode_handler %hd", (FMT__H, param)); - - ZB_ZCL_SET_ATTRIBUTE(wwah_endpoint, - ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_CONFIGURATION_MODE_ENABLED_ID, - (zb_uint8_t *)&disable_bool, - ZB_FALSE); - zb_wwah_set_configuration_mode(disable_bool); - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_disable_configuration_mode_handler, ret %d", (FMT__D, ret)); - return ret; -} - -zb_ret_t zb_zcl_wwah_use_trust_center_for_cluster_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_wwah_cluster_list_t payload = { 0 }; - zb_zcl_parse_status_t status; - zb_zcl_parsed_hdr_t cmd_info; - zb_uindex_t i; - zb_uint16_t cluster_role; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_use_trust_center_for_cluster_handler %hx", (FMT__H, param)); - - ZB_MEMCPY(&cmd_info, ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t), sizeof(zb_zcl_parsed_hdr_t)); - - ZB_ZCL_WWAH_GET_CLUSTER_LIST_CMD(param, &payload, status); - if (status == ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - if (payload.number_of_clusters > ZB_ZCL_WWAH_USE_TRUST_CENTER_FOR_CLUSTER_TABLE_SIZE) - { - status = ZB_ZCL_PARSE_STATUS_FAILURE; - } - for(i = 0; i < payload.number_of_clusters; ++i) - { - /* The set of clusters that will be assigned in this fashion are the following: */ - if (!(payload.cluster_id[i] == ZB_ZCL_CLUSTER_ID_OTA_UPGRADE || - payload.cluster_id[i] == ZB_ZCL_CLUSTER_ID_TIME || - payload.cluster_id[i] == ZB_ZCL_CLUSTER_ID_POLL_CONTROL || - payload.cluster_id[i] == ZB_ZCL_CLUSTER_ID_KEEP_ALIVE)) - { - status = ZB_ZCL_PARSE_STATUS_FAILURE; - } - } - } - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS ) - { - TRACE_MSG(TRACE_ZCL1, "Error payload of ZB_ZCL_WWAH_USE_TRUST_CENTER_FOR_CLUSTER_HANDLER", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - /* On receipt of this command, a device SHALL use the Trust Center for all clusters in the list given. */ - ZB_MEMSET(WWAH_CTX().use_trust_center_for_cluster_table, (zb_uint8_t)ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD, sizeof(WWAH_CTX().use_trust_center_for_cluster_table)); - WWAH_CTX().use_trust_center_for_cluster_table_cnt = 0; - for(i = 0; i < payload.number_of_clusters; ++i) - { - cluster_role = payload.cluster_id[i] == ZB_ZCL_CLUSTER_ID_POLL_CONTROL? ZB_ZCL_CLUSTER_SERVER_ROLE : ZB_ZCL_CLUSTER_CLIENT_ROLE; - /* ignore any cluster IDs in the list for clusters not supported by the device. */ - if (get_endpoint_by_cluster(payload.cluster_id[i], cluster_role)) - { - WWAH_CTX().use_trust_center_for_cluster_table[WWAH_CTX().use_trust_center_for_cluster_table_cnt++] = payload.cluster_id[i]; - } - if (payload.cluster_id[i] == ZB_ZCL_CLUSTER_ID_OTA_UPGRADE) - { - /* OTA TODO: check if OTA client is active, else not call and not link */ - zb_buf_get_out_delayed(zcl_ota_abort_and_set_tc); - } - } - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_dataset(ZB_NVRAM_ZCL_WWAH_DATA); - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_use_trust_center_for_cluster_handler", (FMT__0)); - return ret; -} - -zb_ret_t zb_zcl_wwah_trust_center_for_cluster_server_query_handler(zb_uint8_t param) -{ - zb_uint8_t *resp_data; - zb_zcl_parsed_hdr_t cmd_info; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_trust_center_for_cluster_server_query_handler %hd", (FMT__H, param)); - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - ZB_ZCL_WWAH_SEND_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_RESPONSE_START(param, cmd_info.seq_number, WWAH_CTX().use_trust_center_for_cluster_table_cnt, resp_data); - for(i = 0; i < WWAH_CTX().use_trust_center_for_cluster_table_cnt; ++i) - { - ZB_ZCL_WWAH_SEND_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_RESPONSE_ADD(resp_data, &WWAH_CTX().use_trust_center_for_cluster_table[i]); - } - ZB_ZCL_WWAH_SEND_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_RESPONSE_END( - resp_data, - param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_trust_center_for_cluster_server_query_handler", (FMT__0)); - return RET_BUSY; -} - -void zb_zcl_wwah_send_power_descriptor_change(zb_uint8_t param) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_send_power_descriptor_change", (FMT__0)); - ZB_ZCL_WWAH_SEND_POWER_DESCRIPTOR_CHANGE(param, - WWAH_CTX().wwah_hub_address, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - WWAH_CTX().wwah_hub_endpoint, - wwah_endpoint, - ZB_AF_HA_PROFILE_ID, - NULL, - ZB_ZDO_NODE_POWER_DESC()); - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_send_power_descriptor_change", (FMT__0)); -} - -void zb_zcl_wwah_schedule_send_power_descriptor_change(void) -{ - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_wwah_schedule_send_power_descriptor_change", (FMT__0)); - if (zb_is_wwah_server()) - { - zb_buf_get_out_delayed(zb_zcl_wwah_send_power_descriptor_change); - } - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_wwah_schedule_send_power_descriptor_change", (FMT__0)); -} - -void zb_zcl_wwah_match_desc_resp_handle(zb_uint8_t param) -{ - zb_zdo_match_desc_resp_t *resp = (zb_zdo_match_desc_resp_t*)zb_buf_begin(param); - zb_uint8_t *match_ep; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_wwah_periodic_checkin_match_desc_resp_handle param %hd", (FMT__H, param)); - - if (resp->status == ZB_ZDP_STATUS_SUCCESS - && resp->tsn == WWAH_CTX().periodic_checkins.tsn - && resp->match_len > 0) - { - /* Match EP list follows right after response header */ - match_ep = (zb_uint8_t*)(resp + 1); - WWAH_CTX().periodic_checkins.endpoint = *match_ep; - - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_wwah_periodic_checkin_match_desc_req_delayed, ZB_ALARM_ALL_CB); - zb_zcl_wwah_recounter_checkin(); - } - zb_buf_free(param); - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_wwah_periodic_checkin_match_desc_resp_handle", (FMT__0)); -} - -void zb_zcl_wwah_periodic_checkin_match_desc_req_delayed(zb_uint8_t param) -{ - ZVUNUSED(param); - ++WWAH_CTX().periodic_checkins.poll_method; - zb_buf_get_out_delayed(zb_zcl_wwah_periodic_checkin_match_desc_req); -} - -void zb_zcl_wwah_periodic_checkin_match_desc_req(zb_uint8_t param) -{ - zb_zdo_match_desc_param_t *req; - zb_af_endpoint_desc_t *ep_desc = NULL; - zb_uint16_t tc_short_addr = zb_aib_get_trust_center_short_address(); - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_wwah_periodic_checkin_match_desc_req %hd", (FMT__H, param)); - - if (WWAH_CTX().periodic_checkins.poll_method != ZB_ZCL_WWAH_PERIODIC_CHECKINS_NOT_SUPPORTED) - { - req = zb_buf_initial_alloc(param, sizeof(zb_zdo_match_desc_param_t) + (1) * sizeof(zb_uint16_t)); - - req->nwk_addr = tc_short_addr; - req->addr_of_interest = tc_short_addr; - req->num_in_clusters = 1; - req->num_out_clusters = 0; - - /* To implement WWAH Periodic Router Check-Ins device may either: - * 1) attempt to read Cluster Revision Attribute - * 2) leverage the Keepalive Server if supported. - * As discussed second method has more priority. */ - - switch (WWAH_CTX().periodic_checkins.poll_method) - { - case ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_KEEPALIVE: - ep_desc = get_endpoint_by_cluster_with_role(ZB_ZCL_CLUSTER_ID_KEEP_ALIVE, - ZB_ZCL_CLUSTER_CLIENT_ROLE); - if (ep_desc) - { - req->cluster_list[0] = ZB_ZCL_CLUSTER_ID_KEEP_ALIVE; - break; - } - ++WWAH_CTX().periodic_checkins.poll_method; - /* FALLTHROUGH */ - case ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_CLUSTER_REVISION: - ep_desc = get_endpoint_by_cluster_with_role(ZB_ZCL_CLUSTER_ID_BASIC, - ZB_ZCL_CLUSTER_CLIENT_ROLE); - if (ep_desc) - { - req->cluster_list[0] = ZB_ZCL_CLUSTER_ID_BASIC; - break; - } - /* FALLTHROUGH */ - default: - TRACE_MSG(TRACE_ERROR, "Keep-alive polling method not found.", (FMT__0)); - ZB_ASSERT(0); - break; - } - - /* Verify ep_desc assignment. It will unrecoverably fail if ep_desc is NULL */ - ZB_VERIFY(ep_desc != NULL, RET_UNINITIALIZED); - - req->profile_id = ep_desc->simple_desc->app_profile_id; - - TRACE_MSG(TRACE_ZCL1, "send match descr for cluster 0x%x", (FMT__D, req->cluster_list[0])); - - WWAH_CTX().periodic_checkins.tsn = zb_zdo_match_desc_req(param, zb_zcl_wwah_match_desc_resp_handle); - - if (WWAH_CTX().periodic_checkins.tsn != ZB_ZDO_INVALID_TSN) - { - ZB_SCHEDULE_ALARM(zb_zcl_wwah_periodic_checkin_match_desc_req_delayed, 0, - ZB_ZCL_WWAH_PERIODIC_CHECKINS_CLUSTER_MATCH_DESC_TIME); - } - else - { - TRACE_MSG(TRACE_ZCL1, "tc poll finished: can not send match desc", (FMT__0)); - zb_zcl_wwah_stop_periodic_checkin(); - bdb_start_rejoin_recovery(param, BDB_COMM_REJOIN_REASON_UNSPECIFIED); - } - } - else - { - zb_buf_free(param); - } - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_wwah_periodic_checkin_match_desc_req", (FMT__0)); -} - -void zb_zcl_wwah_start_periodic_checkin(void) -{ - /* Get trust center IEEE */ - zb_uint16_t tc_short_addr = zb_aib_get_trust_center_short_address(); - zb_zcl_attr_t *attr_desc; - zb_uint8_t endpoint; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_wwah_start_periodic_checkin", (FMT__0)); - - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_WWAH, ZB_ZCL_CLUSTER_SERVER_ROLE); - if (endpoint) - { - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID); - ZB_ASSERT(attr_desc); - - /* Check it was not started before */ - if (ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc) == ZB_TRUE && - !ZB_IS_DEVICE_ZC() && - zb_get_rx_on_when_idle() && - WWAH_CTX().periodic_checkins.endpoint == 0 && - WWAH_CTX().periodic_checkins.poll_method == ZB_ZCL_WWAH_PERIODIC_CHECKINS_NOT_SUPPORTED) - { - TRACE_MSG(TRACE_ZCL1, "zb_zcl_wwah_start_periodic_checkin: start", (FMT__0)); - /* Send Match Desc - Keep-Alive cluster */ - if (!zb_aib_trust_center_address_zero() && - tc_short_addr != ZB_UNKNOWN_SHORT_ADDR) - { - WWAH_CTX().periodic_checkins.poll_method = ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_KEEPALIVE; - zb_buf_get_out_delayed(zb_zcl_wwah_periodic_checkin_match_desc_req); - } - } - } - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_wwah_start_periodic_checkin", (FMT__0)); -} - -void zb_zcl_wwah_periodic_checkin_countdown(zb_uint8_t param) -{ - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_wwah_periodic_checkin_countdown", (FMT__0)); - if (WWAH_CTX().periodic_checkins.countdown > 0) - { - ZB_SCHEDULE_ALARM(zb_zcl_wwah_periodic_checkin_countdown, 0, ZB_TIME_ONE_SECOND * WWAH_CTX().periodic_checkins.countdown); - TRACE_MSG(TRACE_ZCL1, "cd move %d", (FMT__D, WWAH_CTX().periodic_checkins.countdown)); - WWAH_CTX().periodic_checkins.countdown = 0; - } - else - { - TRACE_MSG(TRACE_ZCL1, "tc poll", (FMT__0)); - zb_buf_get_out_delayed(zb_zcl_wwah_periodic_checkin_tc_poll); - } -} - -void zb_zcl_wwah_stop_periodic_checkin(void) -{ - WWAH_CTX().periodic_checkins.countdown = 0; - WWAH_CTX().periodic_checkins.endpoint = 0; - WWAH_CTX().periodic_checkins.poll_method = ZB_ZCL_WWAH_PERIODIC_CHECKINS_NOT_SUPPORTED; - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_wwah_periodic_checkin_countdown, ZB_ALARM_ALL_CB); - -#if defined ZB_PARENT_CLASSIFICATION && defined ZB_ROUTER_ROLE - nwk_set_tc_connectivity(0); -#endif -} - -void zb_zcl_wwah_periodic_checkin_timeout(zb_uint8_t param) -{ - zb_bool_t is_fail = ZB_FALSE; - - ZVUNUSED(param); - TRACE_MSG(TRACE_ZCL1, "zb_zcl_wwah_periodic_checkin_timeout param %hd", (FMT__H, param)); - if (WWAH_CTX().periodic_checkins.poll_method == ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_KEEPALIVE) - { - /* After 3 failed Keepalive attempts, the device SHALL perform the rejoin. */ - ++WWAH_CTX().periodic_checkins.failure_cnt; - if (WWAH_CTX().periodic_checkins.failure_cnt >= ZB_ZCL_WWAH_PERIODIC_CHECKINS_MAX_FAILURE_CNT) - { - is_fail = ZB_TRUE; - } - else - { - zb_zcl_wwah_recounter_checkin(); - } - } - if (WWAH_CTX().periodic_checkins.poll_method == ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_CLUSTER_REVISION || is_fail) - { - zb_zcl_wwah_stop_periodic_checkin(); - bdb_start_rejoin_recovery(0, BDB_COMM_REJOIN_REASON_UNSPECIFIED); - } -} - -void zb_zcl_wwah_periodic_checkin_tc_poll(zb_uint8_t param) -{ - zb_ret_t ret = RET_BUSY; - zb_uint8_t *cmd_ptr; - zb_uint16_t tc_short_addr = zb_aib_get_trust_center_short_address(); - zb_af_endpoint_desc_t *ep_desc = NULL; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_wwah_periodic_checkin_tc_poll param %hd", (FMT__H, param)); - - ZB_ASSERT(WWAH_CTX().periodic_checkins.endpoint && - WWAH_CTX().periodic_checkins.poll_method < ZB_ZCL_WWAH_PERIODIC_CHECKINS_NOT_SUPPORTED && - tc_short_addr != ZB_UNKNOWN_SHORT_ADDR); - - - switch (WWAH_CTX().periodic_checkins.poll_method) - { - case ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_KEEPALIVE: - { - ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ(param, cmd_ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); - - ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_BASE_ID); - ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_JITTER_ID); - - ep_desc = get_endpoint_by_cluster_with_role(ZB_ZCL_CLUSTER_ID_KEEP_ALIVE, - ZB_ZCL_CLUSTER_CLIENT_ROLE); - ZB_ASSERT(ep_desc); - - ret = zb_zcl_finish_and_send_packet(param, - cmd_ptr, - (zb_addr_u *)(&tc_short_addr), - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - WWAH_CTX().periodic_checkins.endpoint, - ep_desc->ep_id, - get_profile_id_by_endpoint(ep_desc->ep_id), - ZB_ZCL_CLUSTER_ID_KEEP_ALIVE, - NULL); - } - break; - - case ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_CLUSTER_REVISION: - { - ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ_A(param, - cmd_ptr, - ZB_ZCL_FRAME_DIRECTION_TO_SRV, - ZB_ZCL_ENABLE_DEFAULT_RESPONSE); - ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID); - - ep_desc = get_endpoint_by_cluster_with_role(ZB_ZCL_CLUSTER_ID_BASIC, - ZB_ZCL_CLUSTER_CLIENT_ROLE); - ZB_ASSERT(ep_desc); - - ret = zb_zcl_finish_and_send_packet(param, - cmd_ptr, - (zb_addr_u *)(&tc_short_addr), - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - WWAH_CTX().periodic_checkins.endpoint, - ep_desc->ep_id, - get_profile_id_by_endpoint(ep_desc->ep_id), - ZB_ZCL_CLUSTER_ID_BASIC, - NULL); - } - break; - - default: - ZB_ASSERT(0); - break; - } - - if (ret != RET_OK) - { - ++WWAH_CTX().periodic_checkins.failure_cnt; - } - else - { - WWAH_CTX().periodic_checkins.tsn = ZCL_CTX().seq_number - 1; - /* Need to wait some time for the answer (unicast). Minimum border is - * ZB_N_APS_ACK_WAIT_DURATION_FROM_NON_SLEEPY * ZB_N_APS_MAX_FRAME_RETRIES, but intermediate - * hops may add some additional delay. */ - ZB_SCHEDULE_ALARM(zb_zcl_wwah_periodic_checkin_timeout, 0, ZB_N_APS_ACK_WAIT_DURATION_FROM_NON_SLEEPY * ZB_N_APS_MAX_FRAME_RETRIES); - } - - if ((WWAH_CTX().periodic_checkins.poll_method == ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_KEEPALIVE && - WWAH_CTX().periodic_checkins.failure_cnt >= ZB_ZCL_WWAH_PERIODIC_CHECKINS_MAX_FAILURE_CNT) || - (WWAH_CTX().periodic_checkins.poll_method == ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_CLUSTER_REVISION && - (zb_bool_t)WWAH_CTX().periodic_checkins.failure_cnt)) - { - zb_zcl_wwah_stop_periodic_checkin(); - bdb_start_rejoin_recovery((ret != RET_OK) ? param : 0, BDB_COMM_REJOIN_REASON_UNSPECIFIED); - } - else if (ret != RET_OK) - { - /* Reschedule next read attempt. */ - ZB_SCHEDULE_CALLBACK(zb_zcl_wwah_periodic_checkin_tc_poll, param); - } -} - -zb_bool_t zb_zcl_wwah_periodic_checkin_read_attr_handle(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_zcl_read_attr_res_t *resp = NULL; - zb_uint8_t read_attr_resp_cnt = 0; - zb_uint16_t cluster_id = cmd_info->cluster_id; - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_wwah_periodic_checkin_read_attr_handle param %hd", (FMT__H, param)); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_wwah_periodic_checkin_timeout, ZB_ALARM_ALL_CB); - - do - { - ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES(param, resp); - - if (resp && resp->status == ZB_ZCL_STATUS_SUCCESS) - { - if (cluster_id == ZB_ZCL_CLUSTER_ID_KEEP_ALIVE) - { - if (resp->attr_id == ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_BASE_ID) - { - WWAH_CTX().periodic_checkins.keepalive_base = resp->attr_value[0] * 60; - TRACE_MSG(TRACE_ZCL1, "keep-alive: base %hd minutes", (FMT__H, WWAH_CTX().periodic_checkins.keepalive_base)); - } - else if (resp->attr_id == ZB_ZCL_ATTR_KEEP_ALIVE_TC_KEEP_ALIVE_JITTER_ID) - { - ZB_HTOLE16(&WWAH_CTX().periodic_checkins.keepalive_jitter, resp->attr_value); - TRACE_MSG(TRACE_ZCL1, "keep-alive: jitter %hd seconds", (FMT__H, WWAH_CTX().periodic_checkins.keepalive_jitter)); - } - ++read_attr_resp_cnt; - } - else if (cluster_id == ZB_ZCL_CLUSTER_ID_BASIC) - { - ++read_attr_resp_cnt; - } - } - } - while (resp); - - if (!read_attr_resp_cnt || - (WWAH_CTX().periodic_checkins.poll_method == ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_KEEPALIVE && - read_attr_resp_cnt != 2)) - { - ++WWAH_CTX().periodic_checkins.failure_cnt; - } - - if ((WWAH_CTX().periodic_checkins.poll_method == ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_KEEPALIVE && - WWAH_CTX().periodic_checkins.failure_cnt == ZB_ZCL_WWAH_PERIODIC_CHECKINS_MAX_FAILURE_CNT) || - (WWAH_CTX().periodic_checkins.poll_method == ZB_ZCL_WWAH_PERIODIC_CHECKINS_READ_CLUSTER_REVISION && - WWAH_CTX().periodic_checkins.failure_cnt)) - { - zb_zcl_wwah_stop_periodic_checkin(); - bdb_start_rejoin_recovery(param, BDB_COMM_REJOIN_REASON_UNSPECIFIED); - param = 0; - } - else - { - zb_zcl_wwah_recounter_checkin(); - /* restore hub connectivity */ -#if defined ZB_PARENT_CLASSIFICATION && defined ZB_ROUTER_ROLE - nwk_set_tc_connectivity(1); -#endif - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_wwah_periodic_checkin_read_attr_handle", (FMT__0)); - - return (zb_bool_t)(!param); -} - -zb_bool_t zb_zcl_wwah_periodic_checkin_block_zcl_cmd(zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_uint16_t tc_short_addr = zb_aib_get_trust_center_short_address(); - - TRACE_MSG(TRACE_ZCL1, "zb_zcl_wwah_periodic_checkin_block_zcl_cmd: addr %d ep %hd tsn %hd", - (FMT__D_H_H, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - cmd_info->seq_number)); - - return (zb_bool_t)(!IS_DISTRIBUTED_SECURITY() && - tc_short_addr != ZB_UNKNOWN_SHORT_ADDR && - WWAH_CTX().periodic_checkins.endpoint == ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint && - WWAH_CTX().periodic_checkins.tsn == cmd_info->seq_number && - WWAH_CTX().periodic_checkins.countdown == 0 && - (cmd_info->cluster_id == ZB_ZCL_CLUSTER_ID_BASIC || - cmd_info->cluster_id == ZB_ZCL_CLUSTER_ID_KEEP_ALIVE) && - zb_zcl_wwah_check_if_periodic_router_check_ins_enabled()); -} - -void zb_zcl_wwah_recounter_checkin(void) -{ - if (WWAH_CTX().periodic_checkins.poll_method != ZB_ZCL_WWAH_PERIODIC_CHECKINS_NOT_SUPPORTED && - WWAH_CTX().periodic_checkins.endpoint != 0) - { - TRACE_MSG(TRACE_ZCL1, "recounter zb_zcl_wwah_update_tc_connection", (FMT__0)); - ZB_SCHEDULE_ALARM_CANCEL(zb_zcl_wwah_periodic_checkin_countdown, ZB_ALARM_ALL_CB); - WWAH_CTX().periodic_checkins.countdown = WWAH_CTX().periodic_checkins.keepalive_base + ZB_RANDOM_VALUE(WWAH_CTX().periodic_checkins.keepalive_jitter); - zb_zcl_wwah_periodic_checkin_countdown(0); - } -} - -void zb_zcl_wwah_update_tc_connection(zb_uint16_t short_addr) -{ - zb_uint16_t tc_short_addr; - if (zb_is_wwah_server() && - WWAH_CTX().periodic_checkins.poll_method != ZB_ZCL_WWAH_PERIODIC_CHECKINS_NOT_SUPPORTED) - { - tc_short_addr = zb_aib_get_trust_center_short_address(); - if (tc_short_addr != ZB_UNKNOWN_SHORT_ADDR && tc_short_addr == short_addr) - { - zb_zcl_wwah_recounter_checkin(); - } - } -} - -zb_bool_t zb_zcl_process_wwah_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t ret = RET_OK; - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_wwah_specific_commands: buf %hd", - (FMT__H, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - if( cmd_info.cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV ) - { - /* Update WWAH endpoint value. */ - WWAH_CTX().wwah_hub_endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint; - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_WWAH_ENABLE_APS_LINK_KEY_AUTHORIZATION_ID: - ret = zb_zcl_wwah_enable_aps_link_key_authorization_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Enable APS Link Key Authorization command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DISABLE_APS_LINK_KEY_AUTHORIZATION_ID: - ret = zb_zcl_wwah_disable_aps_link_key_authorization_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Disable APS Link Key Authorization command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_APS_LINK_KEY_AUTHORIZATION_QUERY_ID: - ret = zb_zcl_wwah_aps_link_key_authorization_query_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed APS Link Key Authorization Query command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_REQUEST_NEW_APS_LINK_KEY_ID: - ret = zb_zcl_wwah_request_new_aps_link_key_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Request New APS Link Key command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_ENABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_ID: - ret = zb_zcl_wwah_enable_wwah_app_event_retry_algorithm_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Enable WWAH App Event Retry Algorithm command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DISABLE_WWAH_APP_EVENT_RETRY_ALGORITHM_ID: - ret = zb_zcl_wwah_disable_wwah_app_event_retry_algorithm_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Disable WWAH App Event Retry Algorithm command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_REQUEST_TIME_ID: - ret = zb_zcl_wwah_request_time_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Request Time command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_ENABLE_WWAH_REJOIN_ALGORITHM_ID: - ret = zb_zcl_wwah_enable_wwah_rejoin_algorithm_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Enable WWAH Rejoin Algorithm command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DISABLE_WWAH_REJOIN_ALGORITHM_ID: - ret = zb_zcl_wwah_disable_wwah_rejoin_algorithm_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Disable WWAH Rejoin Algorithm command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_SET_IAS_ZONE_ENROLLMENT_METHOD_ID: - ret = zb_zcl_wwah_set_ias_zone_enrollment_method_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Set IAS Zone Enrollment Method command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_CLEAR_BINDING_TABLE_ID: - ret = zb_zcl_wwah_clear_binding_table_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Clear Binding Table command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_ENABLE_PERIODIC_ROUTER_CHECK_INS_ID: - ret = zb_zcl_wwah_enable_periodic_router_check_ins_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Enable Periodic Router Check Ins command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DISABLE_PERIODIC_ROUTER_CHECK_INS_ID: - ret = zb_zcl_wwah_disable_periodic_router_check_ins_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Disable Periodic Router Check Ins command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_SET_MAC_POLL_CCA_WAIT_TIME_ID: - ret = zb_zcl_wwah_set_mac_poll_cca_wait_time_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Set MAC Poll CCA Wait Time command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_SET_PENDING_NETWORK_UPDATE_ID: - ret = zb_zcl_wwah_set_pending_network_update_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Set Pending Network Update command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_REQUIRE_APS_ACKS_ON_UNICASTS_ID: - ret = zb_zcl_wwah_require_aps_acks_on_unicasts_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Require APS ACKs on Unicasts command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_REMOVE_APS_ACKS_ON_UNICASTS_REQUIREMENT_ID: - ret = zb_zcl_wwah_remove_aps_acks_on_unicasts_requirement_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Remove APS ACKs on Unicasts Requirement command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_APS_ACK_REQUIREMENT_QUERY_ID: - ret = zb_zcl_wwah_aps_ack_requirement_query_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed APS ACK Requirement Query command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DEBUG_REPORT_QUERY_ID: - ret = zb_zcl_wwah_debug_report_query_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Debug Report Query command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_SURVEY_BEACONS_ID: - ret = zb_zcl_wwah_survey_beacons_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Survey Beacons command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DISABLE_OTA_DOWNGRADES_ID: - ret = zb_zcl_wwah_disable_ota_downgrades_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Disable OTA Downgrades command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DISABLE_MGMT_LEAVE_WITHOUT_REJOIN_ID: - ret = zb_zcl_wwah_disable_mgmt_leave_without_rejoin_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Disable MGMT Leave Without Rejoin command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DISABLE_TOUCHLINK_INTERPAN_MESSAGE_SUPPORT_ID: - ret = zb_zcl_wwah_disable_touchlink_interpan_message_support_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Disable Touchlink Interpan Message Support command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_ENABLE_WWAH_PARENT_CLASSIFICATION_ID: - ret = zb_zcl_wwah_enable_wwah_parent_classification_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Enable WWAH Parent Classification command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DISABLE_WWAH_PARENT_CLASSIFICATION_ID: - ret = zb_zcl_wwah_disable_wwah_parent_classification_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Disable WWAH Parent Classification command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_ENABLE_TC_SECURITY_ON_NWK_KEY_ROTATION_ID: - ret = zb_zcl_wwah_enable_tc_security_on_nwk_key_rotation_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Enable TC Security On Nwk Key Rotation command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_ENABLE_WWAH_BAD_PARENT_RECOVERY_ID: - ret = zb_zcl_wwah_enable_wwah_bad_parent_recovery_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Enable WWAH Bad Parent Recovery command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DISABLE_WWAH_BAD_PARENT_RECOVERY_ID: - ret = zb_zcl_wwah_disable_wwah_bad_parent_recovery_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Disable WWAH Bad Parent Recovery command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_ENABLE_CONFIGURATION_MODE_ID: - ret = zb_zcl_wwah_enable_configuration_mode_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Enable Configuration Mode command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_DISABLE_CONFIGURATION_MODE_ID: - ret = zb_zcl_wwah_disable_configuration_mode_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Disable Configuration Mode command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_USE_TRUST_CENTER_FOR_CLUSTER_ID: - ret = zb_zcl_wwah_use_trust_center_for_cluster_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Use Trust Center for Cluster command", (FMT__0)); - break; - - case ZB_ZCL_CMD_WWAH_TRUST_CENTER_FOR_CLUSTER_SERVER_QUERY_ID: - ret = zb_zcl_wwah_trust_center_for_cluster_server_query_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed Trust Center for Cluster Server Query command", (FMT__0)); - break; - - default: - processed = ZB_FALSE; - break; - } - } - - if (ret == RET_BUSY) - { - // do nothing: buf has reused, processed has set ZB_TRUE - } - else if(processed == ZB_FALSE) - { - // do nothing: base func will send else if(processed == ZB_FALSE) - /* TODO: Recheck handling of unknown WWAH command. Does server and client correctly respond? */ - } - else if (ret != RET_OK) - { - zb_uint8_t status_code; - switch(ret) - { - case RET_OUT_OF_RANGE: - status_code = ZB_ZCL_STATUS_INVALID_VALUE; - break; - case RET_INVALID_PARAMETER: - status_code = ZB_ZCL_STATUS_INVALID_FIELD; - break; - case RET_IGNORE: - /* ZCL8: CCB 2477: use UNSUP_COMMAND instead of any other Unsupported command status */ - status_code = ZB_ZCL_STATUS_UNSUP_CMD; - break; - case RET_NOT_FOUND: - status_code = ZB_ZCL_STATUS_NOT_FOUND; - break; - default: - status_code = ZB_ZCL_STATUS_FAIL; - break; - } - ZB_ZCL_SEND_DEFAULT_RESP_MANUF(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_WWAH, - cmd_info.seq_number, - cmd_info.cmd_id, - status_code, - WWAH_MANUFACTURER_CODE, - ZB_ZCL_FRAME_DIRECTION_TO_CLI); - } - else if (!(cmd_info.disable_default_response)) - { - ZB_ZCL_SEND_DEFAULT_RESP_MANUF(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_WWAH, - cmd_info.seq_number, - cmd_info.cmd_id, - processed == ZB_TRUE ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL, - WWAH_MANUFACTURER_CODE, - ZB_ZCL_FRAME_DIRECTION_TO_CLI); - } - else - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_wwah_specific_commands: processed %d", - (FMT__D, processed)); - - return ZB_TRUE; -} - - -zb_bool_t zb_zcl_process_wwah_specific_commands_srv(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_wwah_server_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_wwah_specific_commands(param); -} - -void zb_zcl_wwah_trace_ctx(zb_uint8_t param) -{ - zb_uint8_t i = 0; - ZVUNUSED(param); - - TRACE_MSG(TRACE_ZCL3, ">> WWAH CTX", (FMT__0)); - TRACE_MSG(TRACE_ZCL3, "wwah_behavior %hd wwah_hub_endpoint %hd time_server_endpoint %hd", (FMT__H_H_H, WWAH_CTX().wwah_behavior, WWAH_CTX().wwah_hub_endpoint, WWAH_CTX().time_server_endpoint)); - TRACE_MSG(TRACE_ZCL3, "wwah_hub_address %hd aps_link_key_enabled_by_default %hd", (FMT__D_H, WWAH_CTX().wwah_hub_address, WWAH_CTX().aps_link_key_enabled_by_default)); - - /* WWAH tables */ - TRACE_MSG(TRACE_ZCL3, "aps_ack_exempt_table: %hd elements", (FMT__H, WWAH_CTX().aps_ack_exempt_table_cnt)); - for(i = 0; i < WWAH_CTX().aps_ack_exempt_table_cnt; ++i) - { - TRACE_MSG(TRACE_ZCL3, " [%hd]: cluster_id 0x%x", (FMT__H_D, i, WWAH_CTX().aps_ack_exempt_table[i])); - } - TRACE_MSG(TRACE_ZCL3, "aps_link_key_authorization_table: %hd elements", (FMT__H, WWAH_CTX().aps_link_key_authorization_table_cnt)); - for(i = 0; i < WWAH_CTX().aps_link_key_authorization_table_cnt; ++i) - { - TRACE_MSG(TRACE_ZCL3, " [%hd]: cluster_id 0x%x", (FMT__H_D, i, WWAH_CTX().aps_link_key_authorization_table[i])); - } - TRACE_MSG(TRACE_ZCL3, "use_trust_center_for_cluster_table: %hd elements", (FMT__H, WWAH_CTX().use_trust_center_for_cluster_table_cnt)); - for(i = 0; i < WWAH_CTX().use_trust_center_for_cluster_table_cnt; ++i) - { - TRACE_MSG(TRACE_ZCL3, " [%hd]: cluster_id 0x%x", (FMT__H_D, i, WWAH_CTX().use_trust_center_for_cluster_table[i])); - } - - TRACE_MSG(TRACE_ZCL3, "<< WWAH CTX", (FMT__0)); -} - -/* NVRAM Read/Write API */ - -/* TRICKY: Need to write aligned by 4 - so if not aligned, simply write one more empty record. - Macro return: how many 2-byte entries to write - to be sure overall result is aligned to 4. */ -#define ALIGN_TABLE_CNT_TO_4(_cnt) ((((_cnt)*2 + 3)/4)*2) - -zb_uint16_t zb_nvram_wwah_dataset_size(void) -{ - return (sizeof(zb_nvram_dataset_wwah_t) + - (ALIGN_TABLE_CNT_TO_4(WWAH_CTX().aps_ack_exempt_table_cnt) + - ALIGN_TABLE_CNT_TO_4(WWAH_CTX().aps_link_key_authorization_table_cnt) + - ALIGN_TABLE_CNT_TO_4(WWAH_CTX().use_trust_center_for_cluster_table_cnt)) * - sizeof(zb_uint16_t)); -} - - -void zb_nvram_read_wwah_dataset( - zb_uint8_t page, zb_uint32_t pos, zb_uint16_t len, zb_nvram_ver_t nvram_ver, zb_uint16_t ds_ver) - -{ - zb_nvram_dataset_wwah_t ds; - zb_ret_t ret; - - ZVUNUSED(len); - ZVUNUSED(nvram_ver); - ZVUNUSED(ds_ver); - - TRACE_MSG(TRACE_ZCL1, "> zb_nvram_read_wwah_dataset %d pos %ld len %d nvram_ver %d", - (FMT__H_L_D_D, page, pos, len, nvram_ver)); - - ret = zb_osif_nvram_read(page, pos, (zb_uint8_t*)&ds, sizeof(ds)); - - if (ret == RET_OK) - { - zb_uint8_t endpoint; - zb_zcl_attr_t *attr_desc; - - pos += sizeof(ds); - - /* Restore WWAH CTX */ - WWAH_CTX().wwah_behavior = ds.wwah_behavior; - WWAH_CTX().aps_link_key_enabled_by_default = (zb_bool_t)ds.aps_link_key_enabled_by_default; - - ZB_MEMCPY((zb_uint8_t*)&WWAH_CTX().periodic_checkins, - (zb_uint8_t*)&ds.periodic_checkins, - sizeof(zb_zcl_wwah_periodic_checkins_data_t)); - - WWAH_CTX().periodic_checkins.tsn = 0; - WWAH_CTX().periodic_checkins.failure_cnt = 0; - WWAH_CTX().periodic_checkins.countdown = 0; - - /* Restore WWAH attributes */ - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_WWAH, ZB_ZCL_CLUSTER_SERVER_ROLE); - ZB_ASSERT(endpoint); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ds.cluster_revision); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_DISABLE_OTA_DOWNGRADES_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.disable_ota_downgrades); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.mgmt_leave_without_rejoin_enabled); - zb_wwah_set_leave_without_rejoin_allowed(ds.mgmt_leave_without_rejoin_enabled); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_NWK_RETRY_COUNT_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.nwk_retry_count); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_MAC_RETRY_COUNT_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.mac_retry_count); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.router_check_in_enabled); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_TOUCHLINK_INTERPAN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.touchlink_interpan_enabled); - zb_wwah_set_interpan_supported(ds.touchlink_interpan_enabled); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_PARENT_CLASSIFICATION_ENABLED_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.wwah_parent_classification_enabled); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_ENABLED_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.wwah_app_event_retry_enabled); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_QUEUE_SIZE_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.wwah_app_event_retry_queue_size); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_REJOIN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.wwah_rejoin_enabled); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_MAC_POLL_FAILURE_WAIT_TIME_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.mac_poll_failure_wait_time); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_CONFIGURATION_MODE_ENABLED_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.configuration_mode_enabled); - zb_wwah_set_configuration_mode(ds.configuration_mode_enabled); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_CURRENT_DEBUG_REPORT_ID_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.current_debug_report_id); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_TC_SECURITY_ON_NWK_KEY_ROTATION_ENABLED_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.tc_security_on_nwk_key_rotation_enabled); - zb_wwah_set_nwk_key_commands_broadcast_allowed(ds.tc_security_on_nwk_key_rotation_enabled); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.wwah_bad_parent_recovery_enabled); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ds.pending_network_update_channel); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_PANID_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ds.pending_network_update_panid); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_OTA_MAX_OFFLINE_DURATION_ID); - ZB_ASSERT(attr_desc); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, ds.ota_max_offline_duration); - - /* Restore WWAH tables */ - { - if (ds.aps_ack_exempt_table_cnt && - ZB_ARRAY_SIZE(WWAH_CTX().aps_ack_exempt_table) >= ds.aps_ack_exempt_table_cnt) - { - ret = zb_osif_nvram_read(page, pos, - (zb_uint8_t*)&WWAH_CTX().aps_ack_exempt_table, - ds.aps_ack_exempt_table_cnt * sizeof(zb_uint16_t)); - pos += ds.aps_ack_exempt_table_cnt * sizeof(zb_uint16_t); - - - if (ret == RET_OK) - { - WWAH_CTX().aps_ack_exempt_table_cnt = ds.aps_ack_exempt_table_cnt; - /* Fix alignment */ - if (WWAH_CTX().aps_ack_exempt_table[WWAH_CTX().aps_ack_exempt_table_cnt-1] == - ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD) - { - --WWAH_CTX().aps_ack_exempt_table_cnt; - } - } - } - - if (ret == RET_OK && - ds.aps_link_key_authorization_table_cnt && - ZB_ARRAY_SIZE(WWAH_CTX().aps_link_key_authorization_table) >= ds.aps_link_key_authorization_table_cnt) - { - ret = zb_osif_nvram_read(page, pos, - (zb_uint8_t*)&WWAH_CTX().aps_link_key_authorization_table, - ds.aps_link_key_authorization_table_cnt * sizeof(zb_uint16_t)); - pos += ds.aps_link_key_authorization_table_cnt * sizeof(zb_uint16_t); - - if (ret == RET_OK) - { - WWAH_CTX().aps_link_key_authorization_table_cnt = ds.aps_link_key_authorization_table_cnt; - /* Fix alignment */ - if (WWAH_CTX().aps_link_key_authorization_table[WWAH_CTX().aps_link_key_authorization_table_cnt-1] == ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD) - { - --WWAH_CTX().aps_link_key_authorization_table_cnt; - } - } - } - - if (ret == RET_OK && - ds.use_trust_center_for_cluster_table_cnt && - ZB_ARRAY_SIZE(WWAH_CTX().use_trust_center_for_cluster_table) >= ds.use_trust_center_for_cluster_table_cnt) - { - ret = zb_osif_nvram_read(page, pos, - (zb_uint8_t*)&WWAH_CTX().use_trust_center_for_cluster_table, - ds.use_trust_center_for_cluster_table_cnt * sizeof(zb_uint16_t)); - - if (ret == RET_OK) - { - WWAH_CTX().use_trust_center_for_cluster_table_cnt = ds.use_trust_center_for_cluster_table_cnt; - /* Fix alignment */ - if (WWAH_CTX().use_trust_center_for_cluster_table[WWAH_CTX().use_trust_center_for_cluster_table_cnt-1] == - ZB_ZCL_WWAH_CLUSTER_ID_FREE_RECORD) - { - --WWAH_CTX().use_trust_center_for_cluster_table_cnt; - } - } - } - } - } - - zb_zcl_wwah_trace_ctx(0); - - TRACE_MSG(TRACE_ZCL1, "< zb_nvram_read_wwah_dataset", (FMT__0)); -} - -zb_ret_t zb_nvram_write_wwah_dataset(zb_uint8_t page, zb_uint32_t pos) -{ - zb_nvram_dataset_wwah_t ds; - zb_uint8_t endpoint; - zb_zcl_attr_t *attr_desc; - zb_ret_t ret; - - TRACE_MSG(TRACE_ZCL1, "> zb_nvram_write_wwah_dataset page %d pos %ld", - (FMT__H_L, page, pos)); - - ZB_BZERO(&ds, sizeof(ds)); - - /* Store WWAH CTX */ - ds.wwah_behavior = WWAH_CTX().wwah_behavior; - ds.aps_link_key_enabled_by_default = WWAH_CTX().aps_link_key_enabled_by_default; - - ZB_MEMCPY((zb_uint8_t*)&ds.periodic_checkins, - (zb_uint8_t*)&WWAH_CTX().periodic_checkins, - sizeof(zb_zcl_wwah_periodic_checkins_data_t)); - - /* Store WWAH attributes */ - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_WWAH, ZB_ZCL_CLUSTER_SERVER_ROLE); - ZB_ASSERT(endpoint); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID); - ZB_ASSERT(attr_desc); - ds.cluster_revision = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_DISABLE_OTA_DOWNGRADES_ID); - ZB_ASSERT(attr_desc); - ds.disable_ota_downgrades = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_MGMT_LEAVE_WITHOUT_REJOIN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ds.mgmt_leave_without_rejoin_enabled = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_NWK_RETRY_COUNT_ID); - ZB_ASSERT(attr_desc); - ds.nwk_retry_count = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_MAC_RETRY_COUNT_ID); - ZB_ASSERT(attr_desc); - ds.mac_retry_count = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_ROUTER_CHECK_IN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ds.router_check_in_enabled = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_TOUCHLINK_INTERPAN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ds.touchlink_interpan_enabled = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_PARENT_CLASSIFICATION_ENABLED_ID); - ZB_ASSERT(attr_desc); - ds.wwah_parent_classification_enabled = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_ENABLED_ID); - ZB_ASSERT(attr_desc); - ds.wwah_app_event_retry_enabled = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_APP_EVENT_RETRY_QUEUE_SIZE_ID); - ZB_ASSERT(attr_desc); - ds.wwah_app_event_retry_queue_size = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_REJOIN_ENABLED_ID); - ZB_ASSERT(attr_desc); - ds.wwah_rejoin_enabled = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_MAC_POLL_FAILURE_WAIT_TIME_ID); - ZB_ASSERT(attr_desc); - ds.mac_poll_failure_wait_time = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_CONFIGURATION_MODE_ENABLED_ID); - ZB_ASSERT(attr_desc); - ds.configuration_mode_enabled = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_CURRENT_DEBUG_REPORT_ID_ID); - ZB_ASSERT(attr_desc); - ds.current_debug_report_id = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_TC_SECURITY_ON_NWK_KEY_ROTATION_ENABLED_ID); - ZB_ASSERT(attr_desc); - ds.tc_security_on_nwk_key_rotation_enabled = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_WWAH_BAD_PARENT_RECOVERY_ENABLED_ID); - ZB_ASSERT(attr_desc); - ds.wwah_bad_parent_recovery_enabled = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_CHANNEL_ID); - ZB_ASSERT(attr_desc); - ds.pending_network_update_channel = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_PENDING_NETWORK_UPDATE_PANID_ID); - ZB_ASSERT(attr_desc); - ds.pending_network_update_panid = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - // - attr_desc = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_WWAH_OTA_MAX_OFFLINE_DURATION_ID); - ZB_ASSERT(attr_desc); - ds.ota_max_offline_duration = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - ds.aps_ack_exempt_table_cnt = ALIGN_TABLE_CNT_TO_4(WWAH_CTX().aps_ack_exempt_table_cnt); - ZB_ASSERT(ds.aps_ack_exempt_table_cnt <= ZB_ARRAY_SIZE(WWAH_CTX().aps_ack_exempt_table)); - ds.aps_link_key_authorization_table_cnt = ALIGN_TABLE_CNT_TO_4(WWAH_CTX().aps_link_key_authorization_table_cnt); - ZB_ASSERT(ds.aps_link_key_authorization_table_cnt <= ZB_ARRAY_SIZE(WWAH_CTX().aps_link_key_authorization_table)); - ds.use_trust_center_for_cluster_table_cnt = ALIGN_TABLE_CNT_TO_4(WWAH_CTX().use_trust_center_for_cluster_table_cnt); - ZB_ASSERT(ds.use_trust_center_for_cluster_table_cnt <= ZB_ARRAY_SIZE(WWAH_CTX().use_trust_center_for_cluster_table)); - - ret = zb_nvram_write_data(page, pos, (zb_uint8_t*)&ds, sizeof(ds)); - pos += sizeof(ds); - - if (ret == RET_OK) - { - /* Store WWAH tables */ - if (ds.aps_ack_exempt_table_cnt) - { - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_data(page, pos, - (zb_uint8_t*)&WWAH_CTX().aps_ack_exempt_table, - ds.aps_ack_exempt_table_cnt * sizeof(zb_uint16_t)); - pos += ds.aps_ack_exempt_table_cnt * sizeof(zb_uint16_t); - } - - if (ret == RET_OK && ds.aps_link_key_authorization_table_cnt) - { - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_data(page, pos, - (zb_uint8_t*)&WWAH_CTX().aps_link_key_authorization_table, - ds.aps_link_key_authorization_table_cnt * sizeof(zb_uint16_t)); - pos += ds.aps_link_key_authorization_table_cnt * sizeof(zb_uint16_t); - } - - if (ret == RET_OK && ds.use_trust_center_for_cluster_table_cnt) - { - /* If we fail, trace is given and assertion is triggered */ - ret = zb_nvram_write_data(page, pos, - (zb_uint8_t*)&WWAH_CTX().use_trust_center_for_cluster_table, - ds.use_trust_center_for_cluster_table_cnt * sizeof(zb_uint16_t)); - } - } - - zb_zcl_wwah_trace_ctx(0); - - TRACE_MSG(TRACE_ZCL1, "< zb_nvram_write_wwah_dataset ret %hd", (FMT__H, ret)); - return ret; -} - - -void wwah_post_commissioning_actions(void) -{ - if (zb_is_wwah_server()) - { - zb_zcl_wwah_start_periodic_checkin(); - zb_zcl_wwah_start_bad_parent_recovery(); - } -} - -#endif /* ZB_ZCL_ENABLE_WWAH_SERVER */ - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_WWAH */ diff --git a/zboss/development/src/zcl/zcl_scenes.c b/zboss/development/src/zcl/zcl_scenes.c deleted file mode 100644 index e76f14f9e1..0000000000 --- a/zboss/development/src/zcl/zcl_scenes.c +++ /dev/null @@ -1,1205 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Scenes cluster specific commands handling and service functions -*/ - -#define ZB_TRACE_FILE_ID 2081 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_SCENES) - -#include "zb_bufpool.h" -#include "zb_zcl.h" -#include "zcl/zb_zcl_scenes.h" -#include "zb_zdo.h" -#include "zb_aps.h" - -zb_uint8_t gs_scenes_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_SCENES_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_scenes_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_SCENES_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_scenes_client_cmd_list = -{ - sizeof(gs_scenes_client_received_commands), gs_scenes_client_received_commands, - sizeof(gs_scenes_server_received_commands), gs_scenes_server_received_commands -}; - -zb_discover_cmd_list_t gs_scenes_server_cmd_list = -{ - sizeof(gs_scenes_server_received_commands), gs_scenes_server_received_commands, - sizeof(gs_scenes_client_received_commands), gs_scenes_client_received_commands -}; - -zb_bool_t zb_zcl_process_scenes_specific_commands_srv(zb_uint8_t param); -zb_bool_t zb_zcl_process_scenes_specific_commands_cli(zb_uint8_t param); -zb_ret_t check_value_scenes(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_scenes_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_scenes, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_scenes_specific_commands_srv); -} - -void zb_zcl_scenes_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - check_value_scenes, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_scenes_specific_commands_cli); -} - -zb_ret_t check_value_scenes(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - ZVUNUSED(endpoint); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_ID: - { -#ifdef ZB_NEED_ALIGN - zb_uint16_t v; - ZB_MEMCPY(&v, value, 2); - ret = (v <= ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_MAX_VALUE) ? RET_OK : RET_OUT_OF_RANGE; -#else - ret = (*((zb_uint16_t *)value) <= ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_MAX_VALUE) ? RET_OK : RET_OUT_OF_RANGE; -#endif - break; - } - - case ZB_ZCL_ATTR_SCENES_SCENE_VALID_ID: - ret = ( ZB_ZCL_CHECK_BOOL_VALUE(*value) ) ? RET_OK : RET_ERROR; - break; - - case ZB_ZCL_ATTR_SCENES_NAME_SUPPORT_ID: - /* Only most significant bit is meaningful, see ZCL spec, subclause - 3.7.2.2.1.5 */ - /* Acc. to ZCL spec, subclause 1.6.2 Reserved Bit Fields, reserved fields - * should be ignored. These fields are not marked as reserved directly, - * but aren't they de-facto reserved? */ - ret = ZB_TRUE; - break; - - case ZB_ZCL_ATTR_GLOBAL_CLUSTER_REVISION_ID: - if( ZB_ZCL_ATTR_GET16(value) > ZB_ZCL_SCENES_CLUSTER_REVISION_MAX ) - { - ret = RET_ERROR; - } - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_scenes ret %hd", (FMT__H, ret)); - return ret; -} -/** @internal @brief Processes Store scene command - @param param - reference number of the command buffer -*/ -static void zb_zcl_scenes_process_store_scene_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info); - -/** @internal @brief Processes Add scene command - @param param - reference number of the command buffer -*/ -static void zb_zcl_scenes_process_add_scene_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info, zb_bool_t is_enhanced); - -/** @internal @brief Processes View scene command - @param param - reference number of the command buffer -*/ -static void zb_zcl_scenes_process_view_scene_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info, zb_bool_t is_enhanced); - -/** @internal @brief Processes Remove scene command - @param param - reference number of the command buffer -*/ -static void zb_zcl_scenes_process_remove_scene_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info); - -/** @internal @brief Processes Remove all scenes command - @param param - reference number of the command buffer -*/ -static void zb_zcl_scenes_process_remove_all_scenes_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info); - -/** @internal @brief Processes Get scene membership command - @param param - reference number of the command buffer -*/ -static void zb_zcl_scenes_process_get_scene_membership_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info); - -/** @internal @brief Processes Recall scene command - @param param - reference number of the command buffer -*/ -static void zb_zcl_scenes_process_recall_scene_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info); - -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED -/** @internal @brief Processes Copy Scene command - @param param - reference number of the command buffer -*/ -static void zb_zcl_scenes_process_copy_scene(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info); -#endif /* !ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - -zb_bool_t zb_zcl_process_scenes_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - TRACE_MSG( - TRACE_ZCL1, - "> zb_zcl_process_scenes_specific_commands: param %d, cmd %d", - (FMT__H_H, param, cmd_info.cmd_id)); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_SCENES == cmd_info.cluster_id); - - if (ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction) - { - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_SCENES_ADD_SCENE: - zb_zcl_scenes_process_add_scene_command(param, &cmd_info, ZB_FALSE); - break; - case ZB_ZCL_CMD_SCENES_VIEW_SCENE: - zb_zcl_scenes_process_view_scene_command(param, &cmd_info, ZB_FALSE); - break; - case ZB_ZCL_CMD_SCENES_REMOVE_SCENE: - zb_zcl_scenes_process_remove_scene_command(param, &cmd_info); - break; - case ZB_ZCL_CMD_SCENES_REMOVE_ALL_SCENES: - zb_zcl_scenes_process_remove_all_scenes_command(param, &cmd_info); - break; - case ZB_ZCL_CMD_SCENES_STORE_SCENE: - zb_zcl_scenes_process_store_scene_command(param, &cmd_info); - break; - case ZB_ZCL_CMD_SCENES_RECALL_SCENE: - zb_zcl_scenes_process_recall_scene_command(param, &cmd_info); - break; - case ZB_ZCL_CMD_SCENES_GET_SCENE_MEMBERSHIP: - zb_zcl_scenes_process_get_scene_membership_command(param, &cmd_info); - break; -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - case ZB_ZCL_CMD_SCENES_ENHANCED_ADD_SCENE: - zb_zcl_scenes_process_add_scene_command(param, &cmd_info, ZB_TRUE); - break; - case ZB_ZCL_CMD_SCENES_ENHANCED_VIEW_SCENE: - zb_zcl_scenes_process_view_scene_command(param, &cmd_info, ZB_TRUE); - break; - case ZB_ZCL_CMD_SCENES_COPY_SCENE: - zb_zcl_scenes_process_copy_scene(param, &cmd_info); - break; -#endif /* !ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - default: - TRACE_MSG( - TRACE_ERROR, - "ERROR Unsupported Scenes cluster command 0x%hx", - (FMT__H, cmd_info.cmd_id)); - processed = ZB_FALSE; - break; - } - } - else - { - TRACE_MSG(TRACE_ZCL2, "Received scene resp command", (FMT__0)); - } - - TRACE_MSG( - TRACE_ZCL1, - "< zb_zcl_process_scenes_specific_commands: processed %hd", - (FMT__H, processed)); - - return processed; -} /* zb_bool_t zb_zcl_process_scenes_specific_commands(zb_uint8_t param) */ - - -zb_bool_t zb_zcl_process_scenes_specific_commands_srv(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_scenes_server_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_scenes_specific_commands(param); -} - - -zb_bool_t zb_zcl_process_scenes_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_scenes_client_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_scenes_specific_commands(param); -} - -zb_uint8_t zb_zcl_scenes_process_store_scene(zb_uint8_t param, zb_zcl_scenes_store_scene_req_t* req, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_uint8_t store_scene_status = ZB_ZCL_STATUS_SUCCESS; - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_SCENES_STORE_SCENE_CB_ID, RET_ERROR, cmd_info, req, &store_scene_status); - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - return store_scene_status; -} - -static void zb_zcl_scenes_process_store_scene_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_scenes_store_scene_req_t* req; - zb_zcl_scenes_store_scene_req_t req_copy; - zb_uint8_t scene_count; - zb_zcl_status_t store_scene_status = ZB_ZCL_STATUS_SUCCESS; - zb_zcl_attr_t* scene_valid_desc; - zb_bool_t set_scene_valid = ZB_FALSE; - - TRACE_MSG( - TRACE_ZCL1, - "> zb_zcl_scenes_process_store_scene_command param %hd", - (FMT__H, param)); - - ZB_ZCL_SCENES_GET_STORE_SCENE_REQ(param, req); - - if (!req) - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - scene_valid_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SCENES_SCENE_VALID_ID); - ZB_ASSERT(scene_valid_desc); - - TRACE_MSG(TRACE_ZCL1, "Update SceneValid: FALSE", (FMT__0)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(scene_valid_desc, ZB_FALSE); - - ZB_MEMCPY(&req_copy, req, sizeof(zb_zcl_scenes_store_scene_req_t)); - store_scene_status = (zb_zcl_status_t) zb_zcl_scenes_process_store_scene(param, &req_copy, cmd_info); - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - { - zb_zcl_attr_t* scene_count_desc; - if (store_scene_status == ZB_ZCL_STATUS_SUCCESS) - { - scene_count_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID); - if (scene_count_desc && scene_count_desc->data_p) - { - scene_count = ZB_ZCL_GET_ATTRIBUTE_VAL_8(scene_count_desc); - TRACE_MSG(TRACE_ZCL1, - "increase scene count: %hd -> %hd", - (FMT__H_H, scene_count, scene_count + 1)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(scene_count_desc, scene_count + 1); - } - set_scene_valid = ZB_TRUE; - } - } - /* FALLTHRU */ - case RET_ALREADY_EXISTS: - { - /* prevent to send response on ZGP command */ - if (!ZB_ZCL_ADDR_TYPE_IS_GPD(cmd_info->addr_data.common_data.source.addr_type)) - { - ZB_ZCL_SCENES_SEND_STORE_SCENE_RES( - param, - cmd_info->seq_number, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - NULL, - store_scene_status, - req_copy.group_id, - req_copy.scene_id); - set_scene_valid = ZB_TRUE; - } - else - { - zb_buf_free(param); - } - } - break; - - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - if (set_scene_valid) - { - TRACE_MSG(TRACE_ZCL1, "Update SceneValid: TRUE", (FMT__0)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(scene_valid_desc, ZB_TRUE); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_scenes_process_store_scene_command", (FMT__0)); -} /* void zb_zcl_scenes_process_store_scene_command(zb_uint8_t param) */ - -static void zb_zcl_scenes_process_add_scene_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info, zb_bool_t is_enhanced) -{ - zb_zcl_scenes_add_scene_req_t* req; - zb_zcl_scenes_add_scene_req_t req_copy; - zb_uint8_t add_scene_status = ZB_ZCL_STATUS_SUCCESS; - - /* Initialize with invalid IDs */ - req_copy.group_id = 0xFF; - req_copy.scene_id = 0xFF; - - TRACE_MSG( - TRACE_ZCL1, - "> zb_zcl_scenes_process_add_scene_command param %hd", - (FMT__H, param)); - -#ifdef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - ZVUNUSED(is_enhanced); -#endif /* ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - - ZB_ZCL_SCENES_GET_ADD_SCENE_REQ_COMMON(param, req); - - if (!req) - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - else if (ZCL_CTX().device_cb) - { - ZB_MEMCPY(&req_copy, req, sizeof(zb_zcl_scenes_add_scene_req_t)); - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH( - param, -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - (is_enhanced) ? (ZB_ZCL_SCENES_ENHANCED_ADD_SCENE_CB_ID) : (ZB_ZCL_SCENES_ADD_SCENE_CB_ID), -#else - ZB_ZCL_SCENES_ADD_SCENE_CB_ID, -#endif /* !ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - RET_ERROR, - cmd_info, - &req_copy, - &add_scene_status); - (ZCL_CTX().device_cb)(param); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - { - zb_zcl_attr_t* scene_count_desc; - if (add_scene_status == ZB_ZCL_STATUS_SUCCESS) - { - zb_uint8_t scene_count; - - scene_count_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID); - if (scene_count_desc && scene_count_desc->data_p) - { - scene_count = ZB_ZCL_GET_ATTRIBUTE_VAL_8(scene_count_desc); - TRACE_MSG(TRACE_ZCL1, - "increase scene count: %hd -> %hd", - (FMT__H_H, scene_count, scene_count + 1)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(scene_count_desc, scene_count + 1); - } - } - } - /* FALLTHRU */ - case RET_ALREADY_EXISTS: - { - /* prevent to send response on ZGP command */ - if (!ZB_ZCL_ADDR_TYPE_IS_GPD(cmd_info->addr_data.common_data.source.addr_type)) - { -#ifdef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - ZVUNUSED(is_enhanced); -#else - if (is_enhanced) - { - ZB_ZCL_SCENES_SEND_ENHANCED_ADD_SCENE_RES( - param, - cmd_info->seq_number, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - NULL, - add_scene_status, - req_copy.group_id, - req_copy.scene_id); - } - else -#endif /* ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - { - ZB_ZCL_SCENES_SEND_ADD_SCENE_RES( - param, - cmd_info->seq_number, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - NULL, - add_scene_status, - req_copy.group_id, - req_copy.scene_id); - } - } - else - { - zb_buf_free(param); - } - } - break; - - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_scenes_process_add_scene_command", (FMT__0)); -}/* void zb_zcl_scenes_process_add_scene_command(zb_uint8_t param) */ - -static void zb_zcl_scenes_process_view_scene_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info, zb_bool_t is_enhanced) -{ - zb_zcl_scenes_view_scene_req_t* req; - zb_zcl_scenes_view_scene_req_t req_copy; - - TRACE_MSG( - TRACE_ZCL1, - "> zb_zcl_scenes_process_view_scene_command param %hd", - (FMT__H, param)); - -#ifdef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - ZVUNUSED(is_enhanced); -#endif /* ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - - ZB_ZCL_SCENES_GET_VIEW_SCENE_REQ(param, req); - - if (!req) - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - else if (ZCL_CTX().device_cb) - { - ZB_MEMCPY(&req_copy, req, sizeof(zb_zcl_scenes_view_scene_req_t)); - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH( - param, -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - (is_enhanced) ? (ZB_ZCL_SCENES_ENHANCED_VIEW_SCENE_CB_ID) : (ZB_ZCL_SCENES_VIEW_SCENE_CB_ID), -#else - ZB_ZCL_SCENES_VIEW_SCENE_CB_ID, -#endif /* !ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED */ - RET_ERROR, - cmd_info, - &req_copy, - NULL); - (ZCL_CTX().device_cb)(param); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - /*We don't send a View Scene Resp command. Application must send reply - * for this command. - */ - zb_buf_free(param); - break; - - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_scenes_process_view_scene_command", (FMT__0)); -} /* void zb_zcl_scenes_process_view_scene_command(zb_uint8_t param) */ - -static void zb_zcl_scenes_process_remove_scene_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_scenes_remove_scene_req_t* req; - zb_zcl_scenes_remove_scene_req_t req_copy; - - zb_uint8_t remove_scene_status = ZB_ZCL_STATUS_SUCCESS; - zb_zcl_attr_t* scene_count_desc; - - /* Initialize with invalid IDs */ - req_copy.group_id = 0xFF; - req_copy.scene_id = 0xFF; - - TRACE_MSG( - TRACE_ZCL1, - "> zb_zcl_scenes_process_remove_scene_command param %hd", - (FMT__H, param)); - - ZB_ZCL_SCENES_GET_REMOVE_SCENE_REQ(param, req); - - if (!req) - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - ZB_MEMCPY(&req_copy, req, sizeof(zb_zcl_scenes_remove_scene_req_t)); - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_SCENES_REMOVE_SCENE_CB_ID, RET_ERROR, cmd_info, &req_copy, &remove_scene_status); - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - { - if (remove_scene_status == ZB_ZCL_STATUS_SUCCESS) - { - zb_uint8_t scene_count; - - scene_count_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID); - if (scene_count_desc && scene_count_desc->data_p) - { - /* This attribute is not reportable, so may set attribute value directly */ - scene_count = ZB_ZCL_GET_ATTRIBUTE_VAL_8(scene_count_desc); - TRACE_MSG(TRACE_ZCL1, - "decrease scene count: %hd -> %hd", - (FMT__H_H, scene_count, scene_count - 1)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(scene_count_desc, scene_count - 1); - } - } - - /* prevent to send response on ZGP command */ - if (!ZB_ZCL_ADDR_TYPE_IS_GPD(cmd_info->addr_data.common_data.source.addr_type)) - { - ZB_ZCL_SCENES_SEND_REMOVE_SCENE_RES( - param, - cmd_info->seq_number, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - NULL, - remove_scene_status, - req_copy.group_id, - req_copy.scene_id); - } - else - { - zb_buf_free(param); - } - } - break; - - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_scenes_process_remove_scene_command", (FMT__0)); -} /* void zb_zcl_scenes_process_remove_scene_command(zb_uint8_t param) */ - -zb_uint8_t zb_zcl_scenes_process_remove_all_scenes(zb_uint8_t param, zb_zcl_scenes_remove_all_scenes_req_t* req, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_uint8_t remove_all_scenes_status = ZB_ZCL_STATUS_SUCCESS; - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_SCENES_REMOVE_ALL_SCENES_CB_ID, RET_ERROR, cmd_info, req, - &remove_all_scenes_status); - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - return remove_all_scenes_status; -} - -static void zb_zcl_scenes_process_remove_all_scenes_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_scenes_remove_all_scenes_req_t* req; - zb_zcl_scenes_remove_all_scenes_req_t req_copy; - zb_uint8_t remove_all_scenes_status = ZB_ZCL_STATUS_SUCCESS; - zb_zcl_attr_t* scene_count_desc; - - TRACE_MSG( - TRACE_ZCL1, - "> zb_zcl_scenes_process_remove_all_scenes_command param %hd", - (FMT__H, param)); - - ZB_ZCL_SCENES_GET_REMOVE_ALL_SCENES_REQ(param, req); - - if (!req) - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - - ZB_MEMCPY(&req_copy, req, sizeof(zb_zcl_scenes_remove_all_scenes_req_t)); - remove_all_scenes_status = zb_zcl_scenes_process_remove_all_scenes(param, &req_copy, cmd_info); - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - { - if (remove_all_scenes_status == ZB_ZCL_STATUS_SUCCESS) - { - scene_count_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID); - if (scene_count_desc && scene_count_desc->data_p) - { - /* This attribute is not reportable, so may set attribute value directly */ - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(scene_count_desc, 0); - } - } - - /* prevent to send response on ZGP command */ - if (!ZB_ZCL_ADDR_TYPE_IS_GPD(cmd_info->addr_data.common_data.source.addr_type)) - { - ZB_ZCL_SCENES_SEND_REMOVE_ALL_SCENES_RES( - param, - cmd_info->seq_number, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - cmd_info->profile_id, - NULL, - remove_all_scenes_status, - req_copy.group_id); - } - else - { - zb_buf_free(param); - } - } - break; - - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_scenes_process_remove_all_scenes_command", (FMT__0)); -} /* void zb_zcl_scenes_process_remove_all_scenes_command(zb_uint8_t param) */ - -static void zb_zcl_scenes_process_get_scene_membership_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_scenes_get_scene_membership_req_t* req; - zb_zcl_scenes_get_scene_membership_req_t req_copy; - - TRACE_MSG( - TRACE_ZCL1, - "> zb_zcl_scenes_process_get_scene_membership_command param %hd", - (FMT__H, param)); - - ZB_ZCL_SCENES_GET_GET_SCENE_MEMBERSHIP_REQ(param, req); - - if (!req) - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - ZB_MEMCPY(&req_copy, req, sizeof(zb_zcl_scenes_get_scene_membership_req_t)); - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_SCENES_GET_SCENE_MEMBERSHIP_CB_ID, RET_ERROR, cmd_info, &req_copy, NULL); - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - /*We don't send a Get Scene Membership Resp command. Application must send reply - * for this command. - */ - zb_buf_free(param); - break; - - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG( - TRACE_ZCL1, - "< zb_zcl_scenes_process_get_scene_membership_command", - (FMT__0)); -} /* zb_zcl_scenes_process_get_scene_membership_command(zb_uint8_t param) */ - -zb_uint8_t zb_zcl_scenes_process_recall_scene(zb_uint8_t param, zb_zcl_scenes_recall_scene_req_t* req, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_uint8_t recall_scene_status = ZB_ZCL_STATUS_SUCCESS; - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_SCENES_RECALL_SCENE_CB_ID, RET_ERROR, cmd_info, req, &recall_scene_status); - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - return recall_scene_status; -} - -static void zb_zcl_scenes_process_recall_scene_command(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_scenes_recall_scene_req_t* req; - zb_zcl_scenes_recall_scene_req_t req_copy; - zb_zcl_status_t recall_scene_status = ZB_ZCL_STATUS_SUCCESS; - zb_uint8_t req_len; - - TRACE_MSG( TRACE_ZCL1, "> zb_zcl_scenes_process_recall_scene_command param %hd", (FMT__H, param)); - - ZB_ZCL_SCENES_GET_RECALL_SCENE_REQ(param, req, req_len); - - if (!req) - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - return; - } - else - { - ZB_MEMCPY(&req_copy, req, req_len); - if (req_len < ZB_ZCL_SCENES_RECALL_SCENE_REQ_PAYLOAD_LEN) - { - req_copy.transition_time = ZB_ZCL_SCENES_RECALL_SCENE_REQ_TRANSITION_TIME_INVALID_VALUE; - } - recall_scene_status = (zb_zcl_status_t)zb_zcl_scenes_process_recall_scene(param, &req_copy, cmd_info); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - { - /* Update CurrentGroup, CurrentScene and SceneValid attributes. */ - zb_zcl_attr_t* attr_desc; - - attr_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_ID); - ZB_ASSERT(attr_desc); - TRACE_MSG(TRACE_ZCL1, "Update CurrentGroup: 0x%x", (FMT__D, req_copy.group_id)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL16(attr_desc, req_copy.group_id); - - attr_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SCENES_CURRENT_SCENE_ID); - ZB_ASSERT(attr_desc); - TRACE_MSG(TRACE_ZCL1, "Update CurrentScene: 0x%hx", (FMT__H, req_copy.scene_id)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, req_copy.scene_id); - - attr_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SCENES_SCENE_VALID_ID); - ZB_ASSERT(attr_desc); - TRACE_MSG(TRACE_ZCL1, "Update SceneValid: TRUE", (FMT__0)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(attr_desc, ZB_TRUE); - - zb_zcl_send_default_handler(param, cmd_info, recall_scene_status); - } - break; - - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG( - TRACE_ZCL1, - "< zb_zcl_scenes_process_recall_scene_command", - (FMT__0)); -} /* zb_zcl_scenes_process_recall_scene_command(zb_uint8_t param) */ - -void zb_zcl_scenes_remove_all_scenes_in_all_endpoints_by_group_id(zb_uint8_t param, zb_uint16_t group_id) -{ - zb_zcl_scenes_remove_all_scenes_req_t req; - - TRACE_MSG( - TRACE_ZCL1, - "> zb_zcl_scenes_remove_all_scenes_in_all_endpoints_by_group_id param %hd group_id 0x%x", - (FMT__H_D, param, group_id)); - - req.group_id = group_id; - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_SCENES_INTERNAL_REMOVE_ALL_SCENES_ALL_ENDPOINTS_CB_ID, RET_ERROR, NULL, &req, NULL); - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - zb_buf_free(param); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_scenes_remove_all_scenes_in_all_endpoints_by_group_id", (FMT__0)); -}/* void zb_zcl_scenes_remove_scenes_in_all_endpoints(zb_uint16_t...) */ - -void zb_zcl_scenes_remove_all_scenes_in_all_endpoints(zb_uint8_t param) -{ - TRACE_MSG( - TRACE_ZCL1, - "> zb_zcl_scenes_remove_all_scenes_in_all_endpoints param %hd", - (FMT__H, param)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, - ZB_ZCL_SCENES_INTERNAL_REMOVE_ALL_SCENES_ALL_ENDPOINTS_ALL_GROUPS_CB_ID, RET_ERROR, NULL, NULL, NULL); - - if (ZCL_CTX().device_cb) - { - (ZCL_CTX().device_cb)(param); - } - - zb_buf_free(param); - -}/* void zb_zcl_scenes_remove_scenes_in_all_endpoints(zb_uint16_t...) */ - - -static inline void zb_zcl_scenes_send_recall_scene_req_rev1(zb_bufid_t buffer, - const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t ep, - zb_uint16_t prof_id, - zb_uint8_t dis_default_resp, - zb_callback_t callback, - zb_uint16_t group_id, - zb_uint8_t scene_id) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL - (ptr - , dis_default_resp) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( - ptr, - ZB_ZCL_GET_SEQ_NUM(), - ZB_ZCL_CMD_SCENES_RECALL_SCENE); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (scene_id)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_SCENES, callback); -} - -static inline void zb_zcl_scenes_send_recall_scene_req_rev2(zb_bufid_t buffer, - const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t ep, - zb_uint16_t prof_id, - zb_uint8_t dis_default_resp, - zb_callback_t callback, - zb_uint16_t group_id, - zb_uint8_t scene_id, - zb_uint16_t transition_time) -{ - zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) - ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL - (ptr - , dis_default_resp) - ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( - ptr, - ZB_ZCL_GET_SEQ_NUM(), - ZB_ZCL_CMD_SCENES_RECALL_SCENE); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (group_id)); - ZB_ZCL_PACKET_PUT_DATA8(ptr, (scene_id)); - ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, (transition_time)); - zb_zcl_finish_and_send_packet(buffer, ptr, dst_addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_SCENES, callback); -} - -void zb_zcl_scenes_send_recall_scene_req_zcl8(zb_bufid_t buffer, - const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t ep, - zb_uint16_t prof_id, - zb_uint8_t dis_default_resp, - zb_callback_t callback, - zb_uint16_t group_id, - zb_uint8_t scene_id, - zb_uint16_t transition_time) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_scenes_send_recall_scene_req_zcl8", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_SCENES_CLUSTER_REVISION_MAX, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - zb_zcl_scenes_send_recall_scene_req_rev1(buffer, - dst_addr, - dst_addr_mode, - dst_ep, - ep, - prof_id, - dis_default_resp, - callback, - group_id, - scene_id); - break; - case 2: - /* FALLTHROUGH */ - case 3: - zb_zcl_scenes_send_recall_scene_req_rev2(buffer, - dst_addr, - dst_addr_mode, - dst_ep, - ep, - prof_id, - dis_default_resp, - callback, - group_id, - scene_id, - transition_time); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_scenes_send_recall_scene_req_zcl8", (FMT__0)); -} - -void zb_zcl_scenes_send_recall_scene_req(zb_bufid_t buffer, - const zb_addr_u *dst_addr, - zb_uint8_t dst_addr_mode, - zb_uint8_t dst_ep, - zb_uint8_t ep, - zb_uint16_t prof_id, - zb_uint8_t dis_default_resp, - zb_callback_t callback, - zb_uint16_t group_id, - zb_uint8_t scene_id) -{ - zb_uint16_t rev; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_scenes_send_recall_scene_req", (FMT__0)); - - rev = zb_zcl_get_cluster_rev_by_mode(ZB_ZCL_CLUSTER_REV_MIN, - dst_addr, dst_addr_mode, dst_ep, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_CLIENT_ROLE, ep); - - TRACE_MSG(TRACE_ZCL3, "rev is %d", (FMT__D, rev)); - - switch(rev) - { - case ZB_ZCL_CLUSTER_REV_MIN: - zb_zcl_scenes_send_recall_scene_req_rev1(buffer, - dst_addr, - dst_addr_mode, - dst_ep, - ep, - prof_id, - dis_default_resp, - callback, - group_id, - scene_id); - break; - case 2: - /* FALLTHROUGH */ - case 3: - zb_zcl_scenes_send_recall_scene_req_rev2(buffer, - dst_addr, - dst_addr_mode, - dst_ep, - ep, - prof_id, - dis_default_resp, - callback, - group_id, - scene_id, - ZB_ZCL_RECALL_SCENES_TRANSITION_TIME_NOT_USED_VALUE); - break; - default: - break; - } - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_scenes_send_recall_scene_req", (FMT__0)); -} - -#ifndef ZB_ZCL_SCENES_OPTIONAL_COMMANDS_DISABLED - -static void zb_zcl_scenes_process_copy_scene(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_zcl_scenes_copy_scene_req_t* req; - zb_zcl_scenes_copy_scene_req_t req_copy; - zb_uint8_t num_copied_scenes = 0x00U; - - TRACE_MSG(TRACE_ZCL1, ">>zb_zcl_scenes_process_copy_scene(), param %hd", (FMT__H, param)); - - /* Initialize with invalid IDs */ - req_copy.group_id_from = 0xFF; - req_copy.scene_id_from = 0xFF; - req_copy.group_id_to = 0xFF; - req_copy.scene_id_to = 0xFF; - - ZB_ZCL_SCENES_GET_COPY_SCENE_REQ(param, req); - - if (!req) - { - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_INVALID_FIELD); - } - else if (ZCL_CTX().device_cb) - { - ZB_MEMCPY(&req_copy, req, sizeof(zb_zcl_scenes_copy_scene_req_t)); - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH( - param, - ZB_ZCL_SCENES_COPY_SCENE_CB_ID, - RET_ERROR, - cmd_info, - &req_copy, - &num_copied_scenes); - - TRACE_MSG(TRACE_ZCL1, "call device cb %p", (FMT__P, ZCL_CTX().device_cb)); - (ZCL_CTX().device_cb)(param); - } - - switch (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param)) - { - case RET_OK: - if (num_copied_scenes != 0U) - { - zb_uint8_t scene_count; - - zb_zcl_attr_t* scene_count_desc = - zb_zcl_get_attr_desc_a( - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_SCENES, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID); - - if (scene_count_desc && scene_count_desc->data_p) - { - /* This attribute is not reportable, so may set attribute value directly */ - scene_count = ZB_ZCL_GET_ATTRIBUTE_VAL_8(scene_count_desc); - if (scene_count + num_copied_scenes <= ZB_ZCL_MAX_SCENE_TABLE_RECORDS) - { - TRACE_MSG(TRACE_ZCL1, "increase scene count: from %hd to %hd", - (FMT__H_H, scene_count, scene_count + num_copied_scenes)); - ZB_ZCL_SET_DIRECTLY_ATTR_VAL8(scene_count_desc, scene_count + num_copied_scenes); - } - else - { - TRACE_MSG(TRACE_ERROR, "ERROR: not enough space to copy scenes! scene_count_attr %hd, num_copied_scenes %hd, ZB_ZCL_MAX_SCENE_TABLE_RECORDS %hd", - (FMT__H_H_H, num_copied_scenes, scene_count, ZB_ZCL_MAX_SCENE_TABLE_RECORDS)); - } - } - } - - /* We do not send a Copy Scene Resp command. - * Application must send reply for this command. - */ - zb_buf_free(param); - break; - - case RET_ERROR: - TRACE_MSG(TRACE_ZCL1, "ERROR during command processing: " - "User callback failed with err=%d.", - (FMT__D, ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param))); - /* FALLTHRU */ - default: - zb_zcl_send_default_handler(param, cmd_info, ZB_ZCL_STATUS_FAIL); - break; - } - - TRACE_MSG(TRACE_ZCL1, "< shade_normal_processing ep %i", (FMT__H, ep_id)); - - ZB_ASSERT(buf != 0); - - closed_limit_desc = zb_zcl_get_attr_desc_a(ep_id, - ZB_ZCL_CLUSTER_ID_SHADE_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SHADE_CONFIG_CLOSED_LIMIT_ID); - - mode_desc = zb_zcl_get_attr_desc_a(ep_id, - ZB_ZCL_CLUSTER_ID_SHADE_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SHADE_CONFIG_MODE_ID); - - /* Verification: closed_limit_desc and/or mode_desc pointer must not be NULL, - since they will be accessed in the lines below. This function does not return - anything, so the caller will assume it worked. */ - ZB_VERIFY((closed_limit_desc != NULL) && (mode_desc != NULL), RET_NULL_POINTER); - - closed_limit = (zb_uint16_t*)closed_limit_desc->data_p; - mode = (zb_uint8_t*)mode_desc->data_p; - - if (*mode == ZB_ZCL_ATTR_SHADE_CONFIG_MODE_NORMAL) - { - switch (cluster_id) - { - case ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL: - shade_position = - *closed_limit * (ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE_SHADE - value) - / ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE_SHADE; - ret = 0; - break; - case ZB_ZCL_CLUSTER_ID_ON_OFF: - shade_position = *closed_limit * (1 - value); - ret = 0; - break; - } - - if (ret == 0) - { - TRACE_MSG(TRACE_ZCL1, "closed_limit %d", (FMT__D, *closed_limit)); - TRACE_MSG(TRACE_ZCL1, "shade_position %d", (FMT__D, shade_position)); - - ZB_ASSERT(ZCL_CTX().device_cb != NULL); - device_cb_param = ZB_BUF_GET_PARAM(buf, zb_zcl_device_callback_param_t); - - device_cb_param->device_cb_id = ZB_ZCL_SHADE_SET_VALUE_CB_ID; - device_cb_param->endpoint = ep_id; - device_cb_param->cb_param.shade_set_value_param.new_value = shade_position; - device_cb_param->cb_param.shade_set_value_param.is_config = ZB_FALSE; - - (ZCL_CTX().device_cb)(buf); - - ret = device_cb_param->status; - - zb_buf_free(buf); - - if (ret != RET_OK) - { - TRACE_MSG(TRACE_ZCL1, "Error with setting new Shade Position", (FMT__0)); - } - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "Error, mode is not NORMAL", (FMT__0)); - } - TRACE_MSG(TRACE_ZCL1, "< shade_normal_processing", (FMT__0)); -} - -void shade_config_processing(zb_uint8_t ep_id) -{ - zb_uint16_t closed_limit; - zb_zcl_attr_t* mode_desc; - zb_uint8_t* mode; - zb_zcl_device_callback_param_t *device_cb_param; - zb_bufid_t buf = zb_buf_get_out(); - - - TRACE_MSG(TRACE_ZCL1, "> shade_config_processing ep %i", (FMT__H, ep_id)); - - mode_desc = zb_zcl_get_attr_desc_a(ep_id, - ZB_ZCL_CLUSTER_ID_SHADE_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SHADE_CONFIG_MODE_ID); - - ZB_ASSERT(mode_desc != NULL && buf != 0); - - mode = (zb_uint8_t*)mode_desc->data_p; - - - TRACE_MSG(TRACE_ZCL1, "mode %i", (FMT__H, *mode)); - - if (*mode == ZB_ZCL_ATTR_SHADE_CONFIG_MODE_CONFIGURE) - { - ZB_ASSERT(ZCL_CTX().device_cb != NULL); - -/* In Configure mode 0 means 'Go to most opened', 1 - 'Go to most closed' */ - - device_cb_param = ZB_BUF_GET_PARAM(buf, zb_zcl_device_callback_param_t); - - device_cb_param->device_cb_id = ZB_ZCL_SHADE_SET_VALUE_CB_ID; - device_cb_param->endpoint = ep_id; - device_cb_param->cb_param.shade_set_value_param.new_value = CONFIGURE_MOST_OPENED; - device_cb_param->cb_param.shade_set_value_param.is_config = ZB_TRUE; - - (ZCL_CTX().device_cb)(buf); - - - device_cb_param->cb_param.shade_set_value_param.new_value = CONFIGURE_MOST_CLOSED; - device_cb_param->cb_param.shade_set_value_param.is_config = ZB_TRUE; - - (ZCL_CTX().device_cb)(buf); - - device_cb_param->device_cb_id = ZB_ZCL_SHADE_GET_VALUE_CB_ID; - - (ZCL_CTX().device_cb)(buf); - /* TODO: check - free buffer after a call? */ - - closed_limit = device_cb_param->cb_param.shade_get_value_param.ret_value; - - /* Calculate ClosedLimit attribute */ - if (closed_limit > 0) - { - TRACE_MSG(TRACE_ZCL1, "ClosedLimit = %d, setting", (FMT__D, closed_limit)); - ZB_ZCL_SET_ATTRIBUTE(ep_id, - ZB_ZCL_CLUSTER_ID_SHADE_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_SHADE_CONFIG_CLOSED_LIMIT_ID, - (zb_uint8_t*)&closed_limit, - ZB_FALSE); - } - else - { - TRACE_MSG(TRACE_ZCL1, "Cannot set ClosedLimit = 0", (FMT__0)); - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "Not CONFIGURE mode", (FMT__0)); - } - - TRACE_MSG(TRACE_ZCL1, "< shade_config_processing", (FMT__0)); -} -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_SHADE_CONFIG */ diff --git a/zboss/development/src/zcl/zcl_temp_measurement.c b/zboss/development/src/zcl/zcl_temp_measurement.c deleted file mode 100644 index 0b42fc6051..0000000000 --- a/zboss/development/src/zcl/zcl_temp_measurement.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL: implements attribute values check -*/ - -#define ZB_TRACE_FILE_ID 2083 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_TEMP_MEASUREMENT) - -#include "zb_zcl.h" -#include "zb_aps.h" -#include "zcl/zb_zcl_common.h" - -zb_ret_t check_value_temp_measurement_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -void zb_zcl_temp_measurement_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -void zb_zcl_temp_measurement_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_temp_measurement_server, - zb_zcl_temp_measurement_write_attr_hook_server, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_temp_measurement_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_temp_measurement_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - zb_int16_t val = ZB_ZCL_ATTR_GETS16(value); - - TRACE_MSG(TRACE_ZCL1, "> check_value_temp_measurement, attr_id %d, val %d", - (FMT__D_D, attr_id, val)); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID: - if( ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_UNKNOWN == val ) - { - ret = RET_OK; - } - else - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID); - ZB_ASSERT(attr_desc); - - ret = (ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) == ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_INVALID || - ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) <= val) - ? RET_OK : RET_ERROR; - - if(ret) - { - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID); - ZB_ASSERT(attr_desc); - - ret = ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) == ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_INVALID || - val <= ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) - ? RET_OK : RET_ERROR; - } - } - break; - - case ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID: - ret = ( (ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_MIN_VALUE <= val) && - (val <= ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_MAX_VALUE) ) || - (ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_INVALID == val) - ? RET_OK : RET_ERROR; - break; - - case ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID: - ret = ((ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_MIN_VALUE <= val -#if ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_MAX_VALUE != 0x7fff - && val <= ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_MAX_VALUE -#endif - ) || (ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_INVALID == val)) - ? RET_OK : RET_ERROR; - break; - - /* TODO: case ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID */ - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "< check_value_temp_measurement ret %hd", (FMT__H, ret)); - return ret; -} - -void zb_zcl_temp_measurement_write_attr_hook_server( - zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value) -{ - ZVUNUSED(new_value); - ZVUNUSED(endpoint); - - TRACE_MSG(TRACE_ZCL1, ">> zb_zcl_temp_measurement_write_attr_hook endpoint %hd, attr_id %d", - (FMT__H_D, endpoint, attr_id)); - - if (attr_id == ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID) - { - /* TODO Change min/max temperature by current are not agree - * spec/ - * Need consult with customer !*/ - } - - TRACE_MSG(TRACE_ZCL1, "<< zb_zcl_temp_measurement_write_attr_hook", (FMT__0)); -} - -#endif /* ZB_ZCL_SUPPORT_CLUSTER_TEMP_MEASUREMENT */ diff --git a/zboss/development/src/zcl/zcl_thermostat_commands.c b/zboss/development/src/zcl/zcl_thermostat_commands.c deleted file mode 100644 index 633b893797..0000000000 --- a/zboss/development/src/zcl/zcl_thermostat_commands.c +++ /dev/null @@ -1,1447 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL Thermostat cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 2084 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_THERMOSTAT) - -#if defined ZB_ENABLE_HA - -#include "zb_zcl.h" - - /** @brief Context Thermostat cluster */ - static zb_zcl_thermostat_context_t g_thermostat_context; - - void zb_zcl_thermostat_shedule_process(zb_uint8_t param); - - zb_uint8_t gs_thermostat_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_THERMOSTAT_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_thermostat_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_THERMOSTAT_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -zb_uint8_t gs_thermostat_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_THERMOSTAT_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_thermostat_server_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_THERMOSTAT_SERVER_ROLE_GENERATED_CMD_LIST -}; - -#else /* defined ZB_ENABLE_HA */ - - /** @brief Context Thermostat cluster */ - static zb_zcl_thermostat_context_t g_thermostat_context; - -zb_uint8_t gs_thermostat_client_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_THERMOSTAT_CLIENT_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_thermostat_client_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_THERMOSTAT_CLIENT_ROLE_GENERATED_CMD_LIST -}; - -zb_uint8_t gs_thermostat_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_THERMOSTAT_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_uint8_t gs_thermostat_server_generated_commands[] = -{ - ZB_ZCL_CLUSTER_ID_THERMOSTAT_SERVER_ROLE_GENERATED_CMD_LIST -}; - -#endif /* defined ZB_ENABLE_HA*/ - -zb_discover_cmd_list_t gs_thermostat_client_cmd_list = -{ - sizeof(gs_thermostat_client_received_commands), gs_thermostat_client_received_commands, - sizeof(gs_thermostat_client_generated_commands), gs_thermostat_client_generated_commands -}; - -zb_discover_cmd_list_t gs_thermostat_server_cmd_list = -{ - sizeof(gs_thermostat_server_received_commands), gs_thermostat_server_received_commands, - sizeof(gs_thermostat_server_generated_commands), gs_thermostat_server_generated_commands -}; - - - -void zb_zcl_thermostat_init() -{ - zb_uint8_t endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_thermostat_init", (FMT__0)); - - /* Init - cluster-specific part */ -#if defined ZB_ENABLE_HA - if (endpoint) - { - zb_uindex_t i; - - for (i=0; i max_val_s8) - { - *((zb_int8_t *)value) = (*((zb_int8_t *)value) < min_val) ? - (zb_int8_t)ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_MIN_VALUE : - (zb_int8_t)ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_MAX_VALUE; - } - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID: - case ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_COOLING_SETPOINT_ID: - { - /* First check MinCoolSetpointLimit/MaxCoolSetpointLimit, than - * AbsMinCoolSetpointLimit/AbsMaxCoolSetpointLimit, than predefined constants. */ - zb_zcl_attr_t *attr_desc_min = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_MIN_COOL_SETPOINT_LIMIT_ID); - zb_zcl_attr_t *attr_desc_max = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_MAX_COOL_SETPOINT_LIMIT_ID); - if (attr_desc_min && attr_desc_max) - { - min_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_min); - max_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_max); - } - else - { - attr_desc_min = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_COOL_SETPOINT_LIMIT_ID); - attr_desc_max = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_COOL_SETPOINT_LIMIT_ID); - - if (attr_desc_min && attr_desc_max) - { - min_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_min); - max_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_max); - } - else - { - // note: value SIGNED, about (0xff-0) ! - min_val = (zb_int16_t)ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_MIN_VALUE; - max_val = (zb_int16_t)ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_MAX_VALUE; - } - } - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID: - case ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_ID: - { - /* First check MinHeatSetpointLimit/MaxHeatSetpointLimit, than - * AbsMinHeatSetpointLimit/AbsMaxHeatSetpointLimit, than predefined constants. */ - zb_zcl_attr_t *attr_desc_min = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_HEAT_SETPOINT_LIMIT_ID); - zb_zcl_attr_t *attr_desc_max = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_HEAT_SETPOINT_LIMIT_ID); - if (attr_desc_min && attr_desc_max) - { - min_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_min); - max_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_max); - } - else - { - attr_desc_min = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_HEAT_SETPOINT_LIMIT_ID); - attr_desc_max = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_HEAT_SETPOINT_LIMIT_ID); - - if (attr_desc_min && attr_desc_max) - { - min_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_min); - max_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_max); - } - else - { - // note: value SIGNED, about (0xff-0) ! - min_val = (zb_int16_t)ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_MIN_VALUE; - max_val = (zb_int16_t)ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_MAX_VALUE; - } - } - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_MIN_HEAT_SETPOINT_LIMIT_ID: - case ZB_ZCL_ATTR_THERMOSTAT_MAX_HEAT_SETPOINT_LIMIT_ID: - { - zb_zcl_attr_t *attr_desc_min = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_HEAT_SETPOINT_LIMIT_ID); - zb_zcl_attr_t *attr_desc_max = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_HEAT_SETPOINT_LIMIT_ID); - if (attr_desc_min && attr_desc_max) - { - min_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_min); - max_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_max); - } - else - { - min_val = (zb_int16_t)ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_MIN_VALUE; - max_val = (zb_int16_t)ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_MAX_VALUE; - } - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_MIN_COOL_SETPOINT_LIMIT_ID: - case ZB_ZCL_ATTR_THERMOSTAT_MAX_COOL_SETPOINT_LIMIT_ID: - { - zb_zcl_attr_t *attr_desc_min = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_ABS_MIN_COOL_SETPOINT_LIMIT_ID); - zb_zcl_attr_t *attr_desc_max = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_ABS_MAX_COOL_SETPOINT_LIMIT_ID); - if (attr_desc_min && attr_desc_max) - { - min_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_min); - max_val = (zb_int16_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc_max); - } - else - { - min_val = (zb_int16_t)ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_MIN_VALUE; - max_val = (zb_int16_t)ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_MAX_VALUE; - } - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_CONTROL_SEQUENCE_OF_OPERATION_ID: - comp = ZB_FALSE; - ret = (*value < ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_RESERVED) ? RET_OK : RET_ERROR; - if (ret == RET_OK) - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_SYSTEM_MODE_ID); - - if ( attr_desc != NULL ) - { - zb_uint8_t system_mode = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - switch (*value) - { - case ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_COOLING_ONLY: - case ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_COOLING_WITH_REHEAT: - if (system_mode == ZB_ZCL_THERMOSTAT_SYSTEM_MODE_HEAT || - system_mode == ZB_ZCL_THERMOSTAT_SYSTEM_MODE_EMERGENCY_HEATING) - { - ret = RET_ERROR; - } - break; - case ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_HEATING_ONLY: - case ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_HEATING_WITH_REHEAT: - if (system_mode == ZB_ZCL_THERMOSTAT_SYSTEM_MODE_COOL || - system_mode == ZB_ZCL_THERMOSTAT_SYSTEM_MODE_PRECOOLING) - { - ret = RET_ERROR; - } - break; - - default: - // do nothing - // all other pair Control Seq - System mode are valid - break; - } - } - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_SYSTEM_MODE_ID: - comp = ZB_FALSE; - ret = (*value <= ZB_ZCL_THERMOSTAT_SYSTEM_MODE_SLEEP && - *value != 0x02) ? RET_OK : RET_ERROR; // 0x02 is also reserved - - if (ret == RET_OK) - { - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_CONTROL_SEQUENCE_OF_OPERATION_ID); - - if ( attr_desc != NULL ) - { - zb_uint8_t control_seq_of_operation = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - - switch (control_seq_of_operation) - { - case ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_COOLING_ONLY: - case ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_COOLING_WITH_REHEAT: - if (*value == ZB_ZCL_THERMOSTAT_SYSTEM_MODE_HEAT || - *value == ZB_ZCL_THERMOSTAT_SYSTEM_MODE_EMERGENCY_HEATING) - { - ret = RET_ERROR; - } - break; - case ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_HEATING_ONLY: - case ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_HEATING_WITH_REHEAT: - if (*value == ZB_ZCL_THERMOSTAT_SYSTEM_MODE_COOL || - *value == ZB_ZCL_THERMOSTAT_SYSTEM_MODE_PRECOOLING) - { - ret = RET_ERROR; - } - break; - default: - // do nothing - // all other pair Control Seq - System mode are valid - break; - } - } - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_START_OF_WEEK_ID: - ret = (*value <= ZB_ZCL_THERMOSTAT_START_OF_WEEK_SATURDAY) ? RET_OK : RET_ERROR; - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_ID: - ret = (*value >= ZB_ZCL_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_MIN_VALUE && - *value <= ZB_ZCL_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_MAX_VALUE) ? RET_OK : RET_ERROR; - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_REMOTE_SENSING_ID: - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_ALARM_MASK_ID: - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_RUNNING_MODE_ID: - ret = (*value == ZB_ZCL_THERMOSTAT_RUNNING_MODE_OFF_VALUE || - *value == ZB_ZCL_THERMOSTAT_RUNNING_MODE_COOL_VALUE || - *value == ZB_ZCL_THERMOSTAT_RUNNING_MODE_HEAT_VALUE) ? RET_OK : RET_ERROR; - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_PI_COOLING_DEMAND_ID: - { - zb_uint8_t system_mode; - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_SYSTEM_MODE_ID); - ZB_ASSERT(attr_desc); - system_mode = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - if (system_mode == (zb_uint8_t)ZB_ZCL_THERMOSTAT_SYSTEM_MODE_OFF || - system_mode == (zb_uint8_t)ZB_ZCL_THERMOSTAT_SYSTEM_MODE_HEAT) - { - ret = RET_ERROR; - } - else - { - /* Min value is 0x00 according to ZCL 8 spec. Commented to avoid -Werror=type-limits */ - ret = (/* *value >= ZB_ZCL_THERMOSTAT_PI_COOLING_DEMAND_MIN_VALUE && */ - *value <= ZB_ZCL_THERMOSTAT_PI_COOLING_DEMAND_MAX_VALUE) ? RET_OK : RET_ERROR; - } - comp = ZB_FALSE; - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_PI_HEATING_DEMAND_ID: - { - zb_uint8_t system_mode; - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_SYSTEM_MODE_ID); - ZB_ASSERT(attr_desc); - system_mode = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc); - if (system_mode == (zb_uint8_t)ZB_ZCL_THERMOSTAT_SYSTEM_MODE_OFF || - system_mode == (zb_uint8_t)ZB_ZCL_THERMOSTAT_SYSTEM_MODE_COOL) - { - ret = RET_ERROR; - } - else - { - /* Min value is 0x00 according to ZCL 8 spec. Commented to avoid -Werror=type-limits */ - ret = (/* *value >= ZB_ZCL_THERMOSTAT_PI_HEATING_DEMAND_MIN_VALUE && */ - *value <= ZB_ZCL_THERMOSTAT_PI_HEATING_DEMAND_MAX_VALUE) ? RET_OK : RET_ERROR; - } - comp = ZB_FALSE; - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_ID: - if (*value != (zb_uint8_t)ZB_ZCL_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_OFF && - *value != (zb_uint8_t)ZB_ZCL_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_OFF) - { - ret = RET_ERROR; - } - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_DURATION_ID: - /* Min value is 0x0000 according to ZCL 8 spec. Commented to avoid -Werror=type-limits */ - ret = (/* *(zb_uint16_t *)value >= ZB_ZCL_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_DURATION_MIN_VALUE && */ - (zb_uint16_t)*value <= ZB_ZCL_THERMOSTAT_TEMPERATURE_SETPOINT_HOLD_DURATION_MIN_VALUE) ? RET_OK : RET_ERROR; - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_SETPOINT_CHANGE_SOURCE_TIMESTAMP_ID: - { - zb_uint32_t timestamp = ZB_ZCL_ATTR_GET32(value); - ret = (timestamp != (zb_uint32_t)-1) ? RET_OK : RET_ERROR; - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MIN_ID: - { - zb_zcl_attr_t *attr_desc_max = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MAX_ID); - if (*value > ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_max)) - { - *value = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_max); - } - comp = ZB_FALSE; - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MAX_ID: - { - zb_zcl_attr_t *attr_desc_min = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MIN_ID); - if (*value < ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_min)) - { - *value = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_min); - } - comp = ZB_FALSE; - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_ID: - { - zb_zcl_attr_t *attr_desc_min = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MIN_ID); - zb_zcl_attr_t *attr_desc_max = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_SETBACK_MAX_ID); - - ret = (*value >= ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_min) && *value <= ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_max)) ? RET_OK : RET_ERROR; - comp = ZB_FALSE; - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MIN_ID: - { - zb_zcl_attr_t *attr_desc_max = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MAX_ID); - if (*value > ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_max)) - { - *value = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_max); - } - comp = ZB_FALSE; - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MAX_ID: - { - zb_zcl_attr_t *attr_desc_min = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MIN_ID); - if (*value < ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_min)) - { - *value = ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_min); - } - comp = ZB_FALSE; - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_ID: - { - zb_zcl_attr_t *attr_desc_min = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MIN_ID); - zb_zcl_attr_t *attr_desc_max = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_SETBACK_MAX_ID); - - ret = (*value >= ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_min) && *value <= ZB_ZCL_GET_ATTRIBUTE_VAL_8(attr_desc_max)) ? RET_OK : RET_ERROR; - comp = ZB_FALSE; - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_AC_TYPE_ID: - ret = (*value == ZB_ZCL_THERMOSTAT_AC_TYPE_UNKNOWN_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_TYPE_COOLING_AND_FIXED_SPEED_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_TYPE_HEAT_PUMP_AND_FIXED_SPEED_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_TYPE_COOLING_AND_INVERTER_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_TYPE_HEAT_PUMP_AND_INVERTER_VALUE) ? RET_OK : RET_ERROR; - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_AC_REFRIGERANT_TYPE_ID: - ret = (*value == ZB_ZCL_THERMOSTAT_AC_REFRIGERANT_TYPE_UNKNOWN_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_REFRIGERANT_TYPE_R22_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_REFRIGERANT_TYPE_R410A_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_REFRIGERANT_TYPE_R407C_VALUE) ? RET_OK : RET_ERROR; - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_AC_COMPRESSOR_TYPE_ID: - ret = (*value == ZB_ZCL_THERMOSTAT_AC_COMPRESSOR_TYPE_UNKNOWN_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_COMPRESSOR_TYPE_T1_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_COMPRESSOR_TYPE_T2_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_COMPRESSOR_TYPE_T3_VALUE) ? RET_OK : RET_ERROR; - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_AC_LOUVER_POSITION_ID: - ret = (*value == ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_FULLY_CLOSED_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_FULLY_OPEN_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_QUARTER_OPEN_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_HALF_OPEN_VALUE || - *value == ZB_ZCL_THERMOSTAT_AC_LOUVER_POSITION_THREE_QUARTERS_OPEN_VALUE) ? RET_OK : RET_ERROR; - comp = ZB_FALSE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_AC_COIL_TEMPERATURE_ID: - min_val = (zb_int16_t)ZB_ZCL_THERMOSTAT_AC_COIL_TEMPERATURE_MIN_VALUE; - max_val = (zb_int16_t)ZB_ZCL_THERMOSTAT_AC_COIL_TEMPERATURE_MAX_VALUE; - break; - - case ZB_ZCL_ATTR_THERMOSTAT_AC_CAPACITY_FORMAT_ID: - if (*value == ZB_ZCL_THERMOSTAT_AC_CAPACITY_FORMAT_BTUH_VALUE) - { - ret = RET_ERROR; - } - comp = ZB_FALSE; - break; - - default: - comp = ZB_FALSE; - break; - } - - if (comp == ZB_TRUE) - { - TRACE_MSG(TRACE_ZCL1, "comp min %hd max %hd val %hd", (FMT__D_D_D, min_val, max_val, value)); - ret = (ZB_ZCL_ATTR_GETS16(value) >= min_val && - ZB_ZCL_ATTR_GETS16(value) <= max_val) ? RET_OK : RET_ERROR; - } - - if (ret == RET_OK) - { - /* Last check - DeadBand */ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_ID); - zb_int8_t dead_band = ZB_ZCL_THERMOSTAT_MIN_SETPOINT_DEAD_BAND_MIN_VALUE; - - if ( attr_desc != NULL ) - { - dead_band = (zb_int8_t)ZB_ZCL_GET_ATTRIBUTE_VAL_S8(attr_desc); - } - - switch( attr_id ) - { - case ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID: - case ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_COOLING_SETPOINT_ID: - { - /* OccupiedHeatingSetpoint shall always be below the value specified in the - * OccupiedCoolingSetpoint by at least MinSetpointDeadBand*/ - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (attr_id == ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID) ? - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID : - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_ID); - if (attr_desc != NULL) - { - TRACE_MSG(TRACE_ZCL1, "heating 0x%x cooling 0x%x dead_band 0x%x", (FMT__D_D_D, ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc), ZB_ZCL_ATTR_GETS16(value), dead_band)); - - ret = (ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) + dead_band <= - ZB_ZCL_ATTR_GETS16(value)) ? RET_OK : RET_ERROR; - } - } - break; - - case ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID: - case ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_ID: - { - /* OccupiedCoolingSetpoint shall always be above the value specified in the - * OccupiedHeatingSetpoint by at least MinSetpointDeadBand*/ - attr_desc = zb_zcl_get_attr_desc_a( - endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - (attr_id == ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID) ? - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID : - ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_COOLING_SETPOINT_ID); - if (attr_desc != NULL) - { - TRACE_MSG(TRACE_ZCL1, "heating 0x%x cooling 0x%x dead_band 0x%x", (FMT__D_D_D, ZB_ZCL_ATTR_GETS16(value), ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc), dead_band)); - - ret = (ZB_ZCL_GET_ATTRIBUTE_VAL_S16(attr_desc) - dead_band >= - ZB_ZCL_ATTR_GETS16(value)) ? RET_OK : RET_ERROR; - } - } - break; - - default: - break; - } - } - TRACE_MSG(TRACE_ZCL1, "check_value_thermsostat ret %hd", (FMT__H, ret)); - return ret; -} - -/* - * Invoke User App with Thermostat command. - */ -void zb_zcl_thermostat_invoke_user_app(zb_uint8_t param, zb_uint16_t endpoint16) -{ - zb_ret_t result; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_thermostat_invoke_user_app %hx endpoint %d", - (FMT__H_D, param, endpoint16)); - - if (ZCL_CTX().device_cb != NULL && g_thermostat_context.setpoint_mode != ZB_ZCL_THERMOSTAT_PROCESS_NONE) - { - zb_zcl_device_callback_param_t *user_app_invoke_data = - ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t); - zb_zcl_attr_t *attr_desc; - zb_uint8_t endpoint = (zb_uint8_t)endpoint16; - - user_app_invoke_data->device_cb_id = ZB_ZCL_THERMOSTAT_VALUE_CB_ID; - user_app_invoke_data->endpoint = endpoint; - user_app_invoke_data->cb_param.thermostat_value_param.mode = g_thermostat_context.setpoint_mode; - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID); - ZB_ASSERT(attr_desc); - user_app_invoke_data->cb_param.thermostat_value_param.heat_setpoint = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID); - ZB_ASSERT(attr_desc); - user_app_invoke_data->cb_param.thermostat_value_param.cool_setpoint = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - user_app_invoke_data->status = RET_OK; - - g_thermostat_context.setpoint_mode = ZB_ZCL_THERMOSTAT_PROCESS_NONE; - - (ZCL_CTX().device_cb)(param); - result = user_app_invoke_data->status; - TRACE_MSG(TRACE_ZCL1, "result %h", (FMT__H, result)); - } - else - { - result = RET_OK; - } - ZVUNUSED(result); - - zb_buf_free(param); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_thermostat_invoke_user_app", (FMT__0)); -} - -#if defined ZB_ENABLE_HA - -/*********************** Weekly loop ************************************/ - -/** - * Algorithm: - * Weekly Schedule process is schedule on min between near Alarm Set point and - * Max ZB_ZCL_THERMOSTAT_TIMER_MAX with number of Alarm Set point as parameter. - * - * Process - * 1. execute nearest Alarm Set point between saved as parameter and current time - * 2. reschedule self - */ - -/** - * Get last weekly schedule alarm before week_time by specific Weekly Schedule record - * @param week_time - week time - * @param index - index of Weekly Schedule record - */ -zb_uint32_t zb_zcl_thermostat_get_previos_timediff(zb_uint32_t week_time, zb_uint8_t index) -{ - zb_uint32_t timediff = ZB_SECOND_PER_WEEK; - zb_uint32_t start_day = 0; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_thermostat_get_previos_timediff curr %ld index %hd", (FMT__L_H, - week_time, index)); - - for (i=0; i<7; i++, start_day+=ZB_SECOND_PER_DAY) - { - if (g_thermostat_context.schedule_table[index].days & (1< zb_zcl_thermostat_get_next_timediff curr %ld index %hd", (FMT__L_H, - week_time, index)); - - for (i=0; i<7; i++, start_day+=ZB_SECOND_PER_DAY) - { - /* We don't know current day of week, so check every day of - * week. ZB_WEEK_TIME_SUBTRACT takes into account week - * cycle. Checking all days allows to find minimum scheduling - * interval. Possible optimization: start calculations with - * current week day number and break on the 1st found scheduling interval */ - if (g_thermostat_context.schedule_table[index].days & (1< zb_zcl_thermostat_get_current_day_of_week start_of_week %i", (FMT__H, start_of_week)); - curr_week_time = zb_get_utc_time() % ZB_SECOND_PER_WEEK; - curr_day = curr_week_time / ZB_SECOND_PER_DAY; - - /* Because 1 jan 1970 was Thursday (start of week - Sunday), we need to convert - curr_day to days from our start_of_week. */ - - TRACE_MSG(TRACE_ZCL1, "curr_day before %i", (FMT__H, curr_day)); - - diff = ZB_ZCL_THERMOSTAT_START_OF_WEEK_THURSDAY - start_of_week; - - if (curr_day + diff > ZB_DAYS_PER_WEEK - 1) - { - curr_day = curr_day + diff - (ZB_DAYS_PER_WEEK); - } - else if (curr_day + diff < 0) - { - curr_day = ZB_DAYS_PER_WEEK - 1 - (ZB_ABS(diff) - curr_day); - } - else - { - curr_day += diff; - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_thermostat_get_current_day_of_week ret %i", (FMT__H, curr_day)); - return (1 << curr_day); -} - -/** - * @brief Convert data from Weekly Schedule record to cluster attributies and invoke User app wrapper - * @param index - index of Weekly Schedule record - */ -void zb_zcl_thermostat_convert_weekly_alarm_to_attributies(zb_uint8_t index) -{ - zb_uint8_t endpoint; - zb_bool_t is_new_event; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_thermostat_convert_weekly_alarm_to_attributies %hd", (FMT__H, index)); - - is_new_event = (g_thermostat_context.setpoint_mode == ZB_ZCL_THERMOSTAT_PROCESS_NONE) ? ZB_TRUE : ZB_FALSE; - - ZB_ASSERT(index < ZB_ZCL_THERMOSTAT_WEEKLY_SCHEDULE_TABLE_SIZE); - g_thermostat_context.setpoint_mode = g_thermostat_context.schedule_table[index].mode; - - endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE); - ZB_ASSERT(endpoint); - - ZB_ZCL_SET_ATTRIBUTE(endpoint, ZB_ZCL_CLUSTER_ID_THERMOSTAT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID, - (zb_uint8_t*)&(g_thermostat_context.schedule_table[index].cool_setpoint), ZB_FALSE); - - ZB_ZCL_SET_ATTRIBUTE(endpoint, ZB_ZCL_CLUSTER_ID_THERMOSTAT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID, - (zb_uint8_t*)&(g_thermostat_context.schedule_table[index].heat_setpoint), ZB_FALSE); - - if (is_new_event == ZB_TRUE) - { - zb_buf_get_out_delayed_ext(zb_zcl_thermostat_invoke_user_app, endpoint, 0); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_thermostat_convert_weekly_alarm_to_attributies", (FMT__0)); -} - -void zb_zcl_thermostat_shedule_process(zb_uint8_t param) -{ - zb_uint32_t curr_week_time; - zb_uint8_t index = param; - zb_uint32_t min_time; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_thermostat_shedule_process index %hd", (FMT__H, param)); - - curr_week_time = zb_get_utc_time() % ZB_SECOND_PER_WEEK; - - if (param != ZB_ZCL_THERMOSTAT_PROCESS_NONE) - { - zb_uint32_t t; - - /* - SetPoint fired. Need to check if missed target time. If yes, - check if there are another Setpoints. Use the closest setpoint - to set the temperature. - */ - min_time = ZB_ZCL_THERMOSTAT_SETPOINT_TIME_DELTA; - t = zb_zcl_thermostat_get_previos_timediff(curr_week_time, index); - - if (t > min_time) - { - /* find the closest expired setpoint (within - * ZB_ZCL_THERMOSTAT_SETPOINT_TIME_DELTA time interval) */ - index = ZB_ZCL_THERMOSTAT_PROCESS_NONE; - for (i=0; i zb_zcl_thermostat_remove_record_by_day %hd", (FMT__H, day)); - - for (i=0; i zb_zcl_thermostat_setpoint_raise_lower_handler %hd", (FMT__H, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint; - attr_desc_heating_setpoint = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID); - attr_desc_cooling_setpoint = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_thermostat_setpoint_raise_lower_handler: param %i", (FMT__H, param)); - ZB_ZCL_THERMOSTAT_GET_SETPOINT_RAISE_LOWER_REQ(param, setpoint_raise_lower_req, status); - ZB_ASSERT(status == ZB_ZCL_PARSE_STATUS_SUCCESS); - ZVUNUSED(status); - - TRACE_MSG(TRACE_ZCL2, "mode %hd amount %hd", (FMT__H_H, - setpoint_raise_lower_req.mode, setpoint_raise_lower_req.amount)); - - switch (setpoint_raise_lower_req.mode) - { - case ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_MODE_HEAT: - { - zb_int16_t value = *(zb_int16_t*)attr_desc_heating_setpoint->data_p + - setpoint_raise_lower_req.amount * ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_AMOUNT_MUL; - TRACE_MSG(TRACE_ZCL2, "old value %d new value %d", (FMT__D_D, - *(zb_int16_t*)attr_desc_heating_setpoint->data_p, value)); - if (zb_zcl_set_attr_val(endpoint, ZB_ZCL_CLUSTER_ID_THERMOSTAT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID, (zb_uint8_t*)&value, ZB_FALSE) != ZB_ZCL_STATUS_SUCCESS) - { - ret = RET_INVALID_PARAMETER_1; - } - } - break; - case ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_MODE_COOL: - { - zb_int16_t value = *(zb_int16_t*)attr_desc_cooling_setpoint->data_p + - setpoint_raise_lower_req.amount * ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_AMOUNT_MUL; - TRACE_MSG(TRACE_ZCL2, "old value %d new value %d", (FMT__D_D, - *(zb_int16_t*)attr_desc_cooling_setpoint->data_p, value)); - if (zb_zcl_set_attr_val(endpoint, ZB_ZCL_CLUSTER_ID_THERMOSTAT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID, (zb_uint8_t*)&value, ZB_FALSE) != ZB_ZCL_STATUS_SUCCESS) - { - ret = RET_INVALID_PARAMETER_1; - } - } - break; - case ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_MODE_BOTH: - { - zb_int16_t heating_value = *(zb_int16_t*)attr_desc_heating_setpoint->data_p + - setpoint_raise_lower_req.amount * ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_AMOUNT_MUL; - zb_int16_t cooling_value = *(zb_int16_t*)attr_desc_cooling_setpoint->data_p + - setpoint_raise_lower_req.amount * ZB_ZCL_THERMOSTAT_SETPOINT_RAISE_LOWER_AMOUNT_MUL; - TRACE_MSG(TRACE_ZCL2, "old value %d new value %d old value %d new value %d ", (FMT__D_D_D_D, - *(zb_int16_t*)attr_desc_heating_setpoint->data_p, heating_value, - *(zb_int16_t*)attr_desc_cooling_setpoint->data_p, cooling_value)); - if (zb_zcl_set_attr_val(endpoint, ZB_ZCL_CLUSTER_ID_THERMOSTAT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID, (zb_uint8_t*)&heating_value, ZB_FALSE) != ZB_ZCL_STATUS_SUCCESS || - zb_zcl_set_attr_val(endpoint, ZB_ZCL_CLUSTER_ID_THERMOSTAT, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_ID, (zb_uint8_t*)&cooling_value, ZB_FALSE) != ZB_ZCL_STATUS_SUCCESS) - { - ret = RET_INVALID_PARAMETER_1; - } - } - break; - - default: - ret = RET_ERROR; - } - - if (ret != RET_ERROR && is_new_event) - { - g_thermostat_context.setpoint_mode = setpoint_raise_lower_req.mode; - zb_buf_get_out_delayed_ext(zb_zcl_thermostat_invoke_user_app, endpoint, 0); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_thermostat_setpoint_raise_lower_handler %hd", (FMT__H, ret)); - - return ret; -} - -#if defined ZB_ENABLE_HA - -/** - * 1. Read command parameters - * 2. Remove Weekly Schedule by command parameter day-mask - * 3. Add new Weekly Schedule - * 4. Restart Schedule Process - */ -zb_ret_t zb_zcl_thermostat_set_weekly_schedule_handler(zb_uint8_t param) -{ - zb_zcl_thermostat_set_weekly_schedule_req_t req; - zb_zcl_thermostat_weekly_schedule_point_pair_t pair; - zb_zcl_parse_status_t status; - zb_ret_t ret = RET_OK; - zb_uindex_t i = 0; - zb_uindex_t index; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_thermostat_set_weekly_schedule_handler %hd", (FMT__H, param)); - - ZB_ZCL_THERMOSTAT_GET_SET_WEEKLY_SCHEDULE_REQ(param, req, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL2, "RET_INVALID_PARAMETER", (FMT__0)); - ret = RET_INVALID_PARAMETER; - } - else - { - zb_zcl_thermostat_remove_record_by_day(req.day_of_week); - - TRACE_MSG(TRACE_ZCL2, "req.num_of_transitions %hd %hd %hd", (FMT__H_H_H, - req.num_of_transitions, req.day_of_week, req.mode_for_seq)); - - for (index=0; index zb_zcl_thermostat_get_weekly_schedule_handler %hd", (FMT__H, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - ZB_ZCL_THERMOSTAT_GET_GET_WEEKLY_SCHEDULE_REQ(param, req, status); - if (status != ZB_ZCL_PARSE_STATUS_SUCCESS) - { - ret = RET_INVALID_PARAMETER; - } - else - { - zb_uint8_t *cmd_ptr; - zb_uint8_t *count_ptr; - zb_uindex_t i; - - TRACE_MSG(TRACE_ZCL3, "days %hd mode %hd", (FMT__H_H, - req.days_to_return, req.mode_to_return)); - - ZB_ZCL_THERMOSTAT_INIT_GET_WEEKLY_SCHEDULE_RESP(param, cmd_ptr, cmd_info.seq_number, - 0, req.days_to_return, req.mode_to_return); - count_ptr = cmd_ptr - 3; - -/*TODO: CR:MEDIUM add buffer size check */ - for (i=0; i zb_zcl_thermostat_clear_weekly_schedule_handler %hd", (FMT__H, param)); - - zb_zcl_thermostat_remove_record_by_day(ZB_ZCL_THERMOSTAT_WEEKLY_ALL); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_thermostat_clear_weekly_schedule_handler", (FMT__0)); - - return ret; -} - -#ifdef SUPPORT_RELAY_LOG -/** - * This command not implement yet because has not some data value: - * relay_status, humidity_in_percentage, set_point, - * unread_entries. Currently Relay log storing is not defined in the Spec - */ -zb_ret_t zb_zcl_thermostat_get_relay_status_log_handler(zb_uint8_t param) -{ - zb_ret_t ret = RET_OK; - zb_zcl_parsed_hdr_t cmd_info; - - zb_uint16_t time_of_day; - zb_uint8_t relay_status = 0; - zb_int16_t local_temperature; - zb_uint8_t humidity_in_percentage = 0; - zb_int16_t set_point = 0; - zb_uint16_t unread_entries = 0; - zb_zcl_attr_t *attr_desc; - - TRACE_MSG(TRACE_ZCL3, "> zb_zcl_thermostat_get_relay_status_log_handler %hd", (FMT__H, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - // get data - time_of_day = (zb_uint16_t)((zb_get_utc_time() % ZB_SECOND_PER_WEEK) / ZB_SECOND_PER_MINUTE); - - attr_desc = zb_zcl_get_attr_desc_a(ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_ID); - ZB_ASSERT(attr_desc); - local_temperature = ZB_ZCL_GET_ATTRIBUTE_VAL_16(attr_desc); - - // todo get value of: - // relay_status, humidity_in_percentage, set_point, unread_entries - - ZB_ZCL_THERMOSTAT_SEND_GET_RELAY_STATUS_LOG_RESP(buf, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, cmd_info.seq_number, NULL, - time_of_day, - relay_status, - local_temperature, - humidity_in_percentage, - set_point, - unread_entries); - - ret = RET_BUSY; - - TRACE_MSG(TRACE_ZCL3, "< zb_zcl_thermostat_get_relay_status_log_handler", (FMT__0)); - - return ret; -} -#endif - -#endif /* defined ZB_ENABLE_HA */ - -zb_bool_t zb_zcl_process_thermostat_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_zcl_parsed_hdr_t cmd_info; - zb_ret_t ret = RET_OK; - - TRACE_MSG( TRACE_ZCL1, - "> zb_zcl_process_thermostat_specific_commands: buf %p", - (FMT__P, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - if( cmd_info.cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV ) - { - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_THERMOSTAT_SETPOINT_RAISE_LOWER: - ret = zb_zcl_thermostat_setpoint_raise_lower_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed SETPOINT_RAISE_LOWER command", (FMT__0)); - break; - -#if defined ZB_ENABLE_HA - case ZB_ZCL_CMD_THERMOSTAT_SET_WEEKLY_SCHEDULE: - ret = zb_zcl_thermostat_set_weekly_schedule_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed SET_WEEKLY_SCHEDULE command", (FMT__0)); - break; - - case ZB_ZCL_CMD_THERMOSTAT_GET_WEEKLY_SCHEDULE: - ret = zb_zcl_thermostat_get_weekly_schedule_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed GET_WEEKLY_SCHEDULE command", (FMT__0)); - break; - - case ZB_ZCL_CMD_THERMOSTAT_CLEAR_WEEKLY_SCHEDULE: - ret = zb_zcl_thermostat_clear_weekly_schedule_handler(param); - TRACE_MSG(TRACE_ZCL3, "Processed CLEAR_WEEKLY_SCHEDULE command", (FMT__0)); - break; - - case ZB_ZCL_CMD_THERMOSTAT_GET_RELAY_STATUS_LOG: - // TODO command not release because have not info about Relay Status Log - ret = RET_IGNORE; -#ifdef SUPPORT_RELAY_LOG - ret = zb_zcl_thermostat_get_relay_status_log_handler(param); -#endif - TRACE_MSG(TRACE_ZCL3, "Processed GET_RELAY_STATUS_LOG command", (FMT__0)); - break; - -#endif /* defined ZB_ENABLE_HA */ - - default: - processed = ZB_FALSE; - break; - } - } - - if (ret == RET_BUSY) - { - // do nothing: buf has reused, processed has set ZB_TRUE - } - else if(processed == ZB_FALSE) - { - // do nothing: base func will send else if(processed == ZB_FALSE) - } - else if (ret != RET_OK) - { - zb_uint8_t status_code; - switch(ret) - { - case RET_OUT_OF_RANGE: - status_code = ZB_ZCL_STATUS_INSUFF_SPACE; - break; - case RET_INVALID_PARAMETER: - status_code = ZB_ZCL_STATUS_INVALID_FIELD; - break; - case RET_INVALID_PARAMETER_1: - status_code = ZB_ZCL_STATUS_INVALID_VALUE; - break; - case RET_IGNORE: - /* ZCL8: CCB 2477: use UNSUP_COMMAND instead of any other Unsupported command status */ - status_code = ZB_ZCL_STATUS_UNSUP_CMD; - break; - default: - status_code = ZB_ZCL_STATUS_FAIL; - break; - } - ZB_ZCL_SEND_DEFAULT_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, - cmd_info.seq_number, - cmd_info.cmd_id, - status_code); - } - else if (!(cmd_info.disable_default_response)) - { - ZB_ZCL_SEND_DEFAULT_RESP(param, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr, - ZB_APS_ADDR_MODE_16_ENDP_PRESENT, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint, - ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).dst_endpoint, - cmd_info.profile_id, - ZB_ZCL_CLUSTER_ID_THERMOSTAT, - cmd_info.seq_number, - cmd_info.cmd_id, - processed == ZB_TRUE ? ZB_ZCL_STATUS_SUCCESS : ZB_ZCL_STATUS_FAIL); - } - else - { - zb_buf_free(param); - } - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_thermostat_specific_commands: processed %d", - (FMT__D, processed)); - - return ZB_TRUE; -} - - -zb_bool_t zb_zcl_process_thermostat_specific_commands_srv(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_thermostat_server_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_thermostat_specific_commands(param); -} - - -zb_bool_t zb_zcl_process_thermostat_specific_commands_cli(zb_uint8_t param) -{ - if ( ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param ) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_thermostat_client_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_thermostat_specific_commands(param); -} -#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_THERMOSTAT */ diff --git a/zboss/development/src/zcl/zcl_thermostat_ui_config.c b/zboss/development/src/zcl/zcl_thermostat_ui_config.c deleted file mode 100644 index 4444fe63a9..0000000000 --- a/zboss/development/src/zcl/zcl_thermostat_ui_config.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#define ZB_TRACE_FILE_ID 71 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_THERMOSTAT_UI_CONFIG) - -zb_ret_t check_value_thermostat_ui_config_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -void zb_zcl_thermostat_ui_config_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_THERMOSTAT_UI_CONFIG, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_thermostat_ui_config_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_thermostat_ui_config_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_THERMOSTAT_UI_CONFIG, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_thermostat_ui_config_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = ZB_TRUE; - ZVUNUSED(endpoint); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_TEMPERATURE_DISPLAY_MODE_ID: - ret = (*value < ZB_ZCL_THERMOSTAT_UI_CONFIG_TEMPERATURE_DISPLAY_MODE_RESERVED) ? RET_OK : RET_ERROR; - break; - case ZB_ZCL_ATTR_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_ID: - ret = (*value < ZB_ZCL_THERMOSTAT_UI_CONFIG_KEYPAD_LOCKOUT_RESERVED) ? RET_OK : RET_ERROR; - break; - - default: - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_thermostat ret %hd", (FMT__H, ret)); - return ret; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_THERMOSTAT_UI_CONFIG */ diff --git a/zboss/development/src/zcl/zcl_time.c b/zboss/development/src/zcl/zcl_time.c deleted file mode 100644 index 8c0f553181..0000000000 --- a/zboss/development/src/zcl/zcl_time.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2021 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL: Time cluster implementation -*/ - -#define ZB_TRACE_FILE_ID 2085 - -#include "zb_common.h" - -#if defined (ZB_ZCL_SUPPORT_CLUSTER_TIME) - -#include "zb_zcl.h" -#include "zb_aps.h" -#include "zcl/zb_zcl_common.h" - -#define ZB_ZCL_TIME_SERVER_SYNCHRONIZATION_TIMEOUT_SECONDS 100 -zb_ret_t check_value_time_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -void zb_zcl_time_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value); - -#ifdef THAT_CB_IS_NEVER_USED_CAUSING_WARNING -static zb_zcl_time_set_real_time_clock_t zb_zcl_set_real_time_clock_cb; -#endif -static zb_zcl_time_sync_time_server_found_cb_t zb_zcl_time_server_found_cb = NULL; -static zb_bool_t zb_zcl_search_in_process = ZB_FALSE; -static zb_uint8_t zb_zcl_src_search_endpoint = 0; - -zb_bool_t check_value_time(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); - -static void zb_zcl_time_sync_stop(zb_uint8_t unused) -{ - ZVUNUSED(unused); - if (zb_zcl_time_server_found_cb != NULL) - { - zb_zcl_time_server_found_cb(RET_TIMEOUT, 0, 0, 0 , 0); - } - zb_zcl_search_in_process = ZB_FALSE; -} - - -static zb_uint8_t zb_zcl_time_sync_get_auth_level(zb_uint8_t time_status, zb_uint16_t short_addr) -{ - if (ZB_ZCL_TIME_TIME_STATUS_MASTER_BIT_IS_SET(time_status) && ZB_ZCL_TIME_TIME_STATUS_SUPERSEDING_BIT_IS_SET(time_status)) - { - return ((0x0000 == short_addr) ? - ZB_ZCL_TIME_COORDINATOR_WITH_MASTER_AND_SUPERSEDING_BITS : - ZB_ZCL_TIME_HAS_MASTER_AND_SUPERSEDING_BITS); - } - else if (ZB_ZCL_TIME_TIME_STATUS_MASTER_BIT_IS_SET(time_status)) - { - return ZB_ZCL_TIME_HAS_MASTER_BIT; - } - else if (ZB_ZCL_TIME_TIME_STATUS_SYNCHRONIZED_BIT_IS_SET(time_status)) - { - return ZB_ZCL_TIME_HAS_SYNCHRONIZED_BIT; - } - else - { - return ZB_ZCL_TIME_SERVER_NOT_CHOSEN; - } -} - -zb_bool_t zb_zcl_time_server_read_attr_handle(zb_uint8_t param) -{ - zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t); - zb_zcl_read_attr_res_t *resp = NULL; - zb_uint8_t time_status = ZB_ZCL_TIME_TIME_STATUS_DEFAULT_VALUE; - zb_uint32_t nw_time = ZB_ZCL_TIME_TIME_DEFAULT_VALUE; - zb_uint8_t fails = 0; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_time_server_read_attr_handle %hd", (FMT__H, param)); - - if (cmd_info->cluster_id != ZB_ZCL_CLUSTER_ID_TIME || !zb_zcl_search_in_process) - { - TRACE_MSG(TRACE_ZCL1, "Not handled cluster id %ld", (FMT__H, cmd_info->cluster_id)); - - return ZB_FALSE; - } - - - ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES(param, resp); - - while (resp != NULL) - { - if (resp->status != ZB_ZCL_STATUS_SUCCESS) - { - TRACE_MSG(TRACE_ZCL1, "Attribute read error: attr 0x%x, status %d", (FMT__D_D, resp->attr_id, resp->status)); - ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES(param, resp); - fails++; - - continue; - } - - TRACE_MSG(TRACE_ZCL1, "read attr resp: src_addr 0x%x ep %hd", - (FMT__D_D, ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint)); - - if (ZB_ZCL_ATTR_TIME_TIME_STATUS_ID == resp->attr_id) - { - time_status = resp->attr_value[0]; - TRACE_MSG(TRACE_ZCL1, "Time status attr value: 0x%hx", (FMT__H, time_status)); - } - else if (ZB_ZCL_ATTR_TIME_TIME_ID == resp->attr_id) - { - nw_time = ZB_ZCL_ATTR_GET32(resp->attr_value); - TRACE_MSG(TRACE_ZCL1, "Time attr value: %ld", (FMT__L, nw_time)); - } - else - { - TRACE_MSG(TRACE_ZCL1, "Unknown attribute: attr 0x%x", (FMT__D, resp->attr_id)); - fails++; - } - - ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES(param, resp); - } - - - if (0 == fails) - { - zb_uint8_t curr_auth_level; - - curr_auth_level = zb_zcl_time_sync_get_auth_level(time_status, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr); - - if (zb_zcl_time_server_found_cb != NULL) - { - zb_zcl_time_server_found_cb(RET_OK, curr_auth_level, ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint, nw_time); - } - else - { - TRACE_MSG(TRACE_ZCL3, "WARNING!!! there is no callback set to handle time server found", (FMT__0)); - } - } - else - { - TRACE_MSG(TRACE_ZCL1, "Mallformed Read Time Status attribute response", (FMT__H, param)); - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_time_server_read_attr_handle", (FMT__0)); - - return ZB_TRUE; -} - - -static void zb_zcl_time_server_start_search_cb(zb_uint8_t param) -{ - zb_zdo_match_desc_resp_t *resp = (zb_zdo_match_desc_resp_t *)zb_buf_begin(param); - zb_uint8_t dst_endpoint; - zb_uint16_t short_addr; - zb_uint8_t *match_ep; - zb_uint8_t *cmd_ptr; - zb_apsde_data_indication_t *ind = ZB_BUF_GET_PARAM(param, zb_apsde_data_indication_t); - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_time_server_start_search_cb %hd", (FMT__H, param)); - - TRACE_MSG(TRACE_ZCL2, "resp match_len %hd", (FMT__H, resp->match_len)); - - if (resp->status == ZB_ZDP_STATUS_SUCCESS && resp->match_len > 0) - { - /* Match EP list follows right after response header */ - match_ep = (zb_uint8_t*)(resp + 1); - - /* set EP value directly to attribute value */ - /* we are searching for exact cluster, so only 1 EP maybe found */ - dst_endpoint = *match_ep; - short_addr = ind->src_addr; - /* ZB_BUF_CLEAR_PARAM(ZB_BUF_FROM_REF(param)); */ - - /* Send Read time status and time attributes */ - ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ(param, cmd_ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); - ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, (ZB_ZCL_ATTR_TIME_TIME_STATUS_ID)); - ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, (ZB_ZCL_ATTR_TIME_TIME_ID)); - ZB_ZCL_GENERAL_SEND_READ_ATTR_REQ( - param, cmd_ptr, short_addr, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, dst_endpoint, zb_zcl_src_search_endpoint, - ZB_AF_HA_PROFILE_ID, (ZB_ZCL_CLUSTER_ID_TIME), NULL); - - - TRACE_MSG(TRACE_ZCL2, "find_time cluster addr %d ep %hd", - (FMT__D_H, short_addr, dst_endpoint)); - - - } - else - { - zb_buf_free(param); - } - - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_time_server_start_search_cb", (FMT__0)); -} - - -static void zb_zcl_time_server_start_search(zb_uint8_t param) -{ - zb_zdo_match_desc_param_t *req; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_time_server_start_search %hd", (FMT__H, param)); - - req = zb_buf_initial_alloc(param, sizeof(zb_zdo_match_desc_param_t) + (1) * sizeof(zb_uint16_t)); - - req->nwk_addr = ZB_NWK_BROADCAST_RX_ON_WHEN_IDLE; - req->addr_of_interest = ZB_NWK_BROADCAST_RX_ON_WHEN_IDLE; - req->profile_id = ZB_AF_HA_PROFILE_ID; - req->num_in_clusters = 1; - req->num_out_clusters = 0; - req->cluster_list[0] = ZB_ZCL_CLUSTER_ID_TIME; - - zb_zdo_match_desc_req(param, zb_zcl_time_server_start_search_cb); - - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_time_server_start_search", (FMT__0)); -} - - -void zb_zcl_time_server_synchronize(zb_uint8_t endpoint, zb_zcl_time_sync_time_server_found_cb_t cb) -{ - zb_uint8_t time_status; - zb_zcl_attr_t *attr = zb_zcl_get_attr_desc_a(endpoint, ZB_ZCL_CLUSTER_ID_TIME, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_TIME_TIME_STATUS_ID); - ZB_ASSERT(attr); - time_status = ((zb_uint8_t *)attr->data_p)[0]; - - - if (zb_zcl_time_sync_get_auth_level(time_status, zb_get_short_address()) <= ZB_ZCL_TIME_HAS_SYNCHRONIZED_BIT) - { - zb_zcl_time_server_found_cb = cb; - zb_zcl_src_search_endpoint = endpoint; - zb_zcl_search_in_process = ZB_TRUE; - ZB_SCHEDULE_ALARM(zb_zcl_time_sync_stop, 0, ZB_TIME_ONE_SECOND * ZB_ZCL_TIME_SERVER_SYNCHRONIZATION_TIMEOUT_SECONDS); - zb_buf_get_out_delayed(zb_zcl_time_server_start_search); - } -} - -void zb_zcl_time_init_server() -{ - ZB_ZCL_TIME_SET_REAL_TIME_CLOCK_CB((zb_zcl_time_set_real_time_clock_t)NULL); - - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_TIME, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_time_server, - zb_zcl_time_write_attr_hook_server, - (zb_zcl_cluster_handler_t)NULL); -} - -void zb_zcl_set_real_time_clock_callback(zb_zcl_time_set_real_time_clock_t cb) -{ - ZVUNUSED(cb); -#ifdef THAT_CB_IS_NEVER_USED_CAUSING_WARNING - zb_zcl_set_real_time_clock_cb = cb; -#endif -} - -void zb_zcl_time_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_TIME, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - (zb_zcl_cluster_handler_t)NULL); -} - -zb_ret_t check_value_time_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_zcl_attr_t *time_status_desc; - - TRACE_MSG(TRACE_ZCL1, ">> check_value_time <<", (FMT__0)); - - time_status_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_TIME, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_TIME_TIME_STATUS_ID); - - if (ZB_ZCL_ATTR_TIME_TIME_ID == attr_id) - { - if (ZB_ZCL_TIME_TIME_STATUS_MASTER_BIT_IS_SET(ZB_ZCL_GET_ATTRIBUTE_VAL_8(time_status_desc)) || - ZB_ZCL_ATTR_GET32(value) == ZB_ZCL_TIME_TIME_INVALID_VALUE) - { - TRACE_MSG(TRACE_ZCL1, "Master bit is set (Time synchronization is not allowed) or invalid time value", - (FMT__0)); - - return RET_BLOCKED; - } - } - else if (ZB_ZCL_ATTR_TIME_TIME_STATUS_ID == attr_id) - { - /* The Synchronized bit must be explicitly written to indicate this - i.e., - * it is not set automatically on writing to the Time attribute. - * If the Master bit is 1, the value of this bit is 0. - * - * ZCL 2.5.3.3 Write Attributes Command - Effect on Receipt - * 4. If the device is not currently accepting write attribute commands for the attribute, - * the status field of the corresponding write attribute status record SHALL be set to - * NOT_AUTHORIZED or READ_ONLY. - */ - - if (ZB_ZCL_TIME_TIME_STATUS_MASTER_BIT_IS_SET(ZB_ZCL_GET_ATTRIBUTE_VAL_8(time_status_desc)) && - ZB_ZCL_TIME_TIME_STATUS_SYNCHRONIZED_BIT_IS_SET(*value)) - { - TRACE_MSG(TRACE_ZCL1, "Don't write Time Status attribute: Master Bit is set", (FMT__0)); - return RET_BLOCKED; - } - - /* Master(0-bit) and MasterZoneDst(2nd-bit) bits are not writeable */ - - *value = (ZB_ZCL_GET_ATTRIBUTE_VAL_8(time_status_desc) & 0x05) | (*value & 0xFA); - } - else if (ZB_ZCL_ATTR_TIME_DST_START_ID == attr_id - || ZB_ZCL_ATTR_TIME_DST_END_ID == attr_id) - { - if (ZB_ZCL_TIME_TIME_STATUS_MASTER_ZONE_DST_BIT_IS_SET(ZB_ZCL_GET_ATTRIBUTE_VAL_8(time_status_desc))) - { - TRACE_MSG(TRACE_ZCL1, "MasterZoneDst bit is set. Time synchronization is not allowed.", - (FMT__0)); - return RET_BLOCKED; - } - else if (ZB_ZCL_TIME_TIME_INVALID_VALUE == ZB_ZCL_ATTR_GET32(value)) - { - zb_uint32_t val = ZB_ZCL_ATTR_GET32(value); - TRACE_MSG(TRACE_ZCL1, "Invalid attribute value! attr_id == 0x%x, value == 0x%lx", - (FMT__D_L, attr_id, val)); - return RET_ERROR; - } - } - - return RET_OK; -} - -void zb_zcl_time_update_current_time(zb_uint8_t endpoint) -{ - zb_uint32_t time_value; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_time_update_current_time ep %hd", (FMT__H, endpoint)); - - time_value = zb_get_utc_time(); - /* This time setting does not produce any ZCL packets, so no need to catch the status and - * send it in response. - */ - ZB_ZCL_SET_ATTRIBUTE(endpoint, - ZB_ZCL_CLUSTER_ID_TIME, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_TIME_TIME_ID, - (zb_uint8_t *)(&time_value), - ZB_FALSE); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_time_update_current_time", (FMT__0)); -} - -static zb_uint32_t zb_zcl_color_control_get32(zb_uint8_t endpoint, zb_uint16_t attr_id) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_TIME, ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id); - return (attr_desc) ? ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc) : ZB_ZCL_TIME_TIME_INVALID_VALUE; -} - -static zb_int32_t zb_zcl_color_control_getS32(zb_uint8_t endpoint, zb_uint16_t attr_id) -{ - zb_zcl_attr_t *attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_TIME, ZB_ZCL_CLUSTER_SERVER_ROLE, attr_id); - return (attr_desc) ? ZB_ZCL_GET_ATTRIBUTE_VAL_S32(attr_desc) : 0; -} - -/** @brief Hook on Write attribute */ -void zb_zcl_time_write_attr_hook_server(zb_uint8_t endpoint, zb_uint16_t attr_id, zb_uint8_t *new_value) -{ - zb_zcl_attr_t* attr_desc; - zb_uint32_t - time = ZB_ZCL_TIME_TIME_INVALID_VALUE, - standard_time = ZB_ZCL_TIME_TIME_INVALID_VALUE, - dst_start = ZB_ZCL_TIME_TIME_INVALID_VALUE, - dst_end = ZB_ZCL_TIME_TIME_INVALID_VALUE; - zb_int32_t time_zone = 0, dst_shift = 0; - zb_bool_t update_standard_time = ZB_FALSE; - zb_bool_t update_local_time = ZB_FALSE; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_time_write_attr_hook_server endpoint %hx attr_id %d", - (FMT__H_D, endpoint, attr_id)); - - switch (attr_id) - { - case ZB_ZCL_ATTR_TIME_TIME_ID: - { - time = ZB_ZCL_ATTR_GET32(new_value); - - /* Update LastSetTime */ - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_TIME, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_TIME_LAST_SET_TIME_ID); - if (attr_desc != NULL) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, time); - TRACE_MSG(TRACE_ZCL1, "Update LastSetTime to 0x%lx", - (FMT__L, ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc))); - } - - update_standard_time = ZB_TRUE; - update_local_time = ZB_TRUE; - } - break; - - case ZB_ZCL_ATTR_TIME_TIME_ZONE_ID: - { - time_zone = ZB_ZCL_ATTR_GET32(new_value); - - update_standard_time = ZB_TRUE; - } - break; - - case ZB_ZCL_ATTR_TIME_DST_START_ID: - { - dst_start = ZB_ZCL_ATTR_GET32(new_value); - - update_local_time = ZB_TRUE; - } - break; - - case ZB_ZCL_ATTR_TIME_DST_END_ID: - { - dst_end = ZB_ZCL_ATTR_GET32(new_value); - - update_local_time = ZB_TRUE; - } - break; - - case ZB_ZCL_ATTR_TIME_DST_SHIFT_ID: - { - dst_shift = ZB_ZCL_ATTR_GETS32(new_value); - - update_local_time = ZB_TRUE; - } - break; - - default: - break; - } - - if (attr_id != ZB_ZCL_ATTR_TIME_TIME_ID) - { - time = zb_zcl_color_control_get32(endpoint, ZB_ZCL_ATTR_TIME_TIME_ID); - } - - /* Update StandardTime */ - if (update_standard_time) - { - if (attr_id != ZB_ZCL_ATTR_TIME_TIME_ZONE_ID) - { - time_zone = zb_zcl_color_control_getS32(endpoint, ZB_ZCL_ATTR_TIME_TIME_ZONE_ID); - } - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_TIME, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_TIME_STANDARD_TIME_ID); - - if (attr_desc && time != ZB_ZCL_TIME_TIME_INVALID_VALUE) - { - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, time + time_zone); - TRACE_MSG(TRACE_ZCL1, "Update StandardTime to 0x%lx", - (FMT__L, ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc))); - standard_time = ZB_ZCL_GET_ATTRIBUTE_VAL_32(attr_desc); - } - } - - /* Update LocalTime */ - if (update_local_time) - { - if (attr_id != ZB_ZCL_ATTR_TIME_DST_START_ID) - { - dst_start = zb_zcl_color_control_get32(endpoint, ZB_ZCL_ATTR_TIME_DST_START_ID); - } - - if (attr_id != ZB_ZCL_ATTR_TIME_DST_END_ID) - { - dst_end = zb_zcl_color_control_get32(endpoint, ZB_ZCL_ATTR_TIME_DST_END_ID); - } - - if (attr_id != ZB_ZCL_ATTR_TIME_DST_SHIFT_ID) - { - dst_shift = zb_zcl_color_control_getS32(endpoint, ZB_ZCL_ATTR_TIME_TIME_ZONE_ID); - } - - if (standard_time == ZB_ZCL_TIME_TIME_INVALID_VALUE) - { - standard_time = zb_zcl_color_control_get32(endpoint, ZB_ZCL_ATTR_TIME_STANDARD_TIME_ID); - } - - attr_desc = zb_zcl_get_attr_desc_a(endpoint, - ZB_ZCL_CLUSTER_ID_TIME, - ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID); - - if (attr_desc && - standard_time != ZB_ZCL_TIME_TIME_INVALID_VALUE && - dst_start != ZB_ZCL_TIME_TIME_INVALID_VALUE && - dst_end != ZB_ZCL_TIME_TIME_INVALID_VALUE) - { - if (dst_start <= time && time <= dst_end) - { - /* Local Time = Standard Time + DstShift */ - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, standard_time + dst_shift); - } - else - { - /* Local Time = Standard Time */ - ZB_ZCL_SET_DIRECTLY_ATTR_VAL32(attr_desc, standard_time); - } - } - } - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_time_write_attr_hook_server", (FMT__0)); -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_TIME */ diff --git a/zboss/development/src/zcl/zcl_window_covering.c b/zboss/development/src/zcl/zcl_window_covering.c deleted file mode 100644 index a5878102a7..0000000000 --- a/zboss/development/src/zcl/zcl_window_covering.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: -*/ - -#define ZB_TRACE_FILE_ID 81 - -#include "zb_common.h" - -/* 2018/08/10 CR:MINOR (rev. 39551): Probably remove this ifdef? Really, why we need to compile empty ZCL - * library that way? This may be done with one string in Options file instead of bunch of ifdef-s - * in every cluster. - * Need to discuss with EE. */ -#if defined (ZB_ZCL_SUPPORT_CLUSTER_WINDOW_COVERING) - -#include "zb_zcl.h" -#include "zb_aps.h" - -zb_uint8_t gs_window_covering_server_received_commands[] = -{ - ZB_ZCL_CLUSTER_ID_WINDOW_COVERING_SERVER_ROLE_RECEIVED_CMD_LIST -}; - -zb_discover_cmd_list_t gs_window_covering_client_cmd_list = -{ - 0, NULL, - sizeof(gs_window_covering_server_received_commands), gs_window_covering_server_received_commands -}; - -zb_discover_cmd_list_t gs_window_covering_server_cmd_list = -{ - sizeof(gs_window_covering_server_received_commands), gs_window_covering_server_received_commands, - 0, NULL -}; - -static zb_ret_t check_value_window_covering_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value); -static zb_bool_t zb_zcl_process_window_covering_specific_commands_srv(zb_uint8_t param); -static zb_bool_t zb_zcl_process_window_covering_specific_commands_cli(zb_uint8_t param); - -void zb_zcl_window_covering_init_server() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, - ZB_ZCL_CLUSTER_SERVER_ROLE, - check_value_window_covering_server, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_window_covering_specific_commands_srv); -} - -void zb_zcl_window_covering_init_client() -{ - zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, - ZB_ZCL_CLUSTER_CLIENT_ROLE, - (zb_zcl_cluster_check_value_t)NULL, - (zb_zcl_cluster_write_attr_hook_t)NULL, - zb_zcl_process_window_covering_specific_commands_cli); -} - -static zb_ret_t check_value_window_covering_server(zb_uint16_t attr_id, zb_uint8_t endpoint, zb_uint8_t *value) -{ - zb_ret_t ret = RET_OK; - - ZVUNUSED(endpoint); - - switch( attr_id ) - { - case ZB_ZCL_ATTR_WINDOW_COVERING_WINDOW_COVERING_TYPE_ID: - if( *value > ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_PROJECTOR_SCREEN ) - { - ret = RET_ERROR; - } - break; - - case ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID: - if( *value >= 0x80 ) - { - ret = RET_ERROR; - } - break; - - case ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID: - if( *value > ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_MAX_VALUE ) - { - ret = RET_ERROR; - } - break; - - case ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID: - if( *value > ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_MAX_VALUE ) - { - ret = RET_ERROR; - } - break; - case ZB_ZCL_ATTR_WINDOW_COVERING_MODE_ID: - if( !(*value & 0x1f) ) - { - ret = RET_ERROR; - } - break; - } - - TRACE_MSG(TRACE_ZCL1, "check_value_window_covering ret %hd", (FMT__H, ret)); - - return ret; -} - -static zb_zcl_status_t zb_zcl_window_covering_map_ret_code_to_zcl_status(zb_ret_t ret_code) -{ - ZB_ASSERT(ret_code != RET_BUSY); - - return zb_zcl_get_zcl_status_from_ret(ret_code); -} - -static zb_ret_t zb_zcl_window_covering_invoke_user_app(zb_uint8_t param, - const zb_zcl_parsed_hdr_t *cmd_info, - zb_zcl_device_callback_id_t user_cb_id, - void *payload) - { - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "> zb_zcl_window_covering_invoke_user_app cb_id %d", (FMT__D, user_cb_id)); - - ZB_ZCL_DEVICE_CMD_PARAM_INIT_WITH(param, user_cb_id, RET_OK, cmd_info, payload, NULL); - - if (ZCL_CTX().device_cb != NULL) - { - (ZCL_CTX().device_cb)(param); - } - - ret = (ZB_ZCL_DEVICE_CMD_PARAM_STATUS(param) == RET_OK ? RET_OK : RET_ERROR); - - TRACE_MSG(TRACE_ZCL1, "< zb_zcl_window_covering_invoke_user_app ret %d", (FMT__D, ret)); - - return ret; -} - -static zb_ret_t zb_zcl_process_window_covering_up_open_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "Window Covering Up/Open command", (FMT__0)); - - ret = zb_zcl_window_covering_invoke_user_app(param, - cmd_info, - ZB_ZCL_WINDOW_COVERING_UP_OPEN_CB_ID, - NULL); - - return ret; -} - -static zb_ret_t zb_zcl_process_window_covering_down_close_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "Window Covering Down/Close command", (FMT__0)); - - ret = zb_zcl_window_covering_invoke_user_app(param, - cmd_info, - ZB_ZCL_WINDOW_COVERING_DOWN_CLOSE_CB_ID, - NULL); - - return ret; -} - -static zb_ret_t zb_zcl_process_window_covering_stop_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - - TRACE_MSG(TRACE_ZCL1, "Window Covering Stop command", (FMT__0)); - - ret = zb_zcl_window_covering_invoke_user_app(param, - cmd_info, - ZB_ZCL_WINDOW_COVERING_STOP_CB_ID, - NULL); - - return ret; -} - -static zb_ret_t zb_zcl_process_window_covering_go_to_lift_percentage_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_parse_status_t status; - zb_zcl_go_to_lift_percentage_req_t lift_percentage; - - TRACE_MSG(TRACE_ZCL1, "Window Covering Get Go to Lift percentage command", (FMT__0)); - - ZB_ZCL_WINDOW_COVERING_GET_GO_TO_LIFT_PERCENTAGE_REQ(param, - &lift_percentage, - status); - if (status == ZB_ZCL_PARSE_STATUS_SUCCESS) - { - if (zb_zcl_check_attr_value(ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID, - &(lift_percentage.percentage_lift_value)) == RET_OK) - { - TRACE_MSG(TRACE_ZCL1, "Value = %hd, going...", - (FMT__H, lift_percentage.percentage_lift_value)); - - ret = zb_zcl_window_covering_invoke_user_app(param, - cmd_info, - ZB_ZCL_WINDOW_COVERING_GO_TO_LIFT_PERCENTAGE_CB_ID, - (void *)&lift_percentage); - } - else - { - TRACE_MSG(TRACE_ERROR, "Invalid value = %hd", - (FMT__H, lift_percentage.percentage_lift_value)); - - ret = RET_INVALID_PARAMETER; - } - } - else - { - ret = RET_INVALID_PARAMETER_1; - } - - return ret; -} - -static zb_ret_t zb_zcl_process_window_covering_go_to_tilt_percentage_handler(zb_uint8_t param, const zb_zcl_parsed_hdr_t *cmd_info) -{ - zb_ret_t ret = RET_OK; - zb_zcl_parse_status_t status; - zb_zcl_go_to_tilt_percentage_req_t tilt_percentage; - - TRACE_MSG(TRACE_ZCL1, "Window Covering Get Go to Tilt percentage command", (FMT__0)); - - ZB_ZCL_WINDOW_COVERING_GET_GO_TO_TILT_PERCENTAGE_REQ(param, - &tilt_percentage, - status); - if (status == ZB_ZCL_PARSE_STATUS_SUCCESS) - { - if (zb_zcl_check_attr_value(ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ZB_ZCL_CLUSTER_SERVER_ROLE, - ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint, - ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_TILT_PERCENTAGE_ID, - &(tilt_percentage.percentage_tilt_value)) == RET_OK) - { - TRACE_MSG(TRACE_ZCL1, "Value = %hd, going...", - (FMT__H, tilt_percentage.percentage_tilt_value)); - - ret = zb_zcl_window_covering_invoke_user_app(param, - cmd_info, - ZB_ZCL_WINDOW_COVERING_GO_TO_TILT_PERCENTAGE_CB_ID, - (void *)&tilt_percentage); - } - else - { - TRACE_MSG(TRACE_ERROR, "Invalid value = %hd", - (FMT__H, tilt_percentage.percentage_tilt_value)); - - ret = RET_INVALID_PARAMETER; - } - } - else - { - ret = RET_INVALID_PARAMETER_1; - } - - return ret; -} - -static zb_bool_t zb_zcl_process_window_covering_specific_commands(zb_uint8_t param) -{ - zb_bool_t processed = ZB_TRUE; - zb_ret_t ret = RET_OK; - zb_zcl_parsed_hdr_t cmd_info; - - TRACE_MSG(TRACE_ZCL1, - "> zb_zcl_process_window_covering_specific_commands: param %hd", - (FMT__H, param)); - - ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info); - - ZB_ASSERT(ZB_ZCL_CLUSTER_ID_WINDOW_COVERING == cmd_info.cluster_id); - ZB_ASSERT(ZB_ZCL_FRAME_DIRECTION_TO_SRV == cmd_info.cmd_direction); - - switch (cmd_info.cmd_id) - { - case ZB_ZCL_CMD_WINDOW_COVERING_UP_OPEN: - ret = zb_zcl_process_window_covering_up_open_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_WINDOW_COVERING_DOWN_CLOSE: - ret = zb_zcl_process_window_covering_down_close_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_WINDOW_COVERING_STOP: - ret = zb_zcl_process_window_covering_stop_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_LIFT_PERCENTAGE: - ret = zb_zcl_process_window_covering_go_to_lift_percentage_handler(param, &cmd_info); - break; - case ZB_ZCL_CMD_WINDOW_COVERING_GO_TO_TILT_PERCENTAGE: - ret = zb_zcl_process_window_covering_go_to_tilt_percentage_handler(param, &cmd_info); - break; - - default: - processed = ZB_FALSE; - break; - } - - if (processed && ret != RET_BUSY) - { - zb_zcl_send_default_handler(param, &cmd_info, - zb_zcl_window_covering_map_ret_code_to_zcl_status(ret)); -} - - TRACE_MSG(TRACE_ZCL1, - "< zb_zcl_process_window_covering_specific_commands: processed %d", - (FMT__D, processed)); - - return processed; -} - -static zb_bool_t zb_zcl_process_window_covering_specific_commands_srv(zb_uint8_t param) -{ - if (ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_window_covering_server_cmd_list; - return ZB_TRUE; - } - return zb_zcl_process_window_covering_specific_commands(param); -} - -static zb_bool_t zb_zcl_process_window_covering_specific_commands_cli(zb_uint8_t param) -{ - if (ZB_ZCL_GENERAL_GET_CMD_LISTS_PARAM == param) - { - ZCL_CTX().zb_zcl_cluster_cmd_list = &gs_window_covering_client_cmd_list; - return ZB_TRUE; - } - return ZB_FALSE; -} -#endif /* ZB_ZCL_SUPPORT_CLUSTER_WINDOW_COVERING */ diff --git a/zboss/development/src/zcl/zcl_wwah_common.c b/zboss/development/src/zcl/zcl_wwah_common.c deleted file mode 100644 index e9cf55833c..0000000000 --- a/zboss/development/src/zcl/zcl_wwah_common.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ZBOSS Zigbee 3.0 - * - * Copyright (c) 2012-2020 DSR Corporation, Denver CO, USA. - * www.dsr-zboss.com - * www.dsr-corporation.com - * All rights reserved. - * - * - * Use in source and binary forms, redistribution in binary form only, with - * or without modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 2. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 3. This software, with or without modification, must only be used with a Nordic - * Semiconductor ASA integrated circuit. - * - * 4. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* PURPOSE: ZCL WWAH cluster specific commands handling -*/ - -#define ZB_TRACE_FILE_ID 12082 - -#include "zb_common.h" - -#if (defined ZB_ZCL_ENABLE_WWAH_SERVER || defined ZB_ZCL_ENABLE_WWAH_CLIENT) - -void zb_zcl_wwah_set_wwah_behavior(zb_uint8_t behavior) -{ - if (behavior < ZB_ZCL_WWAH_BEHAVIOR_RESERVED) - { - WWAH_CTX().wwah_behavior = behavior; - } -} - -/* - * Check if WWAH client (TC) behaviour is enabled - * @return ZB_TRUE if WWAH client (TC) behaviour is enabled and WWAH client endpoint is exist - * ZB_FALSE otherwise */ - -zb_bool_t zb_is_wwah_client() -{ - zb_uint8_t wwah_endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_CLIENT_ROLE); - return (zb_bool_t)(((zb_zcl_wwah_behavior_t)WWAH_CTX().wwah_behavior == ZB_ZCL_WWAH_BEHAVIOR_CLIENT) && wwah_endpoint); -} - -/* - * Check if WWAH server behaviour is enabled - * @return ZB_TRUE if WWAH server behaviour is enabled and WWAH server endpoint is exist - * ZB_FALSE otherwise */ - -zb_bool_t zb_is_wwah_server() -{ - zb_uint8_t wwah_endpoint = get_endpoint_by_cluster(ZB_ZCL_CLUSTER_ID_WWAH, - ZB_ZCL_CLUSTER_SERVER_ROLE); - return (zb_bool_t)(((zb_zcl_wwah_behavior_t)WWAH_CTX().wwah_behavior == ZB_ZCL_WWAH_BEHAVIOR_SERVER) && wwah_endpoint); -} - -#endif diff --git a/zboss/development/trace/include/libzboss_config.ed.h b/zboss/development/trace/include/libzboss_config.ed.h deleted file mode 100644 index 59c4571fbe..0000000000 --- a/zboss/development/trace/include/libzboss_config.ed.h +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef LIBZBOSS_CONFIG_ED_H__ -#define LIBZBOSS_CONFIG_ED_H__ - -/** - * This is an autogenerated file. - * Please use Kconfig to change it. - */ - - -/** - * Include NCP related code in ZBOSS library. - * - * Compile NCP related code in ZBOSS library. - * This enables building NCP architecture with common ZBOSS library. - */ -#define CONFIG_ZB_NCP_MODE y - -/** - * NCP trasnport type - Serial (UART) - */ -#define CONFIG_ZB_NCP_TRANSPORT_TYPE_SERIAL y - -/** - * Enable UART serial interface for ZBOSS CLI - */ -#define CONFIG_ZB_HAVE_SERIAL y - -/** - * Serial (SPI) [UNSUPPORTED] - */ -/* #undef CONFIG_ZB_NCP_TRANSPORT_TYPE_SPI */ - -/** - * Simulator (linux pipe) [UNSUPPORTED] - */ -/* #undef CONFIG_ZB_NCP_TRANSPORT_TYPE_NSNG */ - -/** - * SDK Type (HA, SE, etc.) - Home Automation - */ -#define CONFIG_ZB_SDK_TYPE_HA y - -/** - * SDK Type (HA, SE, etc.) - Smart Energy - */ -/* #undef CONFIG_ZB_SDK_TYPE_SE */ - -/** - * ZB_SDK_TYPE - */ -#define CONFIG_ZB_SDK_TYPE 1 - -/** - * Compiled-in trace mask of ZBOSS stack logs - * - * Selectively enable Zigbee binary trace logs. - * The mask value should be a bitwise OR of values assigned to selected modules. - * - * Available modules are: - * - * - 0x04000000 Reserved - * - 0x02000000 Reserved - * - 0x01000000 Reserved - * - 0x00800000 Reserved - * - 0x00400000 Reserved - * - 0x00200000 Zigbee NCP: transport (LL) - * - 0x00100000 Zigbee NCP: command adapters (HL) - * - 0x00080000 ZCL: Over The Air firmware upgrade - * - 0x00040000 IAS zone device: battery monitoring - * - 0x00020000 Reserved - * - 0x00010000 MAC Lower Layer - * - 0x00008000 MAC layer API calls - * - 0x00004000 Zigbee Green Power - * - 0x00002000 Custom components - * - 0x00001000 Reserved - * - 0x00000800 Application - * - 0x00000400 Reserved - * - 0x00000200 Zigbee Light Link - * - 0x00000100 Zigbee Cluster Library - * - 0x00000080 Security - * - 0x00000040 Zigbee Device Object - * - 0x00000020 Zigbee Smart Energy - * - 0x00000010 Application Support layer - * - 0x00000008 Network layer - * - 0x00000004 MAC layer - * - 0x00000002 Memory management - * - 0x00000001 Common - * - * For example, in order to enable traces related to OTA DFU, - * one should set this option to 0x00080100. - * - * Note: For general debugging purposes, please use 0x00000C48. - */ -#define CONFIG_ZB_TRACE_MASK 0xFFFF - -/** - * Max compiled-in log level for ZBOSS traces - Off - */ -/* #undef CONFIG_ZB_LOG_LEVEL_OFF */ - -/** - * Max compiled-in log level for ZBOSS traces - Error - */ -/* #undef CONFIG_ZB_LOG_LEVEL_ERR */ - -/** - * Max compiled-in log level for ZBOSS traces - Warning - */ -#define CONFIG_ZB_LOG_LEVEL_WRN y - -/** - * Max compiled-in log level for ZBOSS traces - Info - */ -/* #undef CONFIG_ZB_LOG_LEVEL_INF */ - -/** - * Max compiled-in log level for ZBOSS traces - Debug - */ -/* #undef CONFIG_ZB_LOG_LEVEL_DBG */ - -/** - * Off - ZB_TRACE_LOG_LEVEL - */ -#define CONFIG_ZB_TRACE_LOG_LEVEL 2 - -/** - * Initialize and flush logger directly from ZBOSS kernel - */ -/* #undef CONFIG_ZB_ASYNC_TRACE_CONTROL */ - -/** - * Enable UART test commands support - * - * Enable reception of test commands on UART interface - * (enabled in ZBOSS test configs only) - */ -#define CONFIG_ZB_NRF_TRACE_RX_ENABLE y - -/** - * Enable Zigbee test mode and features - */ -#define CONFIG_ZB_TEST_MODE y - -/** - * Enable LEDs abstract for ZBOSS OSIF - */ -#define CONFIG_ZB_USE_LEDS y - -/** - * Enable dimmable LED (PWM) abstract for ZBOSS OSIF - */ -/* #undef CONFIG_ZB_USE_DIMMABLE_LED */ - -/** - * Enable buttons abstract for ZBOSS OSIF - */ -#define CONFIG_ZB_USE_BUTTONS y - -/** - * NVRAM migration - * - * Include procedures to migrate legacy NVRAM structures - */ -#define CONFIG_ZB_NVRAM_ENABLE_VER_MIGRATION y - -/** - * Finding and Binding - * - * Enable finding and binding, as defined in BDB specification - */ -#define CONFIG_ZB_BDB_ENABLE_FINDING_BINDING y - -/** - * Distributed security - * - * Enable forming and joining Zigbee networks with distributed security - */ -#define CONFIG_ZB_DISTRIBUTED_SECURITY_ON y - -/** - * Install codes - * - * Enable commissioning with install codes - */ -#define CONFIG_ZB_SECURITY_INSTALLCODES y - -/** - * Production configuration - * - * Enable production configuration - */ -#define CONFIG_ZB_PRODUCTION_CONFIG y - -/** - * APS user frames - * - * Include API to send raw APS frames - */ -#define CONFIG_ZB_APS_USER_PAYLOAD y - -/** - * NWK security API - * - * Include API to disable NWK security - */ -#define CONFIG_ZB_LOW_SECURITY_MODE y - -/** - * APS fragmentation - * - * Enable APS fragmentation inside ZBOSS - */ -#define CONFIG_ZB_APS_FRAGMENTATION y - -/** - * PAN ID blacklist - * - * Enable PAN ID blacklisting during rejoin - */ -#define CONFIG_ZB_NWK_BLACKLIST y - -/** - * PAN ID blacklist length - */ -#define CONFIG_ZB_NWK_BLACKLIST_SIZE 16 - -/** - * Enable Control4 network support - */ -#define CONFIG_ZB_CONTROL4_NETWORK_SUPPORT y - -/** - * Enable R22 extension for for mutitple MAC interfaces support. - */ -/* #undef CONFIG_ZB_R22_MULTIMAC_MODE */ - -/** - * Enable R22 extension for for mutitple MAC interfaces support. - Enable single-MAC interface support - */ -#define CONFIG_ZB_MAC_INTERFACE_SINGLE y - -/** - * WWAH cluster - * - * Include Works With All Hubs cluster - */ -#define CONFIG_ZB_ZCL_SUPPORT_CLUSTER_WWAH y - -/** - * WWAH cluster - WWAHu client - * - * Include WWAHu cluster client implementation - */ -#define CONFIG_ZB_ZCL_ENABLE_WWAH_CLIENT y - -/** - * WWAH cluster - WWAHu server - * - * Include WWAHu cluster server implementation - */ -#define CONFIG_ZB_ZCL_ENABLE_WWAH_SERVER y - -/** - * WWAHu server - NWK retransmissions - * - * Enable retransmissions on NWK layer - */ -#define CONFIG_ZB_NWK_RETRY_COUNT y - -/** - * WWAHu server - Beacon survey - * - * Enable beacon survey - */ -#define CONFIG_ZB_BEACON_SURVEY y - -/** - * WWAHu server - Parent classification - * - * Enable parent classification - */ -#define CONFIG_ZB_PARENT_CLASSIFICATION y - -/** - * Check for Out Of Memory state - * - * If Zigbee packet buffer pool is in OOM state for a period, specified - * by ZB_OOM_THRESHOLD, then assertion is triggered. - */ -/* #undef CONFIG_ZB_CHECK_OOM_STATUS */ - -/** - * Check for Out Of Memory state - Generate NWK status frame in OOM - * - * Send broadcast frame once OOM state is detected. - */ -/* #undef CONFIG_ZB_SEND_OOM_STATUS */ - -/** - * Touchlink commissioning (experimental) - */ -/* #undef CONFIG_ZB_BDB_TOUCHLINK */ - -/** - * Enable Zigbee MAC features, used by the verification framework - Enable API for sending inter-pan packets at non default channel - */ -#define CONFIG_ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL y - -/** - * Enable Zigbee test mode and features - Enable Zigbee MAC features, used by the verification framework - */ -/* #undef CONFIG_ZB_MAC_TESTING_MODE */ - -/** - * Certification specific behavior - * - * Enable behaviors specific to golden devices used during certification - */ -#define CONFIG_ZB_CERTIFICATION_HACKS y - -/** - * MAC filtering - * - * Enables filtering frames at MAC level, based on device's short or - * long address - */ -#define CONFIG_ZB_LIMIT_VISIBILITY y - -/** - * Groups of test cases to be included - Enable both TH and DUT test cases - */ -#define CONFIG_ZB_TEST_GROUP_ALL y - -/** - * Enable Zigbee test mode and features - Enable Zigbee MAC test mode extensions - */ -/* #undef CONFIG_ZB_TEST_MODE_MAC */ - -/** - * Enable Zigbee test mode and features - Enable Zigbee PRO test mode extensions - */ -#define CONFIG_ZB_TEST_MODE_PRO y - -/** - * Groups of test cases to be included - Enable DUT test cases - */ -/* #undef CONFIG_ZB_TEST_GROUP_ALL_DUT */ - -/** - * Groups of test cases to be included - Enable TH test cases - */ -/* #undef CONFIG_ZB_TEST_GROUP_ALL_TH */ - -/** - * Enable Zigbee test mode and features - Enable Zigbee profile, used by verification framework - */ -#define CONFIG_ZB_TEST_PROFILE y - -/** - * Enable Zigbee test mode and features - Serial console RX timeout - */ -#define CONFIG_ZB_MULTITEST_CONSOLE_SLEEP_TIMEOUT 4000000 - -/** - * Disable TRACE_FILE_ID assert - * - * Disable sanity check for ZB_TRACE_FILE_ID macro definition in each file - */ -#define CONFIG_ZB_DONT_NEED_TRACE_FILE_ID y - -/** - * Use delayed TX feature of the radio driver instead of entering busy loop in GP implementation - * - * While communicating with Green Power device, ZBOSS will wait before issuing - * mcps-data.req using MAC features instead of waiting in a busy loop - */ -#define CONFIG_ZB_MAC_AUTO_DELAY_IN_MAC_GP_SEND y - -/** - * NWK requests with aliases - * - * Enables making NWK requests with aliases (see sec. 3.2.1.1.1) or - * R21 Zigbee PRO specification) - */ -/* #undef CONFIG_ZB_USEALIAS */ - -/** - * Enable MAC duty cycle monitoring - */ -/* #undef CONFIG_ZB_MAC_DUTY_CYCLE_MONITORING */ - -/** - * Enable per-device MAC TX power control - */ -/* #undef CONFIG_ZB_MAC_POWER_CONTROL */ - -/** - * Enable per-channel MAC TX power control - */ -#define CONFIG_ZB_MAC_CONFIGURABLE_TX_POWER y - -/** - * Length of the internal ZBOSS MAC TX queue - * - * The value of NRF_802154_RX_BUFFERS (ZIGBEE_RX_QUEUE_LENGTH in nRF5 SDK) - * should not be greater than ZB_MAC_QUEUE_SIZE. - * If the node is flooded with requests, that require a response to be sent, - * the node should be able to schedule responses for each buffer, - * stored inside MAC LL RX queue. - * The receiver gets disabled only if the MAC LL RX queue is full. - * The TX queue is unable to block incoming requests. - */ -#define CONFIG_ZB_MAC_QUEUE_SIZE 17 - -/** - * Acceptable noise floor (in ED units) to form a network - * - * If the MAC LL layer returns energy higher than this value for a given channel, - * the node will skip this channel after passive channel scan. - */ -#define CONFIG_ZB_NWK_CHANNEL_ACCEPT_LEVEL 200 - -/** - * Enable internal clusters through filters - */ -/* #undef CONFIG_ZB_FILTER_OUT_CLUSTERS */ - -/** - * Enable enhanced beacon support - */ -#define CONFIG_ZB_ENHANCED_BEACON_SUPPORT y - -/** - * Enable joining list support - */ -#define CONFIG_ZB_JOINING_LIST_SUPPORT y - -/** - * PAN ID translation table size - * - * NWK: size of the long-short Pan ID translation table - * - * Must be <= (packet buffer size - sizeof(*discovery_confirm)) / - * sizeof(*network_descriptor) - * That value limits number of Pan IDs visible for device during active scan. - */ -#define CONFIG_ZB_PANID_TABLE_SIZE 28 - -/** - * long addresses compression table size - * - * Size of table used for long addresses compression: 3 bytes of - * manufacturer id. - * - * ZBOSS implements long address compression: 3 bytes of manufacturer - * id are stored in the separate table; reference to manufacturer - * entry is stored in the long address giving 2 bytes economy. - * - * That is an absolute limit of number of manufacturers known to the device. - * - * Note: All that machinery will not work if instead of legal - * manufacturer ids (or illegal, but fixed ids) use random values. - */ -#define CONFIG_ZB_DEV_MANUFACTURER_TABLE_SIZE 32 - -/** - * Packet buffer wait queue size - * - * Size of queue for wait for free packet buffer - * - * Note: To prevent deadlocks ZB_BUF_Q_SIZE must be < ZB_IOBUF_POOL_SIZE/2 - */ -#define CONFIG_ZB_BUF_Q_SIZE 8 - -/** - * ZDO transactions table size - */ -#define CONFIG_ZB_ZDO_TRAN_TABLE_SIZE 16 - -/** - * number of endpoints per APS group table entry - */ -#define CONFIG_ZB_APS_ENDPOINTS_IN_GROUP_TABLE 8 - -/** - * Broadcast transaction record table size - * - * See Zigbee Specification subclause 3.6.5 - */ -#define CONFIG_ZB_NWK_BTR_TABLE_SIZE 16 - -/** - * Broadcast Retransmission table size - */ -#define CONFIG_ZB_NWK_BRR_TABLE_SIZE 16 - -/** - * Number of endpoints - * - * Maximum number of supported endpoints per device - */ -#define CONFIG_ZB_MAX_EP_NUMBER 8 - -/** - * Number of supported APS groups - */ -#define CONFIG_ZB_APS_GROUP_TABLE_SIZE 8 - -/** - * Green Power Sink table size - */ -#define CONFIG_ZB_ZGP_SINK_TBL_SIZE 24 - -/** - * Green Power Proxy table size - */ -#define CONFIG_ZB_ZGP_PROXY_TBL_SIZE 5 - -/** - * Dynamic memory configuration - * - * Enable dynamic memory configuration feature that allows to change memory - * footprint if application uses ZBOSS binaries - */ -#define CONFIG_ZB_CONFIGURABLE_MEM y - -/** - * Dynamic memory configuration - Expected overall network size - */ -#define CONFIG_ZB_CONFIG_OVERALL_NETWORK_SIZE 128 - -/** - * Expected Zigbee traffic intensity - high - */ -#define CONFIG_ZB_CONFIG_HIGH_TRAFFIC y - -/** - * Expected Zigbee traffic intensity - moderate - */ -/* #undef CONFIG_ZB_CONFIG_MODERATE_TRAFFIC */ - -/** - * Expected Zigbee traffic intensity - light - */ -/* #undef CONFIG_ZB_CONFIG_LIGHT_TRAFFIC */ - -/** - * Expected Zigbee application complexity - complex - */ -#define CONFIG_ZB_CONFIG_APPLICATION_COMPLEX y - -/** - * Expected Zigbee application complexity - moderate - */ -/* #undef CONFIG_ZB_CONFIG_APPLICATION_MODERATE */ - -/** - * Expected Zigbee application complexity - simple - */ -/* #undef CONFIG_ZB_CONFIG_APPLICATION_SIMPLE */ - -/** - * Dynamic memory configuration - Source APS binding table size - */ -/* #undef CONFIG_ZB_APS_SRC_BINDING_TABLE_SIZE */ - -/** - * Dynamic memory configuration - Destination APS binding table size - */ -/* #undef CONFIG_ZB_APS_DST_BINDING_TABLE_SIZE */ - -/** - * Dynamic memory configuration - Number of packet buffers - */ -/* #undef CONFIG_ZB_IOBUF_POOL_SIZE */ - -/** - * Dynamic memory configuration - Packet buffer wait queue size - * - * Scheduler callbacks queue size - */ -/* #undef CONFIG_ZB_SCHEDULER_Q_SIZE */ - -#endif /* LIBZBOSS_CONFIG_ED_H__ */ diff --git a/zboss/development/trace/include/libzboss_config.h b/zboss/development/trace/include/libzboss_config.h deleted file mode 100644 index 2622f4fc69..0000000000 --- a/zboss/development/trace/include/libzboss_config.h +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef LIBZBOSS_CONFIG_H__ -#define LIBZBOSS_CONFIG_H__ - -/** - * This is an autogenerated file. - * Please use Kconfig to change it. - */ - - -/** - * Include NCP related code in ZBOSS library. - * - * Compile NCP related code in ZBOSS library. - * This enables building NCP architecture with common ZBOSS library. - */ -#define CONFIG_ZB_NCP_MODE y - -/** - * NCP trasnport type - Serial (UART) - */ -#define CONFIG_ZB_NCP_TRANSPORT_TYPE_SERIAL y - -/** - * Enable UART serial interface for ZBOSS CLI - */ -#define CONFIG_ZB_HAVE_SERIAL y - -/** - * Serial (SPI) [UNSUPPORTED] - */ -/* #undef CONFIG_ZB_NCP_TRANSPORT_TYPE_SPI */ - -/** - * Simulator (linux pipe) [UNSUPPORTED] - */ -/* #undef CONFIG_ZB_NCP_TRANSPORT_TYPE_NSNG */ - -/** - * SDK Type (HA, SE, etc.) - Home Automation - */ -#define CONFIG_ZB_SDK_TYPE_HA y - -/** - * SDK Type (HA, SE, etc.) - Smart Energy - */ -/* #undef CONFIG_ZB_SDK_TYPE_SE */ - -/** - * ZB_SDK_TYPE - */ -#define CONFIG_ZB_SDK_TYPE 1 - -/** - * Compiled-in trace mask of ZBOSS stack logs - * - * Selectively enable Zigbee binary trace logs. - * The mask value should be a bitwise OR of values assigned to selected modules. - * - * Available modules are: - * - * - 0x04000000 Reserved - * - 0x02000000 Reserved - * - 0x01000000 Reserved - * - 0x00800000 Reserved - * - 0x00400000 Reserved - * - 0x00200000 Zigbee NCP: transport (LL) - * - 0x00100000 Zigbee NCP: command adapters (HL) - * - 0x00080000 ZCL: Over The Air firmware upgrade - * - 0x00040000 IAS zone device: battery monitoring - * - 0x00020000 Reserved - * - 0x00010000 MAC Lower Layer - * - 0x00008000 MAC layer API calls - * - 0x00004000 Zigbee Green Power - * - 0x00002000 Custom components - * - 0x00001000 Reserved - * - 0x00000800 Application - * - 0x00000400 Reserved - * - 0x00000200 Zigbee Light Link - * - 0x00000100 Zigbee Cluster Library - * - 0x00000080 Security - * - 0x00000040 Zigbee Device Object - * - 0x00000020 Zigbee Smart Energy - * - 0x00000010 Application Support layer - * - 0x00000008 Network layer - * - 0x00000004 MAC layer - * - 0x00000002 Memory management - * - 0x00000001 Common - * - * For example, in order to enable traces related to OTA DFU, - * one should set this option to 0x00080100. - * - * Note: For general debugging purposes, please use 0x00000C48. - */ -#define CONFIG_ZB_TRACE_MASK 0xFFFF - -/** - * Max compiled-in log level for ZBOSS traces - Off - */ -/* #undef CONFIG_ZB_LOG_LEVEL_OFF */ - -/** - * Max compiled-in log level for ZBOSS traces - Error - */ -/* #undef CONFIG_ZB_LOG_LEVEL_ERR */ - -/** - * Max compiled-in log level for ZBOSS traces - Warning - */ -#define CONFIG_ZB_LOG_LEVEL_WRN y - -/** - * Max compiled-in log level for ZBOSS traces - Info - */ -/* #undef CONFIG_ZB_LOG_LEVEL_INF */ - -/** - * Max compiled-in log level for ZBOSS traces - Debug - */ -/* #undef CONFIG_ZB_LOG_LEVEL_DBG */ - -/** - * Off - ZB_TRACE_LOG_LEVEL - */ -#define CONFIG_ZB_TRACE_LOG_LEVEL 2 - -/** - * Initialize and flush logger directly from ZBOSS kernel - */ -/* #undef CONFIG_ZB_ASYNC_TRACE_CONTROL */ - -/** - * Enable UART test commands support - * - * Enable reception of test commands on UART interface - * (enabled in ZBOSS test configs only) - */ -#define CONFIG_ZB_NRF_TRACE_RX_ENABLE y - -/** - * Enable Zigbee test mode and features - */ -#define CONFIG_ZB_TEST_MODE y - -/** - * Enable LEDs abstract for ZBOSS OSIF - */ -#define CONFIG_ZB_USE_LEDS y - -/** - * Enable dimmable LED (PWM) abstract for ZBOSS OSIF - */ -/* #undef CONFIG_ZB_USE_DIMMABLE_LED */ - -/** - * Enable buttons abstract for ZBOSS OSIF - */ -#define CONFIG_ZB_USE_BUTTONS y - -/** - * NVRAM migration - * - * Include procedures to migrate legacy NVRAM structures - */ -#define CONFIG_ZB_NVRAM_ENABLE_VER_MIGRATION y - -/** - * Finding and Binding - * - * Enable finding and binding, as defined in BDB specification - */ -#define CONFIG_ZB_BDB_ENABLE_FINDING_BINDING y - -/** - * Distributed security - * - * Enable forming and joining Zigbee networks with distributed security - */ -#define CONFIG_ZB_DISTRIBUTED_SECURITY_ON y - -/** - * Install codes - * - * Enable commissioning with install codes - */ -#define CONFIG_ZB_SECURITY_INSTALLCODES y - -/** - * Production configuration - * - * Enable production configuration - */ -#define CONFIG_ZB_PRODUCTION_CONFIG y - -/** - * APS user frames - * - * Include API to send raw APS frames - */ -#define CONFIG_ZB_APS_USER_PAYLOAD y - -/** - * NWK security API - * - * Include API to disable NWK security - */ -#define CONFIG_ZB_LOW_SECURITY_MODE y - -/** - * APS fragmentation - * - * Enable APS fragmentation inside ZBOSS - */ -#define CONFIG_ZB_APS_FRAGMENTATION y - -/** - * PAN ID blacklist - * - * Enable PAN ID blacklisting during rejoin - */ -#define CONFIG_ZB_NWK_BLACKLIST y - -/** - * PAN ID blacklist length - */ -#define CONFIG_ZB_NWK_BLACKLIST_SIZE 16 - -/** - * Enable Control4 network support - */ -#define CONFIG_ZB_CONTROL4_NETWORK_SUPPORT y - -/** - * Enable R22 extension for for mutitple MAC interfaces support. - */ -/* #undef CONFIG_ZB_R22_MULTIMAC_MODE */ - -/** - * Enable R22 extension for for mutitple MAC interfaces support. - Enable single-MAC interface support - */ -#define CONFIG_ZB_MAC_INTERFACE_SINGLE y - -/** - * WWAH cluster - * - * Include Works With All Hubs cluster - */ -#define CONFIG_ZB_ZCL_SUPPORT_CLUSTER_WWAH y - -/** - * WWAH cluster - WWAHu client - * - * Include WWAHu cluster client implementation - */ -#define CONFIG_ZB_ZCL_ENABLE_WWAH_CLIENT y - -/** - * WWAH cluster - WWAHu server - * - * Include WWAHu cluster server implementation - */ -#define CONFIG_ZB_ZCL_ENABLE_WWAH_SERVER y - -/** - * WWAHu server - NWK retransmissions - * - * Enable retransmissions on NWK layer - */ -#define CONFIG_ZB_NWK_RETRY_COUNT y - -/** - * WWAHu server - Beacon survey - * - * Enable beacon survey - */ -#define CONFIG_ZB_BEACON_SURVEY y - -/** - * WWAHu server - Parent classification - * - * Enable parent classification - */ -#define CONFIG_ZB_PARENT_CLASSIFICATION y - -/** - * Check for Out Of Memory state - * - * If Zigbee packet buffer pool is in OOM state for a period, specified - * by ZB_OOM_THRESHOLD, then assertion is triggered. - */ -/* #undef CONFIG_ZB_CHECK_OOM_STATUS */ - -/** - * Check for Out Of Memory state - Generate NWK status frame in OOM - * - * Send broadcast frame once OOM state is detected. - */ -/* #undef CONFIG_ZB_SEND_OOM_STATUS */ - -/** - * Touchlink commissioning (experimental) - */ -/* #undef CONFIG_ZB_BDB_TOUCHLINK */ - -/** - * Enable Zigbee MAC features, used by the verification framework - Enable API for sending inter-pan packets at non default channel - */ -#define CONFIG_ZB_ENABLE_INTER_PAN_NON_DEFAULT_CHANNEL y - -/** - * Enable Zigbee test mode and features - Enable Zigbee MAC features, used by the verification framework - */ -/* #undef CONFIG_ZB_MAC_TESTING_MODE */ - -/** - * Certification specific behavior - * - * Enable behaviors specific to golden devices used during certification - */ -#define CONFIG_ZB_CERTIFICATION_HACKS y - -/** - * MAC filtering - * - * Enables filtering frames at MAC level, based on device's short or - * long address - */ -#define CONFIG_ZB_LIMIT_VISIBILITY y - -/** - * Groups of test cases to be included - Enable both TH and DUT test cases - */ -#define CONFIG_ZB_TEST_GROUP_ALL y - -/** - * Enable Zigbee test mode and features - Enable Zigbee MAC test mode extensions - */ -/* #undef CONFIG_ZB_TEST_MODE_MAC */ - -/** - * Enable Zigbee test mode and features - Enable Zigbee PRO test mode extensions - */ -#define CONFIG_ZB_TEST_MODE_PRO y - -/** - * Groups of test cases to be included - Enable DUT test cases - */ -/* #undef CONFIG_ZB_TEST_GROUP_ALL_DUT */ - -/** - * Groups of test cases to be included - Enable TH test cases - */ -/* #undef CONFIG_ZB_TEST_GROUP_ALL_TH */ - -/** - * Enable Zigbee test mode and features - Enable Zigbee profile, used by verification framework - */ -#define CONFIG_ZB_TEST_PROFILE y - -/** - * Enable Zigbee test mode and features - Serial console RX timeout - */ -#define CONFIG_ZB_MULTITEST_CONSOLE_SLEEP_TIMEOUT 4000000 - -/** - * Disable TRACE_FILE_ID assert - * - * Disable sanity check for ZB_TRACE_FILE_ID macro definition in each file - */ -#define CONFIG_ZB_DONT_NEED_TRACE_FILE_ID y - -/** - * Use delayed TX feature of the radio driver instead of entering busy loop in GP implementation - * - * While communicating with Green Power device, ZBOSS will wait before issuing - * mcps-data.req using MAC features instead of waiting in a busy loop - */ -#define CONFIG_ZB_MAC_AUTO_DELAY_IN_MAC_GP_SEND y - -/** - * NWK requests with aliases - * - * Enables making NWK requests with aliases (see sec. 3.2.1.1.1) or - * R21 Zigbee PRO specification) - */ -/* #undef CONFIG_ZB_USEALIAS */ - -/** - * Enable MAC duty cycle monitoring - */ -/* #undef CONFIG_ZB_MAC_DUTY_CYCLE_MONITORING */ - -/** - * Enable per-device MAC TX power control - */ -/* #undef CONFIG_ZB_MAC_POWER_CONTROL */ - -/** - * Enable per-channel MAC TX power control - */ -#define CONFIG_ZB_MAC_CONFIGURABLE_TX_POWER y - -/** - * Length of the internal ZBOSS MAC TX queue - * - * The value of NRF_802154_RX_BUFFERS (ZIGBEE_RX_QUEUE_LENGTH in nRF5 SDK) - * should not be greater than ZB_MAC_QUEUE_SIZE. - * If the node is flooded with requests, that require a response to be sent, - * the node should be able to schedule responses for each buffer, - * stored inside MAC LL RX queue. - * The receiver gets disabled only if the MAC LL RX queue is full. - * The TX queue is unable to block incoming requests. - */ -#define CONFIG_ZB_MAC_QUEUE_SIZE 17 - -/** - * Acceptable noise floor (in ED units) to form a network - * - * If the MAC LL layer returns energy higher than this value for a given channel, - * the node will skip this channel after passive channel scan. - */ -#define CONFIG_ZB_NWK_CHANNEL_ACCEPT_LEVEL 200 - -/** - * Enable internal clusters through filters - */ -/* #undef CONFIG_ZB_FILTER_OUT_CLUSTERS */ - -/** - * Enable enhanced beacon support - */ -#define CONFIG_ZB_ENHANCED_BEACON_SUPPORT y - -/** - * Enable joining list support - */ -#define CONFIG_ZB_JOINING_LIST_SUPPORT y - -/** - * PAN ID translation table size - * - * NWK: size of the long-short Pan ID translation table - * - * Must be <= (packet buffer size - sizeof(*discovery_confirm)) / - * sizeof(*network_descriptor) - * That value limits number of Pan IDs visible for device during active scan. - */ -#define CONFIG_ZB_PANID_TABLE_SIZE 28 - -/** - * long addresses compression table size - * - * Size of table used for long addresses compression: 3 bytes of - * manufacturer id. - * - * ZBOSS implements long address compression: 3 bytes of manufacturer - * id are stored in the separate table; reference to manufacturer - * entry is stored in the long address giving 2 bytes economy. - * - * That is an absolute limit of number of manufacturers known to the device. - * - * Note: All that machinery will not work if instead of legal - * manufacturer ids (or illegal, but fixed ids) use random values. - */ -#define CONFIG_ZB_DEV_MANUFACTURER_TABLE_SIZE 32 - -/** - * Packet buffer wait queue size - * - * Size of queue for wait for free packet buffer - * - * Note: To prevent deadlocks ZB_BUF_Q_SIZE must be < ZB_IOBUF_POOL_SIZE/2 - */ -#define CONFIG_ZB_BUF_Q_SIZE 8 - -/** - * ZDO transactions table size - */ -#define CONFIG_ZB_ZDO_TRAN_TABLE_SIZE 16 - -/** - * number of endpoints per APS group table entry - */ -#define CONFIG_ZB_APS_ENDPOINTS_IN_GROUP_TABLE 8 - -/** - * Broadcast transaction record table size - * - * See Zigbee Specification subclause 3.6.5 - */ -#define CONFIG_ZB_NWK_BTR_TABLE_SIZE 16 - -/** - * Broadcast Retransmission table size - */ -#define CONFIG_ZB_NWK_BRR_TABLE_SIZE 16 - -/** - * Number of endpoints - * - * Maximum number of supported endpoints per device - */ -#define CONFIG_ZB_MAX_EP_NUMBER 8 - -/** - * Number of supported APS groups - */ -#define CONFIG_ZB_APS_GROUP_TABLE_SIZE 16 - -/** - * Green Power Sink table size - */ -#define CONFIG_ZB_ZGP_SINK_TBL_SIZE 24 - -/** - * Green Power Proxy table size - */ -#define CONFIG_ZB_ZGP_PROXY_TBL_SIZE 5 - -/** - * Dynamic memory configuration - * - * Enable dynamic memory configuration feature that allows to change memory - * footprint if application uses ZBOSS binaries - */ -#define CONFIG_ZB_CONFIGURABLE_MEM y - -/** - * Dynamic memory configuration - Expected overall network size - */ -#define CONFIG_ZB_CONFIG_OVERALL_NETWORK_SIZE 128 - -/** - * Expected Zigbee traffic intensity - high - */ -#define CONFIG_ZB_CONFIG_HIGH_TRAFFIC y - -/** - * Expected Zigbee traffic intensity - moderate - */ -/* #undef CONFIG_ZB_CONFIG_MODERATE_TRAFFIC */ - -/** - * Expected Zigbee traffic intensity - light - */ -/* #undef CONFIG_ZB_CONFIG_LIGHT_TRAFFIC */ - -/** - * Expected Zigbee application complexity - complex - */ -#define CONFIG_ZB_CONFIG_APPLICATION_COMPLEX y - -/** - * Expected Zigbee application complexity - moderate - */ -/* #undef CONFIG_ZB_CONFIG_APPLICATION_MODERATE */ - -/** - * Expected Zigbee application complexity - simple - */ -/* #undef CONFIG_ZB_CONFIG_APPLICATION_SIMPLE */ - -/** - * Dynamic memory configuration - Source APS binding table size - */ -/* #undef CONFIG_ZB_APS_SRC_BINDING_TABLE_SIZE */ - -/** - * Dynamic memory configuration - Destination APS binding table size - */ -/* #undef CONFIG_ZB_APS_DST_BINDING_TABLE_SIZE */ - -/** - * Dynamic memory configuration - Number of packet buffers - */ -/* #undef CONFIG_ZB_IOBUF_POOL_SIZE */ - -/** - * Dynamic memory configuration - Packet buffer wait queue size - * - * Scheduler callbacks queue size - */ -/* #undef CONFIG_ZB_SCHEDULER_Q_SIZE */ - -#endif /* LIBZBOSS_CONFIG_H__ */ diff --git a/zboss/development/trace/lib/cortex-m33/hard-float/libgppb.a b/zboss/development/trace/lib/cortex-m33/hard-float/libgppb.a deleted file mode 100644 index d88f55d118e7bc933210709d91a7408b5f078e71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93146 zcmd?S4R}?>)h|B#oRj1vBqSsV0Ro;6z(5cV1ThLPJtVkAL4zM{5w%H3f{6q;B!E$A z4T1_PEeci;X=(Mge%63srAR~7`nJ8=CsDDe^)0R1DA?YUkm9MdFZcJGJ#)@JI|K%LY(b+2qTNqTXpZm6$awo))^O?^|X9+y--_}4B}Yn)>N&mLSi*aaw@Es zZ=AlaYFQ1k&|64JT$eU1t(6sBy?ALw^`hQkH$e$>n3Ff~#@eRH@?}kSePE1+Tbd}- zs+yX{3afzix7le_=E%@qH&A_eX}Q-ft7e@xkkg7)NjlYZ>$2*KNWILjjIy%10_igQ z60LTz6f$S5$Ry(1@pxK&~+OOZwtne1=erRNyVVKMtk-xiBlNFiQ`FBJ#!S*_YST0Y$7a=vPmRgZzwP+5~*Q%@< z`Ynb=HPu-RB9LN2)vDuKspGQCkaeSq-B?>yBRg_SL3BfidnXYmx_#-ra!~{FMP;UL z0HGRLeK~q)bZh9MR5mLXFK<-+9mL;g>8ibVtEp{}Z0vqgQhFGuUcQR;)+bR76uQ4~ z=>E#(jqGvMc+wxCY-YWPtctYfO6H%9yrK~~sz+zGxW2YQRs`kHo0N>dBx!X66f>Et zgQcv3UP54X_42H*v8vjhBU!H)dHV{p#LcN=zrwU+bVd?#X;@KT(THKPSC(XV6%Vvz z3ste_uy$!AF_7B>mSOCcffcNQ`r0Ndms+vyq|Ad=O(<$2o*Wi1p4CDwXR6mGXt7-g z{n7R#jjCmsu&ANEk7}u1wrXi@W7SHl*OP;mMQsaMRIzMzW7SeQve+mZYM0%#vW}Tg z1l!BqSGaD`&ahPx^yRg-6wrQ`FJ6o?CHUKDR5E=KNtL4J+cIh!@vNL$J;&Lo;;ih2 zIs>mWlEs;637mnElLWohQmec|#2i-T_-rYXCSN9r*=^fHIo++RYLc}~Cd6;5UB*fQ#xihnq!kzg&I+aKwat-w zOq}h6a*SJ4QJoY~@ocQEUXGDCK4(U!T(PLWrXJn2Y#uc_5*m!+xwJacWaS`vQpju~ zBi7JkO(0fano)(32}=rQ5334{FIMq;QDXS2aS*KFm{y}>%E7}~=w1XI^lfQq7M4^r zD;q&_b}|0cqB$V1BtZqpmeDJ()m4bbRS704a$M02Ej6!-SOa0Au~9bmCZH*7%9tRL zD(j?}%*T?v zY^^TIUyiWJKAcB$?n7~5iJ25g)#VH`$rBky8=@51fyRR-=_0Ap+P`EJUo^R7%2fUh zg(inW)22@K`6gc|0jMi8?zm*0X&44RXjsk=g(86oQ8Qior%aWgQ2d*iAq-#S(wu$5 z?=eq*{-39V8xQR+i{`j@>_l zx#mQt5Ka3oxH3h?FRrWJPu_F(i_PKglf~igJEpk&fZK2nBQV$2~P;TGwNU+W*4kE@v zkMZ{RQay)1txIrO;K`KI*`DULq~kKiyOne$xe9l0a!4LLQ@`?d(Z=^v!d(xw zKvL;*q#XTqsb-0MdqEh}4s~5EPVPCh=kC&*-VJyEa`LdF-oQ8+8mx17d0m0Zhhje8 z@J1`2+d4~3zbqHy9omy!m~tfC{orKCBgC@j1blT*=JPFBmxFS>)M?2k6|t-|Q;*-B zx;iOc*SqCCH?R0WQ3mT$y2hsFLoUoQWiupZj5s~+oc7cw+z*hmdwW*b5LxTqKIXK(3L@gX1LmQwQn4vEvgMb1a-K|k zqT-8tVodkY^UVA0vMp8a_uAT0m(1@QpBhpx{6P@__m<1Mj}Cg{Q}>kapwC3uWURih1J2|q%3ud4DMa!uhFG=e%(q4MYXXZTReUdz$>ufdm zq9+m}ZC}b<5fEDpzh|!B$1r#6jWN$DhSBM8S3lus@8u)>KSsSU?o(H!nniVa2l$@c zYkV^=(Q6dd-6v%c*>6eD6Err9Ei46|yhQ)^LM%JvFA7J;um9;cPplD>MAWrb01vD$ zs_U!v_XHDZSe#vjspjZ*ab92alt8ZBbHB{P(~-5UlKz1`89 z=VUY7onp&_T>}Tm`mj=JF|{rv`qlCtx6I8OF;5Grtdw@f!XfWwqiAqjelRCUtsUgI z^mbNUZw>10ww&4C&5UQ5-py9r>@PN)U{CYfo>z{);{IOgjcOzPWc#qR;Ehj()RcekERTxx@~CIPZ_HOZr+m{GAC9K1Gp1)0edT1} zIpc>{$AVGOcF-lnWRDQPhTiJu2M&B`iV)A@p|j*vgg(75ZR)-zp-t|&>0Hy>l;WHSeTi=|)AG~~riKc=@@`nlluh81 z`f-a@3*qR|mT>o_)tr;q=Ob?)WjU;Jp13WwD>H3V?Ap-Xofk>|6_S5Zo$EqT^kY?@ zk98c3Rj4wR_q6)C?^>ryLOBVChI5j_D)rH?|onw{gL#Y?P+8^%zKFU&pmeQA=K5Hw3*60Ddjq@J* z*s9IHLl(OcKfhD=M`@6ol|oCOn*WeZ^S8xBC22Q2Uw-oQrk}>reUFr8y{qGkqTi^R zehsO-d5zfo@tar|X*{ zju`^m${jtv=SV3E@8}uv99lc-F1c>9JK1Mh^0@uBO;~9(by5djlse#6I&h>@atXRj zvE@GhY0OxNzai%qT1)!wU$3*(#Oh|oy1Ue64t{gpi1+u1Ey7Y#Hji~?fMV1$xla|FL(SB#{LCR{e%*C--eUJ_)t5{$Kkpc}VMp`Y zz~mO6d6D^igq)WBS)AwjNVKKx%enl)*p*Yar`^z27WKIA#Czu45w@0A9z8w9@M9#J z688N@j!ldY-;kOq$#oCMlRNfJxT2`;8rf<~u%bIGsSSVF#~5ShZ3XYVXsUZmdr{p0 zIY(;QPd~%|%83@&D<{HkV~aQFdeE8+y&tsV71doYIfmsLF-6WyG*1s!UsZveD+kT# zjufw8Dj_NVZkb}{+(R+9?1vb_l+x#vMP2Uoc%x5;TC*|lPM5cD=scs)7r~mTaA3Qu zHRs^qxm#lM-Hew5{jMxZREzCC|uiZbxn2`5w^2+%tDV4;`k*m@| zsZ+Urx9m;-Y%8m4ZhqoK2?J^t9% zByC_Rtab3Ot$z0*md9G(J7eDntuJs#T4F})fi97KS-an~Qvd2)&L2nAo!nD_RfIKXHOvL^6%1=L z+9Am@jr2*<-HE>nM(|HPUym?qmx?uR)y( zch72iBWBG}b(sxS_JgrcLL%^NY-%WdhqWF{S@&-{3Qf-zf6(f8cg8;Rp;wsvMyz0S zmds_cPL@lJPw3=ixq{F-PiX1gBhb5z)Vmf-@9wem?)kg>(Yso!J=pZ__PMF%h`N98 z^J`7LMJ?AjH|?G^iF&zo1tcNcq2KJ@^QH7MILJTTgkEm3G^29v@a6~8O4}AT7e)^m zvyR<4=#l0HZL`d`;rD*CzvpPxtYdCJYa$=|=P@tpp!N~JYVPn`J5bNt>zw*`X+%uA zFs^&1(!IV*^{}l}`8_S=&^ol{?mhFrxclVKOS3*G?>SL*zZ}0T4WmX;$AXPNhgO~Y zi2Rt%(He;t@6@OilX6=Xej6JLN{D|7Ki>2yId;Cg!3bBSy*)nqn^kkO@E32MR z)|2in9Kq3UFn&{ygw)<-{n__r^atPCT3gPQ-`ddgm=EAD4l~ z))+Ai>q%?X?rvUK;EGg7T)~eck41bVpGk8azD&xa{Nz8IK24p|CNKwoHkKdC+2Id( zRNguFFi0k@&6?-FIJW>XsC9i1}=6l+=v!a*sLPHtxoI z+LL~3jwLmISTGo2O77-V%$}HQ11qw}BGwlkcOd=AUGf`R>W*C_uTQJ#$Wi@4>W(9+ z)00+Zl^w;Gc>`8oI0ZeBSD?4gBkxr7o5RvZAKn?87h*q?x?>@}Li)_Xab6=lDZq0A z=SZKNso?IW&%xLNSr(6(x??+5SvzAlNDjjsa`Q{M6`I9nR@W#wW1DXO{&4a(huj9V zMh|)eIkK1GS|oca@->62se>3j9#>=A6K<<_vA)5++A>P&#m3eY%!)pUg*Q{ueXJl( z-eZ%m2xOqG7pfUK=i?|#WLn3HG|^><^E%#*xnv0qGuKfj>bWRpd8SLf=yQGszwG^pmg!M z<3CUP<Q+IM#mQvy6&StuwK+(P z8khPmS-PmUrlz*WckS}!4cNz1zsxr|G_m;nDWNHoCr%EHli0+`KH?$#kmDFx|~u4k}ujxp4oZwxbr8zYPY zW0WUgj5Q{z!XZ-J*}XiXOG(WNcB2e-=N8H3b_>qaM7BKw@Lb^J!n$$EzX<|2 zB$P~_f{&UO{ne6QeV9^F+#=0EpC+mm{qH4xnz#?}h@!{W+V~q^+^E##^wPz*;m`cd zN6}meXZ(5bVp>W7FX`N3fFu3@@pFVQekK065YG5F&_lWb`b9#w$a2KblJxm;s;u}M zU)-Qh&TqDZJ~`Aa207>liTA;W+4(sdg$v=#-~I9OS@?@KoE%@W;iS)JgObkTUtq&^ z2%%f#InvLQ>CKK4<;CAD`g0ug=Scd!ajJ9TZx;Pf2mMe*VSO@)BNzb-txv~01LN|U>rv4;c zq4!=5vknY#p`9H0nIOKBL_f_DKGA`P9QYImZvEP= zJ>5t@IsX^vAPL=Knj_qq{)LWkXZ}kZ{4NsJ@w(y|C&afM_~Q=z1qc3~1Mha=sc~Ji z_z!pB6CJqez^`!NUw7ck9QfT1{80z~D+m681OFcmJl!_rP(J4YXAymPa?!t3%?Z;g{L9Qa=x zxGUA-C-W{wh%pLph92aK0&xX!?MM@G;P*T5#~k=84*W21=07a?j}kG3zXZQr;S-~6 zQwXM444m{F<8#s9UZwDMNk3XNEBvU$#|jUL;aJQ;Vv2Z1@e4{kBz7sBrbUCqRIyj# z90>-Ai9+|?>?sGKzZccr_>^4dQl#A7^;q)=F`!7ueG@ z&@x3Ul-$v3RgkrvwcqXQkff}an%c!xs~TVe0K26MsBN#B<*rYgXCmLakC1_J`#CFF zZO1|T3+krMuxuezk4DH`+Umhdr5=q)Mpz_`bZn+#jr9>&N3d{JR%5{?+Q@QrGSZMt z7n+T8Ia(by$yVJ8+dO;u6LwLMEdI+)@%@?b$t|MN$c5XQneBuzp5EwuQ^jp@BP)mf zRJ`sW^#82}fc@Ehu?|;Oq4iTs*wPZa!P$nP8_TOJ8fq6?c8C-gMK7ye$FO=2X^|zv zQHDOOa+Ea=0{@o{5s?Abm#S}jW2X2VO+ohoGRp|J?cx8I?Go$HVt|NooKupFg+dHh zkgFEr(jOCpfyA#DVl?3mLM$V^QHXm9zahjkD*QDS&hH%(tD2(>3l@E2)r=|$*30c3moxj#A`5zQvO#GB7X}A5#Fru zM+j?$;2I`lu@FBY1fQ1(D`96$$aDyA68Ok&!F(5Boe&cUA%{{zNQgs(ORPCD<9$LL@dh$IOl0#3;XjcO{udMC)6CU``1r`V zAJdifg38E8d>7_z%!g}v|NaoY%$Kg0kV==UK&BTaT%qa%>E5RNw-N$>M1?=4{9jf6 zuPgjd3Xc*t3h|%HUzP{)eat`PGM*4}k>zU=qJ%iozm^bm3ke~w`w1(B_%0#j_8)|h z&z}ib3h`G$$i?RZ1Rd9o^uL%8a+*U3zKaOKm*1USBZb(k;8q26+B3hq^q->+C7KL=#Fxu#^gepAn+GUnrRAw(yAx&QOqRN5-omM7;INf185O zDEKnrDj|ML2>MS5LEodoGd;kop%;V*pF)Uyl`8xOLeMWG1l@YV)sTw{{~;mhxfW#n z*9bxX9wF$v6&#L51>0SK5dI|!&Ll+rnS`kCE0zD(2yYSM8-(B+QSe?u@aNhtqgjYY zm47QC;=f3U{JgCEe@_Vdj|gu?J0(OsuHDFYw1O8Cf^H5WKIJV^{>{q&PC_X8y@cSu zl@RHDj}UxbBt-l-2~ocH2yaKagwWf+5`xZ)wnw@gLc||V2znnO26TN3@d%;EAd~zg9l|Fn{Axnr3l)y8N8&An_;WYmTC_95JJD_l zm#TgvqQ;4JLhOY<(|M5)>ApmGmDMl0<_qyE@pI9R2-jQvTLzd<0iJOW%1Maw%6uR{ zm81h7sG@Lf5TcF{{0jj`L5`V#q#sKN`Vxg-sqh7acUgR>pE^FOO1L(1osDqFc{CyT z%p?S#*@WmXzd?w^8ISdbqDnouP2o~55Q>z?CL!LYeJ&0sfR*gb;FD zNx1p!<-VHv1|Q0a>7fdw9KcHE7c8V49#Qy@2qA|T2qA}~gq1=>36Xy}t^>;PVo^d4 zr7RctFD8T>v^>5|9Pxidh? zq*4y|DqQldRPw5_+5^k~9>d|E$?`$?Qg2u;;$SA{L!jfg8|H)KD$BV*!BLD4`VvCW zn}nzju$1ZFNeI5EDoOW4LeT9Y1mD*I$#*buWZKy-BtMjI8N;j4uM>iw)B~j3N*w$S z5rW_E0m+Zfg+hA>A)HJ?C>7HoEKrc?xxR+^n8GPn;xiPK@vrSaz6{?X@M{_3p?}IF zeAKEZSA^fWfFrZ$I)!Vy^}Wr-LQQPCbtz2X09Q6zuui|N!}5cfjm%nd^*VV* zon3QwLUlxqjgZTrGkuIpCe`cmWZ&M)^5k%)0ipMM){TwYDxiHGmpF#OI(^4kwf(M+ zler=fdilrKJ`c({Q;c3K)qaUBjqClTrH{Hy&Xj$*YU6GrI>W;C%n|IZKreM=47RL^ z{d{mu5XjG}$zNLg4dka)N1zhC(;Mgb*a?$9_R1zd(e~{oe$3Cr#^o~8x;D@BIrz)c zT6wnk>QBfMS%dgSCnnCi`ihAxeEp(TD{Gt3Uwuh80(2M}M5>}^e`%VonJnL;X}A~nx79u zc7C(ZPslF|#G2m~4t`ws`7|>{NAxlWzZ-1)vK1Z6yV}8T0r(wafO0y2jShY*!Ox38 zmX~9;&fgCl{PHmoo2Qv6I-)xr{MJmi%0Ygd6KH-vb?~bJzt_n?Ii0`f9sC{zKhAx~ zk8=sl?{^M57U^q)BFt3+3UB##*aHu zbpH4q#m+A?$NH^aGt~U9chD7pt{HyXX*&K!Z%_9bq#FYf<-$3gPIr@o-_~4|w-0_B z9sC|IPVnR0R`dIrgWubjNWO${?R5TLaPWH+9pD@gF@HWhnqSnxZ!;>D-{Q2>{P?}c zUfz$u57S!7F94|dac7}j&YuktqFpmnbVLV(&dzVm1&REPR&;DGmpS;o1SL5Nf9-Vs zE^+XC75wIdh~*uNN9XT$#ScKbNAs;Pg-SZU-{Rmmc$(FZkzXMm&F@hMzg^%*Icujy z$?skE@)m$!7)0bZ9*^d?-@)$_@MC(~X@2`0{B8h0ABe~gU1pr$I}Uz1XcW{Z?KHnP z9sJhV_)P?{&fi}g{3e25P%{J6{62N?dldZ8lw|%wHh!la{H_8&j%(U!ey1G#o&i7V z2g{457th~dWR!70F5TC_FGIZ(XnqqF9n@O7O3>+ddg%9s4!TAC(B18zs{vi6#ajMF zuyo&5bd&*I1ay~MuktVR$LIT?Lm47E=x3mtp%Fzxl(agp#ABdqhoVi#`$9ZSmvX1> zX_??v{3Ur{%&i$4<8wa(+%{9$}hp(v;+bQqFo#%Ct}kj!S_%`#CAsUMMpa zKPM$bv;2KCuk^rvD+~Lx?`qY1vAw}?_qU|2)FVM*Jv(oV$%cH|Rzwg{J zJiiT=NX75(iNZed^on~+M|M2cb=q}J={2)F$Je<=$Aa^}-ck&kv|mb_G!Jaj4s|4Q z_tT`@?d?2WWVDOmA3KZd@^&wehCNS93rAYAeGW^u1F}@wj_t3Vlt$jZOxWz$Z3cD8 z!`(ykY}RWyEhTOUT>0Ue2V=8*uq@0II6uH0FmN_W zzO;oKe6+YuTZu3hQ^VfN7_Mkj>$`%;{2bri=xllDZQgbSsfp)2}+p{ zjfS(eti4j!Kk7sYP?A3$`D4-lX#YdeU*7$_)EOlu)-N=-fKIxC)|By zS+bmq>v*=oRilh?;qI%~o(`rxwb|Sh8y4CW8;)m02-fbN)UI>fc`;+;qoppKLi6{I z>1cr$%NAI-|Ap8&QtNoyfh%r}cS9L-KD}sr=Kb67la%rFI{dX$ej`pP0!UE|g0;;sX~BxGYq0Fz&|;V=o3pxxyDclAlt)D2 zs*atpVZNOx$ClDtI#?Fqc!vA(!l#Rdb{Mc20G5Uk;f%SZb7vLJUKbnNA|}ji7o(G{r>q_%+?_3@VD+ejyG9@%4}e}o zH?`bwbdVW_Ooq#nh{Cn)tfRYS9f`s_A&KF#mUuGAu#n47+e!9jv`?;=brnHxnTOu; zfMo?<_)mrnNT+dCIY32B*rD~SfOo!WOxIX z%^k)GQUTw0W1&#S?ng>5dQ*(P3+=tQ?mEv!hu?v0j@4}`oeH@h=NVKfrENj=W}&$qP7fGHetR4Jb9~~Jx^27+BZ6RRu@hV3Kid;_5@B13N_We5gQeH z9)AO}M{=2e=wyxkvRzDgrTs4X{%gFqbiCG?1OGdE);#wVY>3YP^z@}O{i(9I-5eWx zD8+oK%bmSBc40WR4Uc#@;>$<*9jrw1bAmi%-|M3uPW6 z!Z-e#|K00~rn#89*L|7DD>I@YoSZVOj8=*MvROT%3b~o$dZ5g_+%){|hxgm;so1~L zZY=D7xYd%(Oq}Cp<@FD-p0(EbWPOcEpH|BeTiT7Kbq&VJU)GsP>@j}T0vkF}-Rvs5 zsojkeD!$!f;M|lKTY}9-5iM)4gJtcvWZf+&UNSo`mV3kL^F{ROmT|Q6lairT9M4+$ zK?{2@&PBq}9W4h@@9be=p?M8X0EqX9RZXNSkGj0)nPbeaJwMZLl|TeuS>wS;5~V)( zg9l@UzBeJM5(6^(3Io=;*BcpS?jBJ+yo{-o_UtM}DtC%49SjI;@!w(;fji1l_-m%6yp~hp@?MK{Odef%-J3P5ErH5mKHZ!#+yVBE6?-51s z#Aj=7b|BSglG%N7+=Wh{tvuM8 zCQBQ}{L4C9ZD+qTurDlqkQUU%b%QUkpRDoo>f~_|_Tg&Q5sr4ZR5y#FsTeU9MZ_57 zCmp4}Ef}e8b{9=}x4PL=WOST{HEY5`y}DU)+X6Wy^|dKd3xdt3p>aoBM(!sE(S5i@ z;QW)woLtu4rKo{6XkqcMJ6%Ozhi*3G1eF_M{cg|g3P)~{CoeTO^e)Gz^)b;hw4L+h zSyJ*F_ItbLxU-JCz4@`+8O&MoXnj{TYrVMc8aY~*9B@4ZUKk-bI&5^Llz-Io)bQC4 zVkUHYd}=#W8`5T6Q1QjO*kAS-#RoeN!nSyL>Q@g3A+f6=v5{sV!t&nHv*fwtGW0k& zSEJ0;5dk?~ExEj(GDUKk7W=BjAY^DzeFwB-xG7^l6_%y z&SdJ`6!ZPM0XQXV+odA7Bmx`XPfEh9U-oGw`%=u;_gL-Lnh__$@4$M(vgn?O^CgSx zie$~$S69~s6RVNpx~JtByLtaZu^F=WaYqfeYm0BL%fAIPPDv^2^P54|G^yTC%RB5> ztB7LTxg_5XCbt8gOCl!x1=^%%X!bPFn#&Ts+`W>!H3NG)X>QDMEz9JYKAUB0{X@+2 zK&m_kuy?3EBCfnEXw5f+j2ZVp5oY@<}55hP}CA2;^Yd-lr4i4n4rMfjX zOY(l@gvfJkAw_blZj|Ld2WMhdpQMGki*@DLlkwZ*7sMO zA@x(l`mj?JeWLt6g5Lr7y=xoWn^f5?E$?0S@}6RAT`A8fT_Vf=+j!Z>HT$oaeBdGE z#D(7Zp;)o+A)NB@Na>JvH%>3Q3;tHWrc1)pYojV;kByfSIMrNe z4k%s^*_^t4eQa9D6%a);NHWC$2ZhzEy$+f7 zuGw(+NSh>dndjpyom4r8+!-62Q)rHu%o^Mo8x!)F(W1;YcMzxc;hc!F$hru9%T|HT z7ao7-D$d!8C+k*`)pedRLY93e#v`1Z1Xp0BEv{bi*oqHV1RGsP({{WX zO9@>b5WzpKG6L1BA6s2$23A{I$Fr`!5kHyhI-Jb)RY>@X&Wymw%Z?WO5>i<3%SS5F+u z=v{~9JwL0K+AMqOpW(!z#qG=IzItNTkR3PXMF(Wh#u*bLwC?%4#wJc16Ww|1?wKf} zIqSym-xeDxXV4kzMg(T5dbj3qQ!tlHmF2hrXXhl^Z@9anI#~+`%hd|=D++&;v}XN} zYh>Q!?Ej$bgD;=^R%~l%TWQ`~%-4Y38^`XE{-W^j_#PPU{`8t;-hb^J3|-0VSW@@a ze#X%G2zUQYp0Q@{5$_p$Kjv%HpUIaMN_`TAAGLp&`sxWW;0pmqWPhc{``oOlBKp;}=pCy*JsS4i(kXl`ewVqbQ*dtE=rtpq*P6F= z>O5c_JK^W;FWYo-T;Do*)*8lnE(Z=nhktWo)^N_<1isS!tjh)XjHBMe-P3Jp$hI8V zr@rzHa1-~Kh4SQOtH;Edb^8$>?=ztjIO8_l{grD-3v4R&iv913c>mk*9L^@*N~-T% z^Nmi1?~DzYueG?mXPvEI5wgAPgtk3hTG+lb_7%Xf9Y*kUU_QPDxMR5!7{7Oa815cZ zCi@)K-VStFx_cDo!TLf$d@qC+h0ZxDg74zn*a*-2omM^XLqE8#bX5nb@>5qF4)(aN zA?35NKp1|$x6;dwJ(yQ^EI0UW+Kq1`g@}|<;nnT~kM)9Q*9Y#@MGn7L&fxBc8R!gHt%)ae1`Cy{+`cwtUlD_(Yr6cY2)YS|-9LOp)Gx z&$#p>1IBG_6Mn-VKDIXJ(4NSpZvWpqUH;EIJ%-Es|H>IQ*!Ey^9=Uf!{+5V8Ji`Xt z9pdL$Sif2($lcflk{mx(+9ff52_6^189%YdOYi!!c;Jh@BfeKuA&Bvh;Bg_G@qdNK za$a#4UKq}O+b&0JH-1r0&QFGn?_&h%GQ@L$M7f@F$=%m7K>l&#m*M32nc_`^kbVOm z7s8pJHFzwS8Q(v}pJH8d7q$-L@3jLR{IHqF=G^!NI61u>F$Re-y%+FfuM6Q!?@0WI zWQ+dyHr&Pz>E$~3<;wWnyKTAT)ZEzZoa{4L%uwlb|GEp|Og|@{9yYbuoEuhm$?=DX z>s9=1GX4-5e{($k5OIeJ=UyC_+^wEq=tg}c^UIg<8OR%BYrada7TE7BfLQJ zdo@nQTqK+uJ1~;@jgs^U`Pp}9Fnync-Y4mM;w*jfH@@)9nq>X~M}7hh`q2*h(ULwP z&xB+w{$m~V++mY&ZtRv!PX9c~&l9g7E1Y$2IV=27eB*}|o;dg7JWVK}8!Lun{#-#M z9M8PrJ~%qI7X!H6xdk>U+8ockc|y_CoBJhx?!em}IPEF5BmLhTct*Tz7QX@q&i!cG zG5$rs$zlTj$7>9rz&!{-y(uI&kje(vJBHIPi-d_>B(yn-2Wj zz*)X_JUny6c}9%h_f#OuKT3Syi2sp_{|_18mo!8$f4Qt^<%rWhkm+$xBhM7M(hz)}c~@K0_iJ1bzYs0X&pM>Vy4CJ1nQ;co14qEfo?#n}BLrvCL`2y&U%$3& z&cw-6E?`!_)M+XGoOr^s29ge*=<@&(eFOxKC8%nQ-w@ZwVFT6$Z*i&6b^vFrB(C|5 zhgdd3j`JxjPjwIFqWHlRR;m@%Rk#loS9!{lCSbE8kJ*uDAUOPZ*oxiDRx3DjqrW?B zzntbuzP*ljah~In+;);`RvM`<*2>c~*qFiMe-Nd4^H{clIWA z4T!Ccv~0)hNGYR`wu^#glFsXUEn(Acsvg(IS|@8rG4sTprMTZ(-4)I=M(p%4Evx4mB`XIyljF8?(!}Kmqzo+9s4wm?> zQYT-a+ph^2tAp})p0%XuQ84|Ix~yYef2o07qS;&I18c&L_#Ad#A~7CE-_<{V)6!7!ad!gH)W(d5q+1o?*)UsK`8g0z3VLHRc-|22T**Fp$>>j~8|XB0A> z1Dt%v5`u4y!tYf0y$XLu;d>SSj>7*;h(uX0JjW!&a(n~(w+X>_J|XxvD13v$Usbp~ zCj;SM5J!Az2ab50M>8JnoXKaQ!s`^yc{0Plt#Howh_@>IHwx$4m*roGd1gi$?1Twn zzw2dwA+#34N@X7n{~r-YdM^`#AJ=Y_TMi)%m1w_Ae!AWVlMZ}Ft9Ub2yvqqu&&`BY z%C2}3?BW&OtBOv_k@3Mdqgu%i`Itu>`M8-7`DiAD{~_i7roxXY9E)K|$Mp&IDF?8x zeEL-S7pwGVD;%mQ<0FeQ-``dKFDUn%Hc(j8U)F+%hQ|4E2KBeaAxj_k)gd@sNH= zqFw89UQGWgWygWHKKvYZX-{2cgiR{kxFqgivKaSA}y_l>bW#%J$F% z8t5_4{~1CEep3~^nh^O}O^E(O_H(N&y_e_Sz(3wTZh@^9amf8q!e(_I5b#Wv1NjQ5 za?McXx|0z3+(39c@<+G^@d=TSJ%mVK${qL-h5rZPH-$K<=(Jp9zXdwk-y@#v4^TeY zZ^3^J%MG}d5aF_4K&8K|{C}_f|C2Bu`onUd5;+dAoIDRh_P>NEUkH%=c-AiY$$kTJ zx=s1B|DgXPglJb^V}BpPI82Cms|gYQEy8or?-MQry$a`Dwv7&I{8c?1YdqHATG}vx)u2&j(+|b!aGn8gjMMG z0V$8)5=Xp06C&OybZo?@5dtqIY=NyGA>>>~i1KYCg#P|Z=RzbM`q2Le0cmg^KSKi3 zLp=xNYhQ-~@VkI5QhXlT=SoI?A+S-~mLJZAQWDjd{Rq%cq~4zkaP*>eKe{bOJnKmx z29gQB+?S2yIM%$puWuZE3QiLC`GMifvUMJ$5HA>B>|ZS8cL^KQ#GUfC^}j7V&Zp11 zm8(=6wXJTQ3)M4F*%qKSDrd^TO4{Qvh{ zgb=zEblv!+&T>-;=%F0CJ?SRkZ#tf^#4z8*#AFWMF~yT}2GVg%Uw|ixACMCGX{Y&N zXiMVP0DeCBkstG-`EA0xonHfxBkU89l*Pt-)xLC6X>Cw z=J!+Jc78oJei;bU{Qih{JHH6VpACu^f#&xC-tGKuz+4yIzRVxTdd+VLnA!Qoz)$l4 z8J7vt<$}o0?-@0BW_btV(fsB(`27R?Uc{rF<~`fNZ!h@8Ktz5ycr?Fy2S1+S&EI0R z)BI{3{GNdVg+WAqxp*``{vO2WTK`^0WhH)pN|b%OgWqT1_k`j%*v60Na@qMEMP+f0 zrJc?n=P!2oZAHeYSIplKJUV|p4t~v9$#&nGU(~^`0TbGM#g9<)^CK_z{Otn20)%U) zvpNzl_WZ54@f!|e&F?Y?zn8$TT{Ba3L@#mhdldX4@Mn3MzUEi&;CDZiiNF15r^{RG z;FmecS}T*^C_I|q!w!B=;G4=nG&4mqXn_M(MR8tZi&*gZ|7E#kpnp!Na+x4Hb+QU!2@WLsQ`0V!Z>ybCOxIKIs zPK&&7-=Mjfw4s=qVq*6{Z2Z#Xj>~(4M!+389rT!YM#>^tU1`Pu=`VugOzslq4q@xI z(q#Kwz2AMjwCb?!AUiqD#k)w$dpu3$JuP9&#?#vGp6d^voF*;K#y4NQemTL+7k;t+Fa-}_wNbFQ@5n6Z1<8Om1P zGp6ZmW&6&V%QoS+9UpbdTIZi&4y+OGZhbbEn!~%pQ;n>yEZiTSDQngnzvJIOaQCnCl3N8&-e9_PY5R=LGVj~nbL5@Z$E~_#*ysDksS^YGD$VD% z(iA8Ql>+R}wrrO?!4rWX>@xnmdf1iKxQB7ks>fD+7nUe_2i}3@#Hs!1!N($fSxI=L z9Z_=r(;fOkTcnJD2R0MT`TOzqIu3b`?z>R-MwyUgU%Ae<<@$W|oW(g?VpDw&l+JFS zw|@(IPci;t?4iwD0g1_W?d~d0b9YVkBrG|nH%n>4lG8}Cf9Xf zRSo~aPrTGdQ1b3=p54-04&iR=+!jllTw^S48aOxmvURb-`64iIuCJe*|4`<9oT+u5 zqleCmhUb5JV%9cuu)MjL=f>Du+69i5HehbOcs@2SY(xhdqYY2g=kb?`;Ki`!hP6Y> ztf(Pxk>=Sd(Y2cYh5K^knJig0&al;R$kcne2=0l^6XGFEWTHOf!TYUJCXc_-ecph_ z+|oMfGOGoJcC)s`d8uY>Piv|1Rvv1`vitS!H!kdvcBtEML+ruW@EqD|J%CdJU`Mbj zza2eB*hhV_3Z1C@XTX0v{AbQ*tS5(GQF_I!;i-cUTXq~C>^%?Rbd8jd z=V|wUe*+gc8Be?s%gA9~XbZHi6zA5Q|MPYc0G5+7Cy(-wwQP)m{*QqLopR{wD>>4n z@|2aSm6)OM*83f}^;gb5+H}87au@ABJOWD_Yixo|=B!jxG-sQ?NcXl4FwZeJuN>Ug z)V#9bt(CMt&u`mXFn*OW`G@;+qV8h$8p|4KF&M%h0AC+#(O)KtobGET?QO|YSpn-<5%Cjy0g=YZCT@crasN{ zb6m#wl#c6DztMJFo}F`i<*pHj_OwcQMJ~m^eVMqUdte>&FnPGu&U}^7>HkOWIK}eM z<~;K3!#Qyu`^tgy@l?kS=v3?=w$=$R0dhY$$NatV__m2X{J0-HIX$o3r_Fi8Q9Rra z&iF_0SPlyao8$iP~D^BCaDTvAGT^tXy_|K5(Cp_(6PMF_+bA;cZa$t|eA%f_1k3L$>m2yK4*dHL{ACCJwgW%r!2jXEQ<)j% z*t-QBc(DV&)PYw!aQ-f>9r>+u;QZa5UhLy?(Vst@gbx(YDx5W$3yJVMuy*A4t_qLf zop+3W>5b&hwAUaWA2<)S~mE(sqdfA1#!W*I(0Y*67_B|cK#2gL9- z5yAo5&S@@v*}9N<1i1@C}UdqY@t@ih*m#_@xf~T1C%ql-$3*RN>7M zA15Am(EmtP^LKx`5S~Gpjl8Mw`N-!Wv~Rh`l)qIkUuNyyS2v3~e?H}};eGAa zmA@S0g1-vvuf-jI+~uEi(_G?mzB6vGwJyYr@35_o?^0e=u@qMq)-SE9wvy+a1?sST zYx600T03_jf62Y>+#(*|qaFXbw^zw6{)yf1{cMp>W?=hGS?{8*S#I6Sr>;Y^1XkND z?AHzA&OC08WuYkX#MXJcuj5X_MHS0dH&!iGH)V29gW9xB4&2Tx>lp86yzha;D;G7W z2v+iEj&MdAnI_{m)Gu37ftwXAMeBcGJ(8!)dhH5^{~5MSLrx%&`#7K#{ch1FljI%X z$y?HUho5QNIRt*ol8Q(@w$)oz<=kKmcD%8Zd)}8vaBHthJ6@~FS&^#Jdo#LDL#hKa zsBBwgi|gOyWEpPfm76iN3aM!Q#-QA!u6-%~mO+e;qc&y4+rQj(kFD}5ZTs%jcKW8Fd18x(gl?a*)_*3R2?9(vfrixX|mMmL-%QEXmT~xMpD=Ec@7RLLO zbsnXTFRACvp|m9Go3XaGpq!X!Qz8OxP!(})YW8{1Ba-F2~1*@8h zdR)7@NZ+F?8ARfD=(2!R>`>gagFcp7Lh^;5EEO&i#$CRTAE;_FWyoa(s{_`0QKFbuJ7Q&@!pCSCer~IEH1b#^2uM;A@BY-ZX_j^L5 z$N2>JLl+W)X_#=iDtE-n59ydM95iX|#|Ga3=}_*e^asC*fTLDg^Esx=c@M)iU#2`a(kRoks}$y+Qd)`M_WDyHo931^pgH{~F;s>oQl2Oj zWzp~%hq}ti-YCrmS)P8g% z{u1Ji`nIM2Ovgt)RaXBp>Om`A`Y(h(^U3;W`d}^V>o*F12FQGPiEmSSwjId7a^F~D zU#Xgd+`6oq` z#;eyRPn>Kom6fEN)b-+b#@X7JrM4%AQ6y;wXXC*Err)_-G9AZD=d3Q7;tcb<1Yvw_ zfTV5KcL@SHhe@7UB~9|qNO^|oUUIxX=XEv`r4z~dpa`lRGdx=y3iC@%zA!0Lle_;) z?8MY9Id-o}oZ8)*P;WV3vPH5&l4nl6f|KV-wqO*uj~P=^qKx0! z<;{eYalAdsYYXGvFh>5rYya$gbf?;R)XN0GbUa~&&&C9)P~oKE!#??PJO-XrJap^v zuLh^Lq{N zc77}S;rBA=?EGqM{5Xfv{Qm6Vw+8$;N77E`?@#cs^J}n`HwR&wpMlIVe^V5Lz2L{+ zWVB-#AD^OQUDEvubgU2Ubh_M|X;1flq+1E1FdqIIq|=?|;8)_d+2F@=YNz>CI{5W~AL+t)_-m5px5>ee-zEFvx6#4RQ;^`tUz;?)Cmj50 zz;83cwbS`~+`(@!_=P|e#)GWJ`L#Rv^?)Deu-a*Uv=6h_$87MUzJ&3N#G~`q?chf{ zq%{cFPV=MPrJdgz@S6joFdqJzrTL9;CF{Kh-x)y~cbeZ&(AoLD3Zi^ah4J|DXnwTY zMbhzp$OnFVforGvl{onQ9{d)7D2ykFNAp|k;P*E8MG>x@=C{bfZz_b=45BceF?ck; z?>YFriiUzNEA9|19qq{M<$VVHs8?Y;=i$-(e&OJE6#SU3b~=CDe{ARX68OyrQ5erS zJeuF%9Q+ofS?v-e(rJEO4t|-V65|4YozwjI9p7FbFM{7Z#fw1mn*=(0{-)aa@z*=e zZ-s-O2c2nqAN=@xfSunB;8y~=FdqK8r}@z?+n&F-!B6*HAQLF2bo%!L9rkXEKO`;rO$F5a^m#@)e>vb6)yxzf z(W4H2du?*&T3z!q@M4z>2R|(f^3m@j9dumV>M%RqbO)UWbd-yBI?jclv)9}2kw3~M zjOSuJ2$tplI$kIT6i2!O@C&JT0@Bef>w}KJVQ8mczl9f;SMwmh%QX=o!}#0-I;0uV zL5o2*LnDfYC~0+>h(8XxLnzoRyjS62x-1vVs>^^^Q8QSG575VGM?Q2MYwdKOK`syL z%p*+GO`2xy0{1C*)_vn87frKB&%SRw$I4d<^^UDQ8^03szLJftJ7eK6PrM&x;?9hm z(fdpMmvk?zoU-ye)ZA_&&%7BW$GT}{XKdbl=JR~x zl4Gx=q(rRUp6=$$Oy;pV;tC!ucr3#7W|@N?5i#RFz7Os*cOl$TlAOE$Gk0BSondWy z1dhtKIowTU!>D_9Z6U36tn3N&wTCJ>91Y0k+_=4$ZGySnfQNeq z3T@$RTY9caZ{oB0q8xFWC2L3gCXE0RzY7oflW#6Yg&hiCEpe~>_J>#LNH2d5sjF?k zPdAD4%=8MKXHiw~=4tt*J@NaY^EV)@k#We5T=`q4T}4){tdJ(Qbt{)Q)J~oze+>Z1 zVtmbMs>AQ6HP+9A`WFD(SAlq%Nk7yiE@9WKn8fO;hE=uvHmx0?D{HLljFNnFKPD^Zj-_P zU2Ax@1?_Z;b*|xgwg7cnuRqyRy?Cy|Lw(nCh?nqAI_)&SE8t-tqf5Ym@yU;IHNO>j zxAXf5INOePn%`1**!hLQKWz)-n2m(Bv;`+cle& zZL{sVL0k{pE{~aIdSSy*C+|BLk2|!iH|ww5IUdL{bM|?8Z$QqyrS7gAx9G?@2rO(& z5fgZG!l6CgYM(y#K4-@ERhrr74ZY%UY-?pJZZ|z=-b*+y-{0;*DtXdY!w3c=v4byr z2Tn;jey0m}v$+Q?eN_0r@SMntX1g=m)4uTh!+$K(zztlP#`O31JQf~MmRD8)RB{*F1`Rr^tMBT&Jx;jt_5bB%F_@WS@IuMl*M{Zz-iTv2Wd1a_~>P zUE{y#Fd*9}q|HVMw`};#ftQhoDEv#ulIE>A)qG3oAl$>0-M(Pdp*{aB#M#|G!*{e( z)E$Ox(6&-{ds)GP(gm}A*J=0;cQQT9QDzM^zujuhK~5|&iU-5uEhpxhj-@2-2J!g4 zex}gW(0b~`=V_<%(wZ8cE*)?L=b3wpj{4P&alDm*yVL_mQ;(TB11~xaP0n&H;{7No%c%Y@vz@a>6$N7=6UPC zM3~PkIY`;kLB7o%6T9L&%9^PS|HM64LfLPGcdy#*otr*qOKh989Do7lQDaQBQ`rg? zM%z(xQF74YguZBBnoPfBe=79(exLieEAOq?F5x|hltZUFb(%T*vLxN+{h5;PZQk8y zxR0;*Y!Gk9Hst&woSx=s*RgX{Y|*CUd-tWw`1ALBFMku|aiOGd#U9OhCAKT4qt<(n zxjF?s*7PO&vdqCUhR5_C$dhS)Pz(NpI*_|xe0p9A)8Bw*^d?%3`}m#i;Y-(s1IG;9 zkT<;6J9k8LaK9(uH&dmaQhGeW{)>2dbotNS=i2Btc@N>Hn8)Wbw_q-uX}W(y`wLoM z7*AweMw<-kQ00EMc}qrHVm}L&ec_4Ha>7IVIA20m{|e6q`wd^39rS)`?qMO@NpPd#ee9aXtxML6I1Vr1w$b-c5sI2y~3Ug-IJ7&%Pn^vcXao&HD%FHktci>tSfaL z5k6YDQA1H{p%J_HV!Sh^ezeE9;IqzIvb3V`WQXB9uEzUw(SEh#PjHSpmJZUmu zkIb8BJt0kH^=yMAPm2yEYs-`4%4ytJWIVu*3`mSg>;Lrjd*88hZ>Zhbqp)t6@G8d;{N z>rs5zX0A$Td#Xmxw_}@q?dA)ox=)rzv(wE>7Pj-2qOW(1!!1&KkvrE@jB%$KIlvpk zT~FXXFxa!{`2xAWZML53K7rQnzHX%FxRJBylJL?o?ML_Heb5!PDce2A-MKGg{CW=~ zkO%WNN_o)I9U}b;_X+r_thTb-it zNP7nQ5X(B!P&Z8fM9$ZAFC*_fzekT(Xy@f(>_zj|n%QP6?u`9I?C7osT2bcz+1{6c zS5>5GpSxwb1PBRYM8KPSBSwOFAt)%0UP8PEM1tVhxU>*LFepnT!H#wug3^kuv}odr zbfeha;L z>Z`ZD`f53K&iSgU7c?6GX_^1c=TOQ}TLLHDJ-DhL`{iA`(VBdvBicE~_-WZNoJKVx zd8!zhBTw&5J+`lRS60qTpY^q##O3vWic#QBT)QzMoRtiF> zPu_=Ia{E1f;h<1^<>522c2 zdEf%9ExeTVTs%CdJ(e7a)wum8kxpz*94xtLHdXAd47yro*{yNvdzUee2xoP5f6XF!yj>&@r&ojxbdSN{-}q)$irV` z-3<=bAKRec_2rHDLp}UM1%7`f5N@dcA^ZS(j$58$!Jn|X9L+L_=fAl5hY5a1i+tnh zIG+FF<{vKjSJ^D`C5W&{P@EjCJ5~kw%LpT4~g5T+X{1WK6 z0D7{U-|5-p;(9}OJl{+^E?^}*@d+mqzXGtnb*C@$#Fu;G9ZAU;u+I0ypYKVZ^u#Ac zd7V)v>EW;N@H->3%x|J6exfJ+Bv1S#PyL#2RVn{u55F@q$owwy#PbcY;{v$*xb-(h zpZkxpE_Ug%k`-EDID>h@$m2T(A;lX zJM#YlG=nDN%ESFOpg#tHW<2+b(~k6MpvljXIS=<+?pIAZA?N~Yv7+OG9%!vrbgiHV zS=$vY^)HpK_VheRb-m^n^f2qkihe-Q z!!2z;BIO@p{YJ%0{l~2XicSdrQC4ph1mnlqz3jJIX3c&ztSG)ICwjGvDx zx=7IHSie=Y%>P__y(xmhpRju4+dj+Bku?wF-6@LZ%rXzNCcWNN@}FioX?cc^DsFQnYNpsAZac8|%!R54K#)$c0~67FA!XmtHYYE-kBGv}9oez8Nm8 zZ$R?85pi)Y6~Mq!KeOuUc?++W2MUQCm~Q@}DlFHM95Zp)3D$JM9D8Bad>4u%kIV;F z(o3*&FfyCB0PADt)y$t$Zwc9WMiL_yA}cPO1E+Cn&6%TT&*PFVM|LbUU@>e%cy-8< z5=bue{FW}R{ zE{zjsR>}O*9s(uKoH2BQMG5M7BWa`VUSr|Zjg(55sMo+Ue_q24*l8SfRD+VEBu0Z0 zpYU;*R*&)66uM#2;u?IsKL(Jnm+!_TMAS>(})~b3{+Wbr=+)yMj`=kUuWk^-rtE#*BBYDgMjPHZd9a#T z&@N@bV7h4TT$G6#mG}mas-iSZ!VbnGsIlJN9G8y8WkZ<_;v2BO1shXyF~4(smoA*0 znby!ZWaMSReJ=+W*9;DzkGHLSUgg?9&H?V!f?*T$glBrxGop-XS|k+Pf=m$WrhmBQu(v!L(g;QE4>hZvWgda z1&)ySJA`u{6#kjA$AUka^jfu+6Mh`@5QLZ02QAtI@TY(dqx_f^Sz$~77t()JuHm8n z50ggybArb9!1pRFC-+aM&$S%>pE%{_9FjN*_>9jYy-wywdKhWcV(#f9iP>!_i+>(0^X8WoCW-9ckd~q>uC;(ntCO@R`1o{tL1`iIY;{1>^%i^+)~+ z`oOuAK5*x%c(4eZRrHbmX81$EpQGZ7>4T=;C>P(d5O;pojIm?fus(%vmvZfw#$SWb7{;m4fFy4mfAgYLmSJ|?(XU3V88 zUfOf4oH==Bn%~TBPF{QF>~R{~a}qfz=~DXi)rk!mYVBKrFr+N1`CZepe278);e`9i)^qW=LT~fQr;IZ!;D!?;8Hw3X8pLas8 z);c3T?R?!{3hhkG4L&vVHuBL^&>rURY2fq(RAcF5iMq|xy>t0Axqj2E-jlUGM>dM1 zr^y~x`B2}(3_pz&HneM)Rr_S6;dk)AWdb_`tvg$AbEgXL<4HGWu2t{;X6XMfyLQg` zwDYSU!{KM+N@zMF*OXlbI;gHJ_>*yA>Lljn@WgzCX|*FS9p^nJUU@{$U5S^0i+sep z0hful9CQON?KIvJ1ekb}BbJ3fvDYPWG~NUFZQ`XsUxG_Jjn|3*6K{S*&M7G$rm;5O zM*KGMcs63X@?xs$!h1O4;N=*2uX*qqfj1vv+G+V-MSv;au830~eGsS1dj!8t`922m zD}-sM>zDIi6Yt}QoLjTJxwtf5Z=^TzS^-dwc?cy}6jd?wO(AA0a!0A4Ktl+*I@3}&-F9s?fpWqJ8* zs`2_k|6sNIZxJHW^^e}*Gx2rPJ>Zpj@D3Pw5d-gs9=u&W;QhdZ zhqV&6eE4b0x56?IIr7oH=fRr{ zyr~FheGJ8=@xJ!pt-#<|j(F`f-cb)8)>zo(W&787L(o1<`E~&>qQMj&$${WA%li!Q zI1W%gK1*x7b3AwlfcF66wbSx(F9{QG2k;_bA|A&}jW^qaw;a#t>H6B+t(?%iBNZ)W;~rmj(YL4_*NR z#}Ys}E#F=b-f-YWz(f6w#--&8l8qPCG3h&kQ#4S`EAem^I#M z9=tdbQ6JiAyi+}R4;%U`1GC1v$b)wc@X&>Ar}5@{`09En$GslD2JrE|pq(!J-5&X# zG~`QyS3d;5$Jr zAJ1eq@pkr*ZF2ux!DrS- zEATk35RdZ{E#C#;W4{jIqH6=5p+5WfRVrVO?R4a0y=uoaysicxu_{B14+3?e9QIH$}i?2VP0v|t~Z?1z<=&4!Tt_0=p4?04z z&pIeI&LO&BZ)(u8RjK?{wDu2Ty~91p-yC{5`>4Q~Ad$2ijra0B>^RzXn`o&k3*@TIoKijojDBbnD;*fcij8_8UEtmy_~66D{$3>)X=>`i-GI0Vqyjn#yn5{*k-FJlI$zikuY@Z)`#rc zv+idIxvY}?;^f94R>6JR9>mFKt7E=ZW-Y(pF*2F`xIA0wvHiV*w6{Hx3NlEg}herDoE>V zwOal$_R9{YU01I2yyK|9#fmXUt2DgfilodhV|6f@-|6q$e_Jr>kH(Yzk{S0f52g)a z9gNO1m$ct#o8Fr`$i^1O4pTNHGicwo#E0nR;s@{ zuC`?JqRtRjc!pWS;uJ2c_>a(uY!zJl@@T!YitV$GtzCh>p{`S`@cv--+3ms6qmou@ z#)j##E|Q@K%aRkzLtSHq6uY*{a^$AM@gJq4@o~`mZ%bbIwV{U|g2s`vXd$dA*3*Sb4y$-)yIU4=haQ+-Ztc$w zqD_f*QI-VdlOsbmNvklj z=HSG;4^p$%evqnN)gs2L#;pZ*PfHwJjklfw_?JVB0Dl&9C@F;V)Q4gQvRGDr<9(QzV1lyX?o zH+ZVh3)2iLZ&jto6E*r>g^1zUbA^zTXLD8_{#T)KJwnSBXu)V$jQLwTPFU?L4Yx3j zRkB6Z)UVpZ;tt}Bnw5v&6X&%);?h&1@eoovfwG-HTrT^5fjXlygcIg^ZJ@4lqZ5aK*NNuFoAF zNcsNp_wC`wLtVK(nQvJ#QYh;%njDXnjVy^6t#7&f0?zyDp3O)OPL^D_VpB_MY9J@+ z6Qh;y!ORg8-`@LKMrW{BpMJrLiXpjCsUhqafYTgNuH=!9+~|;rhdPE_7~C*$#p=eV zQn`_psl0d~S|W1!yrTfC>@!QS*6`p%SeY$HoShfA(|ujA{;OF}<-e#G(ff9H-+&fJkA{!i=)g(;`u zf?~c&J*>yYb#ItLT94TroRK)_n!GX%e5+ipx!k&Nr!-27RB|6yD4oP|4%>)hP@ zVZr~l&5s8Y!||LwH-C=ckJ$W}up5r++}!+q1b>#zZ@vYg{J9=}&dwc|?p!@Le!i5) zPLeP1oOcB>{uv|Q{)rzvch7WO*LI2#KxzKULsxoe+KgyN{_kr7KI!XlvG~RK$33-f z!Efyt53?`Zk$%#qWcrsuGyP*CeO9-16Q6qc&F4zu(RN8Y(kFms&_00|wnlp5lOB4i zho0-97kFr%^Ti-p-W=;8Md!lLL;HA+k;+k?*H!#g_|0>^-u1+PuHtuy_qN&Z51_G!f<`@lIn(;RWMJ*hx6(hVZi<^4Zz*z=IPAAagx&lY12Hj z7F(XtFgo2qOFf)P!r*G`M%L}15`0l@sDadTabl4;gN2;<)NCJeQeC|OpYy91-%y9` z(q>jIkw&OaHjC$7U5n&P7FN3sPMT9AlW-d~GZ8=RH&o5THfu~_m^IIy$((dDl@rub zEsw9!1u(L6424Arcz%mG*GO6ixRH1ojE*JL;+iEmB1X%=PuEClTld3seCF&kZBj>H zU9->*Lp_h{ky&y<0Ka#Iqw;$}IHqg_F&OiGL-=HAn@GP&@%@B8_#RU6 z9JBpHl?@?q_-1|C{c9Ef0(}fnzomaF`XPPf`vv`B(ngJVT;D`| zj{VG+uK}12QC4`kk{<-eAM(wo5BhHu{bNN_ZpLq-kHKvh{Y?4(DSR5m)U$8VEN$8}z$wY<%wkxt7? zIl~a@N&07C&vyDq_a=R$U!sUTc+dtWu{B2bhDH%^awdbz2jxvtqe!I zTBYK3`~8KYg*?#bZ%ISGw^jH)`p73mANlZ}O+Bz(P!9=)Lx@Srzl1)@Df-np@_P&9n~d!7SN7>)t2$1_h<{QtmF4Psw)R6k}d(y=d_ z&aa3<_~Z*H+RMi{I&^c_d*Pn=;^6b3)y*EU==5WKzZf%mwEEm}>^-!bWhVCbi)^<1zmPp}SU1`Q zEObI!(beB=EdbA*g(a;uV*Ip=MsQE%d9#-^)YNP2Z{uURh^TMf_Pt}TZg+)>Pq!~G zpKdeXb}Z)@%{01?5HDRH!BouEM>wDPHhqNi26ikAA>!((kFf7^Ow&%6!`ny3BI10_ z1Yh%=K5|s)clpLQ=8QAHbsxD?X7Yc1#Ox#ToKWn~jqSnlDF2=2ga6lG>~_nhrTaFU z^>^tnyzgkI`+>K=lp`Wte-T4n!;;zG_MS4bbW}Vpdd#u!DUEpEg0uU}DYVv$`Y*gC zmB0>#axcw)dp4&~eya;LW~y&O1sCqva$>FAw{FH(ejmdr@c8aqd3dPteJprdUR&U_ zoNfN7g>Qp5h<%O&r-j?C;W^uSMKhyW$fr2M9YTH4FFS&#{Yk`xq8ZUH^*xuuEk*uv zKjTZMgp#GTvFG^?-OM#{@a35ERj#ylwfJ_^yj6b7Druy2_-+!&65sO4S$TM*_!=WQ zn#Tr<6L|k`bV$yhAe?<6)3&6F|HUT(}&$2Pai4t`Vw>hF$b+fN*9^^{KR26^hywoeS(kG-jf@6JfRgKx37ZR*~3Di1HO7Hvn^35-C! zMaSzFEWc<@XbdHNC017;E75sJGjX(K2=}p+V_f3k>!Jms3}P=$Uvzx(0@feeU@)2J zytUa^IKigpU?=ru;hf0cRMzHUjn>iN)3>BrV~Kz%f*s>Bt}I!j@;JKgE$g~^!8aadbU ztkCG$Csm~F+4=pJQ8%}wekMj~cT2i`y1R7j+37~h#KGl;46?tzBiglD9`3_BuW|^! z;|F1HbX;=9CVl^j4Z-OLF(2+1vhDb=2kIXM;v1=~X4WQmr?t@1p4o~$gM;I`jk`>- zK(<+74-!dcu_l(a!k(${b|3CE{SI5#1=?Cug}E;uy4g3fjxoNH*zISuKN#A*2jP)d z4&Cez4x8MTIc!&Z{$Xor-?m^^ZblaF$bThvy|s$R;@kAu6N6m^;{LVb`Pl7NRPK@7 zKaNuf;(=W&Q^&>MNDaUq@B?#8l9`c^uoke2e%{gVaP#<=IxY|X)W|D{yzWC@&6PVl zUOm)YYL(n&=NS=sCN}3rx%(`2@E&*)u>&1h(GzSLtl}@*mvpplMrk70gMC<7NFHv> zjiN;HM+#m&baSAz?spx`<4{M=#9p{#meyso`Nu&gM=sllFZLt$Tcr#@>{*Zu_Cv z0<^lx8I5x){BI>b$n@_SbPq%B8~>58o(aJwY&XV)@~o_*!C%~m zUVK(^LZ?4)ZuD0C9<-j4aCFEi>~}OcG910QyikPwAvPFeZ^rt9qrtKFr4H2Hm-_vt z`%+)7BLCLRifwCB1@X4>@@>5LuEg&fGZS5pH8Ygx3<<xe>hXznSZEI4?XAS5KWYo8Rkh(SE8?~t2 zIz4M!aOmHDbzAB^j6RiL%qYOV(Ak^I^|YsJZ1m5GS#w*QuFR-b-vi#XM@x@ z4COoTZcZG$s4%00@vAeJ9{&DDe++qy5}G{nb^S`rwVp~fK#Ql~lG=PKb$uilyQ(7} zqx8Bie-3uhKE*nv@{6~#-|w;l6ZYo>PU!S!!(wizHPl}^u6#&2rQCVw|h;;6H6w3Q3uX zv?g^$nYI1U%~r5D*zSvj_Q^i_4=2@?)s4sb5We1B_xpQy{W8!; zwCiCw@9ch`Z1;m!4~9k38>x|^MGlT;h*2hocgDwB(efBeDF>rB%hboKkYMt7^bW?Y zNu3p0*VK2z>_f@?bq(5*mS@O))YQA{0w2S(q8~M^Eg<)csq=BpNZ$>SWb9^{dTiwG z%&a{hH3d3n1!k4_x2l`K7c@oAHuG0K>X>gvSjxN8$W=R39Xi#G%39d6v1k9HhvM?L5M;neev)NOpE zX-Y4; z=GUZ3g%bF4(^vTFHuLI zZcSg8sFx!njk*kuusUyV_KmO(-rKzN@YTNx#MXQY*|z_w=>^!IL-u`ZFt)sW=w<7; z_92I@#Rc0i9{N|6o!id%mk%ZSwh$xIZU58?h75KdHT9^VDQ!*O)+N*D2y$NwkL}*JuCmrZu=nwv>f%f)h@z5GNC5 zzGIDepe-=eS18*`ONW1Gs^eNdL(TGyxTD=F?t-m%G`_Fo_wB)<%RA;U20h`t!+*2! zPfh*MfAZQ`7ya5<6ZxH4u)Lm{v?4lpmVr9QnJ7bRI;_aS4&TtK4)p!_+Zff>HC>hw z+Wk?}gV9^~2l(ez+VO;w1?MIuYX8dN)-jdhe`K&{x z^PM!ZJQxisTj`)0b!1%ZrhnMN)2qfs&y3zz#+Fz7ewsddlY0oG!?UQtf8x2G$%Rk%w0%QGztis#XSl@=(gyhInU+VOkw zi>ZO}ma_9PR({#0$FXyH@`o6knA7TPzN5;D2C*JRjt^^6gW^|YjNB7Aw>UYpftran zEgKjSmcOy4oRZ`_XNh$IuPA%wm)f}s1fx<5Mlr01;aHeBc(&-@n=o@9VOz6W#m}_e z-%&DYOX?S~hsvI5ySoFj#zW^0ZCHoVV_^KFW-Za{LZY<=J780LBCOo+RC%os*5wmL z`Q<2i6Xst-c$XED>ib4C`SKR|l({?=!)Mv|+N74)E?>Q}IJq2cjcs*#s;ExBkvh3~ zN6K2Y9APZ+_tf(MzYz=f7xFF5{C2}Hq4+c}-f{DLDD7&YOXK^F{*o&+WYMnHoj!wa zj79op_&i^N=^JrLr@xX(igvc{^jU&`zGg=})6dZ_$;H=wI}-VaJ?X=Ozrkh+TNmIr zlRt^e@8PB$t~>u6k$x?BrE|y94%Z#hN9-j?{293Xh^M@l$i(>1uk((hU9LNQuJr>% zGdrS6%twc1_H{s%W6in}wA0OBa$MY!M>H7=4Fnuj9KjMYH z?KJ)EU;IHkUU&Kdg5R-=9^m0G@bDK1ets*F&ioQW{DB_+fr9@@3Md>5nGDDCDctf5 z68v0`FP)4pH)tJ0pXXJ$(+?5pciA6yWIXrnkWR*P&uLBTU-WsNg&Qv-@OIepOZqxH zk!=5q4ch)G@S-LO{Ftya)PZar|Dp-_qz`!LfStFDr=7BPPcb<6eS)m>EbE@68qL0BKlsB&lY+Rm zikJI_yOOx#4Kr{2q#1cPYjz!2-%!=Cq~10#7u%*||Gjw&>*vj>!N%;udLKotu9>-@ z{_2@^ixy+=Wt4=wUoKSpwJ)5z2xj?<7ROAJ2?iAMCUlYZ((Z&A! z#djw%a*c4QUy!UR*UBm5WM%y_MkP zQinQw_w#Ou(0)yW;AW=PS_oC^Di4*hf)v~R3kGo0Tz7Fz^`h%*7T=)v{a4a!OWw3g z8_fN)@q4yiom*t7-%;STY~SJXBTBgl_BQ_<~_#2~G%*&5Lr)(Yi#P zX*taWFx0I$1_7qlb43MfF3*A*@R{w0n-F$uRBWH!8?k%Eif#0*G{bD%%U0c`(?@u!Wku*CKl};2 zOW^x~N4bYwj4*}+H$oq{#q_7CHB1N>@*o^gBEKxgPgi&V1FIGOYjp-9hgv*C;;Lrw>`IjkrhN2hJ2W}JnE3npuK5#gf4$^e0Q3 zeAdHy72Z?*j;1_VxGCBP^e)N)IeyG=$Z;Qi(3=$fYx-!1d_E-pcKXP7hw^vQuTX2Y zSRT;C5$zFlt)iJeJX5X7f`5ecEYvULWw>bn(AQK&vs~dSIp=4-n?U<#%d@DM|8u0P z<=O(as{-QHsI^0=uZ5)NsRgT^D)cC{q0!Z zgrfh3@fd7)=2ZAv^gH@xsCW9n+oEXh6GwW7qJK*t<@{KM|5^DtLCH6XJ{p1OcfcD+ zy+EEQeJD?icaRHFR(O#bR}d-2J+uc=uizK$AAIY{H%FdzM)^Kecz>pkc+vjrJOVhtPUUn%+p`oP_(_&!wO2kGm(yo^gipP<(VuNuyXiy!o$#41mwE$^sISGco)|t&h0mf7`bI_jgP@@#?oSsU ziZz6aev7$-^EBaIVNFP-7mPa4@pGF_y4fMe;#yfzE@$N>|4iGNt ze*xMz_*g$|2kig5l>ePDCk<9#`vC}2-C81w(E+pC&qGvaQ$fG@O;CA zrNg8paXn%>(faAc_2g*Cag4`K2k2N2pbn>;=n3^eC?hXKxE>CSBq)XJDZq$Qk1^() z-WBVbBfDY%ns&PR-`^!0?_SVu(Zs}j37%{3KGGN_ge$~<@?jVdZnW~X$2huEaAn~- z7GE4Z-h6Wrrd?3|7!E%hS3=PhF^OLUnmoLi-xORXUODJyT-uS3ZW1mNZz}LO1{C4S zz(qddVTf?y?Eua9k=kiI3^gvi6~J4MFyawM^gG=MRhus>yM6hrgkMDj>yte_w zx+Gp7TpI5y{5J8P0p2AD(@x`Yo@C->o$TPTJ!rgv05kEj5YeQ;6d%a}U^4N>0S%*j(l_vd+>GwuMy$I z8;DEe@tr#U?D9sSbiVJ^PXGK{4_*QTL;_*N<2_m9z2m{F>n-2cdhzyn@S0J%DTRk= zhK+Z~gLfs?OSU0QJ1rm2ay8pa<1p}niSk8oY5Dr2e=#}RI^FQ&(yx6R3_dhT0EGS>18z@9wy&kh!A2~3;5bHqxW zi(-|Bn-g-EIV%?2|CaCWRAU5IzgF}s>&TJJg5B?L@x^XQ44kkG;UzAsK#6dffq?ZD zu%X62XeIBoe_hnkK|$o6mCrS22n)F0wpA7F8YM!lK!DXy4Zp|BulH6_WoJ(IzYPj? z`NJ9ecL!Qhjq#wctbH%@v^~eC{KHEcTgr;t_ixQU8mxXR6^QJ?j&Ki^oz(uZ*o(4z zNpEz?DR+&`!tQ3$0;gc>@hRW%Ya2i4@Qn@+&+N*{d=({tmG?H5q4U|ulpxkF^iKZB zUQgi2f2)@Nd|_J>%ZUWLdikJB|2IGbE}BC!Gbs&nhFa|^>Sq}enIJLD$OCV~?R~X#CCm8C?3~flXrW&V~ z)}H)@FSH!LuCRChdq+s`SZ9hAC!#*^S=Om#-|ML5;2zf5p>_-F=6qZ`_rKDb#2Gy} z#&vzoHm+U3HJWfdGe=0$<_Jex?#ZUp6A{C_Vf&#+dC5WB5ss;j%MkqA?EuaI9Ya|B+qW)L$nn*d%P4}TxQKgVX_jLUJf^>E|6 zser}1gyU%2!8r%(gmbAp=q~|ZJEp!=6Yxo!b0pGC$MidJaZj{0@U>(7W=+5+&F5$G zufWA``|l|FQ9*~Tql%`EX?ZdT%;aaj+;fccG15^%15rPH^820q{wcq8s&Mx=qwb%C z@GSSOJ{7jwzTBkKj$3ti`_V*0>i`y;(j(QFqsAMmbWc%*weK5H=DeEPs?hR<|4Djd^V5uQ{uUg-#$ z6N-l zs@e0^tO^q)-lpV%jv@{R6|3_yU2*axNzK96=dkjj0fduWoE_=q_)d3ReL$y!so}gw zcsd;E1+#Bg4r5yJ{`(;`1p4syBI5Wk=$NNb-K5aj)@i=~I4E(fz z{|vvGuO1W6#qV@u;(COeW8wOB63BCt(u^7!WTg+9ZTvQZBioIcOzZ z)OdRv3@VCP5bGO6DgpV|h%_qJ_HDII#QFxU73Ff&*ft4)Y_&E2-i;XRlsuIM-kcAaw7@&^y$Ruqy(NERlJWZbnPj~8 ze88m5zZm&G^eB^p->s=k+M2q4c~xCqacOmR@tV@gwQOx!b#Yl~eOX2E`m)u<)um;t z%IkS#UHRG-!Qt|T^0MOPtE&L8f&-MVtyx#TuDp2px|K{It*g9!ZRzUbiqf?!R+rZb z)KzQN6qn(rvaYVOYHj7(+lyCL)s~ePudZCXibGVO)Y_{0s^ZGEm7-+C)Ros$>((1~x`T+9M6)RBPy5jHW zs;mP)*RESxT2{ZVw!C;v)rxWm5Amb84D79115VyvSyx|P3lHQA94}iQ0s(eZLS!LM zAqmt7Rcq@4JPfLJeO>wLm7Gx!mYQ{?Yegd>5F&ht36*>_PjP*1=~^JK1v$0l-~>u0 znpafbfl61_SC*~@^MWE#6;!Xjp}2ZgeNePfrd|Nrv%k>IFh7DufuR;ZF$)pdSqE`STetT1k+D^El`FxwT1fB35~?djEa5g7#=G5c zG+L&vu6)gMXmgI6(}A%C5Q4Pe(K-9_%$%(0^y_wKy4^FUV_cpEzkneahh%5=>bY@h_1py(7AF-R z*RIcrn@d@2hld8g8;Y4nzsxDwM;9LZLU!I#a!iX$KBkSu8=V|cxLJEHoFM28D=>Uk z?mPOq&4ZW@*1<^#{c*Vu-+MsWYgUyO%4brORdQLfr}z2B@#(8O6T6l4u_t2Fmv*iw zoK!LU2&LMOm|S`N2bQxI$x$?LbzRW_E0MNQ%7l~Bm2&#n?oU29^^Tr(C7Y0bd*^d~ z8OnzTmDIm{u`~sGIpZV#RC4bpT?&p4GyU9(y4+6fffbX4v?>7P8n|?Ryv$DQIWSMFUxN91Hlu zN+{OO`T3B4T;YWDNfl$eSlYc^6mL>la$}c{%SEM0*-|s*b*NPSO@5ZPVW9dY19ro} zk6$vNrDoPrG>}{8_XjuUi?Rq+AD+D6eJww^q=BVob-u4%nPa+8U{-qan3SCor}U0i zrrlc5@Ib>`NMSDNimCABC%dXm)2wJ6bFUI*i5|~voNnN;O|51*agfpKqeRPjzX*~4 z?|u_+tsXy1{%6%4+Cx%3Xc15U!EE9x@swcX1Jy@~8qk&uj$c9Lp{!&oE57|L z^seP4U-?s;PF3uPKUI>}w7eoV|Jb>3rL5#rUE)6OvR8kk*EL#i0PErS!uSTf)sk}} zeyJqm9nX2h>=YKiv4yeok7>3HirL;4^F4|u#RgN%?8<@LG}E^Ptp)Qqxbby=^x-yb zwA-W}I?t+NI_LMFjBV3m>`!?kI&EC56t)o-hic|DN%rWY%>EC5occ`=-f3S97G1rt zQT>w^morM8&1Ku(F1c1!D+i8#-uqL@g_Pv9>d~o-x?3xHDqcU&RvbIe%Jz7ZJ6!5B z-Z|Yb!#5rI$F_c=z0xdYh4)Fy-V2ct#Oq%pZ?5W8m*)Rk8=FJa^i(|Wb>;Vz?5hat znQwJ*Ztp9xpQ!pWKfmhB>+@5zcn{GsI&Bil%T=j7QNq%ECzaA5u!Qx@MQ*}l;JC7p zon%SRd!IcK0UoooXL!$((DR<`GBg;;MbW^@I_Yu3@<enlbA?ibls(g(kv%QTot2r9=}zIH zj7&R)-5Buf$+hK}d)Jkxu-w@Yt#a0w2raIYT*QYzX|g5cqK%ez^U|g}_e;fuF$P ziFe|eV0gHzu!$k?6FL0Y0F;<48bJlA#Q))E5?iYW8b~*Vq$-f~b$U9{EFnz!i}g5? z7iyo9pfIJ+3510_s6pX?7aoNr1_u$I%r*wa&{%k1NO*fl_=S-0XCYxzKvo$ee3L`M zb3(!uA>p5dgtv!;_lJZ#Lc$+}gue<2e-{#-5Tv4r-sF(*Wg+34L&7y7;rm0vPltpL zg@k_}56`WRNC1stv8*K|{V5}z=O4%R>EVZYcmg}3hvRq{`hym}w3sbpNiY}PQCrF_6R=IO zq!p~J6sC#NmAV~qIR{>OXK`J9X)U)c!OsmTr7OtLK{nS=vn02u>Q>Yhtd78I7>qsT z<*)_9f(HM3ffqJEm?wg5q-0SUj=@5|v~qcIeHpAQ+z_H0-e8d-0~!oXu&0s5wRlyz zk4#K8>ndw?GcFltVUGC$3oT(L8$rFO=Lpjq)v0`K>GIWN7eonU4ZO3mzM>eDqP6_z zc5d7QfJ5qh++I0aFUa+Y%#HKmY7z{$m#6xy%-Q0^9n5KCwaM!P^D_*&7 zZ5i64nA<&IiL6{(SGfYj*VR%itTZs0t*N^mwkk9sV(Q8&%2%vI^$07q_i~uWDS_~= ztVJ_%jIdaht*NGXog1a=&{UzeQP`NOR$ca(MquWQ;#UG1uv*~P`1!6g*paHOu%rCB4P7KTk}-i3QL5L`AYQH zVsxos%Wud&NnIt3^TocZb;Y+=)fd-Sl-3v5`PM8)e_OYfH|-s;ol`Qp<#O~19~oas zBG=WG7vJJ7o|9jEUD1L$NG{hcjcDB!~IybF;fes$&Y+R|Fm z9^B$dE|*-|f>>Qux`NxtxlOumT^ZSqSFT%KObNh3z{JqiRlum5$;xZ7Bq^q9 zaE%3c(6s^}ZYOBldC|`}R z=v6@>Xv}r!E!2A7+jjyHBsA;R(l!$+E!sF}BZ|5j49ArD|9n4+=5g}XG#6(q{2H+q z3HLCTO5t3_*Bjwp?Eg_XkFgwbG1wpr3!fv_9x|rIix8Hx8M~fbBrYWv7Dif2$OVki zoNqFIXx$S&k1?8)hGX%OMQ)+M6OM(Ps&6JZF-- zjIjc80rw+v0k?u&RO${reiON%=UF{`Ko7qTSH2B&k&9) z3>3-2F_B(LZV852a>0kY;SygP$t~66morvN>186G=zE;Ppzi~6G3h={@W}VM?o$1U z9-4E6m+SmTVR00`9c@Ey1^7U2rQZHO1|KNAiZO@)=L5AX=L5N`8N+`juVJj3To7GP zZWUt<)6o5)4Jd*DvKR`7-LMN$}x9pcwyv=7UG zW~(n<4!6EmxD|%4zPzEHWsnwS8O!VHSO!I8jF=l`z}z9CL#If?Db#@jlcnM4@6VHl z(*k`yFk>2#7ChY=P6$!r!wDBvKO>Wa2ZNC*BUDdFQqZROaLR~!8QbH;zYKlWmjTra zo@NBk{xWD%Mtg)Axz{bsD6Oxrtz5pYz8r$_Z$7jhg@`bV4nI94pR9)+a0w2}1O9}< zQ5rp$;w4%8S8(Zo2`$%-IO8$to;d2p?IQ419lqKNugaC-V_!JO;iG5fO~9 z8~E&qBYb3qGVuKq{$PCXBZ1a>#$(|78WF+xw4nONBF(@z0eOS*orEx5O#Wg46pSwi zrYIZm5PfKx0KTjcd|v?{wWaYG^wGE*jL!pnM*EVL%b;&T2)+h%WE#Va$G}J9b}+tb zAR#!S53AS!zS{vubQ}G*8TiQdWjqGHI=x&&KM-6H80Q(~xnGAP+UeO2I7|-$50W`- zGdw7>+DP~ea5M%Q55dtxu2Ck1?dXivcHsfm9)&puDFXd5@R95U z!!>~~yNpDn8Q#nE9ca7${Hs0d?3r2r_MY`~)M25frgJA5V=Q_I_NQg+$L3gGKi9~x zBZ6nz7rl8Kip=Wlib(bT17a^@X}b+O!!PrlVNZW?tjGTD7t-~#m$7PcY#Qr-uaWkD z!!Jp_%5&X4o9=CDy0__}Cw}+tys=}ME5i}5irrF&`eVL7HM?RN-yxxWyrO{<*jasf zx#aNhoir=$MQzSoBd_{hS}Tv zEd7Dbqkf6wAUwh+Xu8{>27dHXmYNBesJ;mbVYavL)Fwnv;M{enC$#*jW4V7GC}H;1_?7IH{@EcrQ`DZc zPv+_08!L9EiU$5vlN+>GM)DwkGc-glJ?26Sb~t~VYR2z7{I@d|<#&kGpx^(W>{F4> z9ezw)*HK?4{YCp!!4K_Ajf6L|D*!<7q)TXDYAM`dy&t4V5KsG3BlBAsmP$N-0+bc) zOHqEpDINij>2)AX>85~UgF*{>XrF2%{xFU&E&xN?Zup^nrr<{b<#z@}P@QNUVmuUn z)Cj<(@N*&IUxtL=2?>7?67C5J%Z4IFJmHTD35V`G+!&I+AtZcXNciU=;kQG=ABTho zLc(DI-V6GshJ@#agl`E6-yIVEkC5=QA>m(zgnt(jK7%lkn2dJ}+TR*9ND=>pZ6w$t zt6QMSWJ1k{@sF!udReiqRvd@qs~Un>Lv~-XJi&NY55r{{owJ0|IshOR zAp)IlFXh%|!^ZS)SVxCVt^AlUw=Nk5(_mw%Zejyw!yH>*T8U%3x-pg_$x;<;qa`v& zT5*T1t-v#E>*fYFaWwT`*}A`%k4&vNX)0D#D?mfpy4uQmA2ZCk{NODe?Zmm)`m)ul z!1lGpIHy=krbMbOog#)ky}GormNyBkjpYr+%YDK;2>`Jyz7tr5;StrOd}QKUj+2V3 zR-<@f1!m%yFHDAOxUrd^)iq#2NNqW9=+c$kkWUABIlGBuUbJD`H%f;wkW;9i!v#&W ztH748SPr8b44JSK>bn6z4c^vO6ql|ptzE;h8jUDo3=>|k85Wfwg1HTF9T&>#)#dzn zaQz4qEtU5J1qCGWhqoS30x^V(cJQfj($zBNa@1GCp(sKS!T9b*APyM`AI)YA ze9yxljBf>Sp&JAq1K+cV3C6b#GD&cRkKzq{)DHsmgjU1h z&j*0J(g?sM7<$M>Qs5bjOdh=GA`IPymrML48W0_LuD3888w>;k_(Ip0uc03PVXy!k z^#p88@%>sl82zu-mou}nW{8vB|N2aH_j|m+!20r!&|XSKc3WP>L*D5fRlO-7y?QRW z)pMf{OTMuA()q^4Sz3&{usy%Ysl|9CUz{qRXV-1g*qG>}RlN%PR$q(k>a!`ahfQjD zS}Z?lY#9?iX3UsTc)=yRty(@1eN=KWdqnlue%bYnUvX)EIvW_)G1W zyUBOR^%;Dz`7PSPY&IKbX5<|?bpIr<#hh;UgJGUt#(obPpDy>|5T9FNz@S4_M- zDcN?|(kUlfJLx<(Uv1Kvzo9`+@qpiY*ybV(?|#9uHae9;N)x9>Sw}0%m~uF*kU3kl zw(KFtBRC-{xd`$)XH?&4zAiNL6Q-hWHaa8PQ9YOFvZ+zLhLUP;i*||?=_U0!N3r%V zn)X-uA(r&OfhX0mI~vtds_k#lsaEw9?aH=jZ>mv=_AnnG^87g>ddXk5fp3UJl zwDEY;O>@le35XwcQabrJ>*pa$+6g+Zzb)uAcJ75moYM3o&#G~Mi{|IuS0w<>e%s{h z=ER?Pr#-yqLHX5qQ))ps;kt|CD&Z$9sU00^?uBIvtzzHROpU}JD%B3!_fJZ!4m)u4 zEBPTh-AXAe`ME&*=OW)#Bl11&k5b2J((JjDA3!;e24rSO7uh}xnaRDdP=W1ZJ>mNg zf2<}gn5deZ)>bn=XYb&3us%hp<{gmNJ}KOs{RHodvkph9X7vr9;I{aco%=PM7wnNG zQ=g4duCxY|^VqqK%AVR)4HSRuoJToT%OF{0b$`-ExlMhen8eFUUe9_*^E^0~*(`93 z;o(&c$Ifk1_N?n^c%ebTorI5A-j~r>a$8P;V;doOm+ z9hB$w*i(1xgKJV;cPcoykMaJntd3d`)`s#+VlR!F=c*W05jn3*dwuLPUb(xfcM^*@ zY5i6?UodguZBq7Mt>^v}qq<5sukG5=pmXC;4YLl9pKnqhMc;lFeLO-{&NnW~(xMmr z+-vS)4yP6!-F=Wsm9jrN_@wvmUDSUg+J@`{ftJt$ttYG&%d$o9{mRemLfJ(hwm7JC zlUg+3<)^i+h1U6THSs0Pc}vYxHBO(+@nKCI`eC#OaKdgO*_2s_V++l&D@oq;Hd8g- zOORxug>Xf;C0E*y=T% zsDoXrjq}G*Av-7L6a1bEIeSk@^wDVaO989&*(8GA8U$?%K-+Za%@y8?TNAbct}*~8 zR~)}JqIxsV+;7$~Zbs?A$C?3mJOF2}usP%O(!Y;yUjR<7=(^s(7JHaV+^<=pd0kY~ ziNgUnhT25+StJ7|)rfSm_re1>$=_BY?z;#K($Osc2inYjDB88cJGB;P8+p> zf(tz44!K;_W!2F~ZHFnnB9OkhA)@Wx6s60!bz?){AlgdWnjPXkj>&E7a&Wm~PJVl$ zyO45e5*rL5>wrB6`?yQ+G}VKh`qXk;W1!s+RcuoErm?Rot_ zS!~G5P_o>W*MHCA3w~>%O_%66)#@OrCTM$zOh?GLSA_cjO2b25GcS?#DGc&TC2^XD zoH;alByHB1Q+C=GZq{=0_GsT>w34P1#^`i&pJE>Dk_&Qhn}Dbj4~-wzg_0WW6yuu5 zY3hrS%zZJ8ayjo##W-@gOW2W{)CUesa!gPyVzhZdQManBFU~wxjjOo1!j`SPwa@ER z2fHRV?PzeTj>bK_&rVn{p-^_ZN)lZ69(2`^T$Ch2PjZ{=Jav-uWFnR1R<~%*#x0tQ z=Q*m$c1bn$C2=aueN!d7`oKW}N57ICV*xD7dV9!nnESBu^qIuS1+2|f;;e~>#%Qc& zX|HrBeM9n?G1qyQd6(DR;(hPnM+cX7Eb-bKOB?spv>qg_DB9`11L3@#lxCsJvH9*$ zo@!{b6;6t0Tg|QET%ynh+o^m3V?m#YQ2*{{5VdJv49zvEc}-O)SIJjkMc=*glh0#& z>oEIEl~zjTl$9rz`<6`p=-@xoR&=wedyAgX7KK^Q$CmXSZ1Rpiu|zXXT9>d@W3O+U zGq!8U6;W;NxlcK+xu0x@%{U6OHA!LiqJfRjdaRjfFcAmt&rtv3_x7jH_(Z$)S>_1u zvDo4?v%P?~P&hO*LecMO$=S=|-^4F-*)+4;az3_UM!vPD$#z3NsJL93dB|((mS*1% zKXd)wU!eZDp<6RWQz@$&(yHNi7igy07*DUk4J9S4XLHzRevHh@Vf>C)4*DZgJpKC` zU3Y!9ew$`)jL%=fl)flyyVujZtC4KptoPZ*HP&m zIces5m^WQ+~R&BZ~I)C#GQdY9M5q{!vnE~nE3eeW zrat7SodB6;l|%AOdB!>7v!xNg<19bHZ1 z-Q;@O%)J)Hk|uSfT21d)^@b~>PVTdQ^L|g5TmAL9*X3WIYvdFi)kg6i#xUFV^eddV zooA_KFHl*^IX>6XRRy!9xKEV$cKej%v%cva>=HnjV|umGahNNHo0SaL`l~u?Co8E} zbf>i`y@RqTRqC{*P3&6No+UI!Mr4P{!5ne(AJs18D81h*5qX>7WA-%k*G*iqw^Hfm z^C&&i-0vUFXAR8Wbe3wxlE3aMYm!uIX=-tOzvII5b(GqJJP~G=_D0tS`uv~h#vFL= zgX%`L=>UxZ3Aq6cj2vdQS(6$WznNrJqmk~+{hQz0KoYy8>s9>T*qMG8OTVeplb+n+ zNmA7^7Maa&0Xni(Q!AC)sNQ$Pl5E=XXh*hc&3=2zyI+`RGS}V&bE}ol>na~Gb2!2_ zsWas+5qi0;QukS>oBKvt%su(0Otd<+Bw>|jqGh55?DO8fu3Xi`^-hjj$*C3n+r~8j zjz3?Upg!MYv$XlcUDvBOs{8#BuBqw^e)jFqkVJZ`gO7(DBYDvq!i)TdU`|}f{X00p z(y!xuSlXF!7t2`M>B#^erq=0PkR7f77q;kJaDfYN5f`TaYcBk+VJ^%B7fj|J)#3=| z!t`M-y!uwcAFMBSAgR+o<=jRlS!}lv+AcK7%Q8m-hNALD3^xM6~Y^dTh&{^SjEH z#Vf5v0}`J#m{euE1R08utZtGb2g2mK)t$&gz8qfu81$;)+pyjXHq}xt=V03GBG7l;Wvk6%nrt~y>WzVe9|9+`Wcfal# zsq3z@>nZQ#{Niu!`}Rlb9n8`fuHcA%>ue5X-dP46*;BJS5jgc#8R=tlUpNz5cF+3J zGmb$cn>FRiQ|qChC83o`C#R{!bBcOpSw6lyu65!saR*b`D)W9V?@*qUv!z*b=3o88 z?YFunxc!V;3yG?$>GhZD?e|5y%cry|&?OO&DzVCOs>+TrnrVtzJyAn*{9}DXF6I0N zMa$l%nO=V*?%_FE-56QoMxQizMs088mYld9zJ0juQ+}ZBX&n~a_D^BIKD6z}Xwnpn zUz6U{+t;XHUVn=8L-ot+cS}@1WvjP=Y9|M3XQkdZ86%EKW ztVL;caVe5?ZYHZWT#iLQqVk4$GvDz)m9p4zu~Iz!VUB;N6vj3jwy4RV_U#d+nDu@I zI~UU4arB}l6_~m1YC}6iXOVmuGgqMt?7Aj$^Lm+Z&pJZ=lG+(#1^RE^M&5t(`me|g zu8kqdjVPyRU?Fs4IV71)yS3AhMNj`|$FfO6J6dp>LFhe?TFUt)#w&3e#F~A63cK{( zFO(VPCw4aoefg>GI?yXfTFMh$zMpwNdJj^}!zt^9dsqvL7QQd^n4b00Y$H_H}^$KBHZs+9OGPeU+lLmmS|@!a%&pri6z+rS>4y2hS4LK zBLhFkk-YwIG7XMg8{kOMfT`yHIgUV==`~4tP}FGe-NOAsca54?>Kqsk4*VIl9uqi7i!kr)F@-(5-rN(WJmvl439LvaiCPc%_h1}|afCsqj%>-_ zp-#W^yRpu__kgh)H>dCZBt4)&jnbg?)D7F2-c&w9~w$M6x0`sz;u@7dWQ~1biR&&~;`kZ_o4gMsv z-ut&O*CU$Ky;BphuzxhCsZL*M({-nwn8$i|zlK$;8Q;kmfz=MI7Kgpn+46|y;`1rO zrgla3xdOPa>9RO>Y9ee=VSnekr!7IanTf)!(cPj8gSB-{EnekB(S?83wsbW~@UkDUWEE;KbSFEm3`!1h_)5V~o;}GiHnIEKQ8$F;upIJgT|fkjKW^ zC`H6jDPL};`VO9AE-P?P1@58EQGHW`aDTlyHVAkB=Ci&!ZdGCZgPW8PF_|g%A$H)in2aJS(gTt^{35agUb4Yz#piGfIO;A=k>#;fM-AA>V?%ng! z8p$OLtKiFV|DtAJErsH=XiGa)*A@E&F=Xg_8;m+7A+@0F{ z?zmQ^_jP4oEpgDS7PMat=@B_edM@SCLov^v8L5>n0}YDfverz{kgn5UI}*XmF{>xr zO`ss1(_>LLCS1njGgaYE)S(L6lTey~qSB`8rKPi~kkYbvX<4n)QQ9=Uv}n|LnqFg3 zo(NHSS$cWGjSrL;hVldymB;k*rm-bBzlwF8_&Pk)r1a13LO0@maHI86a%2bkFJ&U#_SUf!cI&VAZdgKrT%>`HCR z>;H3Lo&-G3V~9O^x~kV{`C~}mqt=?G_q*zL3GF7N+tWUyHH%|5YPs`tNfV`A4la}K zz0B=85!H8@&P}a7LC@LQE;RZTJcY&%0drKl!aaYU(rARK?f$rt+K$Gj6pV@jPK@-P z{!tF6?^eGxWgNHP(m3wvJ+`qFx>V3OW3TKKEjwf0QN2|QQO6Xsfnhu_%m#*OItGnX zCUOJIUXfe$Gqc**PPD$psRll`gVQR)RQfdoi7yHc82Bdue*`R;WcwViTRkIA6OS%# z^~~+RKATc|{G)fkB95<+_3q=)p&iN|8iDg&piRt#sLv#FUbiI(7uFNW@I~mpL+hoq zYc8zWH(GBMI=O!HzC-H?3zdA^zOA}6ztTl*Ff=&-Nc4_F{;Z~$9S+~C-oKn4vm?ou z+Jq6M=E1;d@}He?)wfm;4L)&1w3wI!2!4=7%jw&EHg*T!XFz+3QQP2_8QiLer8wN& z=O4SHlk?3OeGM23V3u=hGL3MYH+Ah^T{2Z; zys-sFp74M#Quk%wC87SmcyV}q8Xv@?pS`#M+C|_VN`9O3X4~lrJKp4Ficv|FDMp=4 z)fk6tlHm&v_#$o-4<-MWm)UeWj?2h31AqHPT=gyZ{?*Xn z$FJG~I_u}ys}b@G>zD1aeH{l`ORk!urtHglf%pa*(c&leL!#Y7@f`=H%dQ#tZ2tsE zDYgFZ_jBF?;_dy$*@{dxum6urAPa7suDFTPe|aWh$7}wH;CXG+H)rE_eB+-4f7Sy7 zXGK4le^%ei3ldlNVKZN|O|TONo5T3-p;ED`jbS}Dfv?A$Bi3WI60^*+&VQ(;ux7JQ z+4}pMW4`c`$eM`SFbChuC;Sq=2;(xP^d6p|ZtsZ4nhiEp_m&QCVj)%&iVHeP#pw=R zld!e*yI{#$mu_m>d=;Y&1 zcwq$gu5FGuHNNE5nm;!Zz2a09d>#0*pAI)*lq)I9NIdetiATT<!Nf z6L#r|T<4zsFTGjx}F$&b3|4$&1&p8n~cr@T1} zKGFWsJfDvkD{G#wiJGcxdrM=@7=@jet62q{5@%*XJ3o^qaz5pq-m?6 z&F)V7$rjDwUWH#L=QFIReeu#nj%~t8DxIiOwxvxKR2}jY-4u`Yqe}Z+({r*+ts|@`>FwVBqL_f4XPS)C z7sXugGpEu3`CR-zS#)5lm}|k#VbQ>z65du0rCHcV%&Kser#7h>DBwxUb17xgBL`b2xb@vDaIn$jHJXNwH$3$s4$b$64Mc~2>87CVWSK2h0VQia86Z-a2Z(B1I9@bI37Bi`}dxHY$(s1%fmy}?o6 zDt!r>6pb$&ru;|82<0CN3t+9ZC>8?m90X1uqOPFjr*)aY5f#T`#CxgyF z{uH!RDS~#41b7UYiNA=b1z@Mk8RQq}lLm^7bxd#3s=Ul|Tt0)?)I#Pa@WoKhL(P+(aU7B?lA za4F5^?ZTR3oV=9j%5ZyKv?`8mr;vjQo$en6Tz8_Yj;ooE&3N!J^jmar~0E8#1-0A zqjWkWYxYMJj4iY{l#-%>#=6aoLuai8I6s0@O^>3Uc{mHZ32s!OQqq5x`ZIqd$wcS1 zpT|p29qzmGJFjw>371sxjxyt8GI;GKI)g54rMgN_=Cp;Yk{zcHFs?-t{T=ooKhE>_ zOIb7?R2H!wkLBA+lbW4>NR!+TA87HKAO|s7Ene918prBVYSmB2MMsV^PRISaY)&dp z$9ek4WW`k^mwa3Kv6i-oV~NHI$_|tB5iJ#`aALCvZ;SW3E(t4rZmEi9DYtgnke(DR zcG8M^M~8n~37RsWy3K-pt9LcFi|Wy+TDD)O&eQi3t^x1QajEQXU*#P>{bp)OQ`xjv zI?Q@2zWar|B-%y2g1!}=+yBQr>bYX%%>_on{B5OOot)2Hb=8NeIma$ZRwHQ+aQ~t6 zb2dm_va1!6Iu2Zrx)j&5@Q;UoR~K_V4J&~R>ai>7S5kI&>NUVTsZreyonn)rSEK^f z)^SuzXe8WNzqt3qFQu6}$l8(QzRw?txD2mac(2hrPvb(E9**p26j)I>}&qo?0%uH zr;hBa(KGh?H=uuGgu-~7-(*(HCXdFbd^PMqhwr1^m221vcF1xkwEd@8{mg}?Un~7t z>Xj~&4_OXb^5kW5gM7byRQ^!@T<(zv<%vqNGE2!-7AfV*{mRSAA(GCOkt)IG<+6OkI&-%}V7b;7sZl{+9WQ?@{e#=T8eB(Z<@h&X-FRlqNazYBtxH z^)m#vq(Ax1DOaAz_sQw;Cmw)wWn;`6k2996+3ZO5bq7uuo*Qw}&(nXdPV@}FUrP5C z+B)$i{Z5wDq8+}(+bcnnAHKw{Zq{D*5{1lB$7kD;orhe1^cyL3!YxJl4QTN67j5xy z+L`OepAsCjT@5H_KW-{6Nb^aJ-o|JA76-e8ZIyl4E#-4H^V7-d8LqvR=7P3UKHM6} zK2>u`E%8r`ohN;)r;))5Z7T7HrR1JaeH#_8RwW#>)ZTd&VX|j z?(N>*ZUc_Kga1WWaN1|bpKqHDuF;*G$)=Avx2R8g`gfO+CK2DqXZ+OAUv;d%qdJ>@ z<4-G;eJ$F{vC|er&}|!~MLQImR2W~woCzg#0=m0qVr^KG+3!F*9@L(9B^K;QJG$mm zE6OGEh<5Bh%Pq#2&c@lcxi?{-OVqaHh&Y$vIfB2T!0Ufhi{vskx^R(G zYLQ(-*#F!^A3v%BQ<4DujK!BRIVc^1k^G@n5pV#!Bfi~prnd-y6u}ePZCFK_q57C$E zxnwoo+$dyA0$%rty!jsJhzmLHLy|qOHxe_63ps@C>HzO@{s-ROrr$I(`Zd)r7PUBf z#--!x=KZ^$Q{uQNB}?18Ym#shcAM)x>xT2c-2b7^i<4#_*0i0GoFCTo`6m@h=q2gN z2?a5QZ(@!(u?8n+`Cj~29Ba=RbIKyvJ#g}i%k)lY464CLXChPb5pUDuMQZ06VPB(r zW=x9Uq8s>;QUhMp1nF4CPqpBT@z|0n+_EBY9MwyB;f#?QeUa21XU3(NPUQZ?%%x)+ zb}hy$--j(PwsEn~1aF^Rgv6y%ErH6oVDtc8~K|jirBn zrp;|W%P#rp0%-U7k6!C6an)pF)ik_vIGKpE;IYJmxasg^@59W@u71Jq4a7{BW+>Cn zbzPBk;&fEXl&)d^7+S*KKBVi5*W2zG(PBb!Xg@F7sk9_Cb|*edeMG?r_#P!0Q(E7^ zUcn@snPy33hf-SiYmpwJgY-;g)3L;#c~gC3j?0)kV|3xIWqt;5drfLDU-JOY{zak% zntR(BNNnAW1xjP8E4NXu$tOM~ZQwfrX+E?FD=PRgNp%e$(=av=CuNM2f}6|FC_c4d zfzIh+E{{&SjpL|0OLU#^E554=^1cVv&o9*rBGmlh8AEv^gxsfE4%1XsWRlESa>{uS@% z{y40P;e5YmfW0Tp!|`c#F39@(=t)1M6!e3*!q8X{}kx z-euCEZ~M>Dt-MGsi*nLyeBIBa1V(pSgskJDK0QzzOqz=KQoO;pi$(Ge{bD3wo(rF5 z%g%!Z%3h-+Z~v2Zvhx>uj46qDevf~&OLn#fLH#GF9=Im9R~|jKqiA4v-Gi>v{yl|< zwBKfBZ*2ANLTb4ytF}d3={l}~fwh0)9H3hO!?H)xv>7`nla%wAON_@T@aX)qwnw$K z`ub=s?tGATN{4nD8eDq>DY0een6wFQKi5%z_utDk&05#J1@{%on8W-RG>ZxIETVd7 z@MYScQ4-IHP}>nx3hY#_qF!cs6t;7+nVVBE?z*gx&+n8mzP>hvAfMyC4r8kO8LxDl zB`GJ(>EWc!O_WL$xzr3!Q&M15hW%C&y~CuB)0QibYSHfJ4nFPu^tkmY%l0SZHsa>n zlMZ8bZ{2Es5_1)NO_ffH6XxW0$|21>9sk_H4nNj0)8D3An)EXWu6VU@iZ_wyCHt|p z<&v&>3uNECdCnS#n2q*@=`_5og|SnKSi|>4;XHBfg+54dgo0VA^g6E_#(L}`+BUwd zMX}NDEr{FyDshVHb{VhPFJCpMfKMhHw{^hI?4a2J-3xw!Lta3OQMyG>XWQJ!$8FDw zCiYfG&}##|i@JkT>3uo5@{&$1?zu{8#Yy3`9-h@86rtq48 zKAGbD6PF|R>30sA(*<9^M{w*4&auflU*0)rN*^g@Wm7EaLdr%3I6y5=^~>fMW^)Yx zY^OH3;D6`fxb(0tF$Reqa3xRwtDY|UN_?QN$d~~beI6zw<=e?o0|Ld(gv z^eUFgd9hu2P0GLq@4@qpRjl{GrWM@>&$A7zcW>j=ZhVZS_nAhdApA^Y8+53+J57HR zYgH4?xPz@thxy)ct1*gIlRl5b{O9JztDUU(?q3}|@7eI@uBrh~ZEXJdwEymwp1n?U z;g1F}b{-!xP%uZx!@C&oTu^=!+M5)jB%FlH?R|SQwIpW4-0H;AS??bkg_ZzB4My2d51zMIZR&z0)d?FzZ^x!; z@PPIoeSxp3)xR{%35FSc-i0Tir-Ti%oa;`L`VC)UeZxb8&<|MgGO5X`T;mA}G;ys@Bv_)K;Glpvkgxwjwil(&o z-2U5h4gKkuKc+&0oo3*@Df8)OUsvTjaW89Mjcf^F|>1*Vxp01oM}C5L2?#-FM(37LP*IP#JXK{ ziNG&D{XoxxDa?_V7}GjtTTDwVx6PSU8!ttyi;jPazo}MhU>gr?W?(a?RChLO=H{@z zA>23rd)n%5<|yiojQB)*dGjaQb9=UHOXsefY{D%oThA6#T|y4dD{s>tx0w3>V>#|3 zW^eYUe~6m{zyEZO*7YI2R`6iEzWcj_`WN=F%Z#0ElBeAM$}*}8uwE)%@wnIa;iHox zzLon;=Z}|~`X4T#G|7R~S<>t#`n@{x%D4Po?QcV3^V;4nq`P+3Ov7UF@>w&lr};^i z+}oAge-~dryH&a`Xy(i>u1+Kt}UGq`zJpH$)1vN8w6;Em8==IJ^z~(v z<+QjH_ks(-*8AN4%sSFvMo-1;26sJKGu`%_fc~)BkChBYWlf#kKk-fjuG{h6 z3_L%@I}iQHz)?wkDo8p!M+}*WI}#m`hv)jtVa4A(@O8{SbDue!_I(@GuzdyUV%}eO zYWZ%oV~@gNa@yPbB1dO+jzt?j1j`SdFf-29r1{1eb`XXUnOiXa<1Dp2*^VN)eHoVK z7JSoWdM3Wtv0pJ-{6qbGz%txH;YvXNk)7c^iYXpv)ON=;(LO_itFD+HI*{z{)T`qIv)z>SvgapUm-H-s$9xv4&j z&X3Q#41GeJ_=a-=T87j8p?{(#yYDY}5H+US+&F^fWT6X_>CUawBDkw|-PmrlY;t?q z6kD3qKesWob!tQCQ9#eH&Va)*argn8qFB=K0Opb{_#Msl$&(0q+LT_4Y)O^6;`mMC zQI_}pPvRyqQC2*H&!=OKpN4MFn-2};w7h}e@s?jfPnj{k=DTA%iB{O8+I2mmmf(aS z_{m3>RX(K}{^$h-pU|m0lMzq5a+EKbpN6Cxn5JCTTz1BilE^I&qSi;zZeo;E)a~u5 zzF7sc=gBov39Wu@82`k|cyy9O&EypCrZV_E9is=hFdG(=1a2`g^dglhz6QG=xW{*< z`J4rp>Z@g8e>BG9u%zQ$FO$Z?T|8hL3yTNY0t}pj#xRWaf&<&z!?p`*qhQ@dpMgy; zzh+BKVt~@5q`ibwx65Lz0M;)~fB$?`psz?~6O$}>ttMfa$uAkh`6KFc6#QS+_Kkfh z--8shWt@qm_UD`k-1VMnONn`WEOMHhIwy7OB-O6b3#!IzEZw}jJtG0j&L zToGh1f`sV(DkAARuGP|f=;zE`kQD?a1)yw6*YJ75#rYW%D3_?Eb{ZPA2GMB_;pf*c zgzXjb0omaFDjaqIai?Wy@XJ>T!>Ewe4_Wc7Nl(>$dq#4IJgGhfCv{B)mU&W%TtnL8 z%Cr9%S|hrZl#2e8hBprVuxMa2&gl#dUU~$x99|yfjc(snuxs8)NFq*_KramqPB_9` zWC4u9yk5-7sP8Rf*6gRfsmFx|z^-SzGcfw*<7+AeWA3wtDUIZN+8c4)-~wrtJZQam z$m7u9=dViB=i%msrAKH@x^Z!aG==TU|3OyEUI>=eU`e>~)nSPZm7jti%r*N}8bkB> z2tmE!27SIq{-Ul=w8o7#r$=2jkJ^AG=XY+`Y?-a+)9%Q|UeBRymNvWdhJ|Srg&+#`!_ie_nF(%Siz*+(;x3r2Ke9V&o`?&TpKUpDg(fol{y=0wv%thtx)W;JV z`zK-S-|ZM0d;sSa6QTKrV8@yeG_oXmD97-~lE_Dg2!utl@`S*24SFBPgHhixu_}u@b|&>WEn7ns9G~ z?y=c<&%@E+5eJ<|NWT_Ae<=$#Yo|Dt-MvoEolnV#rGpHxHP81_&@ID)B@%FFB7h!_eHG=CF-1UjN zGG^~dZbP)F2ihu{s5}~dR=jG<=;>a-sqhD=_zYA?kJH~0mzR9tpHm2`VQ+|%D>&st zgR@^@Qx{ChOXMr&$04yLqMh-T|A55W_4y%v<4T$ukgtqu2Ci=v{(SBV+22`8}gnYC+3kKN^s>ZF)7>=#!D<^r;FGjGimuTt9yzQ%&D z-wpl*D;bg%Ysxb0$^}{8n3!P^{}y$HPmOj)>UwFX=5c?bHEcYFUC~Fh>+Q#2eWkA~ zKBC=Ve?+^{eH2!(Zf)$$sJ@$+Bx{W32r?9s5jCjNyb12Swc z;AVcHS==U^+*!uL_*~EC4Bs2oSIo8Im6)qvH9sG7^)1+Wa|Px#sj>C!2CW8;#|) z8q;A-naJxSczaamBJKPee&Pb@^l?1L*T16iX@JlC`(V);)5VgU*Jf4hI=IPe>XS@X zoEH{+8_(fC{S~#N*e&P>ytPaG#Rvg4Gyvv1&b&zQq}T2l_~gY^O~%Oi zH6KyG8~ic<7TWi^k`!xZ(pdVu?}+EWwdU-7?Jw)Ne;I_k?ZvzcJ6)K!1le@H8+`t? z1yk@%IKGOusMYO1*KNk=jd{MfG_u%|EjOw!p10vqEuO5oHaoZG-rpGQ%+xJm(E+v_+g`_U)O(SCk8TY%%^4JcUl;eoC5e z%{&FSFdSN}9lK2}pfW~L!ygT66(^O#p21fWAz@+%nC!vlYQG!Y_bX5ty%X37557UD z#oNh8_8Jj~{^-V+eyWdZbL{l(i(Q&zpNJd1bKSeJjz6juVT7K@p2Llnqp&tVr$r&W z#C@vn<1egZ<`)t!mVEVqegA&g)uQ_5O5!dDzh}kvK>Eh9U4HSkvwH@9&sQ2kW`4cT zkeQ-^o+YQb4b2!EvJ)+x%#r5HG{*mElGJSaZf6bk@rRBM+na38%EXPFORMfu(yqSH z^U`yDqihd=PJ9C@JZ9gNZ<;jLvKV&0uzg{DHkl|U&2-Pe_Lr#ctv!m3U|#7{MqfSf zvzH9{zF*%5xMyI~OU6u++nHi%o@iKCz8kFT$XC%{VYw1|jVyzn7iXWAk}#t1Zz&pr zE;;4G&Dw)5{*6UDwuM!h+M+`#G~wQhncsV%Fo&1Z`1c-(S}EDoHT(rf<2)%AVTU6Y z(jBI7{M8#e=PJHGv^${{XEi9_p7qJ!rJL40-5osj+X!J+|HH?aWc4;sh0 z=zENF8mB&|QxtBcr_~ACiO12H zb))t4_KPs(9FF37BlY$Xts=e_6{+877j1NEeYB&eZe%-+m50j~?fb*|L)&HUg}+%8<6qBV_LI<5afOEa5VmM)YY87qi|YX z1xC^8QnT(pDeHPzgmY9!;sf~ZFU|!E3D#+o!+Q^#9ruRZi%6@0MO1}ebg*XqP8`nJ z{wC4ROU%MPg*d}L{FM^XcJ$q)oWpeHW1CByp5Nv&H(b>wO*41qUAQc;yJcNq3p!D5 zS1+lH9`0MHAAjTs6PuftcZEH9?zK1Ab8FYw=d4*?zG6lB3j6g{RjctQrz_XmGu;{4 z)3V%InHibx6duaRv{TrflQrF*j6Y0Sjz4;v!g8_g&PvNmmsc_ge=vcWbEYlKSeQHS zT4sr{E(}w`ZDUMhrE$^(B~F?s#Y>Z<1ZgskZcdfxZ?}a$!BHmGHx!(XHFI!~DGZCg zphrPW@T1^6r1}<{9&N&3GKWsX8;AE|f8S^%yqTrw@NN!o=6^da9e(kcS+4He?jpRu zF%q~-fA44{J}WCk3YA}hm;T<-)o_PlM0f?_#6wzS_@TdVGz?4eVf^oN5WWR?WrPV| z0bcQ711IRAzjrh;e+2U(o$@E)m61;Q?Rdo#!T%N^rQ7l1JKrK&|5Xqki7zyLbV&MW z)`Gml_(t>cNKc9fn?ga4!eT=5$FOISPWh<~WTX?lu=VK={S|@XM?q_kq%W53M>6HN z;gz{G1jCODfgi^e2f-7Ka>!qoQt+1!M&h5qJ_a1Y)88$Tkxuk2r3n7eUq%>y6#PZO zk@+XGzayEz58{>iUmOgEpA-T=iOB#ac+vioczK>c7X0CsphsbeA^8#3^OMZUNGE!4 z4dh7-_{gK+uON=3cMAXe$5cN3{R|oDl;4e4JW~u0cNH8^7@6O}yn6Xd0U;xu@-GVH zas+(jQ83LPncu}0>G_2`pc4i?3XYGDgujIU9cH381Fwwq;77sX+>!8?vb%NsqJLZ( z3=VoyLf}&vohKpuf*#Ty!;gZ`$&AFG#{N@>cLGdCdhnyLX(8~_*sD4`{S8DJ>A{b} zE(?LbjQv4}$2KY8ah56QQCMaOd?x#=4xh#0NuLit3d;_G&t?)-FtX_Nr9Xr-{3vWj z2>c8-PKQqgn2hw`M`5!<;AgQk9bWKfRxmjDe|ZS}${N*9=vqRu#vq~M_4M>^I z=JGeJPiC_%dOGz9nbn2hyD9|VRqQbxUdYQ;9G^Xq>#Bf{JPNxeB>y$+H9f!R&)4w$ z`GH*51biZYZb<%Ic3jVI2Y`&xiTcy9e$Az9fk$C^A^Gz-Jjt$j@`y;@zAs{_C$rr~ z0(TWQCnWzIo}cP2o;ikxy9##cN6P+?m>6AY%kVU}TgTj>FjW!UENIxAE zru1guGSUqnxe6-^DZhwash3ZUAS0df|09s8DBvTH!WM_*U(6Qi`EkSp`4@-4FA0HP z!b(TLFA0IaAq4&gwpNGNIQ|<#;BN|nzlm)gf&Zou_?tuEZ)T5;fWJ8eepv|oGPXyD z-^S@##`)D8$h9osBagyv``_(-31C#!z5ba62qR()sHq~Ikf;$fCV+@S+Xy&B#3ya3 zrPeyx1~QUmoFr^j8<8rtE~u!urxq301_VU~!AdQ)>I;^(*7_<>eFAl9pr~=F{=e@m z_ntYK2tMC??fdr~n0)tl&hLC@U+=m1I{v>WR%!p6;U0uL^LrhYrTLz@kQfqi$A4UG z)c#d|#2x)AN54vRYW;1{42mil-pih^D({LHAyMP_uMw|l{}01G2zT3rM8eTe;GuBU zo@Yw^gsl$#S&sfJv0L*i{aKEF($Ph;=5YETI!$Y=r=q1%`&|+ zJS}&;Xm#{k#XQZwO!Bu%|9*XK^_X}O!q-VN`?tB`I_+Q0H|9F}^Bw*9;$f{{I)M2# zUxw$84@!TE$D-W#c>R}h&qWz4qud9xbCE{57g;jfPp!8MnJ<2&!#^ALLGgVVzr~h2 z^`nTJGF+YbCZzR!oA1l`^BZl-eBWG142cVz^j{!e(cy<>{klNT3k+4crV5ISw4Qgt4{fiy_i#?yb z2#Fs$`acw-bbQiq55nCxA#tgrf2o+L^+(J6xm1QXm>D3=rRG9nNc_n0|08jZ_Fo5$ zAlzm7d%k|;UGXA>XLB?2@5iE1`)8R3;clCdxWduDLR_fzi)4JSkl{tW_+DXqM|f8` z{;$GI(^dJhj}O9~@m=fry2`uaMMzxj_`h1*n-Slu9sO$^{cFXOTAzJHP_Bl3FClTA zqko0WXz29IQB!Fgz`nNjzw>s{(JMOoOojO0-_h)|GF8L4kd?|g7{mLl!3a`IX?kP)V zzT!J8o<8%g!jkE}Ajfy79QFDu#m8?#Dx<;+di|G@Cs{K2D=nFPOOO_2ZZ{VaLzr*- zWl5`_$n@UgX(@NV|5ENbUiy@K)RGxqJMvH&<(~4=tNiEp%XB}+lIedu&iX2&{8w7C zdilPsC;QwL?b*I6>%Z}BRG;@@n^bZ^I6Mwy?O z3yC4|QzyTFD)ZYbF1Xt!B<^(d@3fuKU)=4u-!1vPy!J*`K*E5-k~qyMW(_ujIo#U;Si!hgdS> zbFG(Qy1%z%y7%`Qta6W7vPXrBka)%xA^%zwczvPTmp{RgPj%$)IdZKdCmngABQJC0 zpEz=dBX4lz=NMapXH3`C&)i=*Yix?s#Z`4llk%k5I0EXusPq0)P@BY#utvrovwep8*}o^s?LIr8m} z{IDZ$bL77{@&Vr5LB+4gk-zH5(;YeK$Zd{%og?4p$WJ)(Zyb5MBlDZ*#;~6&aO5&a zKE;vi9Qis&?r`Kyj=a^8-*DuQ9eMD6CblYnM>z6iM?S}qFL2}~kXhgOz3V*8zuO)6 z)sFmYM}AZL9}bQ@%%|UT-1~Wbm5T2nkQv@u{K*qHi{rHXj`V-4nC$3(&ynXl@{b+) z4o7~!O|d5t4K<;Z_<}6Do4J{k$>UH zFFEqtj-10x)`piu9eIQ!PjKWj9l6PoFLLCY9Qi&+UgyZacjUi1@`2vkLgjafBhPf? zHb=hQk=Hx&Q;xjNk@w3pxu?P(<;Ycz+~CMpJMtZl{Inzg&XND($bG!El#0)n9C?f* zf5(x}b>xd3`F2Ns(ve?tWW3JVGc3A82798M8=mOM-*x0Uj(oWzFL&f89Qikn{GlTs za!_V`zUs);j=a#3f9lAa9r;g={DC76^47MhyiRcB?>h1i9r<6sY zGN*NU*bn%%mgy}I>-&G#@=z(?BR-&mHsshJdlBRti(ekr_eEOXEaeA8xt7&@;b-F8 zT0Tj-uM}x5tNH6g;!-V_OZPQmMTYw$;ul)x8Zu8jDqh!esgxfVA8DD@JWs3_2Op~9 z$6-GY>(jAXo+{-h#n-hwP0CM+x(xSUh&IT^FukI&CKa!%kEha2ElnjgqNv5#R5#Vm zkJr>CYG%jl6OE#|r7GPLZ%#JOs!zmgni?9a8f!&St(X-jLru#(F)Ps$Pu9d+=BEiN=>CZCzCuaBSGlx&Qr6V0hOnME_GYg@qut3-=vsG4mqo98#y#Os?HXT_^(YturC z>3Q*{Mp4~5Gd?q&NW_yf<8!L&leGdG@y5BcjBt3a zu`yBK9IsC{w}_gi#yJV3qp`Y$`iP%YqL^rGNh4YJrAX0+5Do1vO&h4(C~(mso-4rxJcQ@ph$ zSsza}CUvSxQYgEU(w^+2MrPQ_NH}&3tty?anlCjy@*12rOzS*jIy?uRS*R{8tsirzJBzkI0%vE8Ppa7d&P+3z*4*jJP=>{Z|l}naNbE>Cr zS+cAb3##KS&5aoxx(rfPHM0>;I#H8I&Pmh?RLOX%sxh9dMO|;4nM^kboiKV}?5j}L zsCX<$S?$;)P(?kv#5~Y3HkOh|CQx}@FTSPmIbX8UCrhBwODcLBwEY^&jG84g$6HE(Y z>Km)m@nlOPUDbkmkBZ!!sA)~Jz}Yc+a%}>Q(~?=kA+v+>m9!;lZL)TrZ=FswAfMvs za5O~{-4+U4CK%OHw;uH9GTvUNYtn71uT12uR>U;PTFaWJnn|N>Sd@~9W`Q=-)QtW% z*^CaQIf(*DHm7OZlCG*r#2cDt#Zyh`7K{VR!YIMJXh<~Fq~^nEK{b7t29MZRr5oZk zRgE5PA!nO86AO9 zb~^}VAD7((y1>>ndQA2fGWn(_@jFsOgNo3Un(y~BRA=X7b-;=9Xvrk9nk1|0+4eBl zn{tr7oYg}secJlH7sd<2Y$cq-h_Uv&ZOhW`xTy+GyQlVjOIy`ZJC^nAryV=Hn|7Ss z(NsCx-lgPMl?%YfjDrXFM@4Ap>PLU>HfGN5-6FmaNmZo$kwI{Ll}|-Xz`1 zu>?L)5V{MqsO2T;hS_FFYg^|k`5R&8Qt zRck%G&a9P_9o;3!4pD+2z$?sKBHJ6Cls3hflR0GuFOhebZdWE0bvS8md%8 zXlDv(R!Vkla&**-GOy#sya3Z5WQ^M@h1pHjeE2XOWJ6Vrs+03D zQNT==`m|#dS}Z$ehg{~x=hk6xNn*)m3Mh*;J45z8sJpzR=PHaqn1!f;SK2a&Oj`!b z<~t|Zoa8X9#v3(xnHjHbZAf7ys#KDVMoHFNX|J2H>m=(DXL<+_lR{Q)OgB{QY0cQx zCmX#%^u;U$?NQgPIEIC$bi&s{wMAuRTG<3hz|w8SrUZN>WUd)U^whFc8xt*a zo6^W`uJ}x+pc3I%SD7%wk~L0q=T_ChJNJgLG*BzYxyhC~wtt-h&XVRb1?XOM=<*sO z`J3y|>0=(qs3u$Hs|_3ufYhgg$wfv>4hz*yO)d3JRkaw=(ygdOGdZ@U6SSs|>4HqR z#gpG-tA?M`4P27@#X;Y*6NwZyMzKTCU{*gef02652Gz!d?}WY1UR=1@ ztHyk4%tT+smfhS`k1;|`%2XFcCA~@3yG~Ur_F6xKjr#-`d38fzNySZX;#GJ%udTdP zn+PE1{vCH35@~GJVBC{zY&xp^MXgSWxxdXbY z#60#bCWCARIo>I1rqXs|w=27(+IfBkV4j!2QpfbuJ>2yyDBg^s#Qr0u?KRl&Ps>T2 z+ETFlU|HaDM3R57%Hdoe+XxL+7_K;{KbK1y+1qOuxk(~7iC8n$zOUK$Qr6tB(8|i9 zv8g3F6YG6!`y+`gC}po^9-i(zJui%7VqW9LL`Ij}5@^j}R_ilO@3$7q@~^hL7Tze5|)N)+r{#w74+1@@$I%U<7|eWp1!cUx3*2ZeuDwlAj?sY)7aa= zPOaB^xXH-2>T4jBB$kD`XRsVtFy37f6poeZmgYpg+)ML1H62Iw?CSi0D97!o$d3Z@ z`RB-G0en9UXUu;bklzJ}Tpkd-)k&B_h(sH+!2jIpc{S7C=-*_V9PrL!VKremEbo_1%h+*^(J>KIZo=LnZAZBWL46#he z{0e?QAb2k^c(b1`C(#|@N`DCVY`P)*({ zr%Qh_9VVQ1T`wTBe1}#;hk8HJ<$SJwR=Q3-mpk+hU4Jgr<&OL?{A1`3`62Tc=`JT9 z>IZp)(3kZG{LDAzi_AyZkEXl;-@FGheyo>7riXemzQ}*ce^)?!L%Xw_sD~(u2p&wI zr{zUN#N#p|!e0g?527kDhxQP7f0zDbey#|}XYA>Z@u9y)BJ7tCkxyHR_XI?W^%3Qa zCL+uEMdG~yu|wO3gUWs|5%G&^oThQ1#>b9@qvJR9+&OwWyq{I+lYvN z6leG%529WY5&nfl)Uzc(>Mtcie=y^T^2{e9eX?G(s`n%?J?GQ@bRlFueN%{QD5J98 zqHz@w@qU5`_h*R6mluc$JTFW{{vcXnC_Ec@D6Vyl-fKXAu!zEfL|#bRaxgFA=ZhTF->DL(9FT$K*>J_26IfAYIESBb+;k2xkQm z;YePjYcpk}>t!I*(Hnm`^}s9387T7u{7Y#M{@aM)m+{V$@231JG|x2cZ-(}F4)F{4 zGyR{;f0VQAZ&1$Tb$BxW5znbQJXsD1PwHo>XHp;O{1@uOpRDglpR6bFC+h_gA@c)x z3H5-o-lILp{D3U;8}+k8yKf{ymihi2Av(1z+aL6IP=(KqE^qIqQbqn?`bpF(@+_f}s_JCgMS{(5VtGX8L10zS6;9P*m@B7VatBYxFH zJTK5lEZ6<>QR;bq+CQW1Um_xXuM-j3w>0h{BGMmgJe2jK0pl$Z4>isqf~SpGE(E56 zBC;|dKqYw)6{-I)aTUfLBJ|$T_Uv%k|3!%KH-z{Q=4nLeO(7z@bBWMvAwq94adkkf zAVTk9BJ?&Bq4xq2dVKFhWKBTu`RyPYM>p{fq=(2y4LQEuDMXlf58jDHd;s$XA}YmD zAo-6Wg1?*y{wW$~5)sY{A`U(dela5AdnWM-%nyl2p`8-Jdp!|)?HcbTZU~5{wfk0W z|0j*F6A{jCB6x#%b|tbA<0=vH7)ivqJB^5Ow~~m#h3_W_{u1wGBVyiHPkcs*6!AQi z2NC_uJYpy64RI^lJ@FO9mx%HEN+82sMnt)_6DJFCFA@2&TI0`&$cLASPhuX5v@+da z)mW|Ze2upd!MlP8UOpp3-p7bj&~Iz|=e4{|%X~J5;dB#!j(otgCgd4H1WyqWJSD^_ zID@L~Cun)Pmd_%Br=Iu}<{dBJwwX01){e1qN?Kc*I9g z|A>#FJ`j;_h@R9NOho*OiKv&QMD*j+fz1CR%1|CdEEgh1g#I)l(jmtSq@$KH(kJ_U z$a0{w;7KJ-I1l{(c0SkJJasd;%`e{OdHze1ZM*l;Q6Ujon0q$NXS^Dt=`CTfd8**eOW&cuc?%g z->7af9S0MUFGGpQCt1(n?_A0VX9*FRv`k~W##Kb{ttEo*RpRM-z5snWZ;Ye=N4m%( z)BTKJUrhZzlKv2$oaaEVMf03b1dj|KJTiQQC+D*WuY>N;XZXP^yn9Q34*etDxkS_l zSue(_{TK4ed_#Fpp*zAwRAf3$`N;YNf3jXfpY=F`M9KDO^ij_%X^--oM@0EuLqs@t z5y3C>5%@6WX9M#6N|EQ#uTuuk3q<(eL4^N3MC8{e+Me}{_HsUk_>7?ptR=$VLhUZ+ zW3b16+5Ywr@nWHmiHOgDAQ0)uCnDSuBGNOO2=_*f7ZSm{jEHdgt%=CQ`kLh&Fd_edg zQ$~CTFde8DQ;9bQL>&?Sp(5i83K?HaRb{+Z6A@n-57c{E50FmT-k|K3JKI@gYe22< ze;W{Olo6j!;_vkO^Y<8^DPz+{#uM(c9D%YNfwCO)^*kEkupc1L6e99WDMlk@36AzdsN@D9^BocId*5#lzqH{!ozenWf} z^^=J3mk<%SEZ^5uIg+O@=dq~#eBTl0H~GYJ%x8#`gnTz#1d)*QV(jBig+1%RbRx^0 zi2SZ3{s-n2#7l&@14zF6iQrpHoGio>#5b@nMnw2#9?gLwvK{du?m$0FM7&Fgh_{?a zL%)qOP|l-wqC6-gf3|6ShY0%*iGKzk=dW*Ky+M2n`9uW&G$Q!rd>Q;H%A1i-#J4f; zBO=q^BO<&{h=0L66BUax=fROK%rk(@k0=rOQB3?Y#(g64rIfe}F&taZpg??hhOsl<(bPILjcD ze=7Si)cZOj>isQ1e4au zmo;wF_`1d&8sE~`rIF(UdE~f=7p)Fs|A>BfIuYq=AtGH1h=pdH#C{Ov-(#IZM7`NW zMEgONmNL3Z*-xQKOM7IUw3p*0+Kb$;fWJw!KN#ghT#5Y`tyfRPyrV_Sml08a))Fxu zK26+$afNsr=2gT)f^wfCvR&^>pqvJvUu3_*{+Q*)XYkoR*e|pEh7j|Eq6EnPbqw)K zLA77;9@0k{`LLOYe0ZIB5BjYz5a~FW2=`-%a34+FjCM#wU9TsWV?9AcdKME=ua*!e zVZWbvXi%&pg6|C?;_)64`IEzb68uAn;FtX_?Ei)GVL?$%gg@Ee!oD3c%X7KL6&ml? z*r9Q?#e9lX&R?%O~u5){85Ns2BGWkJbAzN1@-LjB?LK zU0}KM{aUQY+>Z&4$2yUS`ddsyy`BPOeUbYyz_Tf1bCB;|VY|45h;Ww>5w0A!5bk4? z5$>zRqtF@T09oIN2v?3%@Hc_-I@CMj+gJw@!ILJ!-wNV=X#Yfn_aPDf!W=)Kmq$c+ z!->$B`zm9xuB43ko<%%7DCTIH`y`yN%KZ?y-$nUG+=tTcdo+Gb92yik2#fcZ<-Q2? z$3qT&IVj4B$hS#EZWmK~PMiJPhL?kny;XSQr%dYIz;8C@5Yg9uZXgB1a-T zj!Q>jTp$()#b7NTLqvO=N<2C!&Lx63Ma1NC4iPV?KA(6@P%I>Z?-p&pj)<~&mN*6V zfp~0Cyru0wCZ3Hr4*y5NACTp- zNy~2$5#A?6)RzGRfh$p8h@*p|f(Z9IBEp|XMEI8wj}HpIQ-k&oYWsD>F+uSRF(Sn8 zh~WJ*@q{48ejw_32@&;tjF!*Ray4-*<~hWpaGzAlc*i~wd`}P&-ew|rw-OPbmo>hw z@f{-SeIyr%c2P_OUj^|*)IT8eVFvM}pg5a|`dUdG7ZkNbwDa?U4DS*m!e2r}xVI6( zzk)ak`}#!W`_n`WvcDrDytDBR38r@*5$Rn>MBJ_+ekCZDYxj-X{ben`r{#}{2se_a z{0%0e{SGIBcPjC#h%XU(DI(&#fQWc5CL$h7iSWmFPB7jN5+@_x#IFU#C&Y5hLk0oa zj)1`r&`%JNPt%FWpBcozAzj1(@{5RkswF;yc>^$Va!@QIg69Py;`J&K@p^}dc=1Lv z<1vsp1?MP;6EGhjLjS8o=vNS-e-;t?bwuc=h!asyh|pg~gx$1zOE%=U9gULYEWz>BA+)Ak*_ZT$+w$``h(9@$az~H5%$GIv{$~X zf$17cMEa)^m!jTj`)i1pC*Gpv6&hD-+)PCNZ6#t}_$m?k+81+Dmg8U|_=gh_-e@g< zm5A`#h*QwNY5NW$;`ag(_3slR^m4ug1kXs~v8YEx=$%hQ`mQ8GpYMHSJ}f69pZIQs z-~no1kTRxeV(8oI91CT1lkz+g?IULd<$mhWsX@7KHuQ8QGu$C`2bKcq?-=b5-II*p z1ma!(`KfCtLw^|&`!LJ3d_NK6Y2W-F5!gti%+1_p8D|t^L$aAK`cd*`f;afUyzHl7WJ1~4pKJk$GHVoel zM=8x?NLk*C;p;Jl`Y{mwh78{g=dkhoLdLr?d`Eip-c6)m)3+B1`wbqwsPy(O4_}>Zj0YN$`&JKMiKXcUD=SXc*LnCJsO&zNf&<>Z zLJvmy%ngsA<6N@)ijPchs6N({?>*f35Cz=5XW)A%sH5xVFn15<%%|RcXUUuSLJ{B5 zd7TAbE#kZJ#54~^^K}+@6hppbB#SG0JNd$kEKYo3hHq^>+MbQjckapPyJb@P&(*t8 z@ZR5%=^^7G_>9>3&%t|dH1VTuKM$YbOFj9WVPzia&agDq#(s*vcZDphnFRVBD1HPp zoLO-Cw0&mkv)69@UKF1!vuV{})boZdI+=&HFVIrz%b~@x9#+Bm!;9uRfX-pjK%k-LuN6!uVwL- z)I&KOEiuk#x^I&RRJPse0N%g#^zKwpmV``I3Zp&kd?n^w=5*fhP4D$IKSVWA#@$dXZS zPH`R^`YcuJQJ}19*&ZdzRMZdbm~Jj>PG@_($Y;rXj40cKM!o4;j~w-;;yrxiE9gpS z<)?ZKiED-u|5bKUbY6-i?b!2juE94W;XPsv4G=`h$=^7=q^bqB)$+-8ELZl)@V)9- z)yQ=sJ#al|o1hj7fYih75ougKy3t@sE!SXs)8l&B4L6?z+L&;sLbmlNbFFDiSYK2C zu~jVBZM4e2O~vC`T;tY*T*q^5I2%8k?|jI0_!(pPX2HVdi-M2wBVRxKs7JoV_}P4~ zLuMR}F?@?)Ve^f(_-JqV9>BHDR|=uXkZC=N_uyyqO|$s0h3xS?jcc24I)o_fj4}EA zb6D7Xbrv7CY(2g|;@akGarjJnfA8?Mfsbo)<{!2tJ-$7-w)wCWmwP3!md5aPL9*kw z#Nxx&rN`GF{%yXE5LiyenDq96z0KDSKI$=k*gEw1j&S%kLmpztfQGNY;ag$F4_kR2 z-{}q?&#Rn`pD`xAr#gIV!B+_-#t&O&9$(VoD@Vgy1$Sdi{1Ogd{_UzAkq=v59^WMn z-yZNyHDp?kBF|IV`BwqHDD26{K85LEe&W_`MtPLOp%(VWnDpM{@YPv-heO%$t#kO6 z!-0D`#uz@H3$o+4*y8&#lno#AAOF4n?`1g5Fl1Vf;x>nG1^9|#&-51HXZSvL_(r4i zIR@^=nDW3;k&O6tg3q*%LMR(P+&a#PUnTgsM`euR!&Yhr-!_Zy2q+sq-j_$vUV5(t zUy&gL8a~__$>8e(pJ^ZL;|@w4o9po9wEOWJ zVeu_<_?U2e?1Hm2OC7%4cE3E1g@#G*!ww(sGY?c0@~`1r#_crZ+jZPTJTMU zy)lOG6^F0A-S4ly24xe!FfQ!!?EqiYkZCF{3`_?R6S$(S{%Nd zpWq%Lv>3n1_!+(%a1nrP_&UMIdj-ZAzH1%6Y2bsZ(onH8g9KID6-#0D3 zuQ`1Dwn#T4rj3c;IESwTe09)adcTFAN$)uh-&+_wOj(oC@SWxG<^R-A@3$?!1rFct zUijuXd{K+HRK#CcXDLd^~5dS#uE#-`x&h z3VbQJlka<4kLCT8!#5p+V7Btu;P7n&UnTsLFOHvy-@iG0Q?Z!X26tmj{QltZl`r@C zs-SH6K6Lnw!41`i4H?jsFV9Ka`PU9UlYcc9-yl>DyZycjzL{D04uGD`w*!3acbVRV z#doB`SAoS&HojpFU-V9&Z|blxKoei%X4;idIt~2 z*)pqtG5N=Hc{bk?@U_D~)5|r!;XB{qJMti$y@b0lhHsw3S9+Iv=7xL?_!+*N9ljyB zLA}+G0S(^`4&O%b)xn*7P52qUCmp^n@KwXz7{j;T;VZt|U%#CPWy80_;hT=d;@O5w z>rs5&;hSOcHETVVN2p(Bd31np840vuxHO+Se2c+14fafLD}E+^!yUeg{Ot47BcW%P z?~CArs^pt%@qNqTYk?BajvHg*_jQM_3w%5~%lOU5&%`h7@GUROo_~!F-?9h%@%Q@{ zAHRKP*Jp7A!m{eKiQknD-$w8)1`p$RfyMWr!xug>`+WRfhp*y6KmUGU@o|1;$FCH8 z6>vAk#P3;$uM&Km7c+hr;b-!%%i){X3*TD~-x7=OVvCQ@3)}JA2);DjjWO*b0zJFF zYy@91lo-Ds;%DMl?C^~~3hTivAl+Gd)48a0X~LnjLAPf zA8ywdvC=P(YoTo7_ld*T0lu#qGN9q(d1#w&EclAy&h%b~pWzz{CA&U%fsfBD7-RD9 zQ0UowmEeoQBl&K?&+v_P_`=6!?+^HVkj=gd^jJ zttT&jYaPCMSRCK~rJj7N9lq#V%scl}d_S@H{^0NxVRD`8)5<{?_5k-{jBle`@jl z&EXpjK2$Z&nEd;|;fq>)cUpWyan{nVf8)WI@3E0tidjUTd7 z#)I!Cu=%EgZz$Z1G4VUe;TsD+hD*MC@H2ds4qprS#u_rMNAYZjZyNZbuqWSr_!+*7 z9KQR(w;ArnP><#Uhc5-b8L%fGhGLKJZilbstnBUWrw-p{@R{_YtM>RdJAAi+?-gfw21YfrOh@B2!7x<#!VS3S2JiY;_<97KD#^SCV?#6`m z1)rC&r7oXcUzis(S3!^0#*N`lkuK^F-S}GuJ;W_#oX&*acq3>XiqtiENqH&sx{eUy zIb7qIyNq8hu9?Rst+*76E{5)*yi$fdGza2m>y;w^Rv<3M7(IPh0xz@1D_~2Sjw>5; zd|BD((orXrMx&!nEE_v=H2;>CmX(%{89f?yqf7CZrZVz_Q>MlO0mH;J6w7p&Fv94Q zVET-fP%I8YOX*s3?9{6}&e*fL`k0FFt|5U>-~Z%O{?6EgFY^@g>badFkc<^o@H!c5 zuOk*z}=mKauWVP%rK{QXB=Ve;)m zc_ofL=--AV1IOZ7^x&|n{kJf@iSK>~QD^K)eWT#Qhd$c9TlqY&qig*myFUF| z&W4BacjuP(w&SCS+KgS3Gu4F9Cr0Lj9(}DYFzU6+^*hFvL*AftdDXmT|5)Ex-c)LB z+9?vm1Ez?=>Z(tN4VyD?N}m|gTKHOJVO4u2-TXWV#`cR9$C8r2kIac+M{2!^gTX;- zBC$a10O=l%MIR+cG#2d0UBBOHht&;Q+0+#Zzqg&XftV@TO`Zwa2hg`S-XbgSdY6KwVb&kB%kzaLW zt2>hZqgI_F--(X=O-HVGWS)yKhW_yi2O0lLT<4*@9&p^Bc4WLl#WVEJ^9jaK#;YMD z-&9=Zp}g?w1JBSMkFa`%G9EGX3}rl`=q%vxgo!vA`fcfJ2LpNjy&tn4-g>go_BrZ-F#O<$3TCI!PAoO zf5(UPK<}N)vq+3Hz6fMFJD;wzJ{c&ZXTEB}e2`y4V2(+H3%E9=h+dO4uKAIA^> zX&;%N`STR{(ExnrMU{g|5zbMXPb=>8_ZLycSkEF~R`cFSRILvqhpTl{q(Gf_hzwKf zo=BmZFGkQw&ZIxgY0f1ciFfW1v0v9tM2E_LIEYC%+k6oF`s^JeN2~J~)Mr0ScdkeI zt|c0-f2H0C9j{~5{xjn>2JVd41mdx3{~=PM;zJ(xWkHb5AfoHTRMZc*RP%u!LCa^= zId6-MRO=DOuY&rc@aOY9L*^a0*X5;JPUdM+)UeNJsXcV9HrvCk*XL3g2ERh8zj7f@ zqIxY}omEwR2AlmCK9(xakg@CQiyzHs1>RrNjiLI;{?Lrvt{ypPSo|#az3HJCC7&Jc zM%Wp{ahL|xCS(25-B0cN=E0si{4u=A_}S^$1GyMKV+`L!SlH{KN_dXKj(m)Z;cLdV z%{K&s;eeAjqiMpm&DRD##)o`F!*>;~ZN4akO4u1=xPJ@_n{P2lrooPUoMjlk`*3aZ zwL#!mWsKpw8x}U-i{NA4lWzcihHn$D8DCRw&w|fhml(bmvgmQnVT{px6&8#i!=fSI z6m=>8(v812@k5v?X^B5PU&r=r40ULTrY=&R4xt<#2jLoBiA+Z>kZCn(z@=E)2a{gQ zqv7NH%+||+$B*bi8>4sJ$TBXfJhQiT*a^pv)Vh0Lhb>ltcLU9Th_Adgl07I4g9^r~Ur-{mmmEqGa#_y?0q+Z$^zY_mR`janZBswgg9bo;% zbQ0r6Se_Lf?CF?MN?C9}A=7_fdGC?_*-p5hz|9kmm&#ZJ9xS+@km)~1o~5FHj z2h%no^kS3>!w5jiA3O3uW|lT|ALhvH1C613wIk1Q+X&FWgO+pn+_lRp|1q9A+J>5}_iV;jp&_u0x<#*J`=%kz!TO5BOoN zl);_pE~75p@wwnM_dU$Y8c+81x+gHQR~MNjS@#Cix;r>bw>cnN4cEgGi^`gWB@aI3hUUn;vx6|T2j;m{7wo010MAnMVGqgIKp0=`v zWM%Mz>gg$?K{?J@i&!qdz3Tsk7vF~=%h?B*(PT8PZ4=Z&0g!rTz2fT8jRsXMV-44v z9_yVOF6)FbW^_cA%vd{aLPXieqsqxTMLo*j!O!NK3ON@)V+`N7V9_7Ha_#V}#m77_ zd<$`H^PLUZ9wAJ=aQR|D_p-&u5!vuP=tF(!Vmz{2L^ zJ1-3%(eMS~-{#{vz9K`W^(cOVpUuZ-W}>iT{8)a5uK@m8KBhj;fEI`DxKhUH4#@0FjiC+=(bOHv+h7reN7j9|9fr$vGYuwgxRehz|J;y3 zG?(tWXc5v|VH_>JQ=orav(;;(lw{m^@)vpC{h>P^}e`x!hU~vKlIr zKkOK>vJ+=~Zko_<3mGcwIzDXcD(~N?qjY@(&h8Y;6F%3$Pk2{Oh<@MR{*SpcZ|V-~ zQux2=91g=c2S4tk*@j~->#T1u23sbC-R4YpOpq)S!b~gEoii`rWIK1`yK>C8XSI~~ zm-qY_U+!b)A%0)6JaBF|6+gPO-RB{G==wZE_cVTV=X^R3@w-CHJS)s|CD<5{{ibew za(~9N!bjBcM!_Urcjc?e69w4H;ZXpk*noo`JV#;aIHv#@0<~(IQu8gXbV8oHkOw*B z%ZU7d&5;W4JO$_5LveGAM-U@e>lYJ|{j}%1r;Yr%*8K84tA3zqTgpGNN*T-*0-j9v`(_F8NQ zrq5h+v0k&4vL#ba;%D=%fNYP6hA#non-3kVTq}`}t=jNif@_;^H)QGRAIELB zA*Pq{VBEmxnQ{osLt_{wjXSpIg5W=tll*J+bQ@@GNXhB%Uhkp(-~5;PZ)%Im(0yDh z%6^;~UGqOX{r$W5F{X|DJ?Fo6pJ3{~+eX-iPs!3ojyn;D;4QPa`^+OpmyJ>Cd!PUE zJ2x=i{Fi6rbJv9Bd@#IwI!=@4mUDh8a82YdwdRtJ@B;&Irre)7hD1Y5%^gFS_4eI8 zy^8ZpHKWXxGs?a^Ic~B1bIdQf7w8-IqQ2pM*i3gb$|)V*XU%ly2<98k7c<>CLimRB z#Y}g1{y5Naw`(c;8TR7`ku9kM0~RIUn5yG=}a0I%-3i=hkSY!oz)H$Nfz0uEHBAS{-*i{p1Nm zPC2Vul1+{3uA~~ND? zKj5rKoUPbqIm68O@+H4Mt4Z+Qr{6M4W-gj}q}e3IxO%g5D>j~6#$jmsWTZUT1kNEh zHYa4g;CE74wnH(mXSog4m3k;{vdei9Cb37tK7t#3(tRidn4wYp`A^;Bv*K%&wL2;A zS(e!~GBR2pLC>n0QBqkoO#ayU{+WvQk@Ww~>xEJjC7Y`0Avu<_4>HEgh>n4UJ%8Sa z3c>H-xXY*BPdw?{CkLzcfkI#CmzD32w@UdUB`N&Ty-ENs3PEk5!Z zzFTl@^G%1GZN0$za5mpI5SaAZ>xCyAzAGU!JY!7!9)pF=*JZ_zqlby#c3j)>yI#8i zq%nN2L9+R{-)8cUZP)M(02%p8rEei_0%lv!90VmSIZ|3pypD@~SC3G*(VchiI~ZwSsSufvmryMiAbIO^~XXY5&&{^P3PM@UQ*dw{DucLoawO^j>_ zB`2=LF5zhWj^DU5cuIM)bY1@B(silHp=4WkUGAWjfx@=#%2FlIJJ6SN)-36sR~C%* z8xhs{}CZbxpKBRC`s*w@SU?hca3=WiPQjTpR=;9JA863?7}hSb7}YY z%L1bo;cubzvj~22*NJd-$bK&7Y)-Zuzm8G{|A>p1r$ zrY4UCSFlO!O7#hx6r3e?wFX+`lY}`1Q5j}n*wHcb9ApS*Bg^GkNv5H$G#Cqy7|@wB zBG4HaF>p&z$A0~eoN}3t4WXuf<8GV~*wUw9_xAn;UE58{10!-eLnDTEF6mxS)~_Hi zstp+0cIu+PW4hbk3XVvEKX^@ z!V)}E9EF-QYtzmFg`0Nf72?HoLdrM;;8!m>r(7nIe^ES$9*^=ec1qB5K`4TZ38ja|~yk}+{@|I?y% zfopS4dv0fNG-Dd>=v;4|_v8yEZBuyc&aN|9cPGv~AhuDg8I8;)Jk zA$FDa&+qKqIbh@cr=;HOJ8i8OT{08@u6_*p>KuNo>`d1ARgHxFYUgtU}^XHU%%R?V|iQ`$S%VpZNz)i=8$k)P?&BBgSqB6fWwXU$)=P)ySd9 z&CC~3cv*M2Y({sV_VwGBcF&H6-~D+j>P%o{=hp5;D<9t_4v22~E_V2rcAuO3T({_W zZfE#$`didJy8{|!Vnlh@cP|Q~z0$T1p3t3!Iv$4o)GYzsomWPKS1pM0Qr4b zR|HQ`9f!9B&cH6;`}j8lJ5GvC9C1PQrQOjEum-jwj3pD!do$E${02VXToL;v>N3+( zF5AXZ)S<&x;^nc0w6AG=yk`H7^*g$*8rIZrc)!kQ?B~1s1;e{i0s1(68(QEuS9iBW zZ<;W83tL`z*Bt4xw0lA6#SOfCkunONNyTeTe;Q851@tn;|f zNo4=m?R^TiqdezV{(fih&cF7{|E1q_yr=$pQRt=#1GX^dn1{@}gS&#E zNT<+Dih1CR;)wfVv2Cb*1?+QC1IuojFa*64Tj5&>BU$?NUoYx=+l0PbO3;HZ>P}WJ z>OQyf#BGI5{YJd^hw!co0{DFFNujHm;?>>XN4k#Og4$jhy0PzwH?};68unbLIQG|_ z3~ySj-|(>;`VH%M(sdJxHyjijj(RtrXV5?OnNeFxO&sY`x;^BDO1HbVXO{lg_MH1O zxBM$n+rGU$P_XKae~x{G%=<>_d2!A;ityW)`&36k&)3J~#WLBRFXxzi!PpWhB=>PPY8d2!qD z`SVQvf#MM;P@n6Epj=h@KDZB(sh{iZODKKjl5cqaJ5xVT{1MLNXUx^t5^eoKj{YF@ zUP^zA)aQ)VH$4BH$$yaG`EBx_gS-x=uBnt!?qRG4jLi7pbMBsOu81K~Xp4}GM2d;ihNb^QN9Ok?jG;R|0qGga z4?6N=kZHyGornB+&T)TPyE6@W$e%wu?w@M+4>9G>Lw>l=@9TXXvoNvlTtMYsqKG@%h9=&1~Nin+e=(;s^1}&0YA$UPKn#s(OB35qmm`7N3BhW1N+chuD*i zv-m8&OQyWdtxC4UtDK;DwB4st8yoW*YkVs{f83D3E=OZ?3pPqpC8fSw=8=AHm6mxV z+Oy`SkAINbvu65Rs${bG;s7MU4*+SAAFbq#Zakr&{P+*lTao9T?uMp0CI@TMHDk59 za}OLY_|Bpix=dHPwZ`P9b6=fB%ZK^hkS$B7Sg$VdBgb4oz2bVD-<#(4S!92;PUk&z z?zu#8({&hd=+{&ojg+hN^wcY+Jvs)SE2S*;@JH^+fv=SAwA9Gnn0nNwzX_C27UE1I zgi7K>{rmtnl-Y+wCad-zMAx$zau8kO5+a@_U^@>Y65I<39--dD%Wt}upiK}b5s{9w zh)72@5%Fpvo{Hy)w0u1gdTg8gb}*merT$x5<~K9=+A&Zc*Zqeq$ZTw@F$`zw2Iv<)3F`Ot;QJ<_no$ANaZ z&p_rp!5G8GIjqgM1bjKLBOkjF!?zvRHs7BhNAWYp@Vy2Ln{S!L$3EQf^#_^F_X*rs zM#dPvK2Wmx+ATg@dVEC=-*Cv;_@WNq3XpJ2VS1U5CVpRW_;?SH`C*KSUyY+z33-fB z0vf$I?Co@HM7XBh%-%Bdoo8+E->at_UpPNE#_+W{e4Q2_Zh3j>xYOb5g3L4;WB7jJ z@NEO1sRz7uX7Yvah{As_etRGcF=Rl)$7ez8^zN|Y$CZHL<2Y&aalf5ow=srqhr`Ej zL6~ymO2P2$2M;#iWstMg`+l&uUYvMq89rW4}80Te}#>sGVfsC6KZE-dl_b|&Nd1$ysvi0)exgm?5 z8f-B=RY$t^dZw$aY~SCDuvvxY-2)jQ@BnCG?wXq>h%LG6pFMli^uVa@?TaVmt~ua0 z=dS#5e(t0}-GO6ooFMS`gDv50O5>&pA3|Fcez-j_X)%1_O#9YL$I_~CTd5q15d~6atKC)+ghdWn)S?hHI9aF-Gr9 zSlD{(oLHX57`@rBpkAqVxDc4Fk86Rw-N$W)yf1xRnB@3H0IbKX-K>9ZAIH6)ufX0I zdZTgsxRar`NIA*BMo(2yetmr3&aIZ=<+V|1_I{stoyx3?J}!4n->CsS0mA)q+$j?U z-WB>WWBy6rePY)umN3iApSQUEStIS*U>;@ zShpq`0Z3W*U$Sz@4vcTCKuxi>a_rYD`ui~ca?W3`ax+VA`lvZg1c_%mjbIMJGzU4+ z`8@jr-h2Q2AXH@3yY?8(|IPgx`xTaz>90oPI*Ok$rgm^WVb96Qh zh-Th11J|rK#?Xys8h#9y;nPqrTfg=l*xUWu9gz2>U)u&f2C%n&Z5wph7aPMk(YXEE zG^97FoaA4lcU)On#!IdCcGkG;#4-EaugM27tn({;)=mt2zd-C7916%M;ucmuRmrF0 z^4Ys>7>nod7UJo(Lnke)y!r!V?TA4yiMqO#iMsHv!2xrBkv*d77mH(K*KgX1+&$uh z?Rau8^bnq*8@oaA7jO9ayPK;HorGuZ3f|d{r|enXwJ%UEBhj(z$E#M9`3aNw31KZt>2MSXQD@Zum$I9*8gMPfmHR;6!Cw> zvvSz7w2ajVV9R-7rn`E_6zdh&yglzB<~aJMC8;3ztXw7^Tc&S#_Bqp?EyFk2o|PL3 zXU2#9Cj0TpzPjwU&vfJjWa_go;o0OxT2}Ma{^Cw8pCsKQVk6KP)NC^jpnGk`%Z{t- zalgPmO3d@F>d3Ei_?8aby!))D=)CEw>c%BkwsWSw^Jkv-rGIm_6xZtPt@7*5fz^IJ zHaLz%(s(A9eJG!;llKeId6q!tcZj~oc;uwr-M*CRl*gpKJhP|f(m7i;xJtcbMz-L3 zWXl&G9=XS1>J={kuJ54r=S}{c-yIvbp-W}!WW8sr=a2Fk_}S^;7?^E;>onN2T9o5Q zgAP}=H}bJ<8NNnb+kE$GcYrh)vZT2de{H=E$mBA{=sf`oTaPl^sxe0IF<98~>$c*@ zUd6=k6@hF}@9YJbQ|%ot)z_++6$^H}H9e z_mBS7lT?@#-7!7~1dO9Gj2n$=*Lb(oKAur68+F1yzqfL_im11C*&k;wc=GdrUoFC0 zBy-o}DfCeO}^j$MosWQ*#q#oxl1s0(#`uRDC2@3N_f%RlBQYx0!&`d=}|vJ8F0 z8sM9~KY!kHt>gP<9opOT={?6_u9cWZYzfLSvqZ~kOzb1qK6F1+y7!gyUSGyqDzma# z`#HTYdwdt`-nDNj?^YXH^TK+0fBka}Jl2g;pW9!7*&~MUuI{O2^(v#4-It8q7alhL z?$1%O%xSo$Vtp{i^rKT@!Lm1c<<>PWy*;H_xVH6TkXe6>F?h;U}Vg9^vV(yxat0I#wn-JWxapJ~Rx$6(?4vd>o zo>N%_QQGWBP!1#-$)?e@) zpPWUXe)^BuQ>(gUvi-lJujV-Io1T4jrh6YbrWbo2dhV-xPPkxS&3k{W8=Q}Ey%Nok z;oq(>W}`{jS%-?$DWd;u*C>hXUQN+`;m+*uH3w#1GEYq(#lDPo#;9hZ_J(b}N+{TR zrnJw1J@riAb2+ZF^*!7VviqLjLEe|XXE4aOL6>vD0r>US_we4W9Y4m2#_fBeNMN0E Jl7Eff{{w-o_L2Yq diff --git a/zboss/development/trace/lib/cortex-m33/hard-float/libncp-dev.ed.a b/zboss/development/trace/lib/cortex-m33/hard-float/libncp-dev.ed.a deleted file mode 100644 index 3fbbb395057f9ffe1171b987a43e6fab45d12455..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97498 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

hzRy^EyBxli;LA$lfRf**9KJg6RluL+ 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

u1*N>(PaZcxOQP>e><<(qXH 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

Y~8msq}mm&ezj2Z07M!A+?|c{HyxY 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"#II)X9pU403rIQB&1 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 z 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 P|H1>H9|Kc=&!S&TXYer?=Dh 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 diff --git a/zboss/development/trace/lib/cortex-m4/hard-float/libncp-dev.a b/zboss/development/trace/lib/cortex-m4/hard-float/libncp-dev.a deleted file mode 100644 index 84d96b92ce3814794de5609f33bb09532596fe5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103706 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 CklX

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ò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 I{)*iH129O;2><{9 diff --git a/zboss/development/trace/lib/cortex-m4/hard-float/libzboss.a b/zboss/development/trace/lib/cortex-m4/hard-float/libzboss.a deleted file mode 100644 index acf8d0416b28a62c627cc4829067886c0e981d01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 995034 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%0Ag@RSch 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%0DYu?jK13*o6gZ-9_KR^vAbKh43fw$@rPz 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%0Ak@cDDpIy(L16T29h0m;tLwJyzb; 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 F{|AyV)s6rF diff --git a/zboss/development/trace/lib/cortex-m4/hard-float/libzboss.ed.a b/zboss/development/trace/lib/cortex-m4/hard-float/libzboss.ed.a deleted file mode 100644 index 21e9f4bf9d8fd64393b025f05b2ce512fec9a2aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 778822 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 z z`Wp&j&Cfg=>L~bys0bA_Kl5xTe=hWfGALgrF3s;oL%w7fb%l_wgXVX=Az#K7*`a?%x{9{U^xusnu~ zFa78I3yc}Z6L=WD*xrrLKnS+ITQbfnp$FMZn^LdN#TSm!Hmz9Mk^B z)Yr$k71xTd!6x7v>R-Dke7o};XTblf`(cDsH^7q+rar+0W)gLf@z zc`J`Zmb<>#F~@GUUQ>cVzD6)(zwDb8+oh`gTBfHLD=cQ&A{;b>-T&_8af`Hmh1{#b zJeP^OCBb1C=ZGX!HjfbT1uCBH;6($?BIHf+pLxa+$H;u4T3l<_?gCr?zg@SEg1Xob z^?jb}R>w4E|Ngo`$NtN{tAidf*CN7sKjS1xTE=mdkdE^`9-T$GY)gi_arHF6uR=Un zRFj6`HC$h2e&@a$_t=s^pNxy;rraR>k zmA=s2N1PYZd+L)7f$Ux4ySH(B67l6%La^%0A@4fCgyJ#6N?F>Am2{o0ZEMqYd`fo& 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

u_nO@z_6_cpD8o#?^RV!o7)? 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 O#P3#~ZUVu>JpLc_8e!r9 diff --git a/zboss/doc/zboss_configuration.rst b/zboss/doc/zboss_configuration.rst index ad51443f6c..02b7a0dd91 100644 --- a/zboss/doc/zboss_configuration.rst +++ b/zboss/doc/zboss_configuration.rst @@ -8,12 +8,9 @@ ZBOSS library configuration :depth: 2 The ZBOSS stack is distributed as a set of precompiled linkable libraries. -These libraries are available in the following versions: +The available libraries are the `ZBOSS production libraries`_. -* `ZBOSS production libraries`_ -* `ZBOSS development libraries`_ - -Each version supports different Zigbee device roles, with each variant having its own configuration. +The libraries supports different Zigbee device roles, with each variant having its own configuration. This allows you to scale the application and select the most suitable set of features. These libraries are used in the Zigbee protocol configuration in the |NCS| when defining the Zigbee device role, as described in :ref:`nrf:zigbee_ug_configuration` in the |NCS| documentation. @@ -30,22 +27,6 @@ For a complete list of the ZBOSS configuration options, see the following files: The ZBOSS production library version is enabled by default with the :kconfig:option:`CONFIG_ZIGBEE_LIBRARY_PRODUCTION` Kconfig option. -ZBOSS development libraries -*************************** - -The ZBOSS libraries in the development state include all the production code, but also features that are still in the experimental state. - -For a complete list of the ZBOSS configuration options, see the following files: - -* :file:`zboss/development/include/osif/libzboss_config.h` - Library for Coordinators and Routers -* :file:`zboss/development/include/osif/libzboss_config.ed.h` - Library for End Devices - -You can select the ZBOSS development library version with the :kconfig:option:`CONFIG_ZIGBEE_LIBRARY_DEVELOPMENT` Kconfig option. -These libraries include implementation of the eight version of the ZCL specification. - -.. note:: - This implementation includes new features defined in the new version of the specification, but they introduce incompatibilities with devices that implement older versions of the specification. - Configuration options *********************

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 diff --git a/zboss/development/trace/lib/cortex-m33/hard-float/libzboss.ed.a b/zboss/development/trace/lib/cortex-m33/hard-float/libzboss.ed.a deleted file mode 100644 index d5ed0954256cf4efd5a0ad71cc5cc75a3c49fb04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 779722 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