From a3c29375e83a622a610ee462de0122061f4c33b1 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 22 Aug 2022 21:32:39 +0200 Subject: [PATCH] Berry Zigbee integration for received messages --- lib/libesp32/berry/generate/be_const_strtab.h | 41 + .../berry/generate/be_const_strtab_def.h | 41 + .../generate/be_fixed_be_class_zb_coord_ntv.h | 18 +- ...be_fixed_be_class_zcl_attribute_list_ntv.h | 24 + .../be_fixed_be_class_zcl_attribute_ntv.h | 23 + lib/libesp32/berry_tasmota/src/be_zigbee.c | 18 +- .../berry_tasmota/src/be_zigbee_zb_coord.c | 146 +-- .../src/be_zigbee_zcl_attribute_list_ntv.c | 38 + .../src/be_zigbee_zcl_attribute_ntv.c | 36 + .../src/be_zigbee_zcl_attributes.c | 928 ++++++++++++++++++ .../src/embedded/zigbee_zb_coord.be | 26 +- .../src/embedded/zigbee_zcl_attribute.be | 367 +++++++ .../xdrv_23_zigbee_1z_libs.ino | 176 +++- .../xdrv_23_zigbee_2_devices.ino | 2 +- .../xdrv_23_zigbee_2a_devices_impl.ino | 2 +- .../xdrv_23_zigbee_5_2_converters.ino | 34 +- .../xdrv_23_zigbee_6_commands.ino | 9 +- .../xdrv_23_zigbee_8_parsers.ino | 12 +- .../xdrv_23_zigbee_A_impl.ino | 18 +- .../xdrv_52_3_berry_zigbee.ino | 349 ++++++- 20 files changed, 2136 insertions(+), 172 deletions(-) create mode 100644 lib/libesp32/berry/generate/be_fixed_be_class_zcl_attribute_list_ntv.h create mode 100644 lib/libesp32/berry/generate/be_fixed_be_class_zcl_attribute_ntv.h create mode 100644 lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attribute_list_ntv.c create mode 100644 lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attribute_ntv.c create mode 100644 lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attributes.c create mode 100644 lib/libesp32/berry_tasmota/src/embedded/zigbee_zcl_attribute.be diff --git a/lib/libesp32/berry/generate/be_const_strtab.h b/lib/libesp32/berry/generate/be_const_strtab.h index ebb7ae44e..e8e2d2c54 100644 --- a/lib/libesp32/berry/generate/be_const_strtab.h +++ b/lib/libesp32/berry/generate/be_const_strtab.h @@ -889,12 +889,21 @@ extern const bcstring be_const_str_zip; /* weak strings */ extern const bcstring be_const_str__X20for_X20_X27obj_X27_X3A; +extern const bcstring be_const_str__X21; +extern const bcstring be_const_str__X22Device_X22_X3A_X220x_X2504X_X22; +extern const bcstring be_const_str__X22Endpoint_X22_X3A_X25i; +extern const bcstring be_const_str__X22Group_X22_X3A_X220x_X2504X_X22; +extern const bcstring be_const_str__X22LinkQuality_X22_X3A_X25i; extern const bcstring be_const_str__X23000000; extern const bcstring be_const_str__X23FFFFFF; extern const bcstring be_const_str__X2502d_X25s_X2502d; +extern const bcstring be_const_str__X2504X_X25s_X2502X; +extern const bcstring be_const_str__X2504X_X2F_X2504X; extern const bcstring be_const_str__X27_X20not_X20found; +extern const bcstring be_const_str__X28_X25s_X29; extern const bcstring be_const_str__X2C_X22text_X22_X3A; extern const bcstring be_const_str__X2C_X22val_X22_X3A_X25i; +extern const bcstring be_const_str__X2C_X25s_X3A_X22_X2504X_X2F_X2504X_X22; extern const bcstring be_const_str__X2D_X2D_X3A_X2D_X2D; extern const bcstring be_const_str__X2Ep1; extern const bcstring be_const_str__X2Ep2; @@ -902,6 +911,7 @@ extern const bcstring be_const_str_0; extern const bcstring be_const_str_0x_X2504X; extern const bcstring be_const_str_9; extern const bcstring be_const_str__X3Cinstance_X3A_X20_X25s_X280x_X2504X_X2C_X200x_X2508X_X2508X_X2C_X20name_X3A_X27_X25s_X27_X2C_X20model_X3A_X27_X25s_X27_X2C_X20manufacturer_X3A_X27_X25s_X27_X29_X3E; +extern const bcstring be_const_str__X3Cundefined_X3E; extern const bcstring be_const_str_A; extern const bcstring be_const_str_AES_GCM; extern const bcstring be_const_str_ALIGN_BOTTOM_MID; @@ -982,13 +992,23 @@ extern const bcstring be_const_str_TRUE; extern const bcstring be_const_str_Tapp; extern const bcstring be_const_str_X; extern const bcstring be_const_str__action; +extern const bcstring be_const_str__attr_id; extern const bcstring be_const_str__attr_ignore; extern const bcstring be_const_str__attr_map; +extern const bcstring be_const_str__cluster; +extern const bcstring be_const_str__deinit; extern const bcstring be_const_str__dir; +extern const bcstring be_const_str__direction; extern const bcstring be_const_str__event_map; extern const bcstring be_const_str__get_bytes; +extern const bcstring be_const_str__get_key; +extern const bcstring be_const_str__get_val; +extern const bcstring be_const_str__groupaddr; extern const bcstring be_const_str__handlers; +extern const bcstring be_const_str__init; +extern const bcstring be_const_str__iscmd; extern const bcstring be_const_str__load; +extern const bcstring be_const_str__lqi; extern const bcstring be_const_str__lv_class; extern const bcstring be_const_str__lv_label; extern const bcstring be_const_str__lv_obj; @@ -1000,7 +1020,10 @@ extern const bcstring be_const_str__oh; extern const bcstring be_const_str__page; extern const bcstring be_const_str__page_id; extern const bcstring be_const_str__set_bytes; +extern const bcstring be_const_str__set_key; +extern const bcstring be_const_str__set_val; extern const bcstring be_const_str__splash; +extern const bcstring be_const_str__src_ep; extern const bcstring be_const_str__text_rule; extern const bcstring be_const_str__text_rule_format; extern const bcstring be_const_str__text_rule_formula; @@ -1020,6 +1043,7 @@ extern const bcstring be_const_str_angle; extern const bcstring be_const_str_arc_dsc; extern const bcstring be_const_str_area; extern const bcstring be_const_str_atleast1; +extern const bcstring be_const_str_attr_id; extern const bcstring be_const_str_attribute_error; extern const bcstring be_const_str_auto_size; extern const bcstring be_const_str_b0; @@ -1041,6 +1065,7 @@ extern const bcstring be_const_str_clear_flag; extern const bcstring be_const_str_clear_state; extern const bcstring be_const_str_clock; extern const bcstring be_const_str_clock_icon; +extern const bcstring be_const_str_cluster; extern const bcstring be_const_str_color; extern const bcstring be_const_str_color_X24; extern const bcstring be_const_str_comment; @@ -1057,6 +1082,7 @@ extern const bcstring be_const_str_del; extern const bcstring be_const_str_depower; extern const bcstring be_const_str_dim; extern const bcstring be_const_str_dimmer; +extern const bcstring be_const_str_direction; extern const bcstring be_const_str_dispatch; extern const bcstring be_const_str_do_action; extern const bcstring be_const_str_dots; @@ -1151,6 +1177,7 @@ extern const bcstring be_const_str_get_ver_res; extern const bcstring be_const_str_get_width; extern const bcstring be_const_str_get_x; extern const bcstring be_const_str_get_y; +extern const bcstring be_const_str_groupaddr; extern const bcstring be_const_str_has_flag; extern const bcstring be_const_str_has_state; extern const bcstring be_const_str_height; @@ -1168,6 +1195,9 @@ extern const bcstring be_const_str_io_erorr; extern const bcstring be_const_str_ip; extern const bcstring be_const_str_is_color_attribute; extern const bcstring be_const_str_isrunning; +extern const bcstring be_const_str_key; +extern const bcstring be_const_str_key_suffix; +extern const bcstring be_const_str_key_tostring; extern const bcstring be_const_str_layer_top; extern const bcstring be_const_str_left; extern const bcstring be_const_str_line_color; @@ -1179,6 +1209,7 @@ extern const bcstring be_const_str_long; extern const bcstring be_const_str_longaddr; extern const bcstring be_const_str_loop; extern const bcstring be_const_str_lost; +extern const bcstring be_const_str_lqi; extern const bcstring be_const_str_lv_anim; extern const bcstring be_const_str_lv_arc; extern const bcstring be_const_str_lv_bar; @@ -1246,6 +1277,8 @@ extern const bcstring be_const_str_match; extern const bcstring be_const_str_minute; extern const bcstring be_const_str_montserrat; extern const bcstring be_const_str_montserrat_font; +extern const bcstring be_const_str_new_head; +extern const bcstring be_const_str_new_tail; extern const bcstring be_const_str_no_bytes; extern const bcstring be_const_str_obj; extern const bcstring be_const_str_obj_event_base; @@ -1409,6 +1442,7 @@ extern const bcstring be_const_str_splash_init; extern const bcstring be_const_str_splash_remove; extern const bcstring be_const_str_splash_runner; extern const bcstring be_const_str_src; +extern const bcstring be_const_str_src_ep; extern const bcstring be_const_str_start_angle; extern const bcstring be_const_str_start_angle1; extern const bcstring be_const_str_started; @@ -1431,10 +1465,13 @@ extern const bcstring be_const_str_style_pad_top; extern const bcstring be_const_str_style_radius; extern const bcstring be_const_str_tag; extern const bcstring be_const_str_target_search; +extern const bcstring be_const_str_test_attr; +extern const bcstring be_const_str_test_msg; extern const bcstring be_const_str_text; extern const bcstring be_const_str_text_rule_matched; extern const bcstring be_const_str_theme_apply; extern const bcstring be_const_str_theme_haspmota_init; +extern const bcstring be_const_str_tojson; extern const bcstring be_const_str_touch_update; extern const bcstring be_const_str_unable_X20to_X20parse_X20JSON_X20line; extern const bcstring be_const_str_unknown_X20attribute_X20; @@ -1453,6 +1490,10 @@ extern const bcstring be_const_str_y1; extern const bcstring be_const_str_zb_coord; extern const bcstring be_const_str_zb_coord_ntv; extern const bcstring be_const_str_zb_device; +extern const bcstring be_const_str_zcl_attribute; +extern const bcstring be_const_str_zcl_attribute_list; +extern const bcstring be_const_str_zcl_attribute_list_ntv; +extern const bcstring be_const_str_zcl_attribute_ntv; extern const bcstring be_const_str_zcl_frame; extern const bcstring be_const_str_zcl_frame_ntv; extern const bcstring be_const_str__X7B_X22hasp_X22_X3A_X7B_X22p_X25i_X22_X3A_X22in_X22_X7D_X7D; diff --git a/lib/libesp32/berry/generate/be_const_strtab_def.h b/lib/libesp32/berry/generate/be_const_strtab_def.h index 1ac8d0010..397e612c3 100644 --- a/lib/libesp32/berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/berry/generate/be_const_strtab_def.h @@ -890,12 +890,21 @@ be_define_const_str(_X7D, "}", 4161554600u, 0, 1, NULL); /* weak strings */ be_define_const_str(_X20for_X20_X27obj_X27_X3A, " for 'obj':", 0u, 0, 11, NULL); +be_define_const_str(_X21, "!", 0u, 0, 1, NULL); +be_define_const_str(_X22Device_X22_X3A_X220x_X2504X_X22, "\"Device\":\"0x%04X\"", 0u, 0, 17, NULL); +be_define_const_str(_X22Endpoint_X22_X3A_X25i, "\"Endpoint\":%i", 0u, 0, 13, NULL); +be_define_const_str(_X22Group_X22_X3A_X220x_X2504X_X22, "\"Group\":\"0x%04X\"", 0u, 0, 16, NULL); +be_define_const_str(_X22LinkQuality_X22_X3A_X25i, "\"LinkQuality\":%i", 0u, 0, 16, NULL); be_define_const_str(_X23000000, "#000000", 0u, 0, 7, NULL); be_define_const_str(_X23FFFFFF, "#FFFFFF", 0u, 0, 7, NULL); be_define_const_str(_X2502d_X25s_X2502d, "%02d%s%02d", 0u, 0, 10, NULL); +be_define_const_str(_X2504X_X25s_X2502X, "%04X%s%02X", 0u, 0, 10, NULL); +be_define_const_str(_X2504X_X2F_X2504X, "%04X/%04X", 0u, 0, 9, NULL); be_define_const_str(_X27_X20not_X20found, "' not found", 0u, 0, 11, NULL); +be_define_const_str(_X28_X25s_X29, "(%s)", 0u, 0, 4, NULL); be_define_const_str(_X2C_X22text_X22_X3A, ",\"text\":", 0u, 0, 8, NULL); be_define_const_str(_X2C_X22val_X22_X3A_X25i, ",\"val\":%i", 0u, 0, 9, NULL); +be_define_const_str(_X2C_X25s_X3A_X22_X2504X_X2F_X2504X_X22, ",%s:\"%04X/%04X\"", 0u, 0, 15, NULL); be_define_const_str(_X2D_X2D_X3A_X2D_X2D, "--:--", 0u, 0, 5, NULL); be_define_const_str(_X2Ep1, ".p1", 0u, 0, 3, NULL); be_define_const_str(_X2Ep2, ".p2", 0u, 0, 3, NULL); @@ -903,6 +912,7 @@ be_define_const_str(0, "0", 0u, 0, 1, NULL); be_define_const_str(0x_X2504X, "0x%04X", 0u, 0, 6, NULL); be_define_const_str(9, "9", 0u, 0, 1, NULL); be_define_const_str(_X3Cinstance_X3A_X20_X25s_X280x_X2504X_X2C_X200x_X2508X_X2508X_X2C_X20name_X3A_X27_X25s_X27_X2C_X20model_X3A_X27_X25s_X27_X2C_X20manufacturer_X3A_X27_X25s_X27_X29_X3E, "", 0u, 0, 76, NULL); +be_define_const_str(_X3Cundefined_X3E, "", 0u, 0, 11, NULL); be_define_const_str(A, "A", 0u, 0, 1, NULL); be_define_const_str(AES_GCM, "AES_GCM", 0u, 0, 7, NULL); be_define_const_str(ALIGN_BOTTOM_MID, "ALIGN_BOTTOM_MID", 0u, 0, 16, NULL); @@ -983,13 +993,23 @@ be_define_const_str(TRUE, "TRUE", 0u, 0, 4, NULL); be_define_const_str(Tapp, "Tapp", 0u, 0, 4, NULL); be_define_const_str(X, "X", 0u, 0, 1, NULL); be_define_const_str(_action, "_action", 0u, 0, 7, NULL); +be_define_const_str(_attr_id, "_attr_id", 0u, 0, 8, NULL); be_define_const_str(_attr_ignore, "_attr_ignore", 0u, 0, 12, NULL); be_define_const_str(_attr_map, "_attr_map", 0u, 0, 9, NULL); +be_define_const_str(_cluster, "_cluster", 0u, 0, 8, NULL); +be_define_const_str(_deinit, "_deinit", 0u, 0, 7, NULL); be_define_const_str(_dir, "_dir", 0u, 0, 4, NULL); +be_define_const_str(_direction, "_direction", 0u, 0, 10, NULL); be_define_const_str(_event_map, "_event_map", 0u, 0, 10, NULL); be_define_const_str(_get_bytes, "_get_bytes", 0u, 0, 10, NULL); +be_define_const_str(_get_key, "_get_key", 0u, 0, 8, NULL); +be_define_const_str(_get_val, "_get_val", 0u, 0, 8, NULL); +be_define_const_str(_groupaddr, "_groupaddr", 0u, 0, 10, NULL); be_define_const_str(_handlers, "_handlers", 0u, 0, 9, NULL); +be_define_const_str(_init, "_init", 0u, 0, 5, NULL); +be_define_const_str(_iscmd, "_iscmd", 0u, 0, 6, NULL); be_define_const_str(_load, "_load", 0u, 0, 5, NULL); +be_define_const_str(_lqi, "_lqi", 0u, 0, 4, NULL); be_define_const_str(_lv_class, "_lv_class", 0u, 0, 9, NULL); be_define_const_str(_lv_label, "_lv_label", 0u, 0, 9, NULL); be_define_const_str(_lv_obj, "_lv_obj", 0u, 0, 7, NULL); @@ -1001,7 +1021,10 @@ be_define_const_str(_oh, "_oh", 0u, 0, 3, NULL); be_define_const_str(_page, "_page", 0u, 0, 5, NULL); be_define_const_str(_page_id, "_page_id", 0u, 0, 8, NULL); be_define_const_str(_set_bytes, "_set_bytes", 0u, 0, 10, NULL); +be_define_const_str(_set_key, "_set_key", 0u, 0, 8, NULL); +be_define_const_str(_set_val, "_set_val", 0u, 0, 8, NULL); be_define_const_str(_splash, "_splash", 0u, 0, 7, NULL); +be_define_const_str(_src_ep, "_src_ep", 0u, 0, 7, NULL); be_define_const_str(_text_rule, "_text_rule", 0u, 0, 10, NULL); be_define_const_str(_text_rule_format, "_text_rule_format", 0u, 0, 17, NULL); be_define_const_str(_text_rule_formula, "_text_rule_formula", 0u, 0, 18, NULL); @@ -1021,6 +1044,7 @@ be_define_const_str(angle, "angle", 0u, 0, 5, NULL); be_define_const_str(arc_dsc, "arc_dsc", 0u, 0, 7, NULL); be_define_const_str(area, "area", 0u, 0, 4, NULL); be_define_const_str(atleast1, "atleast1", 0u, 0, 8, NULL); +be_define_const_str(attr_id, "attr_id", 0u, 0, 7, NULL); be_define_const_str(attribute_error, "attribute_error", 0u, 0, 15, NULL); be_define_const_str(auto_size, "auto_size", 0u, 0, 9, NULL); be_define_const_str(b0, "b0", 0u, 0, 2, NULL); @@ -1042,6 +1066,7 @@ be_define_const_str(clear_flag, "clear_flag", 0u, 0, 10, NULL); be_define_const_str(clear_state, "clear_state", 0u, 0, 11, NULL); be_define_const_str(clock, "clock", 0u, 0, 5, NULL); be_define_const_str(clock_icon, "clock_icon", 0u, 0, 10, NULL); +be_define_const_str(cluster, "cluster", 0u, 0, 7, NULL); be_define_const_str(color, "color", 0u, 0, 5, NULL); be_define_const_str(color_X24, "color$", 0u, 0, 6, NULL); be_define_const_str(comment, "comment", 0u, 0, 7, NULL); @@ -1058,6 +1083,7 @@ be_define_const_str(del, "del", 0u, 0, 3, NULL); be_define_const_str(depower, "depower", 0u, 0, 7, NULL); be_define_const_str(dim, "dim", 0u, 0, 3, NULL); be_define_const_str(dimmer, "dimmer", 0u, 0, 6, NULL); +be_define_const_str(direction, "direction", 0u, 0, 9, NULL); be_define_const_str(dispatch, "dispatch", 0u, 0, 8, NULL); be_define_const_str(do_action, "do_action", 0u, 0, 9, NULL); be_define_const_str(dots, "dots", 0u, 0, 4, NULL); @@ -1152,6 +1178,7 @@ be_define_const_str(get_ver_res, "get_ver_res", 0u, 0, 11, NULL); be_define_const_str(get_width, "get_width", 0u, 0, 9, NULL); be_define_const_str(get_x, "get_x", 0u, 0, 5, NULL); be_define_const_str(get_y, "get_y", 0u, 0, 5, NULL); +be_define_const_str(groupaddr, "groupaddr", 0u, 0, 9, NULL); be_define_const_str(has_flag, "has_flag", 0u, 0, 8, NULL); be_define_const_str(has_state, "has_state", 0u, 0, 9, NULL); be_define_const_str(height, "height", 0u, 0, 6, NULL); @@ -1169,6 +1196,9 @@ be_define_const_str(io_erorr, "io_erorr", 0u, 0, 8, NULL); be_define_const_str(ip, "ip", 0u, 0, 2, NULL); be_define_const_str(is_color_attribute, "is_color_attribute", 0u, 0, 18, NULL); be_define_const_str(isrunning, "isrunning", 0u, 0, 9, NULL); +be_define_const_str(key, "key", 0u, 0, 3, NULL); +be_define_const_str(key_suffix, "key_suffix", 0u, 0, 10, NULL); +be_define_const_str(key_tostring, "key_tostring", 0u, 0, 12, NULL); be_define_const_str(layer_top, "layer_top", 0u, 0, 9, NULL); be_define_const_str(left, "left", 0u, 0, 4, NULL); be_define_const_str(line_color, "line_color", 0u, 0, 10, NULL); @@ -1180,6 +1210,7 @@ be_define_const_str(long, "long", 0u, 0, 4, NULL); be_define_const_str(longaddr, "longaddr", 0u, 0, 8, NULL); be_define_const_str(loop, "loop", 0u, 0, 4, NULL); be_define_const_str(lost, "lost", 0u, 0, 4, NULL); +be_define_const_str(lqi, "lqi", 0u, 0, 3, NULL); be_define_const_str(lv_anim, "lv_anim", 0u, 0, 7, NULL); be_define_const_str(lv_arc, "lv_arc", 0u, 0, 6, NULL); be_define_const_str(lv_bar, "lv_bar", 0u, 0, 6, NULL); @@ -1247,6 +1278,8 @@ be_define_const_str(match, "match", 0u, 0, 5, NULL); be_define_const_str(minute, "minute", 0u, 0, 6, NULL); be_define_const_str(montserrat, "montserrat", 0u, 0, 10, NULL); be_define_const_str(montserrat_font, "montserrat_font", 0u, 0, 15, NULL); +be_define_const_str(new_head, "new_head", 0u, 0, 8, NULL); +be_define_const_str(new_tail, "new_tail", 0u, 0, 8, NULL); be_define_const_str(no_bytes, "no_bytes", 0u, 0, 8, NULL); be_define_const_str(obj, "obj", 0u, 0, 3, NULL); be_define_const_str(obj_event_base, "obj_event_base", 0u, 0, 14, NULL); @@ -1410,6 +1443,7 @@ be_define_const_str(splash_init, "splash_init", 0u, 0, 11, NULL); be_define_const_str(splash_remove, "splash_remove", 0u, 0, 13, NULL); be_define_const_str(splash_runner, "splash_runner", 0u, 0, 13, NULL); be_define_const_str(src, "src", 0u, 0, 3, NULL); +be_define_const_str(src_ep, "src_ep", 0u, 0, 6, NULL); be_define_const_str(start_angle, "start_angle", 0u, 0, 11, NULL); be_define_const_str(start_angle1, "start_angle1", 0u, 0, 12, NULL); be_define_const_str(started, "started", 0u, 0, 7, NULL); @@ -1432,10 +1466,13 @@ be_define_const_str(style_pad_top, "style_pad_top", 0u, 0, 13, NULL); be_define_const_str(style_radius, "style_radius", 0u, 0, 12, NULL); be_define_const_str(tag, "tag", 0u, 0, 3, NULL); be_define_const_str(target_search, "target_search", 0u, 0, 13, NULL); +be_define_const_str(test_attr, "test_attr", 0u, 0, 9, NULL); +be_define_const_str(test_msg, "test_msg", 0u, 0, 8, NULL); be_define_const_str(text, "text", 0u, 0, 4, NULL); be_define_const_str(text_rule_matched, "text_rule_matched", 0u, 0, 17, NULL); be_define_const_str(theme_apply, "theme_apply", 0u, 0, 11, NULL); be_define_const_str(theme_haspmota_init, "theme_haspmota_init", 0u, 0, 19, NULL); +be_define_const_str(tojson, "tojson", 0u, 0, 6, NULL); be_define_const_str(touch_update, "touch_update", 0u, 0, 12, NULL); be_define_const_str(unable_X20to_X20parse_X20JSON_X20line, "unable to parse JSON line", 0u, 0, 25, NULL); be_define_const_str(unknown_X20attribute_X20, "unknown attribute ", 0u, 0, 18, NULL); @@ -1454,6 +1491,10 @@ be_define_const_str(y1, "y1", 0u, 0, 2, NULL); be_define_const_str(zb_coord, "zb_coord", 0u, 0, 8, NULL); be_define_const_str(zb_coord_ntv, "zb_coord_ntv", 0u, 0, 12, NULL); be_define_const_str(zb_device, "zb_device", 0u, 0, 9, NULL); +be_define_const_str(zcl_attribute, "zcl_attribute", 0u, 0, 13, NULL); +be_define_const_str(zcl_attribute_list, "zcl_attribute_list", 0u, 0, 18, NULL); +be_define_const_str(zcl_attribute_list_ntv, "zcl_attribute_list_ntv", 0u, 0, 22, NULL); +be_define_const_str(zcl_attribute_ntv, "zcl_attribute_ntv", 0u, 0, 17, NULL); be_define_const_str(zcl_frame, "zcl_frame", 0u, 0, 9, NULL); be_define_const_str(zcl_frame_ntv, "zcl_frame_ntv", 0u, 0, 13, NULL); be_define_const_str(_X7B_X22hasp_X22_X3A_X7B_X22p_X25i_X22_X3A_X22in_X22_X7D_X7D, "{\"hasp\":{\"p%i\":\"in\"}}", 0u, 0, 21, NULL); diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_zb_coord_ntv.h b/lib/libesp32/berry/generate/be_fixed_be_class_zb_coord_ntv.h index 5d957ae4a..3c63d5d83 100644 --- a/lib/libesp32/berry/generate/be_fixed_be_class_zb_coord_ntv.h +++ b/lib/libesp32/berry/generate/be_fixed_be_class_zb_coord_ntv.h @@ -1,18 +1,24 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_zb_coord_ntv_map) { + { be_const_key_weak(zb_device, -1), be_const_class(be_class_zb_device) }, + { be_const_key_weak(zcl_attribute, -1), be_const_class(be_class_zcl_attribute) }, + { be_const_key_weak(item, 5), be_const_func(zc_item) }, { be_const_key_weak(iter, -1), be_const_func(zc_iter) }, + { be_const_key_weak(zcl_attribute_ntv, 1), be_const_class(be_class_zcl_attribute_ntv) }, + { be_const_key_weak(test_msg, 10), be_const_func(zigbee_test_msg) }, + { be_const_key_weak(size, -1), be_const_ctype_func(zc_size) }, + { be_const_key_weak(test_attr, -1), be_const_func(zigbee_test_attr) }, + { be_const_key_weak(abort, -1), be_const_ctype_func(zc_abort) }, + { be_const_key_weak(zcl_attribute_list, -1), be_const_class(be_class_zcl_attribute_list) }, { be_const_key_weak(zcl_frame, -1), be_const_class(be_class_zcl_frame) }, - { be_const_key_weak(zb_device, 3), be_const_class(be_class_zb_device) }, - { be_const_key_weak(info, -1), be_const_func(zc_info) }, - { be_const_key_weak(size, 1), be_const_ctype_func(zc_size) }, - { be_const_key_weak(item, -1), be_const_func(zc_item) }, - { be_const_key_weak(abort, 4), be_const_ctype_func(zc_abort) }, + { be_const_key_weak(zcl_attribute_list_ntv, -1), be_const_class(be_class_zcl_attribute_list_ntv) }, + { be_const_key_weak(info, 6), be_const_func(zc_info) }, }; static be_define_const_map( be_class_zb_coord_ntv_map, - 7 + 13 ); BE_EXPORT_VARIABLE be_define_const_class( diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_zcl_attribute_list_ntv.h b/lib/libesp32/berry/generate/be_fixed_be_class_zcl_attribute_list_ntv.h new file mode 100644 index 000000000..6333049c6 --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_be_class_zcl_attribute_list_ntv.h @@ -0,0 +1,24 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_zcl_attribute_list_ntv_map) { + { be_const_key_weak(new_tail, -1), be_const_func(&be_zigbee_zcl_attribute_list_ntv_new_tail) }, + { be_const_key_weak(new_head, 0), be_const_func(&be_zigbee_zcl_attribute_list_ntv_new_head) }, + { be_const_key_weak(_def, -1), be_const_comptr(&be_zigbee_zcl_attribute_list_struct) }, + { be_const_key_weak(_init, 1), be_const_func(&be_zigbee_zcl_attribute_list_ntv_init) }, + { be_const_key_weak(size, 3), be_const_func(&be_zigbee_zcl_attribute_list_ntv_size) }, + { be_const_key_weak(remove, 2), be_const_func(&be_zigbee_zcl_attribute_list_ntv_remove) }, + { be_const_key_weak(item, -1), be_const_func(&be_zigbee_zcl_attribute_list_ntv_item) }, + { be_const_key_weak(_deinit, -1), be_const_func(&be_zigbee_zcl_attribute_list_ntv_deinit) }, +}; + +static be_define_const_map( + be_class_zcl_attribute_list_ntv_map, + 8 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_zcl_attribute_list_ntv, + 0, + (bclass *)&be_class_ctypes_bytes, + zcl_attribute_list_ntv +); diff --git a/lib/libesp32/berry/generate/be_fixed_be_class_zcl_attribute_ntv.h b/lib/libesp32/berry/generate/be_fixed_be_class_zcl_attribute_ntv.h new file mode 100644 index 000000000..651bff187 --- /dev/null +++ b/lib/libesp32/berry/generate/be_fixed_be_class_zcl_attribute_ntv.h @@ -0,0 +1,23 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_zcl_attribute_ntv_map) { + { be_const_key_weak(_def, -1), be_const_comptr(&be_zigbee_zcl_attribute_struct) }, + { be_const_key_weak(_get_val, -1), be_const_func(be_zigbee_zcl_attribute_ntv_get_val) }, + { be_const_key_weak(_set_key, 0), be_const_func(be_zigbee_zcl_attribute_ntv_set_key) }, + { be_const_key_weak(_deinit, -1), be_const_func(&be_zigbee_zcl_attribute_ntv_deinit) }, + { be_const_key_weak(_set_val, -1), be_const_func(be_zigbee_zcl_attribute_ntv_set_val) }, + { be_const_key_weak(_get_key, -1), be_const_func(be_zigbee_zcl_attribute_ntv_get_key) }, + { be_const_key_weak(_init, 1), be_const_func(&be_zigbee_zcl_attribute_ntv_init) }, +}; + +static be_define_const_map( + be_class_zcl_attribute_ntv_map, + 7 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_zcl_attribute_ntv, + 0, + (bclass *)&be_class_ctypes_bytes, + zcl_attribute_ntv +); diff --git a/lib/libesp32/berry_tasmota/src/be_zigbee.c b/lib/libesp32/berry_tasmota/src/be_zigbee.c index a7efdfa25..c6fab141f 100644 --- a/lib/libesp32/berry_tasmota/src/be_zigbee.c +++ b/lib/libesp32/berry_tasmota/src/be_zigbee.c @@ -55,9 +55,16 @@ extern int32_t zc_size(void* d); BE_FUNC_CTYPE_DECLARE(zc_size, "i extern int zc_iter(bvm *vm); extern void zc_abort(void); BE_FUNC_CTYPE_DECLARE(zc_abort, "", "."); +extern int zigbee_test_attr(struct bvm *vm); +extern int zigbee_test_msg(struct bvm *vm); + extern const bclass be_class_ctypes_bytes; extern const be_ctypes_structure_t be_zigbee_zcl_frame_struct; extern const bclass be_class_zcl_frame; +extern const bclass be_class_zcl_attribute_list_ntv; +extern const bclass be_class_zcl_attribute_ntv; +extern const bclass be_class_zcl_attribute; +extern const bclass be_class_zcl_attribute_list; /******************************************************************** ** Solidified function: tostring @@ -153,6 +160,10 @@ class be_class_zb_device (scope: global, name: zb_device, strings: weak) { /* @const_object_info_begin class be_class_zb_coord_ntv (scope: global, name: zb_coord_ntv, strings: weak) { zcl_frame, class(be_class_zcl_frame) + zcl_attribute_list_ntv, class(be_class_zcl_attribute_list_ntv) + zcl_attribute_ntv, class(be_class_zcl_attribute_ntv) + zcl_attribute, class(be_class_zcl_attribute) + zcl_attribute_list, class(be_class_zcl_attribute_list) zb_device, class(be_class_zb_device) info, func(zc_info) @@ -161,6 +172,9 @@ class be_class_zb_coord_ntv (scope: global, name: zb_coord_ntv, strings: weak) { iter, func(zc_iter) abort, ctype_func(zc_abort) + + test_attr, func(zigbee_test_attr) + test_msg, func(zigbee_test_msg) } @const_object_info_end */ @@ -169,8 +183,8 @@ class be_class_zb_coord_ntv (scope: global, name: zb_coord_ntv, strings: weak) { class be_class_zcl_frame_ntv (scope: global, name: zcl_frame_ntv, super: be_class_ctypes_bytes, strings: weak) { _def, comptr(&be_zigbee_zcl_frame_struct) - _get_bytes, ctype_func(zfn_get_bytes) - _set_bytes, ctype_func(zfn_set_bytes) + _get_bytes, ctype_func(zfn_get_bytes) + _set_bytes, ctype_func(zfn_set_bytes) } @const_object_info_end */ diff --git a/lib/libesp32/berry_tasmota/src/be_zigbee_zb_coord.c b/lib/libesp32/berry_tasmota/src/be_zigbee_zb_coord.c index 4906b1aa3..f1f63c60b 100644 --- a/lib/libesp32/berry_tasmota/src/be_zigbee_zb_coord.c +++ b/lib/libesp32/berry_tasmota/src/be_zigbee_zb_coord.c @@ -92,7 +92,7 @@ be_local_closure(zb_coord_add_handler, /* name */ ********************************************************************/ be_local_closure(zb_coord_dispatch, /* name */ be_nested_proto( - 19, /* nstack */ + 21, /* nstack */ 5, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -100,25 +100,27 @@ be_local_closure(zb_coord_dispatch, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[16]) { /* constants */ /* K0 */ be_nested_str_weak(_handlers), /* K1 */ be_nested_str_weak(introspect), /* K2 */ be_nested_str_weak(string), - /* K3 */ be_nested_str_weak(zcl_frame), + /* K3 */ be_nested_str_weak(toptr), /* K4 */ be_const_int(0), - /* K5 */ be_nested_str_weak(get), - /* K6 */ be_nested_str_weak(function), - /* K7 */ be_nested_str_weak(format), - /* K8 */ be_nested_str_weak(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s), - /* K9 */ be_nested_str_weak(tasmota), - /* K10 */ be_nested_str_weak(_debug_present), - /* K11 */ be_nested_str_weak(debug), - /* K12 */ be_nested_str_weak(traceback), - /* K13 */ be_const_int(1), + /* K5 */ be_nested_str_weak(zcl_frame), + /* K6 */ be_nested_str_weak(zcl_attribute_list), + /* K7 */ be_nested_str_weak(get), + /* K8 */ be_nested_str_weak(function), + /* K9 */ be_nested_str_weak(format), + /* K10 */ be_nested_str_weak(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s), + /* K11 */ be_nested_str_weak(tasmota), + /* K12 */ be_nested_str_weak(_debug_present), + /* K13 */ be_nested_str_weak(debug), + /* K14 */ be_nested_str_weak(traceback), + /* K15 */ be_const_int(1), }), be_str_weak(dispatch), &be_const_str_solidified, - ( &(const binstruction[61]) { /* code */ + ( &(const binstruction[71]) { /* code */ 0x88140100, // 0000 GETMBR R5 R0 K0 0x4C180000, // 0001 LDNIL R6 0x1C140A06, // 0002 EQ R5 R5 R6 @@ -126,60 +128,70 @@ be_local_closure(zb_coord_dispatch, /* name */ 0x80000A00, // 0004 RET 0 0xA4160200, // 0005 IMPORT R5 K1 0xA41A0400, // 0006 IMPORT R6 K2 - 0x5C1C0600, // 0007 MOVE R7 R3 - 0x1C200503, // 0008 EQ R8 R2 K3 - 0x78220003, // 0009 JMPF R8 #000E - 0x8C200103, // 000A GETMET R8 R0 K3 - 0x5C280600, // 000B MOVE R10 R3 - 0x7C200400, // 000C CALL R8 2 - 0x5C1C1000, // 000D MOVE R7 R8 - 0x58200004, // 000E LDCONST R8 K4 - 0x6024000C, // 000F GETGBL R9 G12 - 0x88280100, // 0010 GETMBR R10 R0 K0 - 0x7C240200, // 0011 CALL R9 1 - 0x14241009, // 0012 LT R9 R8 R9 - 0x78260027, // 0013 JMPF R9 #003C - 0x88240100, // 0014 GETMBR R9 R0 K0 - 0x94241208, // 0015 GETIDX R9 R9 R8 - 0x8C280B05, // 0016 GETMET R10 R5 K5 - 0x5C301200, // 0017 MOVE R12 R9 - 0x5C340200, // 0018 MOVE R13 R1 - 0x7C280600, // 0019 CALL R10 3 - 0x602C0004, // 001A GETGBL R11 G4 - 0x5C301400, // 001B MOVE R12 R10 - 0x7C2C0200, // 001C CALL R11 1 - 0x1C2C1706, // 001D EQ R11 R11 K6 - 0x782E001A, // 001E JMPF R11 #003A - 0xA8020008, // 001F EXBLK 0 #0029 - 0x5C2C1400, // 0020 MOVE R11 R10 - 0x5C301200, // 0021 MOVE R12 R9 - 0x5C340200, // 0022 MOVE R13 R1 - 0x5C380400, // 0023 MOVE R14 R2 - 0x5C3C0E00, // 0024 MOVE R15 R7 - 0x5C400800, // 0025 MOVE R16 R4 - 0x7C2C0A00, // 0026 CALL R11 5 - 0xA8040001, // 0027 EXBLK 1 1 - 0x70020010, // 0028 JMP #003A - 0xAC2C0002, // 0029 CATCH R11 0 2 - 0x7002000D, // 002A JMP #0039 - 0x60340001, // 002B GETGBL R13 G1 - 0x8C380D07, // 002C GETMET R14 R6 K7 - 0x58400008, // 002D LDCONST R16 K8 - 0x5C441600, // 002E MOVE R17 R11 - 0x5C481800, // 002F MOVE R18 R12 - 0x7C380800, // 0030 CALL R14 4 - 0x7C340200, // 0031 CALL R13 1 - 0xB8361200, // 0032 GETNGBL R13 K9 - 0x88341B0A, // 0033 GETMBR R13 R13 K10 - 0x78360002, // 0034 JMPF R13 #0038 - 0xA4361600, // 0035 IMPORT R13 K11 - 0x8C381B0C, // 0036 GETMET R14 R13 K12 - 0x7C380200, // 0037 CALL R14 1 - 0x70020000, // 0038 JMP #003A - 0xB0080000, // 0039 RAISE 2 R0 R0 - 0x0020110D, // 003A ADD R8 R8 K13 - 0x7001FFD2, // 003B JMP #000F - 0x80000000, // 003C RET 0 + 0x4C1C0000, // 0007 LDNIL R7 + 0x4C200000, // 0008 LDNIL R8 + 0x8C240B03, // 0009 GETMET R9 R5 K3 + 0x582C0004, // 000A LDCONST R11 K4 + 0x7C240400, // 000B CALL R9 2 + 0x20280409, // 000C NE R10 R2 R9 + 0x782A0003, // 000D JMPF R10 #0012 + 0x8C280105, // 000E GETMET R10 R0 K5 + 0x5C300400, // 000F MOVE R12 R2 + 0x7C280400, // 0010 CALL R10 2 + 0x5C1C1400, // 0011 MOVE R7 R10 + 0x20280609, // 0012 NE R10 R3 R9 + 0x782A0003, // 0013 JMPF R10 #0018 + 0x8C280106, // 0014 GETMET R10 R0 K6 + 0x5C300600, // 0015 MOVE R12 R3 + 0x7C280400, // 0016 CALL R10 2 + 0x5C201400, // 0017 MOVE R8 R10 + 0x58280004, // 0018 LDCONST R10 K4 + 0x602C000C, // 0019 GETGBL R11 G12 + 0x88300100, // 001A GETMBR R12 R0 K0 + 0x7C2C0200, // 001B CALL R11 1 + 0x142C140B, // 001C LT R11 R10 R11 + 0x782E0027, // 001D JMPF R11 #0046 + 0x882C0100, // 001E GETMBR R11 R0 K0 + 0x942C160A, // 001F GETIDX R11 R11 R10 + 0x8C300B07, // 0020 GETMET R12 R5 K7 + 0x5C381600, // 0021 MOVE R14 R11 + 0x5C3C0200, // 0022 MOVE R15 R1 + 0x7C300600, // 0023 CALL R12 3 + 0x60340004, // 0024 GETGBL R13 G4 + 0x5C381800, // 0025 MOVE R14 R12 + 0x7C340200, // 0026 CALL R13 1 + 0x1C341B08, // 0027 EQ R13 R13 K8 + 0x7836001A, // 0028 JMPF R13 #0044 + 0xA8020008, // 0029 EXBLK 0 #0033 + 0x5C341800, // 002A MOVE R13 R12 + 0x5C381600, // 002B MOVE R14 R11 + 0x5C3C0200, // 002C MOVE R15 R1 + 0x5C400E00, // 002D MOVE R16 R7 + 0x5C441000, // 002E MOVE R17 R8 + 0x5C480800, // 002F MOVE R18 R4 + 0x7C340A00, // 0030 CALL R13 5 + 0xA8040001, // 0031 EXBLK 1 1 + 0x70020010, // 0032 JMP #0044 + 0xAC340002, // 0033 CATCH R13 0 2 + 0x7002000D, // 0034 JMP #0043 + 0x603C0001, // 0035 GETGBL R15 G1 + 0x8C400D09, // 0036 GETMET R16 R6 K9 + 0x5848000A, // 0037 LDCONST R18 K10 + 0x5C4C1A00, // 0038 MOVE R19 R13 + 0x5C501C00, // 0039 MOVE R20 R14 + 0x7C400800, // 003A CALL R16 4 + 0x7C3C0200, // 003B CALL R15 1 + 0xB83E1600, // 003C GETNGBL R15 K11 + 0x883C1F0C, // 003D GETMBR R15 R15 K12 + 0x783E0002, // 003E JMPF R15 #0042 + 0xA43E1A00, // 003F IMPORT R15 K13 + 0x8C401F0E, // 0040 GETMET R16 R15 K14 + 0x7C400200, // 0041 CALL R16 1 + 0x70020000, // 0042 JMP #0044 + 0xB0080000, // 0043 RAISE 2 R0 R0 + 0x0028150F, // 0044 ADD R10 R10 K15 + 0x7001FFD2, // 0045 JMP #0019 + 0x80000000, // 0046 RET 0 }) ) ); diff --git a/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attribute_list_ntv.c b/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attribute_list_ntv.c new file mode 100644 index 000000000..d2e42f590 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attribute_list_ntv.c @@ -0,0 +1,38 @@ +/******************************************************************** + * Zigbee zcl_attribute_list native format + * + *******************************************************************/ +#ifdef USE_ZIGBEE + +#include "be_constobj.h" +#include "be_mapping.h" +#include "be_ctypes.h" + +extern const bclass be_class_ctypes_bytes; +extern const be_ctypes_structure_t be_zigbee_zcl_attribute_list_struct; + +extern int be_zigbee_zcl_attribute_list_ntv_init(struct bvm *vm); +extern int be_zigbee_zcl_attribute_list_ntv_deinit(struct bvm *vm); +extern int be_zigbee_zcl_attribute_list_ntv_size(struct bvm *vm); +extern int be_zigbee_zcl_attribute_list_ntv_item(struct bvm *vm); +extern int be_zigbee_zcl_attribute_list_ntv_remove(struct bvm *vm); +extern int be_zigbee_zcl_attribute_list_ntv_new_head(struct bvm *vm); +extern int be_zigbee_zcl_attribute_list_ntv_new_tail(struct bvm *vm); + +#include "be_fixed_be_class_zcl_attribute_list_ntv.h" + +/* @const_object_info_begin +class be_class_zcl_attribute_list_ntv (scope: global, name: zcl_attribute_list_ntv, super: be_class_ctypes_bytes, strings: weak) { + _def, comptr(&be_zigbee_zcl_attribute_list_struct) + _init, func(&be_zigbee_zcl_attribute_list_ntv_init) + _deinit, func(&be_zigbee_zcl_attribute_list_ntv_deinit) + + size, func(&be_zigbee_zcl_attribute_list_ntv_size) + item, func(&be_zigbee_zcl_attribute_list_ntv_item) + new_head, func(&be_zigbee_zcl_attribute_list_ntv_new_head) + new_tail, func(&be_zigbee_zcl_attribute_list_ntv_new_tail) + remove, func(&be_zigbee_zcl_attribute_list_ntv_remove) +} +@const_object_info_end */ + +#endif // USE_LIGHT diff --git a/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attribute_ntv.c b/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attribute_ntv.c new file mode 100644 index 000000000..d609afa19 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attribute_ntv.c @@ -0,0 +1,36 @@ +/******************************************************************** + * Zigbee zcl_attribute native format + * + *******************************************************************/ +#ifdef USE_ZIGBEE + +#include "be_constobj.h" +#include "be_mapping.h" +#include "be_ctypes.h" + +extern const bclass be_class_ctypes_bytes; +extern const be_ctypes_structure_t be_zigbee_zcl_attribute_struct; + +extern int be_zigbee_zcl_attribute_ntv_init(struct bvm *vm); +extern int be_zigbee_zcl_attribute_ntv_deinit(struct bvm *vm); +extern int be_zigbee_zcl_attribute_ntv_get_val(struct bvm *vm); +extern int be_zigbee_zcl_attribute_ntv_set_val(struct bvm *vm); +extern int be_zigbee_zcl_attribute_ntv_get_key(struct bvm *vm); +extern int be_zigbee_zcl_attribute_ntv_set_key(struct bvm *vm); + +#include "be_fixed_be_class_zcl_attribute_ntv.h" + +/* @const_object_info_begin +class be_class_zcl_attribute_ntv (scope: global, name: zcl_attribute_ntv, super: be_class_ctypes_bytes, strings: weak) { + _def, comptr(&be_zigbee_zcl_attribute_struct) + _init, func(&be_zigbee_zcl_attribute_ntv_init) + _deinit, func(&be_zigbee_zcl_attribute_ntv_deinit) + + _get_val, func(be_zigbee_zcl_attribute_ntv_get_val) + _set_val, func(be_zigbee_zcl_attribute_ntv_set_val) + _get_key, func(be_zigbee_zcl_attribute_ntv_get_key) + _set_key, func(be_zigbee_zcl_attribute_ntv_set_key) +} +@const_object_info_end */ + +#endif // USE_LIGHT diff --git a/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attributes.c b/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attributes.c new file mode 100644 index 000000000..b9b9a26a1 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_zigbee_zcl_attributes.c @@ -0,0 +1,928 @@ +/******************************************************************** + * Zigbee + * + *******************************************************************/ +#ifdef USE_ZIGBEE + +#include "be_constobj.h" + + +/******************************************************************** +** Solidified function: tomap +********************************************************************/ +be_local_closure(zcl_attribute_tomap, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(tomap), + /* K1 */ be_nested_str_weak(cluster), + /* K2 */ be_nested_str_weak(attr_id), + /* K3 */ be_nested_str_weak(cmd), + /* K4 */ be_nested_str_weak(direction), + /* K5 */ be_nested_str_weak(key), + /* K6 */ be_nested_str_weak(val), + }), + be_str_weak(tomap), + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ + 0x60040003, // 0000 GETGBL R1 G3 + 0x5C080000, // 0001 MOVE R2 R0 + 0x7C040200, // 0002 CALL R1 1 + 0x8C040300, // 0003 GETMET R1 R1 K0 + 0x7C040200, // 0004 CALL R1 1 + 0x88080101, // 0005 GETMBR R2 R0 K1 + 0x98060202, // 0006 SETIDX R1 K1 R2 + 0x88080102, // 0007 GETMBR R2 R0 K2 + 0x98060402, // 0008 SETIDX R1 K2 R2 + 0x88080103, // 0009 GETMBR R2 R0 K3 + 0x98060602, // 000A SETIDX R1 K3 R2 + 0x88080104, // 000B GETMBR R2 R0 K4 + 0x98060802, // 000C SETIDX R1 K4 R2 + 0x88080105, // 000D GETMBR R2 R0 K5 + 0x98060A02, // 000E SETIDX R1 K5 R2 + 0x88080106, // 000F GETMBR R2 R0 K6 + 0x98060C02, // 0010 SETIDX R1 K6 R2 + 0x80040200, // 0011 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: key_tostring +********************************************************************/ +be_local_closure(zcl_attribute_key_tostring, /* name */ + be_nested_proto( + 10, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[15]) { /* constants */ + /* K0 */ be_nested_str_weak(string), + /* K1 */ be_nested_str_weak(_X3Cundefined_X3E), + /* K2 */ be_nested_str_weak(key), + /* K3 */ be_nested_str_weak(key_suffix), + /* K4 */ be_const_int(1), + /* K5 */ be_nested_str_weak(cluster), + /* K6 */ be_nested_str_weak(attr_id), + /* K7 */ be_nested_str_weak(format), + /* K8 */ be_nested_str_weak(_X2504X_X2F_X2504X), + /* K9 */ be_nested_str_weak(_X2B), + /* K10 */ be_nested_str_weak(cmd), + /* K11 */ be_nested_str_weak(direction), + /* K12 */ be_nested_str_weak(_X2504X_X25s_X2502X), + /* K13 */ be_nested_str_weak(_X3C), + /* K14 */ be_nested_str_weak(_X21), + }), + be_str_weak(key_tostring), + &be_const_str_solidified, + ( &(const binstruction[70]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x58080001, // 0001 LDCONST R2 K1 + 0x880C0102, // 0002 GETMBR R3 R0 K2 + 0x4C100000, // 0003 LDNIL R4 + 0x20100604, // 0004 NE R4 R3 R4 + 0x78120008, // 0005 JMPF R4 #000F + 0x5C080600, // 0006 MOVE R2 R3 + 0x88100103, // 0007 GETMBR R4 R0 K3 + 0x24100904, // 0008 GT R4 R4 K4 + 0x78120003, // 0009 JMPF R4 #000E + 0x60100008, // 000A GETGBL R4 G8 + 0x88140103, // 000B GETMBR R5 R0 K3 + 0x7C100200, // 000C CALL R4 1 + 0x00080404, // 000D ADD R2 R2 R4 + 0x70020035, // 000E JMP #0045 + 0x88100105, // 000F GETMBR R4 R0 K5 + 0x4C140000, // 0010 LDNIL R5 + 0x20100805, // 0011 NE R4 R4 R5 + 0x78120012, // 0012 JMPF R4 #0026 + 0x88100106, // 0013 GETMBR R4 R0 K6 + 0x4C140000, // 0014 LDNIL R5 + 0x20100805, // 0015 NE R4 R4 R5 + 0x7812000E, // 0016 JMPF R4 #0026 + 0x8C100307, // 0017 GETMET R4 R1 K7 + 0x58180008, // 0018 LDCONST R6 K8 + 0x881C0105, // 0019 GETMBR R7 R0 K5 + 0x88200106, // 001A GETMBR R8 R0 K6 + 0x7C100800, // 001B CALL R4 4 + 0x5C080800, // 001C MOVE R2 R4 + 0x88100103, // 001D GETMBR R4 R0 K3 + 0x24100904, // 001E GT R4 R4 K4 + 0x78120004, // 001F JMPF R4 #0025 + 0x60100008, // 0020 GETGBL R4 G8 + 0x88140103, // 0021 GETMBR R5 R0 K3 + 0x7C100200, // 0022 CALL R4 1 + 0x00121204, // 0023 ADD R4 K9 R4 + 0x00080404, // 0024 ADD R2 R2 R4 + 0x7002001E, // 0025 JMP #0045 + 0x88100105, // 0026 GETMBR R4 R0 K5 + 0x4C140000, // 0027 LDNIL R5 + 0x20100805, // 0028 NE R4 R4 R5 + 0x7812001A, // 0029 JMPF R4 #0045 + 0x8810010A, // 002A GETMBR R4 R0 K10 + 0x4C140000, // 002B LDNIL R5 + 0x20100805, // 002C NE R4 R4 R5 + 0x78120016, // 002D JMPF R4 #0045 + 0x8810010B, // 002E GETMBR R4 R0 K11 + 0x4C140000, // 002F LDNIL R5 + 0x20100805, // 0030 NE R4 R4 R5 + 0x78120012, // 0031 JMPF R4 #0045 + 0x8C100307, // 0032 GETMET R4 R1 K7 + 0x5818000C, // 0033 LDCONST R6 K12 + 0x881C0105, // 0034 GETMBR R7 R0 K5 + 0x8820010B, // 0035 GETMBR R8 R0 K11 + 0x78220001, // 0036 JMPF R8 #0039 + 0x5820000D, // 0037 LDCONST R8 K13 + 0x70020000, // 0038 JMP #003A + 0x5820000E, // 0039 LDCONST R8 K14 + 0x8824010A, // 003A GETMBR R9 R0 K10 + 0x7C100A00, // 003B CALL R4 5 + 0x5C080800, // 003C MOVE R2 R4 + 0x88100103, // 003D GETMBR R4 R0 K3 + 0x24100904, // 003E GT R4 R4 K4 + 0x78120004, // 003F JMPF R4 #0045 + 0x60100008, // 0040 GETGBL R4 G8 + 0x88140103, // 0041 GETMBR R5 R0 K3 + 0x7C100200, // 0042 CALL R4 1 + 0x00121204, // 0043 ADD R4 K9 R4 + 0x00080404, // 0044 ADD R2 R2 R4 + 0x80040400, // 0045 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: deinit +********************************************************************/ +be_local_closure(zcl_attribute_deinit, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(ismapped), + /* K1 */ be_nested_str_weak(_deinit), + }), + be_str_weak(deinit), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x74060001, // 0002 JMPT R1 #0005 + 0x8C040101, // 0003 GETMET R1 R0 K1 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: tostring +********************************************************************/ +be_local_closure(zcl_attribute_tostring, /* name */ + be_nested_proto( + 12, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[15]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(json), + /* K2 */ be_nested_str_weak(string), + /* K3 */ be_nested_str_weak(dump), + /* K4 */ be_nested_str_weak(key_tostring), + /* K5 */ be_nested_str_weak(_X3A), + /* K6 */ be_nested_str_weak(get), + /* K7 */ be_nested_str_weak(val), + /* K8 */ be_nested_str_weak(tojson), + /* K9 */ be_nested_str_weak(cluster), + /* K10 */ be_nested_str_weak(attr_id), + /* K11 */ be_nested_str_weak(key), + /* K12 */ be_nested_str_weak(format), + /* K13 */ be_nested_str_weak(_X28_X25s_X29), + /* K14 */ be_nested_str_weak(_X2C_X25s_X3A_X22_X2504X_X2F_X2504X_X22), + }), + be_str_weak(tostring), + &be_const_str_solidified, + ( &(const binstruction[51]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0xA40E0400, // 0002 IMPORT R3 K2 + 0x8C100503, // 0003 GETMET R4 R2 K3 + 0x8C180104, // 0004 GETMET R6 R0 K4 + 0x7C180200, // 0005 CALL R6 1 + 0x7C100400, // 0006 CALL R4 2 + 0x00100905, // 0007 ADD R4 R4 K5 + 0x8C140306, // 0008 GETMET R5 R1 K6 + 0x881C0107, // 0009 GETMBR R7 R0 K7 + 0x58200008, // 000A LDCONST R8 K8 + 0x7C140600, // 000B CALL R5 3 + 0x4C180000, // 000C LDNIL R6 + 0x20140A06, // 000D NE R5 R5 R6 + 0x78160004, // 000E JMPF R5 #0014 + 0x88140107, // 000F GETMBR R5 R0 K7 + 0x8C140B08, // 0010 GETMET R5 R5 K8 + 0x7C140200, // 0011 CALL R5 1 + 0x00100805, // 0012 ADD R4 R4 R5 + 0x70020003, // 0013 JMP #0018 + 0x8C140503, // 0014 GETMET R5 R2 K3 + 0x881C0107, // 0015 GETMBR R7 R0 K7 + 0x7C140400, // 0016 CALL R5 2 + 0x00100805, // 0017 ADD R4 R4 R5 + 0x88140109, // 0018 GETMBR R5 R0 K9 + 0x4C180000, // 0019 LDNIL R6 + 0x20140A06, // 001A NE R5 R5 R6 + 0x78160015, // 001B JMPF R5 #0032 + 0x8814010A, // 001C GETMBR R5 R0 K10 + 0x4C180000, // 001D LDNIL R6 + 0x20140A06, // 001E NE R5 R5 R6 + 0x78160011, // 001F JMPF R5 #0032 + 0x8814010B, // 0020 GETMBR R5 R0 K11 + 0x4C180000, // 0021 LDNIL R6 + 0x20140A06, // 0022 NE R5 R5 R6 + 0x7816000D, // 0023 JMPF R5 #0032 + 0x8C14070C, // 0024 GETMET R5 R3 K12 + 0x581C000D, // 0025 LDCONST R7 K13 + 0x8C200104, // 0026 GETMET R8 R0 K4 + 0x7C200200, // 0027 CALL R8 1 + 0x7C140600, // 0028 CALL R5 3 + 0x8C18070C, // 0029 GETMET R6 R3 K12 + 0x5820000E, // 002A LDCONST R8 K14 + 0x8C240503, // 002B GETMET R9 R2 K3 + 0x5C2C0A00, // 002C MOVE R11 R5 + 0x7C240400, // 002D CALL R9 2 + 0x88280109, // 002E GETMBR R10 R0 K9 + 0x882C010A, // 002F GETMBR R11 R0 K10 + 0x7C180A00, // 0030 CALL R6 5 + 0x00100806, // 0031 ADD R4 R4 R6 + 0x80040800, // 0032 RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: setmember +********************************************************************/ +be_local_closure(zcl_attribute_setmember, /* name */ + be_nested_proto( + 7, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[16]) { /* constants */ + /* K0 */ be_nested_str_weak(cluster), + /* K1 */ be_nested_str_weak(_cluster), + /* K2 */ be_nested_str_weak(attr_id), + /* K3 */ be_nested_str_weak(_attr_id), + /* K4 */ be_nested_str_weak(_iscmd), + /* K5 */ be_const_int(0), + /* K6 */ be_nested_str_weak(cmd), + /* K7 */ be_nested_str_weak(_cmd), + /* K8 */ be_const_int(1), + /* K9 */ be_nested_str_weak(_direction), + /* K10 */ be_nested_str_weak(direction), + /* K11 */ be_nested_str_weak(val), + /* K12 */ be_nested_str_weak(_set_val), + /* K13 */ be_nested_str_weak(key), + /* K14 */ be_nested_str_weak(_set_key), + /* K15 */ be_nested_str_weak(setmember), + }), + be_str_weak(setmember), + &be_const_str_solidified, + ( &(const binstruction[72]) { /* code */ + 0x1C0C0300, // 0000 EQ R3 R1 K0 + 0x780E0007, // 0001 JMPF R3 #000A + 0x4C0C0000, // 0002 LDNIL R3 + 0x1C0C0403, // 0003 EQ R3 R2 R3 + 0x780E0002, // 0004 JMPF R3 #0008 + 0x540EFFFE, // 0005 LDINT R3 65535 + 0x90020203, // 0006 SETMBR R0 K1 R3 + 0x70020000, // 0007 JMP #0009 + 0x90020202, // 0008 SETMBR R0 K1 R2 + 0x7002003C, // 0009 JMP #0047 + 0x1C0C0302, // 000A EQ R3 R1 K2 + 0x780E0008, // 000B JMPF R3 #0015 + 0x4C0C0000, // 000C LDNIL R3 + 0x1C0C0403, // 000D EQ R3 R2 R3 + 0x780E0002, // 000E JMPF R3 #0012 + 0x540EFFFE, // 000F LDINT R3 65535 + 0x90020603, // 0010 SETMBR R0 K3 R3 + 0x70020001, // 0011 JMP #0014 + 0x90020602, // 0012 SETMBR R0 K3 R2 + 0x90020905, // 0013 SETMBR R0 K4 K5 + 0x70020031, // 0014 JMP #0047 + 0x1C0C0306, // 0015 EQ R3 R1 K6 + 0x780E000D, // 0016 JMPF R3 #0025 + 0x4C0C0000, // 0017 LDNIL R3 + 0x1C0C0403, // 0018 EQ R3 R2 R3 + 0x780E0002, // 0019 JMPF R3 #001D + 0x540E00FE, // 001A LDINT R3 255 + 0x90020E03, // 001B SETMBR R0 K7 R3 + 0x70020006, // 001C JMP #0024 + 0x90020E02, // 001D SETMBR R0 K7 R2 + 0x90020908, // 001E SETMBR R0 K4 K8 + 0x880C0109, // 001F GETMBR R3 R0 K9 + 0x541200FE, // 0020 LDINT R4 255 + 0x1C0C0604, // 0021 EQ R3 R3 R4 + 0x780E0000, // 0022 JMPF R3 #0024 + 0x90021305, // 0023 SETMBR R0 K9 K5 + 0x70020021, // 0024 JMP #0047 + 0x1C0C030A, // 0025 EQ R3 R1 K10 + 0x780E000C, // 0026 JMPF R3 #0034 + 0x4C0C0000, // 0027 LDNIL R3 + 0x1C0C0403, // 0028 EQ R3 R2 R3 + 0x780E0002, // 0029 JMPF R3 #002D + 0x540E00FE, // 002A LDINT R3 255 + 0x90021203, // 002B SETMBR R0 K9 R3 + 0x70020005, // 002C JMP #0033 + 0x780A0001, // 002D JMPF R2 #0030 + 0x580C0008, // 002E LDCONST R3 K8 + 0x70020000, // 002F JMP #0031 + 0x580C0005, // 0030 LDCONST R3 K5 + 0x90021203, // 0031 SETMBR R0 K9 R3 + 0x90020908, // 0032 SETMBR R0 K4 K8 + 0x70020012, // 0033 JMP #0047 + 0x1C0C030B, // 0034 EQ R3 R1 K11 + 0x780E0003, // 0035 JMPF R3 #003A + 0x8C0C010C, // 0036 GETMET R3 R0 K12 + 0x5C140400, // 0037 MOVE R5 R2 + 0x7C0C0400, // 0038 CALL R3 2 + 0x7002000C, // 0039 JMP #0047 + 0x1C0C030D, // 003A EQ R3 R1 K13 + 0x780E0003, // 003B JMPF R3 #0040 + 0x8C0C010E, // 003C GETMET R3 R0 K14 + 0x5C140400, // 003D MOVE R5 R2 + 0x7C0C0400, // 003E CALL R3 2 + 0x70020006, // 003F JMP #0047 + 0x600C0003, // 0040 GETGBL R3 G3 + 0x5C100000, // 0041 MOVE R4 R0 + 0x7C0C0200, // 0042 CALL R3 1 + 0x8C0C070F, // 0043 GETMET R3 R3 K15 + 0x5C140200, // 0044 MOVE R5 R1 + 0x5C180400, // 0045 MOVE R6 R2 + 0x7C0C0600, // 0046 CALL R3 3 + 0x80000000, // 0047 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(zcl_attribute_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(_init), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x60080003, // 0000 GETGBL R2 G3 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x8C080500, // 0003 GETMET R2 R2 K0 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C080400, // 0005 CALL R2 2 + 0x4C080000, // 0006 LDNIL R2 + 0x1C080202, // 0007 EQ R2 R1 R2 + 0x780A0001, // 0008 JMPF R2 #000B + 0x8C080101, // 0009 GETMET R2 R0 K1 + 0x7C080200, // 000A CALL R2 1 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: member +********************************************************************/ +be_local_closure(zcl_attribute_member, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[16]) { /* constants */ + /* K0 */ be_nested_str_weak(cluster), + /* K1 */ be_nested_str_weak(_cluster), + /* K2 */ be_nested_str_weak(attr_id), + /* K3 */ be_nested_str_weak(_attr_id), + /* K4 */ be_nested_str_weak(_iscmd), + /* K5 */ be_nested_str_weak(cmd), + /* K6 */ be_nested_str_weak(_cmd), + /* K7 */ be_nested_str_weak(direction), + /* K8 */ be_nested_str_weak(_direction), + /* K9 */ be_const_int(1), + /* K10 */ be_nested_str_weak(val), + /* K11 */ be_nested_str_weak(_get_val), + /* K12 */ be_nested_str_weak(tohex), + /* K13 */ be_nested_str_weak(key), + /* K14 */ be_nested_str_weak(_get_key), + /* K15 */ be_nested_str_weak(member), + }), + be_str_weak(member), + &be_const_str_solidified, + ( &(const binstruction[78]) { /* code */ + 0x1C080300, // 0000 EQ R2 R1 K0 + 0x780A0008, // 0001 JMPF R2 #000B + 0x88080101, // 0002 GETMBR R2 R0 K1 + 0x540EFFFE, // 0003 LDINT R3 65535 + 0x200C0403, // 0004 NE R3 R2 R3 + 0x780E0001, // 0005 JMPF R3 #0008 + 0x5C0C0400, // 0006 MOVE R3 R2 + 0x70020000, // 0007 JMP #0009 + 0x4C0C0000, // 0008 LDNIL R3 + 0x80040600, // 0009 RET 1 R3 + 0x70020041, // 000A JMP #004D + 0x1C080302, // 000B EQ R2 R1 K2 + 0x780A000A, // 000C JMPF R2 #0018 + 0x88080103, // 000D GETMBR R2 R0 K3 + 0x540EFFFE, // 000E LDINT R3 65535 + 0x200C0403, // 000F NE R3 R2 R3 + 0x780E0003, // 0010 JMPF R3 #0015 + 0x880C0104, // 0011 GETMBR R3 R0 K4 + 0x740E0001, // 0012 JMPT R3 #0015 + 0x5C0C0400, // 0013 MOVE R3 R2 + 0x70020000, // 0014 JMP #0016 + 0x4C0C0000, // 0015 LDNIL R3 + 0x80040600, // 0016 RET 1 R3 + 0x70020034, // 0017 JMP #004D + 0x1C080305, // 0018 EQ R2 R1 K5 + 0x780A000A, // 0019 JMPF R2 #0025 + 0x88080106, // 001A GETMBR R2 R0 K6 + 0x540E00FE, // 001B LDINT R3 255 + 0x200C0403, // 001C NE R3 R2 R3 + 0x780E0003, // 001D JMPF R3 #0022 + 0x880C0104, // 001E GETMBR R3 R0 K4 + 0x780E0001, // 001F JMPF R3 #0022 + 0x5C0C0400, // 0020 MOVE R3 R2 + 0x70020000, // 0021 JMP #0023 + 0x4C0C0000, // 0022 LDNIL R3 + 0x80040600, // 0023 RET 1 R3 + 0x70020027, // 0024 JMP #004D + 0x1C080307, // 0025 EQ R2 R1 K7 + 0x780A000A, // 0026 JMPF R2 #0032 + 0x88080108, // 0027 GETMBR R2 R0 K8 + 0x540E00FE, // 0028 LDINT R3 255 + 0x200C0403, // 0029 NE R3 R2 R3 + 0x780E0003, // 002A JMPF R3 #002F + 0x880C0104, // 002B GETMBR R3 R0 K4 + 0x780E0001, // 002C JMPF R3 #002F + 0x2C0C0509, // 002D AND R3 R2 K9 + 0x70020000, // 002E JMP #0030 + 0x4C0C0000, // 002F LDNIL R3 + 0x80040600, // 0030 RET 1 R3 + 0x7002001A, // 0031 JMP #004D + 0x1C08030A, // 0032 EQ R2 R1 K10 + 0x780A000B, // 0033 JMPF R2 #0040 + 0x8C08010B, // 0034 GETMET R2 R0 K11 + 0x7C080200, // 0035 CALL R2 1 + 0x600C000F, // 0036 GETGBL R3 G15 + 0x5C100400, // 0037 MOVE R4 R2 + 0x60140015, // 0038 GETGBL R5 G21 + 0x7C0C0400, // 0039 CALL R3 2 + 0x780E0002, // 003A JMPF R3 #003E + 0x8C0C050C, // 003B GETMET R3 R2 K12 + 0x7C0C0200, // 003C CALL R3 1 + 0x5C080600, // 003D MOVE R2 R3 + 0x80040400, // 003E RET 1 R2 + 0x7002000C, // 003F JMP #004D + 0x1C08030D, // 0040 EQ R2 R1 K13 + 0x780A0003, // 0041 JMPF R2 #0046 + 0x8C08010E, // 0042 GETMET R2 R0 K14 + 0x7C080200, // 0043 CALL R2 1 + 0x80040400, // 0044 RET 1 R2 + 0x70020006, // 0045 JMP #004D + 0x60080003, // 0046 GETGBL R2 G3 + 0x5C0C0000, // 0047 MOVE R3 R0 + 0x7C080200, // 0048 CALL R2 1 + 0x8C08050F, // 0049 GETMET R2 R2 K15 + 0x5C100200, // 004A MOVE R4 R1 + 0x7C080400, // 004B CALL R2 2 + 0x80040400, // 004C RET 1 R2 + 0x80000000, // 004D RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: zcl_attribute +********************************************************************/ +extern const bclass be_class_zcl_attribute_ntv; +be_local_class(zcl_attribute, + 0, + &be_class_zcl_attribute_ntv, + be_nested_map(7, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(tomap, -1), be_const_closure(zcl_attribute_tomap_closure) }, + { be_const_key_weak(key_tostring, -1), be_const_closure(zcl_attribute_key_tostring_closure) }, + { be_const_key_weak(setmember, -1), be_const_closure(zcl_attribute_setmember_closure) }, + { be_const_key_weak(tostring, -1), be_const_closure(zcl_attribute_tostring_closure) }, + { be_const_key_weak(init, 2), be_const_closure(zcl_attribute_init_closure) }, + { be_const_key_weak(deinit, 4), be_const_closure(zcl_attribute_deinit_closure) }, + { be_const_key_weak(member, -1), be_const_closure(zcl_attribute_member_closure) }, + })), + be_str_weak(zcl_attribute) +); +/*******************************************************************/ + +void be_load_zcl_attribute_class(bvm *vm) { + be_pushntvclass(vm, &be_class_zcl_attribute); + be_setglobal(vm, "zcl_attribute"); + be_pop(vm, 1); +} + +/******************************************************************** +** Solidified function: member +********************************************************************/ +be_local_closure(zcl_attribute_list_member, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(groupaddr), + /* K1 */ be_nested_str_weak(_groupaddr), + /* K2 */ be_nested_str_weak(src_ep), + /* K3 */ be_nested_str_weak(_src_ep), + /* K4 */ be_nested_str_weak(lqi), + /* K5 */ be_nested_str_weak(_lqi), + /* K6 */ be_nested_str_weak(member), + }), + be_str_weak(member), + &be_const_str_solidified, + ( &(const binstruction[41]) { /* code */ + 0x1C080300, // 0000 EQ R2 R1 K0 + 0x780A0008, // 0001 JMPF R2 #000B + 0x88080101, // 0002 GETMBR R2 R0 K1 + 0x540EFFFE, // 0003 LDINT R3 65535 + 0x200C0403, // 0004 NE R3 R2 R3 + 0x780E0001, // 0005 JMPF R3 #0008 + 0x5C0C0400, // 0006 MOVE R3 R2 + 0x70020000, // 0007 JMP #0009 + 0x4C0C0000, // 0008 LDNIL R3 + 0x80040600, // 0009 RET 1 R3 + 0x7002001C, // 000A JMP #0028 + 0x1C080302, // 000B EQ R2 R1 K2 + 0x780A0008, // 000C JMPF R2 #0016 + 0x88080103, // 000D GETMBR R2 R0 K3 + 0x540E00FE, // 000E LDINT R3 255 + 0x200C0403, // 000F NE R3 R2 R3 + 0x780E0001, // 0010 JMPF R3 #0013 + 0x5C0C0400, // 0011 MOVE R3 R2 + 0x70020000, // 0012 JMP #0014 + 0x4C0C0000, // 0013 LDNIL R3 + 0x80040600, // 0014 RET 1 R3 + 0x70020011, // 0015 JMP #0028 + 0x1C080304, // 0016 EQ R2 R1 K4 + 0x780A0008, // 0017 JMPF R2 #0021 + 0x88080105, // 0018 GETMBR R2 R0 K5 + 0x540E00FE, // 0019 LDINT R3 255 + 0x200C0403, // 001A NE R3 R2 R3 + 0x780E0001, // 001B JMPF R3 #001E + 0x5C0C0400, // 001C MOVE R3 R2 + 0x70020000, // 001D JMP #001F + 0x4C0C0000, // 001E LDNIL R3 + 0x80040600, // 001F RET 1 R3 + 0x70020006, // 0020 JMP #0028 + 0x60080003, // 0021 GETGBL R2 G3 + 0x5C0C0000, // 0022 MOVE R3 R0 + 0x7C080200, // 0023 CALL R2 1 + 0x8C080506, // 0024 GETMET R2 R2 K6 + 0x5C100200, // 0025 MOVE R4 R1 + 0x7C080400, // 0026 CALL R2 2 + 0x80040400, // 0027 RET 1 R2 + 0x80000000, // 0028 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: setmember +********************************************************************/ +be_local_closure(zcl_attribute_list_setmember, /* name */ + be_nested_proto( + 7, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(groupaddr), + /* K1 */ be_nested_str_weak(_groupaddr), + /* K2 */ be_nested_str_weak(src_ep), + /* K3 */ be_nested_str_weak(_src_ep), + /* K4 */ be_nested_str_weak(lqi), + /* K5 */ be_nested_str_weak(_lqi), + /* K6 */ be_nested_str_weak(setmember), + }), + be_str_weak(setmember), + &be_const_str_solidified, + ( &(const binstruction[38]) { /* code */ + 0x1C0C0300, // 0000 EQ R3 R1 K0 + 0x780E0007, // 0001 JMPF R3 #000A + 0x4C0C0000, // 0002 LDNIL R3 + 0x200C0403, // 0003 NE R3 R2 R3 + 0x780E0001, // 0004 JMPF R3 #0007 + 0x5C0C0400, // 0005 MOVE R3 R2 + 0x70020000, // 0006 JMP #0008 + 0x540EFFFE, // 0007 LDINT R3 65535 + 0x90020203, // 0008 SETMBR R0 K1 R3 + 0x7002001A, // 0009 JMP #0025 + 0x1C0C0302, // 000A EQ R3 R1 K2 + 0x780E0007, // 000B JMPF R3 #0014 + 0x4C0C0000, // 000C LDNIL R3 + 0x200C0403, // 000D NE R3 R2 R3 + 0x780E0001, // 000E JMPF R3 #0011 + 0x5C0C0400, // 000F MOVE R3 R2 + 0x70020000, // 0010 JMP #0012 + 0x540E00FE, // 0011 LDINT R3 255 + 0x90020603, // 0012 SETMBR R0 K3 R3 + 0x70020010, // 0013 JMP #0025 + 0x1C0C0304, // 0014 EQ R3 R1 K4 + 0x780E0007, // 0015 JMPF R3 #001E + 0x4C0C0000, // 0016 LDNIL R3 + 0x200C0403, // 0017 NE R3 R2 R3 + 0x780E0001, // 0018 JMPF R3 #001B + 0x5C0C0400, // 0019 MOVE R3 R2 + 0x70020000, // 001A JMP #001C + 0x540E00FE, // 001B LDINT R3 255 + 0x90020A03, // 001C SETMBR R0 K5 R3 + 0x70020006, // 001D JMP #0025 + 0x600C0003, // 001E GETGBL R3 G3 + 0x5C100000, // 001F MOVE R4 R0 + 0x7C0C0200, // 0020 CALL R3 1 + 0x8C0C0706, // 0021 GETMET R3 R3 K6 + 0x5C140200, // 0022 MOVE R5 R1 + 0x5C180400, // 0023 MOVE R6 R2 + 0x7C0C0600, // 0024 CALL R3 3 + 0x80000000, // 0025 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(zcl_attribute_list_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(_init), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x60080003, // 0000 GETGBL R2 G3 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x8C080500, // 0003 GETMET R2 R2 K0 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C080400, // 0005 CALL R2 2 + 0x4C080000, // 0006 LDNIL R2 + 0x1C080202, // 0007 EQ R2 R1 R2 + 0x780A0001, // 0008 JMPF R2 #000B + 0x8C080101, // 0009 GETMET R2 R0 K1 + 0x7C080200, // 000A CALL R2 1 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: deinit +********************************************************************/ +be_local_closure(zcl_attribute_list_deinit, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(ismapped), + /* K1 */ be_nested_str_weak(_deinit), + }), + be_str_weak(deinit), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x74060001, // 0002 JMPT R1 #0005 + 0x8C040101, // 0003 GETMET R1 R0 K1 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: tostring +********************************************************************/ +be_local_closure(zcl_attribute_list_tostring, /* name */ + be_nested_proto( + 12, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[20]) { /* constants */ + /* K0 */ be_nested_str_weak(string), + /* K1 */ be_nested_str_weak(json), + /* K2 */ be_nested_str_weak(shortaddr), + /* K3 */ be_nested_str_weak(push), + /* K4 */ be_nested_str_weak(format), + /* K5 */ be_nested_str_weak(_X22Device_X22_X3A_X220x_X2504X_X22), + /* K6 */ be_nested_str_weak(groupaddr), + /* K7 */ be_nested_str_weak(_X22Group_X22_X3A_X220x_X2504X_X22), + /* K8 */ be_const_int(0), + /* K9 */ be_nested_str_weak(size), + /* K10 */ be_nested_str_weak(tostring), + /* K11 */ be_const_int(1), + /* K12 */ be_nested_str_weak(src_ep), + /* K13 */ be_nested_str_weak(_X22Endpoint_X22_X3A_X25i), + /* K14 */ be_nested_str_weak(lqi), + /* K15 */ be_nested_str_weak(_X22LinkQuality_X22_X3A_X25i), + /* K16 */ be_nested_str_weak(_X7B), + /* K17 */ be_nested_str_weak(concat), + /* K18 */ be_nested_str_weak(_X2C), + /* K19 */ be_nested_str_weak(_X7D), + }), + be_str_weak(tostring), + &be_const_str_solidified, + ( &(const binstruction[62]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0x600C0012, // 0002 GETGBL R3 G18 + 0x7C0C0000, // 0003 CALL R3 0 + 0x88100102, // 0004 GETMBR R4 R0 K2 + 0x4C140000, // 0005 LDNIL R5 + 0x20100805, // 0006 NE R4 R4 R5 + 0x78120005, // 0007 JMPF R4 #000E + 0x8C100703, // 0008 GETMET R4 R3 K3 + 0x8C180304, // 0009 GETMET R6 R1 K4 + 0x58200005, // 000A LDCONST R8 K5 + 0x88240102, // 000B GETMBR R9 R0 K2 + 0x7C180600, // 000C CALL R6 3 + 0x7C100400, // 000D CALL R4 2 + 0x88100106, // 000E GETMBR R4 R0 K6 + 0x4C140000, // 000F LDNIL R5 + 0x20100805, // 0010 NE R4 R4 R5 + 0x78120005, // 0011 JMPF R4 #0018 + 0x8C100703, // 0012 GETMET R4 R3 K3 + 0x8C180304, // 0013 GETMET R6 R1 K4 + 0x58200007, // 0014 LDCONST R8 K7 + 0x88240106, // 0015 GETMBR R9 R0 K6 + 0x7C180600, // 0016 CALL R6 3 + 0x7C100400, // 0017 CALL R4 2 + 0x58100008, // 0018 LDCONST R4 K8 + 0x8C140109, // 0019 GETMET R5 R0 K9 + 0x7C140200, // 001A CALL R5 1 + 0x14180805, // 001B LT R6 R4 R5 + 0x781A0006, // 001C JMPF R6 #0024 + 0x8C180703, // 001D GETMET R6 R3 K3 + 0x94200004, // 001E GETIDX R8 R0 R4 + 0x8C20110A, // 001F GETMET R8 R8 K10 + 0x7C200200, // 0020 CALL R8 1 + 0x7C180400, // 0021 CALL R6 2 + 0x0010090B, // 0022 ADD R4 R4 K11 + 0x7001FFF6, // 0023 JMP #001B + 0x8818010C, // 0024 GETMBR R6 R0 K12 + 0x4C1C0000, // 0025 LDNIL R7 + 0x20180C07, // 0026 NE R6 R6 R7 + 0x781A0005, // 0027 JMPF R6 #002E + 0x8C180703, // 0028 GETMET R6 R3 K3 + 0x8C200304, // 0029 GETMET R8 R1 K4 + 0x5828000D, // 002A LDCONST R10 K13 + 0x882C010C, // 002B GETMBR R11 R0 K12 + 0x7C200600, // 002C CALL R8 3 + 0x7C180400, // 002D CALL R6 2 + 0x8818010E, // 002E GETMBR R6 R0 K14 + 0x4C1C0000, // 002F LDNIL R7 + 0x20180C07, // 0030 NE R6 R6 R7 + 0x781A0005, // 0031 JMPF R6 #0038 + 0x8C180703, // 0032 GETMET R6 R3 K3 + 0x8C200304, // 0033 GETMET R8 R1 K4 + 0x5828000F, // 0034 LDCONST R10 K15 + 0x882C010E, // 0035 GETMBR R11 R0 K14 + 0x7C200600, // 0036 CALL R8 3 + 0x7C180400, // 0037 CALL R6 2 + 0x8C180711, // 0038 GETMET R6 R3 K17 + 0x58200012, // 0039 LDCONST R8 K18 + 0x7C180400, // 003A CALL R6 2 + 0x001A2006, // 003B ADD R6 K16 R6 + 0x00180D13, // 003C ADD R6 R6 K19 + 0x80040C00, // 003D RET 1 R6 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: zcl_attribute_list +********************************************************************/ +extern const bclass be_class_zcl_attribute_list_ntv; +be_local_class(zcl_attribute_list, + 1, + &be_class_zcl_attribute_list_ntv, + be_nested_map(6, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(shortaddr, -1), be_const_var(0) }, + { be_const_key_weak(member, 2), be_const_closure(zcl_attribute_list_member_closure) }, + { be_const_key_weak(tostring, 5), be_const_closure(zcl_attribute_list_tostring_closure) }, + { be_const_key_weak(init, -1), be_const_closure(zcl_attribute_list_init_closure) }, + { be_const_key_weak(deinit, -1), be_const_closure(zcl_attribute_list_deinit_closure) }, + { be_const_key_weak(setmember, -1), be_const_closure(zcl_attribute_list_setmember_closure) }, + })), + be_str_weak(zcl_attribute_list) +); +/*******************************************************************/ + +void be_load_zcl_attribute_list_class(bvm *vm) { + be_pushntvclass(vm, &be_class_zcl_attribute_list); + be_setglobal(vm, "zcl_attribute_list"); + be_pop(vm, 1); +} + +#endif // USE_LIGHT diff --git a/lib/libesp32/berry_tasmota/src/embedded/zigbee_zb_coord.be b/lib/libesp32/berry_tasmota/src/embedded/zigbee_zb_coord.be index a1aa29fa5..3bde73d45 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/zigbee_zb_coord.be +++ b/lib/libesp32/berry_tasmota/src/embedded/zigbee_zb_coord.be @@ -22,15 +22,31 @@ class zb_coord : zb_coord_ntv end end - def dispatch(event_type, data_type, data_ptr, idx) + # dispatch incomind events + # + # event_type: + # 'frame_received' + # 'attributes_published' + # + # data_str: + # string + # '' + # '' + # + def dispatch(event_type, zcl_frame_ptr, zcl_attribute_list_ptr, idx) if self._handlers == nil return end import introspect import string - var data = data_ptr - if data_type == "zcl_frame" - data = self.zcl_frame(data_ptr) + var frame + var attr_list + var nullptr = introspect.toptr(0) + if zcl_frame_ptr != nullptr + frame = self.zcl_frame(zcl_frame_ptr) + end + if zcl_attribute_list_ptr != nullptr + attr_list = self.zcl_attribute_list(zcl_attribute_list_ptr) end #print(string.format(">ZIG: cmd=%s data_type=%s data=%s idx=%i", event_type, data_type, str(data), idx)) @@ -41,7 +57,7 @@ class zb_coord : zb_coord_ntv var f = introspect.get(h, event_type) # try to match a function or method with the same name if type(f) == 'function' try - f(h, event_type, data_type, data, idx) + f(h, event_type, frame, attr_list, idx) except .. as e,m print(string.format("BRY: Exception> '%s' - %s", e, m)) if tasmota._debug_present diff --git a/lib/libesp32/berry_tasmota/src/embedded/zigbee_zcl_attribute.be b/lib/libesp32/berry_tasmota/src/embedded/zigbee_zcl_attribute.be new file mode 100644 index 000000000..700b5c252 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/embedded/zigbee_zcl_attribute.be @@ -0,0 +1,367 @@ +# zigbee zcl_attributes class +# +# f = open("zcl_attribute.c","w") solidify.dump(zcl_attribute,true,f) solidify.dump(zcl_attribute_list,true,f) f.close() +# + +class zcl_attribute_ntv end +class zcl_attribute_list_ntv end + +class zcl_attribute : zcl_attribute_ntv + + def init(ptr) + super(self).init(ptr) # call super constructor + if ptr == nil # if we allocate ourseleves, initialize the structure with `_init()` + self._init() + end + end + + def deinit() + if !self.ismapped() # if we allocated the structure, deallocated all sub-structures first + self._deinit() + end + end + + # virtual accessor overloading some attributes + def member(k) + if k == "cluster" + var v = self._cluster + return v != 0xFFFF ? v : nil + elif k == "attr_id" + var v = self._attr_id + return ((v != 0xFFFF) && !self._iscmd) ? v : nil + elif k == "cmd" + var v = self._cmd + return ((v != 0xFF) && self._iscmd) ? v : nil + elif k == "direction" + var v = self._direction + return ((v != 0xFF) && self._iscmd) ? (v & 0x01) : nil + elif k == "val" + var v = self._get_val() + if isinstance(v, bytes) + v = v.tohex() + end + return v + elif k == "key" + return self._get_key() + else + return super(self).member(k) + end + end + + def setmember(k, v) + if k == "cluster" + if v == nil + self._cluster = 0xFFFF + else + self._cluster = v + end + elif k == "attr_id" + if v == nil + self._attr_id = 0xFFFF + else + self._attr_id = v + self._iscmd = 0 + end + elif k == "cmd" + if v == nil + self._cmd = 0xFF + else + self._cmd = v + self._iscmd = 1 + if self._direction == 0xFF # default direction + self._direction = 0 + end + end + elif k == "direction" + if v == nil + self._direction = 0xFF + else + self._direction = v ? 0x01 : 0x00 + self._iscmd = 1 + end + elif k == "val" + self._set_val(v) + elif k == "key" + self._set_key(v) + else + super(self).setmember(k, v) + end + end + + # tomap() extended + def tomap() + var m = super(self).tomap() + m['cluster'] = self.cluster + m['attr_id'] = self.attr_id + m['cmd'] = self.cmd + m['direction'] = self.direction + m['key'] = self.key + m['val'] = self.val + return m + end + + def key_tostring() + import string + var s = "" + + var key = self.key + if key != nil + s = key + if self.key_suffix > 1 + s += str(self.key_suffix) + end + elif (self.cluster != nil) && (self.attr_id != nil) + s = string.format("%04X/%04X", self.cluster, self.attr_id) + if self.key_suffix > 1 + s += "+" + str(self.key_suffix) + end + elif (self.cluster != nil) && (self.cmd != nil) && (self.direction != nil) + s = string.format("%04X%s%02X", self.cluster, self.direction ? "<" : "!" ,self.cmd) + if self.key_suffix > 1 + s += "+" + str(self.key_suffix) + end + end + return s + end + + # export value so that it can be serialized by json + def tostring() + import introspect + import json + import string + + var s = json.dump(self.key_tostring()) + s += ":" + if introspect.get(self.val, "tojson") != nil + s += self.val.tojson() + else + s += json.dump(self.val) + end + + if (self.cluster != nil) && (self.attr_id != nil) && (self.key != nil) + # we have an alias + var key_alias = string.format("(%s)", self.key_tostring()) + s += string.format(',%s:"%04X/%04X"', json.dump(key_alias), self.cluster, self.attr_id) + end + + return s + end + +end + +class zcl_attribute_list : zcl_attribute_list_ntv + var shortaddr + # in the bytes object we have: + # groupaddr + # src_ep + # lqi + + def init(ptr) + super(self).init(ptr) # call super constructor + if ptr == nil # if we allocate ourseleves, initialize the structure with `_init()` + self._init() + end + end + + def deinit() + if !self.ismapped() # if we allocated the structure, deallocated all sub-structures first + self._deinit() + end + end + + def member(k) + if k == "groupaddr" + var v = self._groupaddr + return v != 0xFFFF ? v : nil + elif k == "src_ep" + var v = self._src_ep + return v != 0xFF ? v : nil + elif k == "lqi" + var v = self._lqi + return v != 0xFF ? v : nil + else + return super(self).member(k) + end + end + + def setmember(k, v) + if k == "groupaddr" + self._groupaddr = (v != nil) ? v : 0xFFFF + elif k == "src_ep" + self._src_ep = (v != nil) ? v : 0xFF + elif k == "lqi" + self._lqi = (v != nil) ? v : 0xFF + else + super(self).setmember(k, v) + end + end + + def tostring() + import string + import json + + var items = [] + # {"Device":"0x246D","Name":"Plug","EnergyTotal":"0x000000000000","Endpoint":1,"LinkQuality":229} + + # shortaddr + if self.shortaddr != nil + items.push(string.format('"Device":"0x%04X"', self.shortaddr)) + end + # groupaddr + if self.groupaddr != nil + items.push(string.format('"Group":"0x%04X"', self.groupaddr)) + end + + # attributes + var idx = 0 + var attr_size = self.size() + while idx < attr_size + # for e: self.attr_list + items.push(self[idx].tostring()) + idx += 1 + end + + # Endpoint + if self.src_ep != nil + items.push(string.format('"Endpoint":%i', self.src_ep)) + end + + # LQI + if self.lqi != nil + items.push(string.format('"LinkQuality":%i', self.lqi)) + end + + var s = "{" + items.concat(",") + "}" + return s + + # return string.format("shortaddr:0x%04X groupaddr:0x%04X %s", self.shortaddr, self.groupaddr, str(self.attr_list)) + end +end + +class zcl_attributes + var shortaddr + var groupaddr + var lqi + var src_ep + var attr_list + + def init(shortaddr, groupaddr, lqi, src_ep, attr_list) + self.shortaddr = shortaddr + self.groupaddr = groupaddr + self.lqi = lqi + self.src_ep = src_ep + if isinstance(self.attr_list, list) + self.attr_list = attr_list + else + self.attr_list = [] + end + end + + def push(attr) + self.attr_list.push(attr) + end + + def tostring() + import string + import json + + var items = [] + # {"Device":"0x246D","Name":"Plug","EnergyTotal":"0x000000000000","Endpoint":1,"LinkQuality":229} + + # shortaddr + if self.shortaddr != nil + items.push(string.format('"Device":"0x%04X"', self.shortaddr)) + end + # groupaddr + if self.shortaddr != nil + items.push(string.format('"Group":"0x%04X"', self.groupaddr)) + end + + # attributes + for e: self.attr_list + items.push(e.tostring()) + end + + # Endpoint + if self.src_ep != nil + items.push(string.format('"Endpoint":%i', self.src_ep)) + end + + # Endpoint + if self.lqi != nil + items.push(string.format('"LinkQuality":%i', self.lqi)) + end + + var s = "{" + items.concat(",") + "}" + return s + + # return string.format("shortaddr:0x%04X groupaddr:0x%04X %s", self.shortaddr, self.groupaddr, str(self.attr_list)) + end + +end + +#- +# Unit tests + +# setup for standalone +# zigbee = module("zigbee") +# zigbee.zcl_attribute = zcl_attribute +# zigbee.zcl_attributes = zcl_attributes + + +# def init(cluster, attr_id, key, key_suffix, val, multiplier) +import zigbee +l = zigbee.zcl_attribute_list() +assert(l.tostring() == "{}") + +l.shortaddr = 0x1234 +l.groupaddr = 0x9876 +l.src_ep = 1 +l.lqi = 99 +assert(l.tostring() == '{"Device":"0x1234","Group":"0x9876","Endpoint":1,"LinkQuality":99}') + +a1 = l.new_tail() +a1.cluster = 0x100 +a1.attr_id = 0x200 +a1.val = 10 +assert(a1.tostring() == '"0100/0200":10') + +a10 = l.new_tail() +a10.cluster = 0x100 +a10.attr_id = 0x200 +a10.key = "Name" +a10.val = 10 +assert(a10.tostring() == '"Name":10,"Name(0100/0200)":null') + +a2 = l.new_tail() +a2.cluster = 0x101 +a2.attr_id = 0x201 +a2.key_suffix = 2 +a2.val = 3.5 +assert(a2.tostring() == '"0101/0201+2":3.5') + +a3 = l.new_tail() +a3.key = "foobar" +a3.key_suffix = 3 +a3.val = "baz" +assert(a3.tostring() == '"foobar3":"baz"') + +a4 = l.new_tail() +a4.key = "Power" +a4.val = true +assert(a4.tostring() == '"Power":true') + +a5 = l.new_head() +a5.key = "Unknown" +assert(a5.tostring() == '"Unknown":null') + +assert(l.tostring() == '{"Device":"0x1234","Group":"0x9876","Unknown":null,"0100/0200":10,"Name":10,"Name(0100/0200)":null,"0101/0201+2":3.5,"foobar3":"baz","Power":true,"Endpoint":1,"LinkQuality":99}') + +b1 = zigbee.zcl_attribute() +b1.cluster = 0x0600 +b1.cmd = 0x01 +b1.direction = 0 +b1.val = bytes('01') +assert(b1.tostring() == '"0600!01":"01"') + +-# diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1z_libs.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1z_libs.ino index 0e76c79f1..2832e98e1 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1z_libs.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1z_libs.ino @@ -88,28 +88,26 @@ enum class Za_type : uint8_t { class Z_attribute { public: - // attribute key, either cluster+attribute_id or plain name - union { - struct { - uint16_t cluster; - uint16_t attr_id; - } id; - char * key; - } key; + // cluster+attribute_id and/or plain name + uint16_t cluster; // only valid if both cluster and attr_id are not 0xFFFF + uint16_t attr_id; // only valid if both cluster and attr_id are not 0xFFFF + char* key; // only valid if `key_is_str` is true. Should not be freed if `key_is_pmem` is true // attribute value union { uint32_t uval32; int32_t ival32; float fval; SBuffer* bval; - char* sval; - class Z_attribute_list * objval; - class JsonGeneratorArray * arrval; + char* sval; // string should be freed + class Z_attribute_list * objval; // contains a list of attributes, should be printed as a map (although it's just a list internally) + class JsonGeneratorArray * arrval; // contains a JSON string representing an array of values } val; Za_type type; // uint8_t in size, type of attribute, see above bool key_is_str; // is the key a string? bool key_is_pmem; // is the string in progmem, so we don't need to make a copy bool val_str_raw; // if val is String, it is raw JSON and should not be escaped + bool key_is_cmd; // if command, cmd_id is the low 8 bits of attr_id. + // The high 8 bits are `0` command sent to device or `1` command received from device uint8_t key_suffix; // append a suffix to key (default is 1, explicitly output if >1) uint8_t attr_type; // [opt] type of the attribute, default to Zunk (0xFF) uint8_t attr_multiplier; // [opt] multiplier for attribute, defaults to 0x01 (no change) @@ -117,12 +115,15 @@ public: // Constructor with all defaults Z_attribute(): - key{ .id = { 0x0000, 0x0000 } }, + cluster(0xFFFF), + attr_id(0xFFFF), + key(nullptr), val{ .uval32 = 0x0000 }, type(Za_type::Za_none), key_is_str(false), key_is_pmem(false), val_str_raw(false), + key_is_cmd(false), key_suffix(1), attr_type(0xFF), attr_multiplier(1), @@ -158,6 +159,7 @@ public: void setKeyName(const char * _key, const char * _key2); void setKeyId(uint16_t cluster, uint16_t attr_id); + void setCmdId(uint16_t cluster, uint8_t cmd_id, bool direction); // Setters void setNone(void); @@ -166,6 +168,7 @@ public: void setInt(int32_t _val); void setFloat(float _val); + void setRaw(const void* buf, size_t len); void setBuf(const SBuffer &buf, size_t index, size_t len); // specific formatters @@ -203,7 +206,8 @@ public: const char * getStr(void) const; bool equalsKey(const Z_attribute & attr2, bool ignore_key_suffix = false) const; - bool equalsKey(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) const; + bool equalsId(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) const; + bool equalsCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix = 0) const; bool equalsKey(const char * name, uint8_t suffix = 0) const; bool equalsVal(const Z_attribute & attr2) const; bool equals(const Z_attribute & attr2) const; @@ -265,6 +269,9 @@ public: // Add attribute to the list, given cluster and attribute id Z_attribute & addAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0); + // ZCL command + Z_attribute & addAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix = 0); + // Add attribute to the list, given name Z_attribute & addAttribute(const char * name, bool pmem = false, uint8_t suffix = 0); Z_attribute & addAttribute(const char * name, const char * name2, uint8_t suffix = 0); @@ -284,12 +291,16 @@ public: // find if attribute with same key already exists, return null if not found const Z_attribute * findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) const; + const Z_attribute * findAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix = 0) const; const Z_attribute * findAttribute(const char * name, uint8_t suffix = 0) const; - const Z_attribute * findAttribute(const Z_attribute &attr) const; // suffis always count here + const Z_attribute * findAttribute(const Z_attribute &attr) const; // suffix always count here // non-const variants inline Z_attribute * findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) { return (Z_attribute*) ((const Z_attribute_list*)this)->findAttribute(cluster, attr_id, suffix); } + inline Z_attribute * findAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix = 0) { + return (Z_attribute*) ((const Z_attribute_list*)this)->findAttributeCmd(cluster, cmd_id, direction, suffix); + } inline Z_attribute * findAttribute(const char * name, uint8_t suffix = 0) { return (Z_attribute*) (((const Z_attribute_list*)this)->findAttribute(name, suffix)); } @@ -326,8 +337,8 @@ Z_attribute & Z_attribute_list::addAttributePMEM(const char * name) { // free any allocated memoruy for keys void Z_attribute::freeKey(void) { - if (key_is_str && key.key && !key_is_pmem) { delete[] key.key; } - key.key = nullptr; + if (key_is_str && key && !key_is_pmem) { delete[] key; } + key = nullptr; } // set key name @@ -336,7 +347,7 @@ void Z_attribute::setKeyName(const char * _key, bool pmem) { key_is_str = true; key_is_pmem = pmem; if (pmem) { - key.key = (char*) _key; + key = (char*) _key; } else { setKeyName(_key, nullptr); } @@ -351,19 +362,28 @@ void Z_attribute::setKeyName(const char * _key, const char * _key2) { if (_key2) { key_len += strlen_P(_key2); } - key.key = new char[key_len+1]; - strcpy_P(key.key, _key); + key = new char[key_len+1]; + strcpy_P(key, _key); if (_key2) { - strcat_P(key.key, _key2); + strcat_P(key, _key2); } } } -void Z_attribute::setKeyId(uint16_t cluster, uint16_t attr_id) { +void Z_attribute::setKeyId(uint16_t _cluster, uint16_t _attr_id) { freeKey(); key_is_str = false; - key.id.cluster = cluster; - key.id.attr_id = attr_id; + cluster = _cluster; + attr_id = _attr_id; + key_is_cmd = false; +} + +void Z_attribute::setCmdId(uint16_t _cluster, uint8_t _cmd_id, bool direction) { + freeKey(); + key_is_str = false; + cluster = _cluster; + attr_id = _cmd_id | (direction ? 0x100 : 0x000); + key_is_cmd = true; } // Setters @@ -393,6 +413,15 @@ void Z_attribute::setFloat(float _val) { type = Za_type::Za_float; } +void Z_attribute::setRaw(const void* buf, size_t len) { + freeVal(); + if (len) { + val.bval = new SBuffer(len); + val.bval->addBuffer((const uint8_t*)buf, len); + } + type = Za_type::Za_raw; +} + void Z_attribute::setBuf(const SBuffer &buf, size_t index, size_t len) { freeVal(); if (len) { @@ -514,10 +543,11 @@ bool Z_attribute::equalsKey(const Z_attribute & attr2, bool ignore_key_suffix) c // check if keys are equal if (key_is_str != attr2.key_is_str) { return false; } if (key_is_str) { - if (strcmp_PP(key.key, attr2.key.key)) { return false; } + if (strcmp_PP(key, attr2.key)) { return false; } } else { - if ((key.id.cluster != attr2.key.id.cluster) || - (key.id.attr_id != attr2.key.id.attr_id)) { return false; } + if ((this->cluster != attr2.cluster) || + (this->attr_id != attr2.attr_id) || + (this->key_is_cmd != attr2.key_is_cmd)) { return false; } } if (!ignore_key_suffix) { if (key_suffix != attr2.key_suffix) { return false; } @@ -525,9 +555,23 @@ bool Z_attribute::equalsKey(const Z_attribute & attr2, bool ignore_key_suffix) c return true; } -bool Z_attribute::equalsKey(uint16_t cluster, uint16_t attr_id, uint8_t suffix) const { +bool Z_attribute::equalsId(uint16_t _cluster, uint16_t _attr_id, uint8_t suffix) const { if (!key_is_str) { - if ((key.id.cluster == cluster) && (key.id.attr_id == attr_id)) { + if ((this->cluster == _cluster) && (this->attr_id == _attr_id) && (!this->key_is_cmd)) { + if (suffix) { + if (key_suffix == suffix) { return true; } + } else { + return true; + } + } + } + return false; +} + +bool Z_attribute::equalsCmd(uint16_t _cluster, uint8_t _cmd_id, bool _direction, uint8_t suffix) const { + if (!key_is_str) { + uint16_t _attr_id = _cmd_id | (_direction ? 0x100 : 0x000); + if ((this->cluster == _cluster) && (this->attr_id == _attr_id) && (!this->key_is_cmd)) { if (suffix) { if (key_suffix == suffix) { return true; } } else { @@ -540,7 +584,7 @@ bool Z_attribute::equalsKey(uint16_t cluster, uint16_t attr_id, uint8_t suffix) bool Z_attribute::equalsKey(const char * name, uint8_t suffix) const { if (key_is_str) { - if (0 == strcmp_PP(key.key, name)) { + if (0 == strcmp_PP(key, name)) { if (suffix) { if (key_suffix == suffix) { return true; } } else { @@ -580,14 +624,20 @@ String Z_attribute::toString(bool prefix_comma) const { res += '"'; // compute the attribute name if (key_is_str) { - if (key.key) { res += EscapeJSONString(key.key); } + if (key) { res += EscapeJSONString(key); } else { res += F("null"); } // shouldn't happen if (key_suffix > 1) { res += key_suffix; } } else { char attr_name[12]; - snprintf_P(attr_name, sizeof(attr_name), PSTR("%04X/%04X"), key.id.cluster, key.id.attr_id); + if (!key_is_cmd) { // regular attribute + snprintf_P(attr_name, sizeof(attr_name), PSTR("%04X/%04X"), this->cluster, this->attr_id); + } else { // cmd + bool direction = (this->attr_id & 0x100); + uint8_t cmd_id = this->attr_id & 0xFF; + snprintf_P(attr_name, sizeof(attr_name), PSTR("%04X%c%02X"), this->cluster, direction ? '<' : '!', cmd_id); + } res += attr_name; if (key_suffix > 1) { res += '+'; @@ -711,26 +761,26 @@ void Z_attribute::freeVal(void) { } void Z_attribute::deepCopy(const Z_attribute & rhs) { - // copy key - if (!rhs.key_is_str) { - key.id.cluster = rhs.key.id.cluster; - key.id.attr_id = rhs.key.id.attr_id; - } else { + // copy cluster anymays + cluster = rhs.cluster; + attr_id = rhs.attr_id; + if (rhs.key_is_str) { if (rhs.key_is_pmem) { - key.key = rhs.key.key; // PMEM, don't copy + key = rhs.key; // PMEM, don't copy } else { - key.key = nullptr; - if (rhs.key.key) { - size_t key_len = strlen_P(rhs.key.key); + key = nullptr; + if (rhs.key) { + size_t key_len = strlen_P(rhs.key); if (key_len) { - key.key = new char[key_len+1]; - strcpy_P(key.key, rhs.key.key); + key = new char[key_len+1]; + strcpy_P(key, rhs.key); } } } } key_is_str = rhs.key_is_str; key_is_pmem = rhs.key_is_pmem; + key_is_cmd = rhs.key_is_cmd; key_suffix = rhs.key_suffix; attr_type = rhs.attr_type; attr_multiplier = rhs.attr_multiplier; @@ -747,10 +797,21 @@ void Z_attribute::deepCopy(const Z_attribute & rhs) { // add a cluster/attr_id attribute at the end of the list Z_attribute & Z_attribute_list::addAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) { Z_attribute & attr = addToLast(); - attr.key.id.cluster = cluster; - attr.key.id.attr_id = attr_id; + attr.cluster = cluster; + attr.attr_id = attr_id; attr.key_is_str = false; - if (!suffix) { attr.key_suffix = countAttribute(attr.key.id.cluster, attr.key.id.attr_id); } + if (!suffix) { attr.key_suffix = countAttribute(attr.cluster, attr.attr_id); } + else { attr.key_suffix = suffix; } + return attr; +} + +// add a cluster/cmd_id attribute at the end of the list +Z_attribute & Z_attribute_list::addAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix) { + Z_attribute & attr = addToLast(); + attr.cluster = cluster; + attr.attr_id = cmd_id | (direction ? 0x100 : 0); + attr.key_is_str = true; + if (!suffix) { attr.key_suffix = countAttribute(attr.cluster, attr.attr_id); } else { attr.key_suffix = suffix; } return attr; } @@ -759,7 +820,7 @@ Z_attribute & Z_attribute_list::addAttribute(uint16_t cluster, uint16_t attr_id, Z_attribute & Z_attribute_list::addAttribute(const char * name, bool pmem, uint8_t suffix) { Z_attribute & attr = addToLast(); attr.setKeyName(name, pmem); - if (!suffix) { attr.key_suffix = countAttribute(attr.key.key); } + if (!suffix) { attr.key_suffix = countAttribute(attr.key); } else { attr.key_suffix = suffix; } return attr; } @@ -767,7 +828,7 @@ Z_attribute & Z_attribute_list::addAttribute(const char * name, bool pmem, uint8 Z_attribute & Z_attribute_list::addAttribute(const char * name, const char * name2, uint8_t suffix) { Z_attribute & attr = addToLast(); attr.setKeyName(name, name2); - if (!suffix) { attr.key_suffix = countAttribute(attr.key.key); } + if (!suffix) { attr.key_suffix = countAttribute(attr.key); } else { attr.key_suffix = suffix; } return attr; } @@ -817,26 +878,35 @@ String Z_attribute_list::toString(bool enclose_brackets, bool include_battery) c const Z_attribute * Z_attribute_list::findAttribute(const Z_attribute &attr) const { uint8_t suffix = attr.key_suffix; if (attr.key_is_str) { - return findAttribute(attr.key.key, suffix); + return findAttribute(attr.key, suffix); + } else if (!attr.key_is_cmd) { + return findAttribute(attr.cluster, attr.attr_id, suffix); } else { - return findAttribute(attr.key.id.cluster, attr.key.id.attr_id, suffix); + return findAttributeCmd(attr.cluster, attr.attr_id & 0xFF, attr.attr_id & 0x100 ? true : false, suffix); } } const Z_attribute * Z_attribute_list::findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) const { for (const auto & attr : *this) { - if (attr.equalsKey(cluster, attr_id, suffix)) { return &attr; } + if (attr.equalsId(cluster, attr_id, suffix)) { return &attr; } } return nullptr; } size_t Z_attribute_list::countAttribute(uint16_t cluster, uint16_t attr_id) const { size_t count = 0; for (const auto & attr : *this) { - if (attr.equalsKey(cluster, attr_id, 0)) { count++; } + if (attr.equalsId(cluster, attr_id, 0)) { count++; } } return count; } +const Z_attribute * Z_attribute_list::findAttributeCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix) const { + for (const auto & attr : *this) { + if (attr.equalsCmd(cluster, cmd_id, direction, suffix)) { return &attr; } + } + return nullptr; +} + // return the existing attribute or create a new one Z_attribute & Z_attribute_list::findOrCreateAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) { Z_attribute * found = findAttribute(cluster, attr_id, suffix); @@ -864,8 +934,8 @@ Z_attribute & Z_attribute_list::findOrCreateAttribute(const char * name, uint8_t // same but passing a Z_attribute as key Z_attribute & Z_attribute_list::findOrCreateAttribute(const Z_attribute &attr) { - Z_attribute & ret = attr.key_is_str ? findOrCreateAttribute(attr.key.key, attr.key_suffix) - : findOrCreateAttribute(attr.key.id.cluster, attr.key.id.attr_id, attr.key_suffix); + Z_attribute & ret = attr.key_is_str ? findOrCreateAttribute(attr.key, attr.key_suffix) + : findOrCreateAttribute(attr.cluster, attr.attr_id, attr.key_suffix); ret.key_suffix = attr.key_suffix; return ret; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino index cf11e2405..869ee7679 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino @@ -1015,7 +1015,7 @@ private: * Berry support \*********************************************************************************************/ #ifdef USE_BERRY -extern "C" int32_t callBerryZigbeeDispatcher(const char* cmd, const char* type, void* data, int32_t idx); +extern "C" int32_t callBerryZigbeeDispatcher(const char* event, const class ZCLFrame* zcl_frame, const class Z_attribute_list* attr_list, int32_t idx); #endif // USE_BERRY /*********************************************************************************************\ diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino index 02df96cf7..80156abaa 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino @@ -555,7 +555,7 @@ void Z_Device::jsonPublishAttrList(const char * json_prefix, const Z_attribute_l ResponseAppend_P(PSTR("\"" D_JSON_ZIGBEE_NAME "\":\"%s\","), EscapeJSONString(friendlyName).c_str()); } // Add all other attributes - ResponseAppend_P(PSTR("%s}"), attr_list.toString(false, true).c_str()); // (false, true) - include battery + ResponseAppend_P(PSTR("%s}"), attr_list.toString(false).c_str()); if (!Settings->flag5.zb_omit_json_addr) { ResponseAppend_P(PSTR("}")); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino index 5a7331b9e..76462970d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino @@ -636,8 +636,8 @@ void ZCLFrame::parseReportAttributes(Z_attribute_list& attr_list) { void ZCLFrame::generateSyntheticAttributes(Z_attribute_list& attr_list) { // scan through attributes and apply specific converters for (auto &attr : attr_list) { - if (attr.key_is_str) { continue; } // pass if key is a name - uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; + if (attr.key_is_str && attr.key_is_cmd) { continue; } // pass if key is a name + uint32_t ccccaaaa = (attr.cluster << 16) | attr.attr_id; switch (ccccaaaa) { // 0xccccaaaa . c=cluster, a=attribute case 0x0000FF01: @@ -666,8 +666,8 @@ void ZCLFrame::generateSyntheticAttributes(Z_attribute_list& attr_list) { void ZCLFrame::removeInvalidAttributes(Z_attribute_list& attr_list) { // scan through attributes and apply specific converters for (auto &attr : attr_list) { - if (attr.key_is_str) { continue; } // pass if key is a name - uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; + if (attr.key_is_str && attr.key_is_cmd) { continue; } // pass if key is a name + uint32_t ccccaaaa = (attr.cluster << 16) | attr.attr_id; switch (ccccaaaa) { // 0xccccaaaa . c=cluster, a=attribute case 0x04020000: // Temperature @@ -694,7 +694,7 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) { // first apply synonyms from plugins Z_attribute_synonym syn = Z_plugin_matchAttributeSynonym(device.modelId, device.manufacturerId, - attr.key.id.cluster, attr.key.id.attr_id); + attr.cluster, attr.attr_id); if (syn.found()) { attr.setKeyId(syn.new_cluster, syn.new_attribute); if (syn.multiplier != 1 && syn.multiplier != 0) { @@ -706,7 +706,7 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) { } } - uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; + uint32_t ccccaaaa = (attr.cluster << 16) | attr.attr_id; switch (ccccaaaa) { // 0xccccaaaa . c=cluster, a=attribute case 0x00010020: // BatteryVoltage @@ -802,8 +802,8 @@ void ZCLFrame::generateCallBacks(Z_attribute_list& attr_list) { static const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s // scan through attributes and apply specific converters for (auto &attr : attr_list) { - if (attr.key_is_str) { continue; } // pass if key is a name - uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; + if (attr.key_is_str && attr.key_is_cmd) { continue; } // pass if key is a name + uint32_t ccccaaaa = (attr.cluster << 16) | attr.attr_id; switch (ccccaaaa) { // 0xccccaaaa . c=cluster, a=attribute case 0x04060000: // Occupancy @@ -1330,7 +1330,7 @@ void ZCLFrame::syntheticAqaraCubeOrButton(class Z_attribute_list &attr_list, cla // Aqara vibration device void ZCLFrame::syntheticAqaraVibration(class Z_attribute_list &attr_list, class Z_attribute &attr) { - switch (attr.key.id.attr_id) { + switch (attr.attr_id) { case 0x0055: { int32_t ivalue = attr.getInt(); @@ -1400,10 +1400,10 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib } // attr is Z_attribute& - if (!attr.key_is_str) { - uint16_t cluster = attr.key.id.cluster; - uint16_t attribute = attr.key.id.attr_id; - uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; + if (!attr.key_is_str && !attr.key_is_cmd) { + uint16_t cluster = attr.cluster; + uint16_t attribute = attr.attr_id; + uint32_t ccccaaaa = (attr.cluster << 16) | attr.attr_id; // Look for an entry in the converter table bool found = false; @@ -1501,7 +1501,7 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib void Z_parseAttributeKey_inner(uint16_t shortaddr, class Z_attribute & attr, uint16_t preferred_cluster) { if (attr.key_is_str) { // find the attribute name - Z_attribute_match matched_attr = Z_findAttributeMatcherByName(shortaddr, attr.key.key); + Z_attribute_match matched_attr = Z_findAttributeMatcherByName(shortaddr, attr.key); if (matched_attr.found()) { if ((preferred_cluster == 0xFFFF) || // any cluster (matched_attr.cluster == preferred_cluster)) { @@ -1514,7 +1514,7 @@ void Z_parseAttributeKey_inner(uint16_t shortaddr, class Z_attribute & attr, uin } } else { // find by cluster/attribute - Z_attribute_match matched_attr = Z_findAttributeMatcherById(shortaddr, attr.key.id.cluster, attr.key.id.attr_id, false); + Z_attribute_match matched_attr = Z_findAttributeMatcherById(shortaddr, attr.cluster, attr.attr_id, false); if (matched_attr.found()) { attr.attr_type = matched_attr.zigbee_type; attr.manuf = matched_attr.manuf; @@ -1542,7 +1542,7 @@ bool Z_parseAttributeKey(uint16_t shortaddr, class Z_attribute & attr, uint16_t // check if the name has the format "XXXX/YYYY" where XXXX is the cluster, YYYY the attribute id // alternative "XXXX/YYYY%ZZ" where ZZ is the type (for unregistered attributes) if (attr.key_is_str) { - const char * key = attr.key.key; + const char * key = attr.key; char * delimiter = strchr(key, '/'); char * delimiter2 = strchr(key, '%'); if (delimiter) { @@ -1572,7 +1572,7 @@ bool Z_parseAttributeKey(uint16_t shortaddr, class Z_attribute & attr, uint16_t } // special case for Tuya attributes, where Zunk is allowed if (Zunk == attr.attr_type) { - if (!attr.key_is_str && attr.key.id.cluster == 0xEF00) { + if (!attr.key_is_str && attr.cluster == 0xEF00) { return true; } return false; // couldn't find any match diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_commands.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_commands.ino index 6990c60db..925f2da9f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_commands.ino @@ -346,11 +346,14 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, // always report attribute in raw format // Format: "0001!06": "00" = "!": "" for commands to devices // Format: "0004<00": "00" = "<": "" for commands to devices - char attrid_str[12]; - snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd); - Z_attribute & attr_raw = attr_list.addAttribute(attrid_str); + // char attrid_str[12]; + // snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd); + // Z_attribute & attr_raw = attr_list.addAttribute(attrid_str); + Z_attribute & attr_raw = attr_list.addAttributeCmd(cluster, cmd, direction); attr_raw.setBuf(payload, 0, payload.len()); + // TODO Berry encode command + if (command_name) { // Now try to transform into a human readable format // if (direction & 0x80) then specific transform diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_8_parsers.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_8_parsers.ino index 3cc1eacb7..43090cda9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_8_parsers.ino @@ -1650,7 +1650,7 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) { #ifdef USE_BERRY // Berry pre-process messages - callBerryZigbeeDispatcher("incoming", "zcl_frame", &zcl_received, 0); + callBerryZigbeeDispatcher("frame_received", &zcl_received, nullptr, srcaddr); #endif // USE_BERRY // create the device entry if it does not exist and if it's not the local device @@ -1704,6 +1704,11 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) { AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":{%s}}"), srcaddr, attr_list.toString(false, false).c_str()); // don't include battery +#ifdef USE_BERRY + // Berry pre-process messages + callBerryZigbeeDispatcher("attributes_raw", &zcl_received, &attr_list, srcaddr); +#endif // USE_BERRY + // discard the message if it was sent by us (broadcast or group loopback) if (srcaddr == localShortAddr) { AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "loopback message, ignoring")); @@ -1716,6 +1721,11 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) { zcl_received.generateCallBacks(attr_list); // set deferred callbacks, ex: Occupancy Z_postProcessAttributes(srcaddr, zcl_received.getSrcEndpoint(), attr_list); +#ifdef USE_BERRY + // Berry pre-process messages + callBerryZigbeeDispatcher("attributes_refined", &zcl_received, &attr_list, srcaddr); +#endif // USE_BERRY + if (defer_attributes) { // Prepare for publish if (zigbee_devices.jsonIsConflict(srcaddr, attr_list)) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino index 378062153..42d7ee74f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino @@ -241,15 +241,15 @@ bool ZbTuyaWrite(SBuffer & buf, const Z_attribute & attr) { double val_d = attr.getOptimisticDouble(); const char * val_str = attr.getStr(); - if (attr.key_is_str) { return false; } // couldn't find attr if so skip + if (attr.key_is_str || attr.key_is_cmd) { return false; } // couldn't find attr if so skip if (attr.isNum() && (1 != attr.attr_multiplier)) { ZbApplyMultiplier(val_d, attr.attr_multiplier); } uint32_t u32 = val_d; int32_t i32 = val_d; - uint8_t tuyatype = (attr.key.id.attr_id >> 8); - uint8_t dpid = (attr.key.id.attr_id & 0xFF); + uint8_t tuyatype = (attr.attr_id >> 8); + uint8_t dpid = (attr.attr_id & 0xFF); buf.add8(dpid); buf.add8(tuyatype); @@ -300,13 +300,13 @@ bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_stat double val_d = attr.getOptimisticDouble(); const char * val_str = attr.getStr(); - if (attr.key_is_str) { return false; } // couldn't find attr if so skip + if (attr.key_is_str && attr.key_is_cmd) { return false; } // couldn't find attr if so skip if (attr.isNum() && (1 != attr.attr_multiplier)) { ZbApplyMultiplier(val_d, attr.attr_multiplier); } // push the value in the buffer - buf.add16(attr.key.id.attr_id); // prepend with attribute identifier + buf.add16(attr.attr_id); // prepend with attribute identifier if (prepend_status_ok) { buf.add8(Z_SUCCESS); // status OK = 0x00 } @@ -315,7 +315,7 @@ bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_stat if (res < 0) { // remove the attribute type we just added // buf.setLen(buf.len() - (operation == ZCL_READ_ATTRIBUTES_RESPONSE ? 4 : 3)); - AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE D_ZIGBEE_UNSUPPORTED_ATTRIBUTE_TYPE " %04X/%04X '0x%02X'"), attr.key.id.cluster, attr.key.id.attr_id, attr.attr_type); + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE D_ZIGBEE_UNSUPPORTED_ATTRIBUTE_TYPE " %04X/%04X '0x%02X'"), attr.cluster, attr.attr_id, attr.attr_type); return false; } return true; @@ -346,8 +346,8 @@ void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZCLFrame & zcl) // all attributes must use the same cluster if (0xFFFF == zcl.cluster) { - zcl.cluster = attr.key.id.cluster; // set the cluster for this packet - } else if (zcl.cluster != attr.key.id.cluster) { + zcl.cluster = attr.cluster; // set the cluster for this packet + } else if (zcl.cluster != attr.cluster) { ResponseCmndChar_P(PSTR(D_ZIGBEE_TOO_MANY_CLUSTERS)); return; } @@ -432,7 +432,7 @@ void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZCLFrame & zcl) // all fields are gathered, output the butes into the buffer, ZCL 2.5.7.1 // common bytes buf.add8(attr_direction ? 0x01 : 0x00); - buf.add16(attr.key.id.attr_id); + buf.add16(attr.attr_id); if (attr_direction) { buf.add16(attr_timeout); } else { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino index 37f506c0d..03a288781 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino @@ -69,7 +69,7 @@ extern "C" { return d->batt_percent == 255 ? -1 : d->batt_percent; } int32_t zd_battery_lastseen(const class Z_Device* d) { - return 0; // TODO not yet known + return d->batt_last_seen; // TODO not yet known } } @@ -166,8 +166,8 @@ extern "C" { be_return(vm); } - int32_t callBerryZigbeeDispatcher(const char* cmd, const char* type, void* data, int32_t idx); - int32_t callBerryZigbeeDispatcher(const char* cmd, const char* type, void* data, int32_t idx) { + int32_t callBerryZigbeeDispatcher(const char* event, const class ZCLFrame* zcl_frame, const class Z_attribute_list* attr_list, int32_t idx); + int32_t callBerryZigbeeDispatcher(const char* event, const class ZCLFrame* zcl_frame, const class Z_attribute_list* attr_list, int32_t idx) { int32_t ret = 0; bvm *vm = berry.vm; @@ -178,9 +178,9 @@ extern "C" { be_getmethod(vm, -1, PSTR("dispatch")); // method dispatch if (!be_isnil(vm, -1)) { be_pushvalue(vm, -2); // add instance as first arg - be_pushstring(vm, cmd != nullptr ? cmd : ""); - be_pushstring(vm, type != nullptr ? type : ""); - be_pushcomptr(vm, data); + be_pushstring(vm, event != nullptr ? event : ""); + be_pushcomptr(vm, (void*) zcl_frame); + be_pushcomptr(vm, (void*) attr_list); be_pushint(vm, idx); BrTimeoutStart(); ret = be_pcall(vm, 5); // 5 arguments @@ -205,7 +205,7 @@ extern "C" { } /*********************************************************************************************\ - * Mapping for zcl_message + * Mapping for zcl_frame_ntv * \*********************************************************************************************/ extern "C" { @@ -234,6 +234,51 @@ extern "C" { #pragma GCC diagnostic pop } +/*********************************************************************************************\ + * Mapping for zcl_attribute_ntv + * +\*********************************************************************************************/ +extern "C" { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" // avoid warnings since we're using offsetof() in a risky way + + extern const be_ctypes_structure_t be_zigbee_zcl_attribute_list_struct = { + sizeof(Z_attribute_list), /* size in bytes */ + 3, /* number of elements */ + nullptr, + (const be_ctypes_structure_item_t[3]) { + { "_groupaddr", offsetof(Z_attribute_list, group_id), 0, 0, ctypes_u16, 0 }, + { "_lqi", offsetof(Z_attribute_list, lqi), 0, 0, ctypes_u8, 0 }, + { "_src_ep", offsetof(Z_attribute_list, src_ep), 0, 0, ctypes_u8, 0 }, + }}; + + extern const be_ctypes_structure_t be_zigbee_zcl_attribute_struct = { + sizeof(Z_attribute), /* size in bytes */ + 8, /* number of elements */ + nullptr, + (const be_ctypes_structure_item_t[8]) { + { "_attr_id", offsetof(Z_attribute, attr_id), 0, 0, ctypes_u16, 0 }, + { "_cluster", offsetof(Z_attribute, cluster), 0, 0, ctypes_u16, 0 }, + { "_cmd", offsetof(Z_attribute, attr_id), 0, 0, ctypes_u8, 0 }, // low 8 bits of attr_id + { "_direction", offsetof(Z_attribute, attr_id) + 1, 0, 0, ctypes_u8, 0 }, // high 8 bits of attr_id + { "_iscmd", offsetof(Z_attribute, key_is_cmd), 0, 0, ctypes_u8, 0 }, + { "attr_multiplier", offsetof(Z_attribute, attr_multiplier), 0, 0, ctypes_i8, 0 }, + { "attr_type", offsetof(Z_attribute, attr_type), 0, 0, ctypes_u8, 0 }, + // { "key", offsetof(Z_attribute, key), 0, 0, ctypes_ptr32, 0 }, + // { "key_is_pmem", offsetof(Z_attribute, key_is_pmem), 0, 0, ctypes_u8, 0 }, + // { "key_is_str", offsetof(Z_attribute, key_is_str), 0, 0, ctypes_u8, 0 }, + { "key_suffix", offsetof(Z_attribute, key_suffix), 0, 0, ctypes_u8, 0 }, + // { "type", offsetof(Z_attribute, type), 0, 0, ctypes_u8, 0 }, + // { "val_float", offsetof(Z_attribute, val), 0, 0, ctypes_float, 0 }, + // { "val_i32", offsetof(Z_attribute, val), 0, 0, ctypes_i32, 0 }, + // { "val_str_raw", offsetof(Z_attribute, val_str_raw), 0, 0, ctypes_u8, 0 }, + // { "val_ptr", offsetof(Z_attribute, val), 0, 0, ctypes_ptr32, 0 }, + // { "val_u32", offsetof(Z_attribute, val), 0, 0, ctypes_u32, 0 }, + }}; + +#pragma GCC diagnostic pop +} + /*********************************************************************************************\ * Functions for zcl_frame * @@ -258,5 +303,295 @@ extern "C" { } } +/*********************************************************************************************\ + * Functions for zcl_attribute + * +\*********************************************************************************************/ +extern "C" { + extern const bclass be_class_zcl_attribute_list; + extern const bclass be_class_zcl_attribute; + extern const bclass be_class_zcl_attribute_ntv; + + void zat_zcl_attribute(struct bvm *vm, const Z_attribute *attr); + + // Pushes the Z_attribute_list on the stack as a simple list + // Adds the output on top of stack and does not change rest of stack (stack size incremented by 1) + void zat_zcl_attribute_list_inner(struct bvm *vm, const Z_attribute_list* attrlist) { + be_newobject(vm, "list"); + + for (const auto & attr : *attrlist) { + zat_zcl_attribute(vm, &attr); + be_data_push(vm, -2); + be_pop(vm, 1); + } + be_pop(vm, 1); + } + + // Pushes the Z_attribute on the stack as `zcl_attribute_ntv` + void zat_zcl_attribute(struct bvm *vm, const Z_attribute *attr) { + be_pushntvclass(vm, &be_class_zcl_attribute); + be_pushcomptr(vm, (void*) attr); + + // instantiate + be_call(vm, 1); // 1 parameter + be_pop(vm, 1); + } + + // Get typed value from zcl_attributes + int be_zigbee_zcl_attribute_ntv_get_val(struct bvm *vm) { + const Z_attribute *attr = (const Z_attribute*) be_tobytes(vm, 1, NULL); + // value + switch (attr->type) { + case Za_type::Za_bool: + be_pushbool(vm, attr->val.uval32 ? btrue : bfalse); + break; + case Za_type::Za_uint: + case Za_type::Za_int: + be_pushint(vm, attr->val.ival32); + break; + case Za_type::Za_float: + be_pushreal(vm, (breal)attr->val.fval); + break; + case Za_type::Za_raw: + be_pushbytes(vm, attr->val.bval->getBuffer(), attr->val.bval->len()); + break; + case Za_type::Za_str: + be_pushstring(vm, attr->val.sval); + break; + + case Za_type::Za_obj: + zat_zcl_attribute_list_inner(vm, attr->val.objval); + break; + + case Za_type::Za_arr: + // json_format = true; + if (attr->val.arrval) { + String arrval = attr->val.arrval->toString(); + be_module_load(vm, be_newstr(vm, "json")); + be_getmember(vm, -1, "load"); + be_remove(vm, -2); // remove module 'json' + be_pushstring(vm, arrval.c_str()); + be_call(vm, 1); + be_pop(vm, 1); + } else { + // push empty list + be_newobject(vm, "list"); + be_pop(vm, 1); + } + break; + + case Za_type::Za_none: + default: + be_pushnil(vm); + break; + } + + be_return(vm); + } + + // Initialize the Z_attribute_list memory zone with provided address + int be_zigbee_zcl_attribute_list_ntv_init(struct bvm *vm) { + size_t len; + Z_attribute_list *attr_list = (Z_attribute_list*) be_tobytes(vm, 1, &len); + attr_list = new(attr_list) Z_attribute_list(); // "placement new" to provide a fixed address https://isocpp.org/wiki/faq/dtors#placement-new + be_return_nil(vm); + } + + // Deinitialize the Z_attribute_list memory zone with provided address + int be_zigbee_zcl_attribute_list_ntv_deinit(struct bvm *vm) { + size_t len; + Z_attribute_list *attr_list = (Z_attribute_list*) be_tobytes(vm, 1, &len); + if (attr_list) { + attr_list->~Z_attribute_list(); + } + be_return_nil(vm); + } + + // Size + int be_zigbee_zcl_attribute_list_ntv_size(struct bvm *vm) { + Z_attribute_list *attr_list = (Z_attribute_list*) be_tobytes(vm, 1, nullptr); + be_pushint(vm, attr_list->length()); + be_return(vm); + } + + // Item + int be_zigbee_zcl_attribute_list_ntv_item(struct bvm *vm) { + int32_t argc = be_top(vm); + if (argc >= 2) { + int32_t idx = be_toint(vm, 2); + Z_attribute_list *attr_list = (Z_attribute_list*) be_tobytes(vm, 1, nullptr); + const Z_attribute* attr = attr_list->at(idx); + if (attr) { + zat_zcl_attribute(vm, attr); + be_return(vm); + } + } + be_return_nil(vm); + } + + // new_head + int be_zigbee_zcl_attribute_list_ntv_new_head(struct bvm *vm) { + Z_attribute_list *attr_list = (Z_attribute_list*) be_tobytes(vm, 1, nullptr); + Z_attribute &attr = attr_list->addHead(); + zat_zcl_attribute(vm, &attr); + be_return(vm); + } + + // new_tail + int be_zigbee_zcl_attribute_list_ntv_new_tail(struct bvm *vm) { + Z_attribute_list *attr_list = (Z_attribute_list*) be_tobytes(vm, 1, nullptr); + Z_attribute &attr = attr_list->addToLast(); + zat_zcl_attribute(vm, &attr); + be_return(vm); + } + + // Remove + int be_zigbee_zcl_attribute_list_ntv_remove(struct bvm *vm) { + int32_t argc = be_top(vm); + if (argc >= 2) { + int32_t idx = be_toint(vm, 2); + Z_attribute_list *attr_list = (Z_attribute_list*) be_tobytes(vm, 1, nullptr); + const Z_attribute* attr = attr_list->at(idx); + if (attr) { + attr_list->remove(attr); + } + } + be_return_nil(vm); + } + + // Initialize the Z_attribute memory zone with provided address + int be_zigbee_zcl_attribute_ntv_init(struct bvm *vm) { + size_t len; + Z_attribute *attr = (Z_attribute*) be_tobytes(vm, 1, &len); + attr = new(attr) Z_attribute(); // "placement new" to provide a fixed address https://isocpp.org/wiki/faq/dtors#placement-new + be_return_nil(vm); + } + + // Deinitialize the Z_attribute memory zone with provided address + int be_zigbee_zcl_attribute_ntv_deinit(struct bvm *vm) { + size_t len; + Z_attribute *attr = (Z_attribute*) be_tobytes(vm, 1, &len); + if (attr) { + attr->~Z_attribute(); + } + be_return_nil(vm); + } + + // Set typed value from zcl_attributes + int be_zigbee_zcl_attribute_ntv_set_val(struct bvm *vm) { + int32_t argc = be_top(vm); + if (argc >= 2) { + Z_attribute *attr = (Z_attribute*) be_tobytes(vm, 1, NULL); + + if (be_isnil(vm, 2)) { + attr->setNone(); + } else if (be_isbool(vm, 2)) { + attr->setBool(be_tobool(vm, 2)); + } else if (be_isint(vm, 2)) { + attr->setInt(be_toint(vm, 2)); + } else if (be_isreal(vm, 2)) { + attr->setFloat(be_toreal(vm, 2)); + } else if (be_isstring(vm, 2)) { + attr->setStr(be_tostring(vm, 2)); + } else if (be_isbytes(vm, 2)) { + size_t len; + const void* buf = be_tobytes(vm, 2, &len); + attr->setRaw(buf, len); + } + } + + be_return(vm); + } + + // returns the key as string or `nil` if no string key. Suffix is not appended + int be_zigbee_zcl_attribute_ntv_get_key(struct bvm *vm) { + const Z_attribute *attr = (const Z_attribute*) be_tobytes(vm, 1, NULL); + if (attr->key_is_str) { + be_pushstring(vm, attr->key); + } else { + be_pushnil(vm); + } + be_return(vm); + } + + // set string key, or remove if `nil` or no parameter + int be_zigbee_zcl_attribute_ntv_set_key(struct bvm *vm) { + Z_attribute *attr = (Z_attribute*) be_tobytes(vm, 1, NULL); + int32_t argc = be_top(vm); + if (argc >= 2 && be_isstring(vm, 2)) { + const char* key = be_tostring(vm, 2); + attr->setKeyName(key, false); + } else { + attr->setKeyId(attr->cluster, attr->attr_id); + } + be_return_nil(vm); + } +} + +extern "C" { + int zigbee_test_attr(struct bvm *vm) { + int32_t mode = be_toint(vm, 2); + if (mode < 10) { + // + } else { + Z_attribute *a = new Z_attribute(); + if (mode == 10) { + a->setKeyId(1111, 2222); + a->setUInt(1337); + } else if (mode == 11) { + a->setKeyName("super_attribute"); + a->key_suffix = 2; + a->setFloat(3.14); + } else if (mode == 12) { + a->setKeyName("array"); + a->newJsonArray(); + a->val.arrval->add(-1); + a->val.arrval->addStr("foo"); + a->val.arrval->addStr("bar"); + a->val.arrval->addStr("bar\"baz\'toto"); + } else if (mode == 13) { + a->setKeyName("list"); + a->newAttrList(); + Z_attribute &subattr1 = a->val.objval->addAttribute(10,20); + subattr1.setStr("sub1"); + Z_attribute &subattr2 = a->val.objval->addAttribute(11,21); + subattr2.setStr("sub2"); + } + zat_zcl_attribute(vm, a); + } + be_return(vm); + } + + + // Creates a zcl_attributes from Z_attribute_list + // Adds the output on top of stack and does not change rest of stack (stack size incremented by 1) + void zat_zcl_attribute_list(struct bvm *vm, uint16_t shortaddr, const Z_attribute_list* attr_list) { + be_pushntvclass(vm, &be_class_zcl_attribute_list); + be_pushcomptr(vm, (void*) attr_list); + // // instantiate + be_call(vm, 1); // 1 parameter + be_pop(vm, 1); + + if (shortaddr != BAD_SHORTADDR) { + be_pushint(vm, shortaddr); + be_setmember(vm, -2, "shortaddr"); + be_pop(vm, 1); + } + } + + int zigbee_test_msg(struct bvm *vm) { + Z_attribute_list attr_list; + + attr_list.lqi = 250; + Z_attribute &subattr1 = attr_list.addAttribute(10,20); + subattr1.setStr("sub1"); + Z_attribute &subattr2 = attr_list.addAttribute(11,21); + subattr2.setStr("sub2"); + + zat_zcl_attribute_list(vm, 100, &attr_list); + be_return(vm); + } +} + #endif // USE_ZIGBEE #endif // USE_BERRY