Berry revamped ``energy`` module to expose all C variables to Berry (read/write)

This commit is contained in:
Stephan Hadinger 2021-09-24 18:05:16 +02:00
parent 7c71c3bdd8
commit 509daa24dc
16 changed files with 2339 additions and 1819 deletions

View File

@ -22,6 +22,7 @@ All notable changes to this project will be documented in this file.
- Minimum PWM Frequency lowered to 2Hz on ESP32 (#13123)
- Use Tasmota Arduino Core32 1.0.7.4 for ESP32 builds (#13154)
- Shrinked Webcam build, uses now `USE_TASMOTA_DISCOVERY` (#13148)
- Berry revamped ``energy`` module to expose all C variables to Berry (read/write)
### Fixed
- OpenTherm invalid JSON (#13028)

View File

@ -51,6 +51,10 @@ enum {
ctypes_be_u16 = -2,
ctypes_be_u8 = -1,
// floating point
ctypes_float = 5,
ctypes_double = 10,
ctypes_bf = 0, //bif-field
};
@ -88,13 +92,23 @@ typedef struct be_ctypes_classes_t {
//
// If no arg: allocate a bytes() structure of the right size, filled with zeroes
// Arg1 is instance self
// If arg 2 is int (and not null): copy the data to the bytes structure
// If arg 2 is int or comptr (and not null): create a mapped bytes buffer to read/write at a specific location (can be copied if need a snapshot)
int be_ctypes_init(bvm *vm) {
int argc = be_top(vm);
void * src_data = NULL;
if (argc > 1 && (be_isint(vm, 2) || be_iscomptr(vm,2))) {
if (argc > 1 && (be_isint(vm, 2) || be_iscomptr(vm, 2))) {
if (be_iscomptr(vm, 2)) {
src_data = be_tocomptr(vm, 2);
} else {
src_data = (void*) be_toint(vm, 2);
}
}
// look for class definition
be_getmember(vm, 1, "_def"); // static class comptr
const be_ctypes_structure_t *definitions;
definitions = (const be_ctypes_structure_t *) be_tocomptr(vm, -1);
be_pop(vm, 1);
// call super(self, bytes)
be_getglobal(vm, "super"); // push super function
@ -107,34 +121,13 @@ int be_ctypes_init(bvm *vm) {
// call bytes.init(self)
be_getmember(vm, -1, "init");
be_pushvalue(vm, -2);
be_call(vm, 1);
be_pop(vm, 3);
// berry_log_C("be_ctypes_init> init called");
if (src_data) { be_pushcomptr(vm, src_data); } // if mapped, push address
be_pushint(vm, definitions ? -definitions->size_bytes : 0); // negative size signals a fixed size
be_call(vm, src_data ? 3 : 2); // call with 2 or 3 arguments depending on provided address
be_pop(vm, src_data ? 4 : 3);
// super(self, bytes) still on top of stack
// look for class definition
be_getmember(vm, 1, "_def"); // static class comptr
const be_ctypes_structure_t *definitions;
definitions = (const be_ctypes_structure_t *) be_tocomptr(vm, -1);
if (definitions) {
// call self.resize(definitions->size_bytes)
be_getmember(vm, 1, "resize");
be_pushvalue(vm, 1);
be_pushint(vm, definitions->size_bytes);
be_call(vm, 2);
be_pop(vm, 3);
// if src_data then copy source data to the new structure
if (src_data) {
// call self._buffer()
be_getmember(vm, 1, "_buffer");
be_pushvalue(vm, 1);
be_call(vm, 1); // call with 1 parameter
void * dst_data = be_tocomptr(vm, -2);
be_pop(vm, 2);
// copy data
memmove(dst_data, src_data, definitions->size_bytes);
}
}
be_pop(vm, 1);
be_return(vm);
}
@ -146,9 +139,35 @@ int be_ctypes_copy(bvm *vm) {
size_t len;
const void * src = be_tobytes(vm, 1, &len);
be_classof(vm, 1);
be_pushint(vm, (int32_t) src); // skip first 4 bytes
be_call(vm, 1);
// stack: 1/self + class_object
be_call(vm, 0); // call empty constructor to build empty resizable copy
// stack: 1/ self + new_empty_instance
// source object (self)
be_getmember(vm, 1, ".p");
const void* src_buf = be_tocomptr(vm, -1);
be_pop(vm, 1);
be_getmember(vm, 1, ".len");
int32_t src_len = be_toint(vm, -1);
be_pop(vm, 1);
// dest object
be_getmember(vm, -1, ".p");
const void* dst_buf = be_tocomptr(vm, -1);
be_pop(vm, 1);
be_getmember(vm, -1, ".len");
int32_t dst_len = be_toint(vm, -1);
be_pop(vm, 1);
if (src_len != dst_len) {
be_raisef(vm, "internal_error", "new object has wrong size %i (should be %i)", dst_len, src_len);
}
// copy bytes
memmove((void*)dst_buf, src_buf, src_len);
be_return(vm);
}
@ -180,6 +199,20 @@ int be_ctypes_member(bvm *vm) {
be_call(vm, 3);
be_pop(vm, 3);
// int result at top of stack
} else if (ctypes_float == member->type) {
// Note: double not supported (no need identified)
// get raw int32_t
be_getmember(vm, 1, "geti"); // self.get or self.geti
be_pushvalue(vm, 1); // push self
be_pushint(vm, member->offset_bytes);
be_pushint(vm, 4); // size is 4 bytes
be_call(vm, 3);
be_pop(vm, 3);
// get int and convert to float
int32_t val = be_toint(vm, -1);
be_pop(vm, 1);
float *fval = (float*) &val; // type wizardry
be_pushreal(vm, *fval);
} else {
// general int support
int size = member->type; // eventually 1/2/4, positive if little endian, negative if big endian
@ -272,6 +305,19 @@ int be_ctypes_setmember(bvm *vm) {
be_call(vm, 4);
be_pop(vm, 5);
be_return_nil(vm);
} else if (ctypes_float == member->type) {
// Note: double not supported (no need identified)
float val = be_toreal(vm, 3);
int32_t *ival = (int32_t*) &val;
// set
be_getmember(vm, 1, "seti");
be_pushvalue(vm, 1); // push self
be_pushint(vm, member->offset_bytes);
be_pushint(vm, *ival);
be_pushint(vm, 4); // size is 4 bytes
be_call(vm, 4);
be_pop(vm, 5);
be_return_nil(vm);
} else {
// general int support
int size = member->type; // eventually 1/2/4, positive if little endian, negative if big endian
@ -300,6 +346,38 @@ int be_ctypes_setmember(bvm *vm) {
}
}
//
// tomap, create a map instance containing all values decoded
//
int be_ctypes_tomap(bvm *vm) {
// don't need argc
be_getmember(vm, 1, "_def");
const be_ctypes_structure_t *definitions;
definitions = (const be_ctypes_structure_t *) be_tocomptr(vm, -1);
be_pop(vm, 1);
// create empty map
be_newobject(vm, "map");
for (uint32_t i = 0; i < definitions->size_elt; i++) {
const be_ctypes_structure_item_t * item = &definitions->items[i];
be_pushstring(vm, item->name); // stack: map - key
be_getmember(vm, 1, "member");
be_pushvalue(vm, 1);
be_pushstring(vm, item->name);
be_call(vm, 2);
be_pop(vm, 2); // stack: map - key - value
be_data_insert(vm, -3);
be_pop(vm, 2); // stack: map
}
be_pop(vm, 1); // remove map struct, to leave map instance
be_return(vm);
}
BE_EXPORT_VARIABLE extern const bclass be_class_bytes;
#include "../generate/be_fixed_be_class_ctypes.h"
@ -317,5 +395,7 @@ class be_class_ctypes (scope: global, name: ctypes_bytes, super: be_class_bytes)
init, func(be_ctypes_init)
member, func(be_ctypes_member)
setmember, func(be_ctypes_setmember)
tomap, func(be_ctypes_tomap)
}
@const_object_info_end */

View File

@ -0,0 +1,162 @@
/********************************************************************
* Tasmota LVGL ctypes mapping
*******************************************************************/
#include "be_constobj.h"
#ifdef USE_ENERGY_SENSOR
/********************************************************************
* Generated code, don't edit
*******************************************************************/
enum {
ctypes_i32 = 14,
ctypes_i16 = 12,
ctypes_i8 = 11,
ctypes_u32 = 4,
ctypes_u16 = 2,
ctypes_u8 = 1,
// big endian
ctypes_be_i32 = -14,
ctypes_be_i16 = -12,
ctypes_be_i8 = -11,
ctypes_be_u32 = -4,
ctypes_be_u16 = -2,
ctypes_be_u8 = -1,
ctypes_bf = 0, //bif-field
};
typedef struct be_ctypes_structure_item_t {
const char * name;
uint16_t offset_bytes;
uint8_t offset_bits : 3;
uint8_t len_bits : 5;
int8_t type : 5;
uint8_t mapping : 3;
} be_ctypes_structure_item_t;
typedef struct be_ctypes_structure_t {
uint16_t size_bytes; /* size in bytes */
uint16_t size_elt; /* number of elements */
const char **instance_mapping; /* array of instance class names for automatic instanciation of class */
const be_ctypes_structure_item_t * items;
} be_ctypes_structure_t;
typedef struct be_ctypes_class_t {
const char * name;
const be_ctypes_structure_t * definitions;
} be_ctypes_class_t;
typedef struct be_ctypes_classes_t {
uint16_t size;
const char **instance_mapping; /* array of instance class names for automatic instanciation of class */
const be_ctypes_class_t * classes;
} be_ctypes_classes_t;
BE_EXPORT_VARIABLE extern const bclass be_class_ctypes;
static void ctypes_register_class(bvm *vm, const bclass * ctypes_class, const be_ctypes_structure_t * definitions) {
be_pushntvclass(vm, ctypes_class);
be_setglobal(vm, str(ctypes_class->name));
be_pop(vm, 1);
}
static const char * be_ctypes_instance_mappings[]; /* forward definition */
// Define a sub-class of ctypes with only one member which points to the ctypes defintion
#define be_define_ctypes_class(_c_name, _def, _super, _name) \
be_local_class(_c_name, \
0, \
_super, \
be_nested_map(1, \
( (struct bmapnode*) &(const bmapnode[]) { \
{ be_nested_key("_def", 1985022181, 4, -1), be_const_comptr(_def) },\
})), \
(be_nested_const_str(_name, 0, sizeof(_name)-1)) \
)
/********************************************************************/
const be_ctypes_structure_t be_energy_struct = {
146, /* size in bytes */
62, /* number of elements */
be_ctypes_instance_mappings,
(const be_ctypes_structure_item_t[62]) {
{ "active_power", 24, 0, 0, 5, 0 },
{ "active_power_2", 28, 0, 0, 5, 0 },
{ "active_power_3", 32, 0, 0, 5, 0 },
{ "command_code", 113, 0, 0, 1, 0 },
{ "current", 12, 0, 0, 5, 0 },
{ "current_2", 16, 0, 0, 5, 0 },
{ "current_3", 20, 0, 0, 5, 0 },
{ "current_available", 118, 5, 1, 0, 0 },
{ "daily", 88, 0, 0, 5, 0 },
{ "data_valid", 114, 0, 0, 1, 0 },
{ "data_valid_2", 115, 0, 0, 1, 0 },
{ "data_valid_3", 116, 0, 0, 1, 0 },
{ "export_active", 72, 0, 0, 5, 0 },
{ "export_active_2", 76, 0, 0, 5, 0 },
{ "export_active_3", 80, 0, 0, 5, 0 },
{ "fifth_second", 112, 0, 0, 1, 0 },
{ "frequency", 60, 0, 0, 5, 0 },
{ "frequency_2", 64, 0, 0, 5, 0 },
{ "frequency_3", 68, 0, 0, 5, 0 },
{ "frequency_common", 118, 1, 1, 0, 0 },
{ "max_current_flag", 138, 5, 1, 0, 0 },
{ "max_energy_state", 145, 0, 0, 1, 0 },
{ "max_power_flag", 138, 1, 1, 0, 0 },
{ "max_voltage_flag", 138, 3, 1, 0, 0 },
{ "min_current_flag", 138, 4, 1, 0, 0 },
{ "min_power_flag", 138, 0, 1, 0, 0 },
{ "min_voltage_flag", 138, 2, 1, 0, 0 },
{ "mplh_counter", 140, 0, 0, 2, 0 },
{ "mplr_counter", 144, 0, 0, 1, 0 },
{ "mplw_counter", 142, 0, 0, 2, 0 },
{ "period", 108, 0, 0, 4, 0 },
{ "phase_count", 117, 0, 0, 1, 0 },
{ "power_factor", 48, 0, 0, 5, 0 },
{ "power_factor_2", 52, 0, 0, 5, 0 },
{ "power_factor_3", 56, 0, 0, 5, 0 },
{ "power_history_0", 119, 0, 0, 2, 0 },
{ "power_history_0_2", 121, 0, 0, 2, 0 },
{ "power_history_0_3", 123, 0, 0, 2, 0 },
{ "power_history_1", 125, 0, 0, 2, 0 },
{ "power_history_1_2", 127, 0, 0, 2, 0 },
{ "power_history_1_3", 129, 0, 0, 2, 0 },
{ "power_history_2", 131, 0, 0, 2, 0 },
{ "power_history_2_2", 133, 0, 0, 2, 0 },
{ "power_history_2_3", 135, 0, 0, 2, 0 },
{ "power_on", 118, 7, 1, 0, 0 },
{ "power_steady_counter", 137, 0, 0, 1, 0 },
{ "reactive_power", 36, 0, 0, 5, 0 },
{ "reactive_power_2", 40, 0, 0, 5, 0 },
{ "reactive_power_3", 44, 0, 0, 5, 0 },
{ "start_energy", 84, 0, 0, 5, 0 },
{ "today_delta_kwh", 96, 0, 0, 4, 0 },
{ "today_kwh", 104, 0, 0, 4, 0 },
{ "today_offset_init_kwh", 118, 3, 1, 0, 0 },
{ "today_offset_kwh", 100, 0, 0, 4, 0 },
{ "total", 92, 0, 0, 5, 0 },
{ "type_dc", 118, 6, 1, 0, 0 },
{ "use_overtemp", 118, 2, 1, 0, 0 },
{ "voltage", 0, 0, 0, 5, 0 },
{ "voltage_2", 4, 0, 0, 5, 0 },
{ "voltage_3", 8, 0, 0, 5, 0 },
{ "voltage_available", 118, 4, 1, 0, 0 },
{ "voltage_common", 118, 0, 1, 0, 0 },
}};
static const char * be_ctypes_instance_mappings[] = {
NULL
};
static be_define_ctypes_class(energy_struct, &be_energy_struct, &be_class_ctypes, "energy_struct");
void be_load_ctypes_energy_definitions_lib(bvm *vm) {
ctypes_register_class(vm, &be_class_energy_struct, &be_energy_struct);
}
/********************************************************************/
#endif // USE_ENERGY_SENSOR

View File

@ -9,11 +9,157 @@
#ifdef USE_ENERGY_SENSOR
extern int b_nrg_read(bvm *vm);
extern struct ENERGY Energy;
/*
def init(m)
import global
global._energy = energy_struct(m._ptr)
end
def read()
return _energy.tomap()
end
def member(k)
return _energy.(k)
end
def setmember(k, v)
_energy.(k) = v
end
import solidify
solidify.dump(m.init)
*/
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(init, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
/* K0 */ be_nested_string("global", 503252654, 6),
/* K1 */ be_nested_string("_energy", 535372070, 7),
/* K2 */ be_nested_string("energy_struct", 1655792843, 13),
/* K3 */ be_nested_string("_ptr", 306235816, 4),
}),
(be_nested_const_str("<anonymous>", 1160973142, 11)),
(be_nested_const_str("input", -103256197, 5)),
( &(const binstruction[ 6]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0xB80A0400, // 0001 GETNGBL R2 K2
0x880C0103, // 0002 GETMBR R3 R0 K3
0x7C080200, // 0003 CALL R2 1
0x90060202, // 0004 SETMBR R1 K1 R2
0x80000000, // 0005 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: read
********************************************************************/
be_local_closure(read, /* name */
be_nested_proto(
2, /* nstack */
0, /* argc */
0, /* 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_string("_energy", 535372070, 7),
/* K1 */ be_nested_string("tomap", 612167626, 5),
}),
(be_nested_const_str("<anonymous>", 1160973142, 11)),
(be_nested_const_str("input", -103256197, 5)),
( &(const binstruction[ 4]) { /* code */
0xB8020000, // 0000 GETNGBL R0 K0
0x8C000101, // 0001 GETMET R0 R0 K1
0x7C000200, // 0002 CALL R0 1
0x80040000, // 0003 RET 1 R0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: member
********************************************************************/
be_local_closure(member, /* name */
be_nested_proto(
2, /* nstack */
1, /* argc */
0, /* 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_string("_energy", 535372070, 7),
}),
(be_nested_const_str("member", 719708611, 6)),
(be_nested_const_str("input", -103256197, 5)),
( &(const binstruction[ 3]) { /* code */
0xB8060000, // 0000 GETNGBL R1 K0
0x88040200, // 0001 GETMBR R1 R1 R0
0x80040200, // 0002 RET 1 R1
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: setmember
********************************************************************/
be_local_closure(setmember, /* name */
be_nested_proto(
3, /* nstack */
2, /* argc */
0, /* 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_string("_energy", 535372070, 7),
}),
(be_nested_const_str("setmember", 1432909441, 9)),
(be_nested_const_str("input", -103256197, 5)),
( &(const binstruction[ 3]) { /* code */
0xB80A0000, // 0000 GETNGBL R2 K0
0x90080001, // 0001 SETMBR R2 R0 R1
0x80000000, // 0002 RET 0
})
)
);
/*******************************************************************/
/* @const_object_info_begin
module energy (scope: global) {
read, func(b_nrg_read)
_ptr, comptr(&Energy)
init, closure(init_closure)
read, closure(read_closure)
member, closure(member_closure)
setmember, closure(setmember_closure)
}
@const_object_info_end */
#include "../generate/be_fixed_energy.h"

View File

@ -59,13 +59,13 @@ typedef struct be_ctypes_classes_t {
BE_EXPORT_VARIABLE extern const bclass be_class_ctypes;
void ctypes_register_class(bvm *vm, const bclass * ctypes_class, const be_ctypes_structure_t * definitions) {
static void ctypes_register_class(bvm *vm, const bclass * ctypes_class, const be_ctypes_structure_t * definitions) {
be_pushntvclass(vm, ctypes_class);
be_setglobal(vm, str(ctypes_class->name));
be_pop(vm, 1);
}
const char * be_ctypes_instance_mappings[]; /* forward definition */
static const char * be_ctypes_instance_mappings[]; /* forward definition */
// Define a sub-class of ctypes with only one member which points to the ctypes defintion
#define be_define_ctypes_class(_c_name, _def, _super, _name) \
@ -410,7 +410,7 @@ const be_ctypes_structure_t be_lv_draw_mask_saved = {
{ "param", 0, 0, 0, 4, 0 },
}};
const char * be_ctypes_instance_mappings[] = {
static const char * be_ctypes_instance_mappings[] = {
"lv_color",
NULL
};
@ -435,7 +435,7 @@ static be_define_ctypes_class(lv_draw_rect_dsc, &be_lv_draw_rect_dsc, &be_class_
static be_define_ctypes_class(lv_point, &be_lv_point, &be_class_ctypes, "lv_point");
static be_define_ctypes_class(lv_sqrt_res, &be_lv_sqrt_res, &be_class_ctypes, "lv_sqrt_res");
void be_load_ctypes_definitions_lib(bvm *vm) {
void be_load_ctypes_lvgl_definitions_lib(bvm *vm) {
ctypes_register_class(vm, &be_class_lv_area, &be_lv_area);
ctypes_register_class(vm, &be_class_lv_draw_img_dsc, &be_lv_draw_img_dsc);
ctypes_register_class(vm, &be_class_lv_draw_label_dsc, &be_lv_draw_label_dsc);

View File

@ -115,6 +115,7 @@ extern void be_load_webclient_lib(bvm *vm);
extern void be_load_crypto_lib(bvm *vm);
extern void be_load_ctypes_lib(bvm *vm);
extern void be_load_ctypes_energy_definitions_lib(bvm *vm);
#ifdef USE_I2S_AUDIO_BERRY
extern void be_load_driver_audio_lib(bvm *vm);
@ -126,7 +127,7 @@ extern void be_load_lvgl_font_lib(bvm *vm);
extern void be_load_lv_all_lib(bvm *vm);
extern void be_load_lvgl_cb_lib(bvm *vm);
extern void be_load_lvgl_cb_all_lib(bvm *vm);
extern void be_load_ctypes_definitions_lib(bvm *vm);
extern void be_load_ctypes_lvgl_definitions_lib(bvm *vm);
// custom widgets
extern void be_load_lv_signal_bars_class(bvm *vm);
extern void be_load_lv_wifi_bars_class(bvm *vm);
@ -160,6 +161,9 @@ BERRY_API void be_load_custom_libs(bvm *vm)
be_load_driver_i2c_lib(vm);
be_load_AXP192_class(vm);
#endif // USE_I2C
#ifdef USE_ENERGY_SENSOR
be_load_ctypes_energy_definitions_lib(vm);
#endif // USE_ENERGY_SENSOR
#ifdef USE_WEBCLIENT
be_load_webclient_lib(vm);
#endif // USE_WEBCLIENT
@ -177,7 +181,7 @@ BERRY_API void be_load_custom_libs(bvm *vm)
be_load_lv_all_lib(vm);
be_load_lvgl_cb_lib(vm);
be_load_lvgl_cb_all_lib(vm);
be_load_ctypes_definitions_lib(vm);
be_load_ctypes_lvgl_definitions_lib(vm);
// custom widgets
be_load_lv_signal_bars_class(vm);
be_load_lv_wifi_bars_class(vm);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,17 @@
#include "be_constobj.h"
static be_define_const_map_slots(be_class_ctypes_map) {
{ be_const_key(init, -1), be_const_func(be_ctypes_init) },
{ be_const_key(setmember, 2), be_const_func(be_ctypes_setmember) },
{ be_const_key(_def, 3), be_const_nil() },
{ be_const_key(member, -1), be_const_func(be_ctypes_member) },
{ be_const_key(_def, 5), be_const_nil() },
{ be_const_key(setmember, 0), be_const_func(be_ctypes_setmember) },
{ be_const_key(copy, -1), be_const_func(be_ctypes_copy) },
{ be_const_key(init, -1), be_const_func(be_ctypes_init) },
{ be_const_key(tomap, -1), be_const_func(be_ctypes_tomap) },
{ be_const_key(member, -1), be_const_func(be_ctypes_member) },
};
static be_define_const_map(
be_class_ctypes_map,
5
6
);
BE_EXPORT_VARIABLE be_define_const_class(

View File

@ -1,12 +1,16 @@
#include "be_constobj.h"
static be_define_const_map_slots(m_libenergy_map) {
{ be_const_key(read, -1), be_const_func(b_nrg_read) },
{ be_const_key(init, -1), be_const_closure(init_closure) },
{ be_const_key(_ptr, 3), be_const_comptr(&Energy) },
{ be_const_key(setmember, -1), be_const_closure(setmember_closure) },
{ be_const_key(member, 2), be_const_closure(member_closure) },
{ be_const_key(read, -1), be_const_closure(read_closure) },
};
static be_define_const_map(
m_libenergy_map,
1
5
);
static be_define_const_module(

View File

@ -255,9 +255,11 @@ static void cache_module(bvm *vm, bstring *name)
/* Try to run '()' function of module. Module is already loaded. */
static void module_init(bvm *vm) {
if (be_getmember(vm, -1, "init")) {
/* found, call it with no parameter */
be_call(vm, 0);
/* found, call it with current module as parameter */
be_pushvalue(vm, -2);
be_call(vm, 1);
/* we don't care about the result */
be_pop(vm, 1);
}
be_pop(vm, 1);
}
@ -339,7 +341,7 @@ bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src)
} else {
/* if not writable, try 'setmember' */
int type = be_module_attr(vm, module, str_literal(vm, "setmember"), vm->top);
if (type == BE_FUNCTION) {
if (basetype(type) == BE_FUNCTION) {
bvalue *top = vm->top;
// top[0] already has 'member'
var_setstr(&top[1], attr); /* attribute name */

View File

@ -8,8 +8,8 @@
runcolor = nil
def runcolor()
var pwr = energy.read().find('activepower',0)
print(pwr)
var pwr = energy.active_power
#print(pwr)
var red = tasmota.scale_uint(int(pwr), 0, 2500, 0, 255)
var green = 255 - red
var channels = [red, green, 0]

View File

@ -40,6 +40,10 @@ ctypes.be_u32 = -4
ctypes.be_u16 = -2
ctypes.be_u8 = -1
# floating point
ctypes.float = 5
ctypes.double = 10
ctypes.bf_x = 0 # generic bitfield
# bitfields (always unsigned)
ctypes.bf_0 = 100 # serves as base
@ -211,13 +215,13 @@ ctypes.print_types = def ()
print()
print("BE_EXPORT_VARIABLE extern const bclass be_class_ctypes;")
print()
print("void ctypes_register_class(bvm *vm, const bclass * ctypes_class, const be_ctypes_structure_t * definitions) {")
print("static void ctypes_register_class(bvm *vm, const bclass * ctypes_class, const be_ctypes_structure_t * definitions) {")
print(" be_pushntvclass(vm, ctypes_class);")
print(" be_setglobal(vm, str(ctypes_class->name));")
print(" be_pop(vm, 1);")
print("}")
print()
print("const char * be_ctypes_instance_mappings[]; /* forward definition */")
print("static const char * be_ctypes_instance_mappings[]; /* forward definition */")
print()
print("// Define a sub-class of ctypes with only one member which points to the ctypes defintion")
@ -239,12 +243,12 @@ end
global_classes = [] # track the list of all classes and
global_mappings = [] # mapping to Berry classes, ex: lv_color
ctypes.print_classes = def ()
ctypes.print_classes = def (module_name)
# print mappings
if size(global_mappings) > 7
raise "internal_error", "too many mappings, 7 max"
end
print("const char * be_ctypes_instance_mappings[] = {")
print("static const char * be_ctypes_instance_mappings[] = {")
for n:global_mappings.iter()
print(string.format(" \"%s\",", n))
end
@ -259,7 +263,7 @@ ctypes.print_classes = def ()
end
print()
print("void be_load_ctypes_definitions_lib(bvm *vm) {")
print(string.format("void be_load_ctypes_%s_definitions_lib(bvm *vm) {", module_name))
for elt:global_classes
print(string.format(" ctypes_register_class(vm, &be_class_%s, &be_%s);", elt, elt))
end
@ -366,6 +370,9 @@ class structure
if type_obj > ctypes.bf_0
# bit field
self.get_bitfield_closure(name, type_obj - ctypes.bf_0, mapping_idx)
elif (type_obj == ctypes.float) || (type_obj == ctypes.double)
# multi-bytes
self.get_float_closure(name, type_obj, mapping_idx)
else
# multi-bytes
self.get_int_closure(name, type_obj, mapping_idx)
@ -438,6 +445,26 @@ class structure
self.cur_offset += size_in_bytes # next offset
end
def get_float_closure(name, type, instance_mapping) # can be 1/2/4
#- abs size -#
var size_in_bytes = (type == ctypes.float) ? 4 : 8
self.align(size_in_bytes) # force alignment
var offset = self.cur_offset # prepare variable for capture in closure
self.mapping[name] = [offset, 0, 0, type, instance_mapping]
#- add closures -#
# TODO no closure yet, anyways need to rethink closures, they are too heavy
# if signed
# self.get_closures[name] = def (b, p) return b.geti(offset + p, size_in_bytes_le_be) end
# else
# self.get_closures[name] = def (b, p) return b.get(offset + p, size_in_bytes_le_be) end
# end
# self.set_closures[name] = def (b, p, v) return b.set(offset+ p, v, size_in_bytes_le_be) end
self.cur_offset += size_in_bytes # next offset
end
def get_bitfield_closure(name, size_in_bits, instance_mapping) # can be 1..32
var cur_offset = self.cur_offset # prepare variable for capture in closure

View File

@ -0,0 +1,157 @@
#
# ctype buidings for Tasmota Energy driver
#
# To generate C bindings, do:
# > compile("energy_ctypes.be","file")()
#
# and copy/paste output in C format
#
import ctypes
ctypes.print_types()
float = ctypes.float
uint8 = ctypes.u8
uint16 = ctypes.u16
uint32 = ctypes.u32
int32 = ctypes.i32
bool = ctypes.bf_1
energy_struct = [
[float, "voltage"],
[float, "voltage_2"],
[float, "voltage_3"],
[float, "current"],
[float, "current_2"],
[float, "current_3"],
[float, "active_power"],
[float, "active_power_2"],
[float, "active_power_3"],
[float, "reactive_power"],
[float, "reactive_power_2"],
[float, "reactive_power_3"],
[float, "power_factor"],
[float, "power_factor_2"],
[float, "power_factor_3"],
[float, "frequency"],
[float, "frequency_2"],
[float, "frequency_3"],
# relocate SDM630_IMPORT and SDM72_IMPEXP
[float, "export_active"],
[float, "export_active_2"],
[float, "export_active_3"],
[float, "start_energy"],
[float, "daily"],
[float, "total"],
[uint32, "today_delta_kwh"],
[uint32, "today_offset_kwh"],
[uint32, "today_kwh"],
[uint32, "period"],
[uint8, "fifth_second"],
[uint8, "command_code"],
[uint8, "data_valid"],
[uint8, "data_valid_2"],
[uint8, "data_valid_3"],
[uint8, "phase_count"],
[bool, "voltage_common"],
[bool, "frequency_common"],
[bool, "use_overtemp"],
[bool, "today_offset_init_kwh"],
[bool, "voltage_available"],
[bool, "current_available"],
[bool, "type_dc"],
[bool, "power_on"],
# #ifdef USE_ENERGY_MARGIN_DETECTION
[uint16, "power_history_0"],
[uint16, "power_history_0_2"],
[uint16, "power_history_0_3"],
[uint16, "power_history_1"],
[uint16, "power_history_1_2"],
[uint16, "power_history_1_3"],
[uint16, "power_history_2"],
[uint16, "power_history_2_2"],
[uint16, "power_history_2_3"],
[uint8, "power_steady_counter"],
[bool, "min_power_flag"],
[bool, "max_power_flag"],
[bool, "min_voltage_flag"],
[bool, "max_voltage_flag"],
[bool, "min_current_flag"],
[bool, "max_current_flag"],
# #ifdef USE_ENERGY_POWER_LIMIT
[uint16, "mplh_counter"],
[uint16, "mplw_counter"],
[uint8, "mplr_counter"],
[uint8, "max_energy_state"],
]
energy_struct = ctypes.structure(energy_struct, "energy_struct")
# struct ENERGY {
# float voltage[ENERGY_MAX_PHASES]; // 123.1 V
# float current[ENERGY_MAX_PHASES]; // 123.123 A
# float active_power[ENERGY_MAX_PHASES]; // 123.1 W
# float apparent_power[ENERGY_MAX_PHASES]; // 123.1 VA
# float reactive_power[ENERGY_MAX_PHASES]; // 123.1 VAr
# float power_factor[ENERGY_MAX_PHASES]; // 0.12
# float frequency[ENERGY_MAX_PHASES]; // 123.1 Hz
# #if defined(SDM630_IMPORT) || defined(SDM72_IMPEXP)
# float import_active[ENERGY_MAX_PHASES]; // 123.123 kWh
# #endif // SDM630_IMPORT || SDM72_IMPEXP
# float export_active[ENERGY_MAX_PHASES]; // 123.123 kWh
# float start_energy; // 12345.12345 kWh total previous
# float daily; // 123.123 kWh
# float total; // 12345.12345 kWh total energy
# unsigned long kWhtoday_delta; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only)
# unsigned long kWhtoday_offset; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
# unsigned long kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
# unsigned long period; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
# uint8_t fifth_second;
# uint8_t command_code;
# uint8_t data_valid[ENERGY_MAX_PHASES];
# uint8_t phase_count; // Number of phases active
# bool voltage_common; // Use single voltage
# bool frequency_common; // Use single frequency
# bool use_overtemp; // Use global temperature as overtemp trigger on internal energy monitor hardware
# bool kWhtoday_offset_init;
# bool voltage_available; // Enable if voltage is measured
# bool current_available; // Enable if current is measured
# bool type_dc;
# bool power_on;
# #ifdef USE_ENERGY_MARGIN_DETECTION
# uint16_t power_history[ENERGY_MAX_PHASES][3];
# uint8_t power_steady_counter; // Allow for power on stabilization
# bool min_power_flag;
# bool max_power_flag;
# bool min_voltage_flag;
# bool max_voltage_flag;
# bool min_current_flag;
# bool max_current_flag;
# #ifdef USE_ENERGY_POWER_LIMIT
# uint16_t mplh_counter;
# uint16_t mplw_counter;
# uint8_t mplr_counter;
# uint8_t max_energy_state;
# #endif // USE_ENERGY_POWER_LIMIT
# #endif // USE_ENERGY_MARGIN_DETECTION
# } Energy;
#
ctypes.print_classes("energy")

View File

@ -276,7 +276,7 @@ lv_draw_mask_saved = [
lv_draw_mask_saved = ctypes.structure(lv_draw_mask_saved, "lv_draw_mask_saved")
#
ctypes.print_classes()
ctypes.print_classes("lvgl")
# Ex:
# bb = ctypes.buffer(test_t, bytes("0101020203030404FFFFFEFEFCFC8080"))

View File

@ -1,69 +0,0 @@
/*
xdrv_52_3_berry_native.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/>.
*/
#ifdef USE_BERRY
#ifdef USE_ENERGY_SENSOR
#include <berry.h>
/*********************************************************************************************\
* Native functions mapped to Berry functions
*
* import power
*
* power.read() -> map
*
\*********************************************************************************************/
extern "C" {
// Berry: `begintransmission(address:int) -> nil`
int32_t b_nrg_read(struct bvm *vm);
int32_t b_nrg_read(struct bvm *vm) {
be_newobject(vm, "map");
map_insert_float(vm, "total", Energy.total);
// Energy.phase_count
map_insert_float(vm, "power", Energy.active_power[0]);
map_insert_float(vm, "yesterday", (float)Settings->energy_kWhyesterday / 100000);
map_insert_float(vm, "today", Energy.daily);
map_insert_float(vm, "activepower", Energy.active_power[0]);
map_insert_float(vm, "apparentpower", Energy.active_power[0]);
map_insert_float(vm, "reactivepower", Energy.reactive_power[0]);
// map_insert_float(vm, "powerfactor", );
map_insert_float(vm, "frequency", Energy.frequency[0]);
map_insert_float(vm, "voltage", Energy.voltage[0]);
map_insert_float(vm, "current", Energy.current[0]);
be_pop(vm, 1);
be_return(vm); // Return
}
}
extern "C" {
//
int32_t b_wire_energymissing(struct bvm *vm);
int32_t b_wire_energymissing(struct bvm *vm) {
be_raise(vm, "feature_error", "Energy sensor is not enabled, use '#define USE_ENERGY_SENSOR'");
}
}
#endif // USE_ENERGY_SENSOR
#endif // USE_BERRY