Berry zigbee phase 1

This commit is contained in:
Stephan Hadinger 2022-05-24 22:45:04 +02:00
parent d9e01ef9da
commit ce33aa5f9d
19 changed files with 2371 additions and 1266 deletions

View File

@ -48,6 +48,9 @@ be_extern_native_module(uuid);
be_extern_native_module(animate);
be_extern_native_module(partition_core);
be_extern_native_module(crc);
#ifdef USE_ZIGBEE
be_extern_native_module(zigbee);
#endif // USE_ZIGBEE
#ifdef USE_LVGL
be_extern_native_module(lv);
be_extern_native_module(lv_extra);
@ -147,6 +150,9 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
#ifdef USE_WEBSERVER
&be_native_module(webserver),
#endif // USE_WEBSERVER
#ifdef USE_ZIGBEE
&be_native_module(zigbee),
#endif // USE_ZIGBEE
&be_native_module(flash),
&be_native_module(partition_core),
&be_native_module(crc),

View File

@ -265,6 +265,7 @@ extern const bcstring be_const_str__timers;
extern const bcstring be_const_str__validate;
extern const bcstring be_const_str__write;
extern const bcstring be_const_str_a;
extern const bcstring be_const_str_abort;
extern const bcstring be_const_str_abs;
extern const bcstring be_const_str_acos;
extern const bcstring be_const_str_active_otadata;
@ -569,6 +570,7 @@ extern const bcstring be_const_str_imax;
extern const bcstring be_const_str_img;
extern const bcstring be_const_str_imin;
extern const bcstring be_const_str_import;
extern const bcstring be_const_str_info;
extern const bcstring be_const_str_init;
extern const bcstring be_const_str_init_draw_arc_dsc;
extern const bcstring be_const_str_init_draw_line_dsc;
@ -1032,5 +1034,9 @@ extern const bcstring be_const_str_y;
extern const bcstring be_const_str_y1;
extern const bcstring be_const_str_year;
extern const bcstring be_const_str_yield;
extern const bcstring be_const_str_zb_coord_ntv;
extern const bcstring be_const_str_zb_device;
extern const bcstring be_const_str_zcl_frame;
extern const bcstring be_const_str_zcl_frame_ntv;
extern const bcstring be_const_str_zero;
extern const bcstring be_const_str_zip;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
#include "be_constobj.h"
static be_define_const_map_slots(be_class_zb_coord_ntv_map) {
{ be_const_key(iter, -1), be_const_func(zc_iter) },
{ be_const_key(zcl_frame, -1), be_const_class(be_class_zcl_frame) },
{ be_const_key(zb_device, 3), be_const_class(be_class_zb_device) },
{ be_const_key(info, -1), be_const_func(zc_info) },
{ be_const_key(size, 1), be_const_ctype_func(zc_size) },
{ be_const_key(item, -1), be_const_func(zc_item) },
{ be_const_key(abort, 4), be_const_ctype_func(zc_abort) },
};
static be_define_const_map(
be_class_zb_coord_ntv_map,
7
);
BE_EXPORT_VARIABLE be_define_const_class(
be_class_zb_coord_ntv,
0,
NULL,
zb_coord_ntv
);

View File

@ -0,0 +1,20 @@
#include "be_constobj.h"
static be_define_const_map_slots(be_class_zb_device_map) {
{ be_const_key(init, -1), be_const_ctype_func(zd_init) },
{ be_const_key(tostring, -1), be_const_closure(zb_device_tostring_closure) },
{ be_const_key(_p, -1), be_const_var(0) },
{ be_const_key(member, 0), be_const_func(zd_member) },
};
static be_define_const_map(
be_class_zb_device_map,
4
);
BE_EXPORT_VARIABLE be_define_const_class(
be_class_zb_device,
1,
NULL,
zb_device
);

View File

@ -0,0 +1,17 @@
#include "be_constobj.h"
static be_define_const_map_slots(be_class_zcl_frame_ntv_map) {
{ be_const_key(_def, -1), be_const_comptr(&be_zigbee_zcl_frame_struct) },
};
static be_define_const_map(
be_class_zcl_frame_ntv_map,
1
);
BE_EXPORT_VARIABLE be_define_const_class(
be_class_zcl_frame_ntv,
0,
(bclass *)&be_class_ctypes_bytes,
zcl_frame_ntv
);

View File

@ -0,0 +1,17 @@
#include "be_constobj.h"
static be_define_const_map_slots(m_libzigbee_map) {
{ be_const_key(init, -1), be_const_func(zigbee_init) },
};
static be_define_const_map(
m_libzigbee_map,
1
);
static be_define_const_module(
m_libzigbee,
"zigbee"
);
BE_EXPORT_VARIABLE be_define_const_native_module(zigbee);

View File

@ -76,6 +76,7 @@ static bbool be_const_member_dual(bvm *vm, const be_const_member_t * definitions
case '>': // call to a ctype function
{
be_ctype_var_args_t* args = (be_ctype_var_args_t*) definitions[idx].value;
be_pop(vm, be_top(vm) - 1); // make sure we have only the instance left on the stack
int ret = be_call_c_func(vm, args->func, args->return_type, NULL);
if ((ret == BE_OK) && !be_isnil(vm, -1)) {
return btrue;

View File

@ -0,0 +1,173 @@
/********************************************************************
* Zigbee
*
*******************************************************************/
#ifdef USE_ZIGBEE
#include "be_constobj.h"
#include "be_mapping.h"
#include "be_ctypes.h"
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
extern const void * zd_init(void* d); BE_FUNC_CTYPE_DECLARE(zd_init, "+_p", "c")
extern int32_t zd_shortaddr(void* d); BE_VAR_CTYPE_DECLARE(zd_shortaddr, "i");
extern const void* zd_longaddr(void* d, size_t *size, void* p2); BE_VAR_CTYPE_DECLARE(zd_longaddr, "&");
extern const char* zd_manufacturer(void* d); BE_VAR_CTYPE_DECLARE(zd_manufacturer, "s");
extern const char* zd_model(void* d); BE_VAR_CTYPE_DECLARE(zd_model, "s");
extern const char* zd_name(void* d); BE_VAR_CTYPE_DECLARE(zd_name, "s");
extern bbool zd_router(void* d); BE_VAR_CTYPE_DECLARE(zd_router, "b");
extern bbool zd_hidden(void* d); BE_VAR_CTYPE_DECLARE(zd_hidden, "b");
extern bbool zd_reachable(void* d); BE_VAR_CTYPE_DECLARE(zd_reachable, "b");
extern int32_t zd_lastseen(void* d); BE_VAR_CTYPE_DECLARE(zd_lastseen, "i");
extern int32_t zd_lqi(void* d); BE_VAR_CTYPE_DECLARE(zd_lqi, "i");
extern int32_t zd_battery(void* d); BE_VAR_CTYPE_DECLARE(zd_battery, "i");
extern int32_t zd_battery_lastseen(void* d); BE_VAR_CTYPE_DECLARE(zd_battery_lastseen, "i");
// moved to constants array
// MUST BE STORED IN SORTED LIST
const be_const_member_t zd_members[] = {
{ ">battery", be_ctype(zd_battery) },
{ ">battery_lastseen", be_ctype(zd_battery_lastseen) },
{ ">hidden", be_ctype(zd_hidden) },
{ ">lastseen", be_ctype(zd_lastseen) },
{ ">longaddr", be_ctype(zd_longaddr) },
{ ">lqi", be_ctype(zd_lqi) },
{ ">manufacturer", be_ctype(zd_manufacturer) },
{ ">model", be_ctype(zd_model) },
{ ">name", be_ctype(zd_name) },
{ ">reachable", be_ctype(zd_reachable) },
{ ">router", be_ctype(zd_router) },
{ ">shortaddr", be_ctype(zd_shortaddr) },
};
static int zd_member(bvm *vm) {
if (be_const_class_member(vm, zd_members, ARRAY_SIZE(zd_members))) {
be_return(vm);
} else {
be_return_nil(vm);
}
}
extern int zc_info(struct bvm *vm);
extern int zc_item(struct bvm *vm);
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 const bclass be_class_ctypes_bytes;
extern const be_ctypes_structure_t be_zigbee_zcl_frame_struct;
extern const bclass be_class_zcl_frame;
/********************************************************************
** Solidified function: tostring
********************************************************************/
be_local_closure(zb_device_tostring, /* name */
be_nested_proto(
14, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[11]) { /* constants */
/* K0 */ be_nested_str_literal("json"),
/* K1 */ be_nested_str_literal("string"),
/* K2 */ be_nested_str_literal("longaddr"),
/* K3 */ be_nested_str_literal("format"),
/* K4 */ be_nested_str_literal("<instance: %s(0x%04X, 0x%08X%08X, name:'%s', model:'%s', manufacturer:'%s')>"),
/* K5 */ be_nested_str_literal("shortaddr"),
/* K6 */ be_nested_str_literal("get"),
/* K7 */ be_const_int(0),
/* K8 */ be_nested_str_literal("name"),
/* K9 */ be_nested_str_literal("model"),
/* K10 */ be_nested_str_literal("manufacturer"),
}),
be_str_literal("tostring"),
&be_const_str_solidified,
( &(const binstruction[22]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0xA40A0200, // 0001 IMPORT R2 K1
0x880C0102, // 0002 GETMBR R3 R0 K2
0x8C100503, // 0003 GETMET R4 R2 K3
0x58180004, // 0004 LDCONST R6 K4
0x601C0005, // 0005 GETGBL R7 G5
0x5C200000, // 0006 MOVE R8 R0
0x7C1C0200, // 0007 CALL R7 1
0x88200105, // 0008 GETMBR R8 R0 K5
0x8C240706, // 0009 GETMET R9 R3 K6
0x542E0003, // 000A LDINT R11 4
0x54320003, // 000B LDINT R12 4
0x7C240600, // 000C CALL R9 3
0x8C280706, // 000D GETMET R10 R3 K6
0x58300007, // 000E LDCONST R12 K7
0x54360003, // 000F LDINT R13 4
0x7C280600, // 0010 CALL R10 3
0x882C0108, // 0011 GETMBR R11 R0 K8
0x88300109, // 0012 GETMBR R12 R0 K9
0x8834010A, // 0013 GETMBR R13 R0 K10
0x7C101200, // 0014 CALL R4 9
0x80040800, // 0015 RET 1 R4
})
)
);
/*******************************************************************/
// Module Zigbee
extern const bclass be_class_zb_coord;
static int zigbee_init(bvm *vm) {
be_pushntvclass(vm, &be_class_zb_coord);
be_call(vm, 0);
be_return(vm);
}
#include "be_fixed_be_class_zb_device.h"
#include "be_fixed_be_class_zb_coord_ntv.h"
#include "be_fixed_be_class_zcl_frame_ntv.h"
#include "be_fixed_zigbee.h"
/* @const_object_info_begin
class be_class_zb_device (scope: global, name: zb_device) {
_p, var
init, ctype_func(zd_init)
member, func(zd_member)
tostring, closure(zb_device_tostring_closure)
}
@const_object_info_end */
/* @const_object_info_begin
class be_class_zb_coord_ntv (scope: global, name: zb_coord_ntv) {
zcl_frame, class(be_class_zcl_frame)
zb_device, class(be_class_zb_device)
info, func(zc_info)
item, func(zc_item)
size, ctype_func(zc_size)
iter, func(zc_iter)
abort, ctype_func(zc_abort)
}
@const_object_info_end */
/* @const_object_info_begin
class be_class_zcl_frame_ntv (scope: global, name: zcl_frame_ntv, super: be_class_ctypes_bytes) {
_def, comptr(&be_zigbee_zcl_frame_struct)
}
@const_object_info_end */
/* @const_object_info_begin
module zigbee (scope: global) {
init, func(zigbee_init)
}
@const_object_info_end */
#endif // USE_LIGHT

View File

@ -0,0 +1,214 @@
/********************************************************************
* Zigbee
*
*******************************************************************/
#ifdef USE_ZIGBEE
#include "be_constobj.h"
extern const bclass be_class_zb_coord_ntv;
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(zb_coord_init, /* 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[ 1]) { /* constants */
/* K0 */ be_nested_str_literal("init"),
}),
be_str_literal("init"),
&be_const_str_solidified,
( &(const binstruction[ 6]) { /* 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
0x80000000, // 0005 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: add_handler
********************************************************************/
be_local_closure(zb_coord_add_handler, /* 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[ 5]) { /* constants */
/* K0 */ be_nested_str_literal("instance"),
/* K1 */ be_nested_str_literal("value_error"),
/* K2 */ be_nested_str_literal("instance required"),
/* K3 */ be_nested_str_literal("_handlers"),
/* K4 */ be_nested_str_literal("push"),
}),
be_str_literal("add_handler"),
&be_const_str_solidified,
( &(const binstruction[18]) { /* code */
0x60080004, // 0000 GETGBL R2 G4
0x5C0C0200, // 0001 MOVE R3 R1
0x7C080200, // 0002 CALL R2 1
0x20080500, // 0003 NE R2 R2 K0
0x780A0000, // 0004 JMPF R2 #0006
0xB0060302, // 0005 RAISE 1 K1 K2
0x88080103, // 0006 GETMBR R2 R0 K3
0x780A0004, // 0007 JMPF R2 #000D
0x88080103, // 0008 GETMBR R2 R0 K3
0x8C080504, // 0009 GETMET R2 R2 K4
0x5C100200, // 000A MOVE R4 R1
0x7C080400, // 000B CALL R2 2
0x70020003, // 000C JMP #0011
0x60080012, // 000D GETGBL R2 G18
0x7C080000, // 000E CALL R2 0
0x400C0401, // 000F CONNECT R3 R2 R1
0x90020602, // 0010 SETMBR R0 K3 R2
0x80000000, // 0011 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: dispatch
********************************************************************/
be_local_closure(zb_coord_dispatch, /* name */
be_nested_proto(
19, /* nstack */
5, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[14]) { /* constants */
/* K0 */ be_nested_str_literal("_handlers"),
/* K1 */ be_nested_str_literal("introspect"),
/* K2 */ be_nested_str_literal("string"),
/* K3 */ be_nested_str_literal("zcl_frame"),
/* K4 */ be_const_int(0),
/* K5 */ be_nested_str_literal("get"),
/* K6 */ be_nested_str_literal("function"),
/* K7 */ be_nested_str_literal("format"),
/* K8 */ be_nested_str_literal("BRY: Exception> '%s' - %s"),
/* K9 */ be_nested_str_literal("tasmota"),
/* K10 */ be_nested_str_literal("_debug_present"),
/* K11 */ be_nested_str_literal("debug"),
/* K12 */ be_nested_str_literal("traceback"),
/* K13 */ be_const_int(1),
}),
be_str_literal("dispatch"),
&be_const_str_solidified,
( &(const binstruction[61]) { /* code */
0x88140100, // 0000 GETMBR R5 R0 K0
0x4C180000, // 0001 LDNIL R6
0x1C140A06, // 0002 EQ R5 R5 R6
0x78160000, // 0003 JMPF R5 #0005
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
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: zb_coord
********************************************************************/
extern const bclass be_class_zb_coord_ntv;
be_local_class(zb_coord,
1,
&be_class_zb_coord_ntv,
be_nested_map(4,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_literal("dispatch", 1), be_const_closure(zb_coord_dispatch_closure) },
{ be_const_key_literal("add_handler", 2), be_const_closure(zb_coord_add_handler_closure) },
{ be_const_key_literal("_handlers", -1), be_const_var(0) },
{ be_const_key_literal("init", 0), be_const_closure(zb_coord_init_closure) },
})),
be_str_literal("zb_coord")
);
/*******************************************************************/
void be_load_zb_coord_class(bvm *vm) {
be_pushntvclass(vm, &be_class_zb_coord);
be_setglobal(vm, "zb_coord");
be_pop(vm, 1);
}
#endif // USE_LIGHT

View File

@ -0,0 +1,255 @@
/********************************************************************
* Zigbee
*
*******************************************************************/
#ifdef USE_ZIGBEE
#include "be_constobj.h"
extern const bclass be_class_zcl_frame_ntv;
/********************************************************************
** Solidified function: member
********************************************************************/
be_local_closure(zcl_frame_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[ 3]) { /* constants */
/* K0 */ be_nested_str_literal("payload"),
/* K1 */ be_nested_str_literal("_get_bytes"),
/* K2 */ be_nested_str_literal("member"),
}),
be_str_literal("member"),
&be_const_str_solidified,
( &(const binstruction[14]) { /* code */
0x1C080300, // 0000 EQ R2 R1 K0
0x780A0003, // 0001 JMPF R2 #0006
0x8C080101, // 0002 GETMET R2 R0 K1
0x7C080200, // 0003 CALL R2 1
0x80040400, // 0004 RET 1 R2
0x70020006, // 0005 JMP #000D
0x60080003, // 0006 GETGBL R2 G3
0x5C0C0000, // 0007 MOVE R3 R0
0x7C080200, // 0008 CALL R2 1
0x8C080502, // 0009 GETMET R2 R2 K2
0x5C100200, // 000A MOVE R4 R1
0x7C080400, // 000B CALL R2 2
0x80040400, // 000C RET 1 R2
0x80000000, // 000D RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: tomap
********************************************************************/
be_local_closure(zcl_frame_tomap, /* name */
be_nested_proto(
7, /* 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_literal("string"),
/* K1 */ be_nested_str_literal("tomap"),
/* K2 */ be_nested_str_literal("shortaddr_hex"),
/* K3 */ be_nested_str_literal("format"),
/* K4 */ be_nested_str_literal("0x%04X"),
/* K5 */ be_nested_str_literal("shortaddr"),
/* K6 */ be_nested_str_literal("payload"),
}),
be_str_literal("tomap"),
&be_const_str_solidified,
( &(const binstruction[14]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0x60080003, // 0001 GETGBL R2 G3
0x5C0C0000, // 0002 MOVE R3 R0
0x7C080200, // 0003 CALL R2 1
0x8C080501, // 0004 GETMET R2 R2 K1
0x7C080200, // 0005 CALL R2 1
0x8C0C0303, // 0006 GETMET R3 R1 K3
0x58140004, // 0007 LDCONST R5 K4
0x88180105, // 0008 GETMBR R6 R0 K5
0x7C0C0600, // 0009 CALL R3 3
0x980A0403, // 000A SETIDX R2 K2 R3
0x880C0106, // 000B GETMBR R3 R0 K6
0x980A0C03, // 000C SETIDX R2 K6 R3
0x80040400, // 000D RET 1 R2
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(zcl_frame_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_literal("init"),
/* K1 */ be_nested_str_literal("no_bytes"),
}),
be_str_literal("init"),
&be_const_str_solidified,
( &(const binstruction[10]) { /* 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
0x60080015, // 0006 GETGBL R2 G21
0x7C080000, // 0007 CALL R2 0
0x90020202, // 0008 SETMBR R0 K1 R2
0x80000000, // 0009 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: _get_bytes
********************************************************************/
be_local_closure(zcl_frame__get_bytes, /* 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[ 7]) { /* constants */
/* K0 */ be_nested_str_literal("introspect"),
/* K1 */ be_nested_str_literal("toptr"),
/* K2 */ be_nested_str_literal("payload_ptr"),
/* K3 */ be_const_int(0),
/* K4 */ be_nested_str_literal("get"),
/* K5 */ be_const_int(2),
/* K6 */ be_nested_str_literal("no_bytes"),
}),
be_str_literal("_get_bytes"),
&be_const_str_solidified,
( &(const binstruction[32]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0x8C080301, // 0001 GETMET R2 R1 K1
0x88100102, // 0002 GETMBR R4 R0 K2
0x7C080400, // 0003 CALL R2 2
0x600C0009, // 0004 GETGBL R3 G9
0x5C100400, // 0005 MOVE R4 R2
0x7C0C0200, // 0006 CALL R3 1
0x200C0703, // 0007 NE R3 R3 K3
0x780E0013, // 0008 JMPF R3 #001D
0x600C0015, // 0009 GETGBL R3 G21
0x5C100400, // 000A MOVE R4 R2
0x5415FFFB, // 000B LDINT R5 -4
0x7C0C0400, // 000C CALL R3 2
0x8C100704, // 000D GETMET R4 R3 K4
0x58180005, // 000E LDCONST R6 K5
0x581C0005, // 000F LDCONST R7 K5
0x7C100600, // 0010 CALL R4 3
0x60140015, // 0011 GETGBL R5 G21
0x8C180301, // 0012 GETMET R6 R1 K1
0x60200009, // 0013 GETGBL R8 G9
0x5C240400, // 0014 MOVE R9 R2
0x7C200200, // 0015 CALL R8 1
0x54260003, // 0016 LDINT R9 4
0x00201009, // 0017 ADD R8 R8 R9
0x7C180400, // 0018 CALL R6 2
0x5C1C0800, // 0019 MOVE R7 R4
0x7C140400, // 001A CALL R5 2
0x80040A00, // 001B RET 1 R5
0x70020001, // 001C JMP #001F
0x880C0106, // 001D GETMBR R3 R0 K6
0x80040600, // 001E RET 1 R3
0x80000000, // 001F RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: tostring
********************************************************************/
be_local_closure(zcl_frame_tostring, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_str_literal("tomap"),
}),
be_str_literal("tostring"),
&be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x8C040100, // 0000 GETMET R1 R0 K0
0x7C040200, // 0001 CALL R1 1
0x60080008, // 0002 GETGBL R2 G8
0x5C0C0200, // 0003 MOVE R3 R1
0x7C080200, // 0004 CALL R2 1
0x80040400, // 0005 RET 1 R2
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: zcl_frame
********************************************************************/
extern const bclass be_class_zcl_frame_ntv;
be_local_class(zcl_frame,
1,
&be_class_zcl_frame_ntv,
be_nested_map(6,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_literal("no_bytes", -1), be_const_var(0) },
{ be_const_key_literal("member", 2), be_const_closure(zcl_frame_member_closure) },
{ be_const_key_literal("tostring", -1), be_const_closure(zcl_frame_tostring_closure) },
{ be_const_key_literal("init", -1), be_const_closure(zcl_frame_init_closure) },
{ be_const_key_literal("tomap", 5), be_const_closure(zcl_frame_tomap_closure) },
{ be_const_key_literal("_get_bytes", -1), be_const_closure(zcl_frame__get_bytes_closure) },
})),
be_str_literal("zcl_frame")
);
/*******************************************************************/
void be_load_zcl_frame_class(bvm *vm) {
be_pushntvclass(vm, &be_class_zcl_frame);
be_setglobal(vm, "zcl_frame");
be_pop(vm, 1);
}
#endif // USE_LIGHT

View File

@ -0,0 +1,17 @@
# zigbee code
class zb_device
def tostring()
import json
import string
var la = self.longaddr # bytes() of size 8, little-endian
return string.format("<instance: %s(0x%04X, 0x%08X%08X, name:'%s', model:'%s', manufacturer:'%s')>",
classname(self), self.shortaddr,
la.get(4,4), la.get(0,4),
self.name, self.model, self.manufacturer)
return
end
end

View File

@ -0,0 +1,59 @@
# zigbee zcl_frame class
# solidify.dump(zb_coord,true)
class zb_coord_ntv end # fake class replaced with native one
#zb_coord_ntv = classof(super(zigbee))
class zb_coord : zb_coord_ntv
var _handlers
def init()
super(self).init()
end
def add_handler(h)
if type(h) != 'instance'
raise "value_error", "instance required"
end
if self._handlers
self._handlers.push(h)
else
self._handlers = [h]
end
end
def dispatch(event_type, data_type, data_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)
end
#print(string.format(">ZIG: cmd=%s data_type=%s data=%s idx=%i", event_type, data_type, str(data), idx))
var i = 0
while i < size(self._handlers)
var h = self._handlers[i]
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)
except .. as e,m
print(string.format("BRY: Exception> '%s' - %s", e, m))
if tasmota._debug_present
import debug
debug.traceback()
end
end
end
i += 1
end
end
end

View File

@ -0,0 +1,50 @@
# zigbee zcl_frame class
#
# solidify.dump(zcl_frame,true)
var zcl_frame_ntv = super(zcl_frame)
class zcl_frame : zcl_frame_ntv
var no_bytes
def init(p)
super(self).init(p)
self.no_bytes = bytes()
end
def member(name)
if name == "payload"
return self._get_bytes()
else
return super(self).member(name)
end
end
# return a bytes() object from a pre-populated zcl_frame payload
def _get_bytes()
import introspect
var payload_ptr = introspect.toptr(self.payload_ptr)
if int(payload_ptr) != 0
var sbuffer = bytes(payload_ptr, -4)
var sbuffer_len = sbuffer.get(2,2)
return bytes(introspect.toptr(int(payload_ptr) + 4), sbuffer_len)
else
return self.no_bytes
end
end
def tomap()
import string
var m = super(self).tomap()
m["shortaddr_hex"] = string.format("0x%04X", self.shortaddr)
m["payload"] = self.payload # add payload object which is a synthetic attribute not included in tomap()
return m
end
def tostring()
var m = self.tomap()
return str(m)
end
end

View File

@ -73,7 +73,6 @@ public:
bool state_machine = false; // the state machine is running
bool state_waiting = false; // the state machine is waiting for external event or timeout
bool state_no_timeout = false; // the current wait loop does not generate a timeout but only continues running
bool ready = false; // cc2530 initialization is complet, ready to operate
bool init_phase = true; // initialization phase, before accepting zigbee traffic
bool recv_until = false; // ignore all messages until the received frame fully matches
bool eeprom_present = false; // is the ZBBridge EEPROM present?

View File

@ -995,7 +995,7 @@ private:
* Berry support
\*********************************************************************************************/
#ifdef USE_BERRY
extern "C" void callBerryZigbeeDispatcher(const char* type, ZCLFrame* zcl_received);
extern "C" int32_t callBerryZigbeeDispatcher(const char* cmd, const char* type, void* data, int32_t idx);
#endif // USE_BERRY
/*********************************************************************************************\

View File

@ -855,10 +855,10 @@ public:
uint16_t shortaddr = BAD_SHORTADDR; // BAD_SHORTADDR is broadcast, so considered invalid
uint8_t dstendpoint = 0x00; // 0x00 is invalid for the dst endpoint
// attributes used in send-only mode
bool clusterSpecific = false;
bool needResponse = true;
bool direct = false; // true if direct, false if discover router
bool transacSet = false; // is transac already set
bool clusterSpecific = false;
bool needResponse = true;
bool direct = false; // true if direct, false if discover router
bool transacSet = false; // is transac already set
// below private attributes are not used when sending a message
private:

View File

@ -1641,7 +1641,7 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) {
#ifdef USE_BERRY
// Berry pre-process messages
// callBerryZigbeeDispatcher("pre", &zcl_received);
callBerryZigbeeDispatcher("incoming", "zcl_frame", &zcl_received, 0);
#endif // USE_BERRY
// create the device entry if it does not exist and if it's not the local device

View File

@ -0,0 +1,239 @@
/*
xdrv_52_3_berry_zigbee.ino - Berry scripting language, native fucnctions
Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Mappgin from internal light and a generic `light_state` Berry class
#ifdef USE_BERRY
#ifdef USE_ZIGBEE
#include "berry.h"
#include "be_func.h"
extern "C" {
extern const bclass be_class_zb_device;
// Zigbee Device `zd`
const void* zd_init(const class Z_Device* device) {
return device;
}
int32_t zd_shortaddr(const class Z_Device* d) {
return d->shortaddr;
}
const void* zd_longaddr(const class Z_Device* d, size_t *size, void* p2) {
*size = 8; // 64 bits
return &d->longaddr;
}
const char* zd_manufacturer(const class Z_Device* d) {
return d->manufacturerId ? d->manufacturerId : "";
}
extern const char* zd_model(const class Z_Device* d) {
return d->modelId ? d->modelId : "";
}
extern const char* zd_name(const class Z_Device* d) {
return d->friendlyName ? d->friendlyName : "";
}
bool zd_router(const class Z_Device* d) {
return d->is_router;
}
bool zd_hidden(const class Z_Device* d) {
return d->hidden;
}
bool zd_reachable(const class Z_Device* d) {
return d->reachable;
}
int32_t zd_lastseen(const class Z_Device* d) {
return d->last_seen;
}
int32_t zd_lqi(const class Z_Device* d) {
return d->lqi == 255 ? -1 : d->lqi;
}
int32_t zd_battery(const class Z_Device* d) {
return d->batterypercent == 255 ? -1 : d->batterypercent;
}
int32_t zd_battery_lastseen(const class Z_Device* d) {
return 0; // TODO not yet known
}
}
extern "C" {
// Zigbee Coordinator `zc`
int zc_info(struct bvm *vm);
int zc_info(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if (top == 1) { // no argument (instance only)
be_newobject(vm, "map");
be_map_insert_int(vm, "channel", Settings->zb_channel);
be_map_insert_int(vm, "tx_radio", Settings->zb_txradio_dbm);
char tmp[24];
ext_snprintf_P(tmp, sizeof(tmp), "0x%04X", Settings->zb_pan_id);
be_map_insert_str(vm, "pan_id_hex", tmp);
be_map_insert_int(vm, "pan_id", Settings->zb_pan_id);
ext_snprintf_P(tmp, sizeof(tmp), "0x%_X", &Settings->zb_ext_panid);
be_map_insert_str(vm, "ext_pan_id", tmp);
ext_snprintf_P(tmp, sizeof(tmp), "0x%04X", localShortAddr);
be_map_insert_str(vm, "shortaddr_hex", tmp);
be_map_insert_int(vm, "shortaddr", localShortAddr);
ext_snprintf_P(tmp, sizeof(tmp), "0x%_X", &localIEEEAddr);
be_map_insert_str(vm, "longaddr", tmp);
be_pop(vm, 1);
be_return(vm);
}
be_raise(vm, kTypeError, nullptr);
}
int zc_item(struct bvm *vm);
int zc_item(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
if (zigbee.init_phase) {
be_raise(vm, "internal_error", "zigbee not started");
}
if (top >= 2 && (be_isint(vm, 2) || be_isstring(vm, 2))) {
const Z_Device & device = be_isint(vm, 2) ? zigbee_devices.findShortAddr(be_toint(vm, 2))
: zigbee_devices.parseDeviceFromName(be_tostring(vm, 2));
if (!device.valid()) {
be_raise(vm, "value_error", "unknown device");
}
be_pushntvclass(vm, &be_class_zb_device);
be_pushcomptr(vm, (void*) &device);
be_call(vm, 1);
be_pop(vm, 1);
be_return(vm);
}
be_raise(vm, kTypeError, nullptr);
}
int32_t zc_size(void*) {
return zigbee_devices.devicesSize();
}
// stop zigbee, abort
// The abort state corresponds to state machine stopped but init not finished
void zc_abort(void) {
zigbee.active = false;
zigbee.state_machine = false; // not ready
zigbee.init_phase = false;
}
// iterator for devices in the coordinator's list of devices
// upval 0: index from 0 to size-1
static int zc_iter_closure(bvm *vm)
{
/* for better performance, we operate the upvalues
* directly without using by the stack. */
bntvclos *func = (bntvclos*) var_toobj(vm->cf->func);
bvalue *uv0 = be_ntvclos_upval(func, 0)->value;
bint idx = var_toint(uv0); /* upvalue[0] => lower */
if (idx >= zigbee_devices.devicesSize()) {
be_stop_iteration(vm);
}
var_toint(uv0) = idx + 1; /* set upvale[0] */
be_pushntvclass(vm, &be_class_zb_device);
const Z_Device & device = zigbee_devices.isKnownIndexDevice(idx);
be_pushcomptr(vm, (void*) &device);
be_call(vm, 1);
be_pop(vm, 1);
be_return(vm);
}
int zc_iter(bvm *vm);
int zc_iter(bvm *vm) {
if (zigbee.init_phase) {
be_raise(vm, "internal_error", "zigbee not started");
}
be_pushntvclosure(vm, zc_iter_closure, 1);
be_pushint(vm, 0);
be_setupval(vm, -2, 0);
be_pop(vm, 1);
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 ret = 0;
bvm *vm = berry.vm;
if (nullptr == vm) { return ret; }
checkBeTop();
be_getglobal(vm, PSTR("zigbee")); // global object of type zb_coord()
if (!be_isnil(vm, -1)) {
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_pushint(vm, idx);
BrTimeoutStart();
ret = be_pcall(vm, 5); // 5 arguments
BrTimeoutReset();
if (ret != 0) {
be_error_pop_all(berry.vm); // clear Berry stack
return ret;
}
be_pop(vm, 5);
if (be_isint(vm, -1) || be_isbool(vm, -1)) {
if (be_isint(vm, -1)) { ret = be_toint(vm, -1); }
if (be_isbool(vm, -1)) { ret = be_tobool(vm, -1); }
}
}
be_pop(vm, 1); // remove method
}
be_pop(vm, 1); // remove instance object
checkBeTop();
return ret;
}
}
/*********************************************************************************************\
* Mapping for zcl_message
*
\*********************************************************************************************/
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_frame_struct = {
sizeof(ZCLFrame), /* size in bytes */
12, /* number of elements */
nullptr,
(const be_ctypes_structure_item_t[12]) {
{ "cluster", offsetof(ZCLFrame, cluster), 0, 0, ctypes_u16, 0 },
{ "cluster_specific", offsetof(ZCLFrame, clusterSpecific), 0, 0, ctypes_u8, 0 },
{ "cmd", offsetof(ZCLFrame, cmd), 0, 0, ctypes_u8, 0 },
{ "direct", offsetof(ZCLFrame, direct), 0, 0, ctypes_u8, 0 },
{ "dstendpoint", offsetof(ZCLFrame, dstendpoint), 0, 0, ctypes_u8, 0 },
{ "groupaddr", offsetof(ZCLFrame, groupaddr), 0, 0, ctypes_u16, 0 },
{ "manuf", offsetof(ZCLFrame, manuf), 0, 0, ctypes_u16, 0 },
{ "need_response", offsetof(ZCLFrame, needResponse), 0, 0, ctypes_u8, 0 },
{ "payload_ptr", offsetof(ZCLFrame, payload), 0, 0, ctypes_ptr32, 0 },
{ "shortaddr", offsetof(ZCLFrame, shortaddr), 0, 0, ctypes_u16, 0 },
{ "transactseq", offsetof(ZCLFrame, transactseq), 0, 0, ctypes_u8, 0 },
{ "transactseq_set", offsetof(ZCLFrame, transacSet), 0, 0, ctypes_u8, 0 },
}};
#pragma GCC diagnostic pop
}
#endif // USE_ZIGBEE
#endif // USE_BERRY