mirror of https://github.com/arendst/Tasmota.git
commit
2d758d32ce
|
@ -16,9 +16,7 @@ All notable changes to this project will be documented in this file.
|
||||||
- Crash protection in ext_vnsprintf_P (#11202)
|
- Crash protection in ext_vnsprintf_P (#11202)
|
||||||
- Extent compile time SetOptions support (#11204)
|
- Extent compile time SetOptions support (#11204)
|
||||||
- ESP32 Extent BLE (#11212)
|
- ESP32 Extent BLE (#11212)
|
||||||
|
|
||||||
- ESP32 support for WS2812 hardware driver via RMT or I2S
|
- ESP32 support for WS2812 hardware driver via RMT or I2S
|
||||||
|
|
||||||
- ESP32 support for secondary I2C controller
|
- ESP32 support for secondary I2C controller
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,111 +1,116 @@
|
||||||
|
extern const bcstring be_const_str_remove;
|
||||||
|
extern const bcstring be_const_str_false;
|
||||||
|
extern const bcstring be_const_str_raise;
|
||||||
|
extern const bcstring be_const_str_opt_connect;
|
||||||
|
extern const bcstring be_const_str_dot_p;
|
||||||
|
extern const bcstring be_const_str_calldepth;
|
||||||
|
extern const bcstring be_const_str_toupper;
|
||||||
|
extern const bcstring be_const_str_break;
|
||||||
|
extern const bcstring be_const_str_map;
|
||||||
|
extern const bcstring be_const_str_bytes;
|
||||||
|
extern const bcstring be_const_str_tanh;
|
||||||
|
extern const bcstring be_const_str_real;
|
||||||
|
extern const bcstring be_const_str_count;
|
||||||
|
extern const bcstring be_const_str_setitem;
|
||||||
|
extern const bcstring be_const_str_split;
|
||||||
|
extern const bcstring be_const_str_if;
|
||||||
|
extern const bcstring be_const_str_format;
|
||||||
|
extern const bcstring be_const_str_pow;
|
||||||
|
extern const bcstring be_const_str_tostring;
|
||||||
|
extern const bcstring be_const_str_load;
|
||||||
|
extern const bcstring be_const_str_setrange;
|
||||||
|
extern const bcstring be_const_str_char;
|
||||||
extern const bcstring be_const_str_acos;
|
extern const bcstring be_const_str_acos;
|
||||||
|
extern const bcstring be_const_str_deinit;
|
||||||
|
extern const bcstring be_const_str_dump;
|
||||||
|
extern const bcstring be_const_str_sqrt;
|
||||||
|
extern const bcstring be_const_str_fromstring;
|
||||||
|
extern const bcstring be_const_str_opt_eq;
|
||||||
extern const bcstring be_const_str_asin;
|
extern const bcstring be_const_str_asin;
|
||||||
|
extern const bcstring be_const_str_byte;
|
||||||
|
extern const bcstring be_const_str_copy;
|
||||||
|
extern const bcstring be_const_str_floor;
|
||||||
|
extern const bcstring be_const_str_find;
|
||||||
|
extern const bcstring be_const_str_var;
|
||||||
|
extern const bcstring be_const_str_opt_add;
|
||||||
|
extern const bcstring be_const_str___lower__;
|
||||||
|
extern const bcstring be_const_str_rand;
|
||||||
|
extern const bcstring be_const_str_sin;
|
||||||
|
extern const bcstring be_const_str_deg;
|
||||||
|
extern const bcstring be_const_str_imin;
|
||||||
|
extern const bcstring be_const_str_class;
|
||||||
|
extern const bcstring be_const_str_try;
|
||||||
|
extern const bcstring be_const_str_allocated;
|
||||||
|
extern const bcstring be_const_str_asstring;
|
||||||
|
extern const bcstring be_const_str_classname;
|
||||||
|
extern const bcstring be_const_str_reverse;
|
||||||
|
extern const bcstring be_const_str_assert;
|
||||||
|
extern const bcstring be_const_str_str;
|
||||||
|
extern const bcstring be_const_str_imax;
|
||||||
|
extern const bcstring be_const_str_init;
|
||||||
|
extern const bcstring be_const_str_except;
|
||||||
|
extern const bcstring be_const_str_return;
|
||||||
|
extern const bcstring be_const_str_opt_neq;
|
||||||
|
extern const bcstring be_const_str_hex;
|
||||||
|
extern const bcstring be_const_str_resize;
|
||||||
|
extern const bcstring be_const_str_as;
|
||||||
|
extern const bcstring be_const_str___upper__;
|
||||||
|
extern const bcstring be_const_str_codedump;
|
||||||
|
extern const bcstring be_const_str_cosh;
|
||||||
|
extern const bcstring be_const_str_abs;
|
||||||
|
extern const bcstring be_const_str_collect;
|
||||||
|
extern const bcstring be_const_str_atan;
|
||||||
|
extern const bcstring be_const_str_attrdump;
|
||||||
|
extern const bcstring be_const_str_input;
|
||||||
|
extern const bcstring be_const_str_;
|
||||||
|
extern const bcstring be_const_str_compile;
|
||||||
|
extern const bcstring be_const_str_iter;
|
||||||
|
extern const bcstring be_const_str_lower;
|
||||||
|
extern const bcstring be_const_str_number;
|
||||||
|
extern const bcstring be_const_str_print;
|
||||||
|
extern const bcstring be_const_str_exp;
|
||||||
|
extern const bcstring be_const_str_pi;
|
||||||
|
extern const bcstring be_const_str___iterator__;
|
||||||
|
extern const bcstring be_const_str_log;
|
||||||
|
extern const bcstring be_const_str_log10;
|
||||||
|
extern const bcstring be_const_str_ceil;
|
||||||
|
extern const bcstring be_const_str_get;
|
||||||
|
extern const bcstring be_const_str_tolower;
|
||||||
|
extern const bcstring be_const_str_while;
|
||||||
|
extern const bcstring be_const_str_import;
|
||||||
|
extern const bcstring be_const_str_size;
|
||||||
extern const bcstring be_const_str_list;
|
extern const bcstring be_const_str_list;
|
||||||
|
extern const bcstring be_const_str_rad;
|
||||||
|
extern const bcstring be_const_str_tan;
|
||||||
|
extern const bcstring be_const_str_type;
|
||||||
|
extern const bcstring be_const_str_insert;
|
||||||
extern const bcstring be_const_str_module;
|
extern const bcstring be_const_str_module;
|
||||||
|
extern const bcstring be_const_str_range;
|
||||||
|
extern const bcstring be_const_str_super;
|
||||||
|
extern const bcstring be_const_str_issubclass;
|
||||||
|
extern const bcstring be_const_str_def;
|
||||||
|
extern const bcstring be_const_str_classof;
|
||||||
|
extern const bcstring be_const_str_sinh;
|
||||||
|
extern const bcstring be_const_str_srand;
|
||||||
|
extern const bcstring be_const_str_end;
|
||||||
|
extern const bcstring be_const_str_clear;
|
||||||
|
extern const bcstring be_const_str_top;
|
||||||
|
extern const bcstring be_const_str_nil;
|
||||||
|
extern const bcstring be_const_str_open;
|
||||||
|
extern const bcstring be_const_str_do;
|
||||||
|
extern const bcstring be_const_str_add;
|
||||||
|
extern const bcstring be_const_str_isinstance;
|
||||||
extern const bcstring be_const_str_pop;
|
extern const bcstring be_const_str_pop;
|
||||||
extern const bcstring be_const_str_int;
|
extern const bcstring be_const_str_int;
|
||||||
extern const bcstring be_const_str_push;
|
|
||||||
extern const bcstring be_const_str_setrange;
|
|
||||||
extern const bcstring be_const_str_sinh;
|
|
||||||
extern const bcstring be_const_str_elif;
|
|
||||||
extern const bcstring be_const_str_iter;
|
|
||||||
extern const bcstring be_const_str_load;
|
|
||||||
extern const bcstring be_const_str_class;
|
|
||||||
extern const bcstring be_const_str_if;
|
|
||||||
extern const bcstring be_const_str_opt_eq;
|
|
||||||
extern const bcstring be_const_str_ceil;
|
|
||||||
extern const bcstring be_const_str_floor;
|
|
||||||
extern const bcstring be_const_str_map;
|
|
||||||
extern const bcstring be_const_str_print;
|
|
||||||
extern const bcstring be_const_str_else;
|
|
||||||
extern const bcstring be_const_str_find;
|
|
||||||
extern const bcstring be_const_str_str;
|
|
||||||
extern const bcstring be_const_str___upper__;
|
|
||||||
extern const bcstring be_const_str_dump;
|
|
||||||
extern const bcstring be_const_str_atan;
|
|
||||||
extern const bcstring be_const_str_size;
|
|
||||||
extern const bcstring be_const_str_tolower;
|
|
||||||
extern const bcstring be_const_str_opt_add;
|
|
||||||
extern const bcstring be_const_str_abs;
|
|
||||||
extern const bcstring be_const_str_lower;
|
|
||||||
extern const bcstring be_const_str_end;
|
|
||||||
extern const bcstring be_const_str_import;
|
|
||||||
extern const bcstring be_const_str_classof;
|
|
||||||
extern const bcstring be_const_str_concat;
|
|
||||||
extern const bcstring be_const_str_byte;
|
|
||||||
extern const bcstring be_const_str_top;
|
|
||||||
extern const bcstring be_const_str_clear;
|
|
||||||
extern const bcstring be_const_str_opt_connect;
|
|
||||||
extern const bcstring be_const_str_collect;
|
|
||||||
extern const bcstring be_const_str_init;
|
|
||||||
extern const bcstring be_const_str_log10;
|
|
||||||
extern const bcstring be_const_str_nil;
|
|
||||||
extern const bcstring be_const_str_;
|
|
||||||
extern const bcstring be_const_str_real;
|
|
||||||
extern const bcstring be_const_str_calldepth;
|
|
||||||
extern const bcstring be_const_str_format;
|
|
||||||
extern const bcstring be_const_str_pi;
|
|
||||||
extern const bcstring be_const_str_do;
|
|
||||||
extern const bcstring be_const_str___iterator__;
|
|
||||||
extern const bcstring be_const_str_number;
|
|
||||||
extern const bcstring be_const_str_type;
|
|
||||||
extern const bcstring be_const_str_dot_p;
|
|
||||||
extern const bcstring be_const_str_traceback;
|
|
||||||
extern const bcstring be_const_str_as;
|
|
||||||
extern const bcstring be_const_str___lower__;
|
|
||||||
extern const bcstring be_const_str_exp;
|
|
||||||
extern const bcstring be_const_str_hex;
|
|
||||||
extern const bcstring be_const_str_char;
|
|
||||||
extern const bcstring be_const_str_split;
|
|
||||||
extern const bcstring be_const_str_toupper;
|
|
||||||
extern const bcstring be_const_str_deinit;
|
|
||||||
extern const bcstring be_const_str_tan;
|
|
||||||
extern const bcstring be_const_str_srand;
|
|
||||||
extern const bcstring be_const_str_imin;
|
|
||||||
extern const bcstring be_const_str_input;
|
|
||||||
extern const bcstring be_const_str_issubclass;
|
|
||||||
extern const bcstring be_const_str_tostring;
|
|
||||||
extern const bcstring be_const_str_break;
|
|
||||||
extern const bcstring be_const_str_insert;
|
|
||||||
extern const bcstring be_const_str_var;
|
|
||||||
extern const bcstring be_const_str_open;
|
|
||||||
extern const bcstring be_const_str_tanh;
|
|
||||||
extern const bcstring be_const_str_upper;
|
|
||||||
extern const bcstring be_const_str_allocated;
|
|
||||||
extern const bcstring be_const_str_rad;
|
|
||||||
extern const bcstring be_const_str_attrdump;
|
|
||||||
extern const bcstring be_const_str_copy;
|
|
||||||
extern const bcstring be_const_str_sqrt;
|
|
||||||
extern const bcstring be_const_str_for;
|
|
||||||
extern const bcstring be_const_str_raise;
|
|
||||||
extern const bcstring be_const_str_opt_neq;
|
|
||||||
extern const bcstring be_const_str_assert;
|
|
||||||
extern const bcstring be_const_str_item;
|
|
||||||
extern const bcstring be_const_str_reverse;
|
|
||||||
extern const bcstring be_const_str_sin;
|
|
||||||
extern const bcstring be_const_str_super;
|
|
||||||
extern const bcstring be_const_str_try;
|
|
||||||
extern const bcstring be_const_str_range;
|
|
||||||
extern const bcstring be_const_str_return;
|
|
||||||
extern const bcstring be_const_str_compile;
|
|
||||||
extern const bcstring be_const_str_false;
|
|
||||||
extern const bcstring be_const_str_resize;
|
|
||||||
extern const bcstring be_const_str_continue;
|
|
||||||
extern const bcstring be_const_str_log;
|
|
||||||
extern const bcstring be_const_str_true;
|
|
||||||
extern const bcstring be_const_str_while;
|
|
||||||
extern const bcstring be_const_str_pow;
|
|
||||||
extern const bcstring be_const_str_cos;
|
|
||||||
extern const bcstring be_const_str_count;
|
|
||||||
extern const bcstring be_const_str_remove;
|
|
||||||
extern const bcstring be_const_str_imax;
|
|
||||||
extern const bcstring be_const_str_rand;
|
|
||||||
extern const bcstring be_const_str_codedump;
|
|
||||||
extern const bcstring be_const_str_deg;
|
|
||||||
extern const bcstring be_const_str_keys;
|
extern const bcstring be_const_str_keys;
|
||||||
extern const bcstring be_const_str_setitem;
|
extern const bcstring be_const_str_elif;
|
||||||
extern const bcstring be_const_str_def;
|
extern const bcstring be_const_str_item;
|
||||||
extern const bcstring be_const_str_except;
|
extern const bcstring be_const_str_push;
|
||||||
extern const bcstring be_const_str_classname;
|
extern const bcstring be_const_str_concat;
|
||||||
extern const bcstring be_const_str_isinstance;
|
extern const bcstring be_const_str_traceback;
|
||||||
extern const bcstring be_const_str_cosh;
|
extern const bcstring be_const_str_upper;
|
||||||
|
extern const bcstring be_const_str_true;
|
||||||
|
extern const bcstring be_const_str_continue;
|
||||||
|
extern const bcstring be_const_str_else;
|
||||||
|
extern const bcstring be_const_str_cos;
|
||||||
|
extern const bcstring be_const_str_for;
|
||||||
|
|
|
@ -1,165 +1,172 @@
|
||||||
be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_asin);
|
be_define_const_str(remove, "remove", 3683784189u, 0, 6, &be_const_str_false);
|
||||||
be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_list);
|
be_define_const_str(false, "false", 184981848u, 62, 5, &be_const_str_raise);
|
||||||
be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_module);
|
|
||||||
be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_pop);
|
|
||||||
be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL);
|
|
||||||
be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_push);
|
|
||||||
be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_setrange);
|
|
||||||
be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, &be_const_str_sinh);
|
|
||||||
be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_elif);
|
|
||||||
be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL);
|
|
||||||
be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_load);
|
|
||||||
be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_class);
|
|
||||||
be_define_const_str(class, "class", 2872970239u, 57, 5, &be_const_str_if);
|
|
||||||
be_define_const_str(if, "if", 959999494u, 50, 2, NULL);
|
|
||||||
be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_ceil);
|
|
||||||
be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, NULL);
|
|
||||||
be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_map);
|
|
||||||
be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_print);
|
|
||||||
be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_else);
|
|
||||||
be_define_const_str(else, "else", 3183434736u, 52, 4, NULL);
|
|
||||||
be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_str);
|
|
||||||
be_define_const_str(str, "str", 3259748752u, 0, 3, NULL);
|
|
||||||
be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_dump);
|
|
||||||
be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL);
|
|
||||||
be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_size);
|
|
||||||
be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_tolower);
|
|
||||||
be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL);
|
|
||||||
be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_abs);
|
|
||||||
be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_lower);
|
|
||||||
be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_end);
|
|
||||||
be_define_const_str(end, "end", 1787721130u, 56, 3, &be_const_str_import);
|
|
||||||
be_define_const_str(import, "import", 288002260u, 66, 6, NULL);
|
|
||||||
be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_concat);
|
|
||||||
be_define_const_str(concat, "concat", 4124019837u, 0, 6, NULL);
|
|
||||||
be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_top);
|
|
||||||
be_define_const_str(top, "top", 2802900028u, 0, 3, NULL);
|
|
||||||
be_define_const_str(clear, "clear", 1550717474u, 0, 5, NULL);
|
|
||||||
be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_collect);
|
|
||||||
be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_init);
|
|
||||||
be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_log10);
|
|
||||||
be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_nil);
|
|
||||||
be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL);
|
|
||||||
be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_real);
|
|
||||||
be_define_const_str(real, "real", 3604983901u, 0, 4, NULL);
|
|
||||||
be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_format);
|
|
||||||
be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_pi);
|
|
||||||
be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_do);
|
|
||||||
be_define_const_str(do, "do", 1646057492u, 65, 2, NULL);
|
|
||||||
be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_number);
|
|
||||||
be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_type);
|
|
||||||
be_define_const_str(type, "type", 1361572173u, 0, 4, NULL);
|
|
||||||
be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_traceback);
|
|
||||||
be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_as);
|
|
||||||
be_define_const_str(as, "as", 1579491469u, 67, 2, NULL);
|
|
||||||
be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_exp);
|
|
||||||
be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_hex);
|
|
||||||
be_define_const_str(hex, "hex", 4273249610u, 0, 3, NULL);
|
|
||||||
be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_split);
|
|
||||||
be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_toupper);
|
|
||||||
be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL);
|
|
||||||
be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_tan);
|
|
||||||
be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL);
|
|
||||||
be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL);
|
|
||||||
be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_input);
|
|
||||||
be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_issubclass);
|
|
||||||
be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, NULL);
|
|
||||||
be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, &be_const_str_break);
|
|
||||||
be_define_const_str(break, "break", 3378807160u, 58, 5, NULL);
|
|
||||||
be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_var);
|
|
||||||
be_define_const_str(var, "var", 2317739966u, 64, 3, NULL);
|
|
||||||
be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_tanh);
|
|
||||||
be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_upper);
|
|
||||||
be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL);
|
|
||||||
be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_rad);
|
|
||||||
be_define_const_str(rad, "rad", 1358899048u, 0, 3, NULL);
|
|
||||||
be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_copy);
|
|
||||||
be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_sqrt);
|
|
||||||
be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL);
|
|
||||||
be_define_const_str(for, "for", 2901640080u, 54, 3, &be_const_str_raise);
|
|
||||||
be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL);
|
be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL);
|
||||||
be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_assert);
|
be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_dot_p);
|
||||||
be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_item);
|
be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_calldepth);
|
||||||
be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_reverse);
|
be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, NULL);
|
||||||
be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_sin);
|
be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, &be_const_str_break);
|
||||||
be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_super);
|
be_define_const_str(break, "break", 3378807160u, 58, 5, NULL);
|
||||||
be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_try);
|
be_define_const_str(map, "map", 3751997361u, 0, 3, NULL);
|
||||||
|
be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_tanh);
|
||||||
|
be_define_const_str(tanh, "tanh", 153638352u, 0, 4, NULL);
|
||||||
|
be_define_const_str(real, "real", 3604983901u, 0, 4, NULL);
|
||||||
|
be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_setitem);
|
||||||
|
be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, &be_const_str_split);
|
||||||
|
be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_if);
|
||||||
|
be_define_const_str(if, "if", 959999494u, 50, 2, NULL);
|
||||||
|
be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_pow);
|
||||||
|
be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_tostring);
|
||||||
|
be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL);
|
||||||
|
be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_setrange);
|
||||||
|
be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, NULL);
|
||||||
|
be_define_const_str(char, "char", 2823553821u, 0, 4, NULL);
|
||||||
|
be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_deinit);
|
||||||
|
be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_dump);
|
||||||
|
be_define_const_str(dump, "dump", 3663001223u, 0, 4, &be_const_str_sqrt);
|
||||||
|
be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL);
|
||||||
|
be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, NULL);
|
||||||
|
be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_asin);
|
||||||
|
be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_byte);
|
||||||
|
be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_copy);
|
||||||
|
be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_floor);
|
||||||
|
be_define_const_str(floor, "floor", 3102149661u, 0, 5, NULL);
|
||||||
|
be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_var);
|
||||||
|
be_define_const_str(var, "var", 2317739966u, 64, 3, NULL);
|
||||||
|
be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str___lower__);
|
||||||
|
be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_rand);
|
||||||
|
be_define_const_str(rand, "rand", 2711325910u, 0, 4, &be_const_str_sin);
|
||||||
|
be_define_const_str(sin, "sin", 3761252941u, 0, 3, NULL);
|
||||||
|
be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_imin);
|
||||||
|
be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_class);
|
||||||
|
be_define_const_str(class, "class", 2872970239u, 57, 5, &be_const_str_try);
|
||||||
be_define_const_str(try, "try", 2887626766u, 68, 3, NULL);
|
be_define_const_str(try, "try", 2887626766u, 68, 3, NULL);
|
||||||
be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_return);
|
be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_asstring);
|
||||||
|
be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_classname);
|
||||||
|
be_define_const_str(classname, "classname", 1998589948u, 0, 9, NULL);
|
||||||
|
be_define_const_str(reverse, "reverse", 558918661u, 0, 7, NULL);
|
||||||
|
be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_str);
|
||||||
|
be_define_const_str(str, "str", 3259748752u, 0, 3, NULL);
|
||||||
|
be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_init);
|
||||||
|
be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_except);
|
||||||
|
be_define_const_str(except, "except", 950914032u, 69, 6, &be_const_str_return);
|
||||||
be_define_const_str(return, "return", 2246981567u, 60, 6, NULL);
|
be_define_const_str(return, "return", 2246981567u, 60, 6, NULL);
|
||||||
be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_false);
|
be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_hex);
|
||||||
be_define_const_str(false, "false", 184981848u, 62, 5, NULL);
|
be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_resize);
|
||||||
be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL);
|
be_define_const_str(resize, "resize", 3514612129u, 0, 6, &be_const_str_as);
|
||||||
be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL);
|
be_define_const_str(as, "as", 1579491469u, 67, 2, NULL);
|
||||||
be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_true);
|
be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_codedump);
|
||||||
be_define_const_str(true, "true", 1303515621u, 61, 4, NULL);
|
be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_cosh);
|
||||||
be_define_const_str(while, "while", 231090382u, 53, 5, NULL);
|
|
||||||
be_define_const_str(pow, "pow", 1479764693u, 0, 3, NULL);
|
|
||||||
be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_count);
|
|
||||||
be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_remove);
|
|
||||||
be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL);
|
|
||||||
be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_rand);
|
|
||||||
be_define_const_str(rand, "rand", 2711325910u, 0, 4, NULL);
|
|
||||||
be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_deg);
|
|
||||||
be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_keys);
|
|
||||||
be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_setitem);
|
|
||||||
be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL);
|
|
||||||
be_define_const_str(def, "def", 3310976652u, 55, 3, &be_const_str_except);
|
|
||||||
be_define_const_str(except, "except", 950914032u, 69, 6, NULL);
|
|
||||||
be_define_const_str(classname, "classname", 1998589948u, 0, 9, &be_const_str_isinstance);
|
|
||||||
be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, NULL);
|
|
||||||
be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, NULL);
|
be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, NULL);
|
||||||
|
be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_collect);
|
||||||
|
be_define_const_str(collect, "collect", 2399039025u, 0, 7, NULL);
|
||||||
|
be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_attrdump);
|
||||||
|
be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_input);
|
||||||
|
be_define_const_str(input, "input", 4191711099u, 0, 5, NULL);
|
||||||
|
be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_compile);
|
||||||
|
be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_iter);
|
||||||
|
be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_lower);
|
||||||
|
be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_number);
|
||||||
|
be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_print);
|
||||||
|
be_define_const_str(print, "print", 372738696u, 0, 5, NULL);
|
||||||
|
be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_pi);
|
||||||
|
be_define_const_str(pi, "pi", 1213090802u, 0, 2, NULL);
|
||||||
|
be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_log);
|
||||||
|
be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_log10);
|
||||||
|
be_define_const_str(log10, "log10", 2346846000u, 0, 5, NULL);
|
||||||
|
be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_get);
|
||||||
|
be_define_const_str(get, "get", 1410115415u, 0, 3, &be_const_str_tolower);
|
||||||
|
be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, &be_const_str_while);
|
||||||
|
be_define_const_str(while, "while", 231090382u, 53, 5, NULL);
|
||||||
|
be_define_const_str(import, "import", 288002260u, 66, 6, NULL);
|
||||||
|
be_define_const_str(size, "size", 597743964u, 0, 4, NULL);
|
||||||
|
be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_rad);
|
||||||
|
be_define_const_str(rad, "rad", 1358899048u, 0, 3, &be_const_str_tan);
|
||||||
|
be_define_const_str(tan, "tan", 2633446552u, 0, 3, &be_const_str_type);
|
||||||
|
be_define_const_str(type, "type", 1361572173u, 0, 4, NULL);
|
||||||
|
be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_module);
|
||||||
|
be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_range);
|
||||||
|
be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_super);
|
||||||
|
be_define_const_str(super, "super", 4152230356u, 0, 5, NULL);
|
||||||
|
be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_def);
|
||||||
|
be_define_const_str(def, "def", 3310976652u, 55, 3, NULL);
|
||||||
|
be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_sinh);
|
||||||
|
be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_srand);
|
||||||
|
be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL);
|
||||||
|
be_define_const_str(end, "end", 1787721130u, 56, 3, NULL);
|
||||||
|
be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_top);
|
||||||
|
be_define_const_str(top, "top", 2802900028u, 0, 3, &be_const_str_nil);
|
||||||
|
be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL);
|
||||||
|
be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_do);
|
||||||
|
be_define_const_str(do, "do", 1646057492u, 65, 2, NULL);
|
||||||
|
be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_isinstance);
|
||||||
|
be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, &be_const_str_pop);
|
||||||
|
be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL);
|
||||||
|
be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_keys);
|
||||||
|
be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_elif);
|
||||||
|
be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL);
|
||||||
|
be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_push);
|
||||||
|
be_define_const_str(push, "push", 2272264157u, 0, 4, NULL);
|
||||||
|
be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_traceback);
|
||||||
|
be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_upper);
|
||||||
|
be_define_const_str(upper, "upper", 176974407u, 0, 5, &be_const_str_true);
|
||||||
|
be_define_const_str(true, "true", 1303515621u, 61, 4, NULL);
|
||||||
|
be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL);
|
||||||
|
be_define_const_str(else, "else", 3183434736u, 52, 4, NULL);
|
||||||
|
be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_for);
|
||||||
|
be_define_const_str(for, "for", 2901640080u, 54, 3, NULL);
|
||||||
|
|
||||||
static const bstring* const m_string_table[] = {
|
static const bstring* const m_string_table[] = {
|
||||||
|
(const bstring *)&be_const_str_remove,
|
||||||
|
(const bstring *)&be_const_str_opt_connect,
|
||||||
|
(const bstring *)&be_const_str_toupper,
|
||||||
|
NULL,
|
||||||
|
(const bstring *)&be_const_str_map,
|
||||||
|
(const bstring *)&be_const_str_bytes,
|
||||||
|
(const bstring *)&be_const_str_real,
|
||||||
|
(const bstring *)&be_const_str_count,
|
||||||
|
(const bstring *)&be_const_str_format,
|
||||||
|
(const bstring *)&be_const_str_load,
|
||||||
|
(const bstring *)&be_const_str_char,
|
||||||
(const bstring *)&be_const_str_acos,
|
(const bstring *)&be_const_str_acos,
|
||||||
NULL,
|
(const bstring *)&be_const_str_fromstring,
|
||||||
(const bstring *)&be_const_str_int,
|
|
||||||
NULL,
|
|
||||||
(const bstring *)&be_const_str_iter,
|
|
||||||
(const bstring *)&be_const_str_opt_eq,
|
(const bstring *)&be_const_str_opt_eq,
|
||||||
(const bstring *)&be_const_str_floor,
|
|
||||||
(const bstring *)&be_const_str_find,
|
(const bstring *)&be_const_str_find,
|
||||||
(const bstring *)&be_const_str___upper__,
|
|
||||||
(const bstring *)&be_const_str_atan,
|
|
||||||
(const bstring *)&be_const_str_opt_add,
|
(const bstring *)&be_const_str_opt_add,
|
||||||
NULL,
|
NULL,
|
||||||
(const bstring *)&be_const_str_classof,
|
(const bstring *)&be_const_str_deg,
|
||||||
(const bstring *)&be_const_str_byte,
|
|
||||||
(const bstring *)&be_const_str_clear,
|
|
||||||
(const bstring *)&be_const_str_opt_connect,
|
|
||||||
(const bstring *)&be_const_str_,
|
|
||||||
(const bstring *)&be_const_str_calldepth,
|
|
||||||
(const bstring *)&be_const_str___iterator__,
|
|
||||||
(const bstring *)&be_const_str_dot_p,
|
|
||||||
(const bstring *)&be_const_str___lower__,
|
|
||||||
(const bstring *)&be_const_str_char,
|
|
||||||
(const bstring *)&be_const_str_deinit,
|
|
||||||
(const bstring *)&be_const_str_srand,
|
|
||||||
(const bstring *)&be_const_str_imin,
|
|
||||||
(const bstring *)&be_const_str_tostring,
|
|
||||||
(const bstring *)&be_const_str_insert,
|
|
||||||
(const bstring *)&be_const_str_open,
|
|
||||||
(const bstring *)&be_const_str_allocated,
|
(const bstring *)&be_const_str_allocated,
|
||||||
(const bstring *)&be_const_str_attrdump,
|
(const bstring *)&be_const_str_reverse,
|
||||||
(const bstring *)&be_const_str_for,
|
(const bstring *)&be_const_str_assert,
|
||||||
(const bstring *)&be_const_str_opt_neq,
|
|
||||||
(const bstring *)&be_const_str_range,
|
|
||||||
(const bstring *)&be_const_str_compile,
|
|
||||||
(const bstring *)&be_const_str_resize,
|
|
||||||
(const bstring *)&be_const_str_continue,
|
|
||||||
(const bstring *)&be_const_str_log,
|
|
||||||
(const bstring *)&be_const_str_while,
|
|
||||||
(const bstring *)&be_const_str_pow,
|
|
||||||
(const bstring *)&be_const_str_cos,
|
|
||||||
(const bstring *)&be_const_str_imax,
|
(const bstring *)&be_const_str_imax,
|
||||||
(const bstring *)&be_const_str_codedump,
|
(const bstring *)&be_const_str_opt_neq,
|
||||||
(const bstring *)&be_const_str_def,
|
(const bstring *)&be_const_str___upper__,
|
||||||
(const bstring *)&be_const_str_classname,
|
(const bstring *)&be_const_str_abs,
|
||||||
(const bstring *)&be_const_str_cosh
|
(const bstring *)&be_const_str_atan,
|
||||||
|
(const bstring *)&be_const_str_,
|
||||||
|
NULL,
|
||||||
|
(const bstring *)&be_const_str_exp,
|
||||||
|
(const bstring *)&be_const_str___iterator__,
|
||||||
|
(const bstring *)&be_const_str_ceil,
|
||||||
|
(const bstring *)&be_const_str_import,
|
||||||
|
(const bstring *)&be_const_str_size,
|
||||||
|
(const bstring *)&be_const_str_list,
|
||||||
|
(const bstring *)&be_const_str_insert,
|
||||||
|
(const bstring *)&be_const_str_issubclass,
|
||||||
|
(const bstring *)&be_const_str_classof,
|
||||||
|
(const bstring *)&be_const_str_end,
|
||||||
|
(const bstring *)&be_const_str_clear,
|
||||||
|
(const bstring *)&be_const_str_open,
|
||||||
|
(const bstring *)&be_const_str_add,
|
||||||
|
(const bstring *)&be_const_str_int,
|
||||||
|
(const bstring *)&be_const_str_item,
|
||||||
|
(const bstring *)&be_const_str_concat,
|
||||||
|
(const bstring *)&be_const_str_continue,
|
||||||
|
(const bstring *)&be_const_str_else,
|
||||||
|
(const bstring *)&be_const_str_cos
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct bconststrtab m_const_string_table = {
|
static const struct bconststrtab m_const_string_table = {
|
||||||
.size = 45,
|
.size = 47,
|
||||||
.count = 90,
|
.count = 95,
|
||||||
.table = m_string_table
|
.table = m_string_table
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include "be_constobj.h"
|
||||||
|
|
||||||
|
static be_define_const_map_slots(be_class_bytes_map) {
|
||||||
|
{ be_const_key(copy, -1), be_const_func(m_copy) },
|
||||||
|
{ be_const_key(setitem, -1), be_const_func(m_setitem) },
|
||||||
|
{ be_const_key(tostring, -1), be_const_func(m_tostring) },
|
||||||
|
{ be_const_key(item, -1), be_const_func(m_item) },
|
||||||
|
{ be_const_key(init, 8), be_const_func(m_init) },
|
||||||
|
{ be_const_key(size, 6), be_const_func(m_size) },
|
||||||
|
{ be_const_key(opt_connect, 7), be_const_func(m_connect) },
|
||||||
|
{ be_const_key(opt_add, -1), be_const_func(m_merge) },
|
||||||
|
{ be_const_key(fromstring, -1), be_const_func(m_fromstring) },
|
||||||
|
{ be_const_key(opt_eq, 14), be_const_func(m_equal) },
|
||||||
|
{ be_const_key(get, 1), be_const_func(m_get) },
|
||||||
|
{ be_const_key(asstring, 5), be_const_func(m_asstring) },
|
||||||
|
{ be_const_key(add, -1), be_const_func(m_add) },
|
||||||
|
{ be_const_key(dot_p, -1), be_const_int(0) },
|
||||||
|
{ be_const_key(clear, -1), be_const_func(m_clear) },
|
||||||
|
{ be_const_key(opt_neq, 4), be_const_func(m_nequal) },
|
||||||
|
{ be_const_key(resize, 9), be_const_func(m_resize) },
|
||||||
|
};
|
||||||
|
|
||||||
|
static be_define_const_map(
|
||||||
|
be_class_bytes_map,
|
||||||
|
17
|
||||||
|
);
|
||||||
|
|
||||||
|
BE_EXPORT_VARIABLE be_define_const_class(
|
||||||
|
be_class_bytes,
|
||||||
|
1,
|
||||||
|
NULL,
|
||||||
|
bytes
|
||||||
|
);
|
|
@ -1,31 +1,32 @@
|
||||||
#include "be_constobj.h"
|
#include "be_constobj.h"
|
||||||
|
|
||||||
static be_define_const_map_slots(be_class_list_map) {
|
static be_define_const_map_slots(be_class_list_map) {
|
||||||
{ be_const_key(pop, -1), be_const_func(m_pop) },
|
{ be_const_key(concat, -1), be_const_func(m_concat) },
|
||||||
{ be_const_key(reverse, -1), be_const_func(m_reverse) },
|
|
||||||
{ be_const_key(push, -1), be_const_func(m_push) },
|
{ be_const_key(push, -1), be_const_func(m_push) },
|
||||||
{ be_const_key(init, -1), be_const_func(m_init) },
|
{ be_const_key(insert, 1), be_const_func(m_insert) },
|
||||||
{ be_const_key(copy, 8), be_const_func(m_copy) },
|
{ be_const_key(find, -1), be_const_func(m_find) },
|
||||||
{ be_const_key(opt_connect, 13), be_const_func(m_connect) },
|
{ be_const_key(remove, 9), be_const_func(m_remove) },
|
||||||
{ be_const_key(item, -1), be_const_func(m_item) },
|
|
||||||
{ be_const_key(remove, -1), be_const_func(m_remove) },
|
|
||||||
{ be_const_key(size, -1), be_const_func(m_size) },
|
|
||||||
{ be_const_key(resize, 7), be_const_func(m_resize) },
|
|
||||||
{ be_const_key(opt_add, -1), be_const_func(m_merge) },
|
|
||||||
{ be_const_key(opt_neq, -1), be_const_func(m_nequal) },
|
|
||||||
{ be_const_key(setitem, -1), be_const_func(m_setitem) },
|
|
||||||
{ be_const_key(tostring, -1), be_const_func(m_tostring) },
|
|
||||||
{ be_const_key(clear, -1), be_const_func(m_clear) },
|
{ be_const_key(clear, -1), be_const_func(m_clear) },
|
||||||
{ be_const_key(opt_eq, 3), be_const_func(m_equal) },
|
{ be_const_key(size, -1), be_const_func(m_size) },
|
||||||
{ be_const_key(insert, 12), be_const_func(m_insert) },
|
{ be_const_key(resize, 13), be_const_func(m_resize) },
|
||||||
{ be_const_key(concat, 2), be_const_func(m_concat) },
|
{ be_const_key(copy, -1), be_const_func(m_copy) },
|
||||||
{ be_const_key(dot_p, -1), be_const_int(0) },
|
{ be_const_key(pop, -1), be_const_func(m_pop) },
|
||||||
{ be_const_key(iter, 18), be_const_func(m_iter) },
|
{ be_const_key(tostring, 3), be_const_func(m_tostring) },
|
||||||
|
{ be_const_key(opt_eq, -1), be_const_func(m_equal) },
|
||||||
|
{ be_const_key(init, -1), be_const_func(m_init) },
|
||||||
|
{ be_const_key(dot_p, 17), be_const_int(0) },
|
||||||
|
{ be_const_key(setitem, -1), be_const_func(m_setitem) },
|
||||||
|
{ be_const_key(opt_connect, 4), be_const_func(m_connect) },
|
||||||
|
{ be_const_key(opt_neq, -1), be_const_func(m_nequal) },
|
||||||
|
{ be_const_key(opt_add, 18), be_const_func(m_merge) },
|
||||||
|
{ be_const_key(iter, 20), be_const_func(m_iter) },
|
||||||
|
{ be_const_key(item, -1), be_const_func(m_item) },
|
||||||
|
{ be_const_key(reverse, -1), be_const_func(m_reverse) },
|
||||||
};
|
};
|
||||||
|
|
||||||
static be_define_const_map(
|
static be_define_const_map(
|
||||||
be_class_list_map,
|
be_class_list_map,
|
||||||
20
|
21
|
||||||
);
|
);
|
||||||
|
|
||||||
BE_EXPORT_VARIABLE be_define_const_class(
|
BE_EXPORT_VARIABLE be_define_const_class(
|
||||||
|
|
|
@ -1,37 +1,39 @@
|
||||||
#include "be_constobj.h"
|
#include "be_constobj.h"
|
||||||
|
|
||||||
static be_define_const_map_slots(m_builtin_map) {
|
static be_define_const_map_slots(m_builtin_map) {
|
||||||
{ be_const_key(map, 11), be_const_int(10) },
|
{ be_const_key(print, 19), be_const_int(15) },
|
||||||
{ be_const_key(str, 14), be_const_int(18) },
|
{ be_const_key(isinstance, -1), be_const_int(8) },
|
||||||
{ be_const_key(int, -1), be_const_int(6) },
|
{ be_const_key(classname, -1), be_const_int(3) },
|
||||||
{ be_const_key(type, -1), be_const_int(20) },
|
{ be_const_key(module, -1), be_const_int(12) },
|
||||||
{ be_const_key(assert, -1), be_const_int(1) },
|
{ be_const_key(size, -1), be_const_int(18) },
|
||||||
{ be_const_key(issubclass, -1), be_const_int(8) },
|
{ be_const_key(type, 9), be_const_int(21) },
|
||||||
{ be_const_key(number, 7), be_const_int(12) },
|
{ be_const_key(compile, -1), be_const_int(5) },
|
||||||
{ be_const_key(compile, 8), be_const_int(4) },
|
{ be_const_key(open, -1), be_const_int(14) },
|
||||||
{ be_const_key(module, 18), be_const_int(11) },
|
{ be_const_key(real, -1), be_const_int(17) },
|
||||||
{ be_const_key(input, 5), be_const_int(5) },
|
|
||||||
{ be_const_key(super, -1), be_const_int(19) },
|
|
||||||
{ be_const_key(classof, -1), be_const_int(3) },
|
|
||||||
{ be_const_key(open, 13), be_const_int(13) },
|
|
||||||
{ be_const_key(__iterator__, -1), be_const_int(0) },
|
{ be_const_key(__iterator__, -1), be_const_int(0) },
|
||||||
{ be_const_key(real, 10), be_const_int(16) },
|
{ be_const_key(super, -1), be_const_int(20) },
|
||||||
{ be_const_key(list, 20), be_const_int(9) },
|
{ be_const_key(issubclass, -1), be_const_int(9) },
|
||||||
{ be_const_key(isinstance, -1), be_const_int(7) },
|
{ be_const_key(classof, -1), be_const_int(4) },
|
||||||
{ be_const_key(range, -1), be_const_int(15) },
|
{ be_const_key(map, 8), be_const_int(11) },
|
||||||
{ be_const_key(size, -1), be_const_int(17) },
|
{ be_const_key(int, 2), be_const_int(7) },
|
||||||
{ be_const_key(classname, -1), be_const_int(2) },
|
{ be_const_key(input, 3), be_const_int(6) },
|
||||||
{ be_const_key(print, -1), be_const_int(14) },
|
{ be_const_key(number, -1), be_const_int(13) },
|
||||||
|
{ be_const_key(list, 7), be_const_int(10) },
|
||||||
|
{ be_const_key(str, 1), be_const_int(19) },
|
||||||
|
{ be_const_key(range, -1), be_const_int(16) },
|
||||||
|
{ be_const_key(bytes, -1), be_const_int(2) },
|
||||||
|
{ be_const_key(assert, -1), be_const_int(1) },
|
||||||
};
|
};
|
||||||
|
|
||||||
static be_define_const_map(
|
static be_define_const_map(
|
||||||
m_builtin_map,
|
m_builtin_map,
|
||||||
21
|
22
|
||||||
);
|
);
|
||||||
|
|
||||||
static const bvalue __vlist_array[] = {
|
static const bvalue __vlist_array[] = {
|
||||||
be_const_func(l_iterator),
|
be_const_func(l_iterator),
|
||||||
be_const_func(l_assert),
|
be_const_func(l_assert),
|
||||||
|
be_const_class(be_class_bytes),
|
||||||
be_const_func(l_classname),
|
be_const_func(l_classname),
|
||||||
be_const_func(l_classof),
|
be_const_func(l_classof),
|
||||||
be_const_func(l_compile),
|
be_const_func(l_compile),
|
||||||
|
@ -56,5 +58,5 @@ static const bvalue __vlist_array[] = {
|
||||||
static be_define_const_vector(
|
static be_define_const_vector(
|
||||||
m_builtin_vector,
|
m_builtin_vector,
|
||||||
__vlist_array,
|
__vlist_array,
|
||||||
21
|
22
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
#include "be_constobj.h"
|
|
||||||
|
|
||||||
static be_define_const_map_slots(m_libpath_map) {
|
|
||||||
{ be_const_key(isdir, -1), be_const_func(m_path_isdir) },
|
|
||||||
{ be_const_key(join, 2), be_const_func(m_path_join) },
|
|
||||||
{ be_const_key(exists, -1), be_const_func(m_path_exists) },
|
|
||||||
{ be_const_key(split, -1), be_const_func(m_path_split) },
|
|
||||||
{ be_const_key(splitext, -1), be_const_func(m_path_splitext) },
|
|
||||||
{ be_const_key(isfile, -1), be_const_func(m_path_isfile) },
|
|
||||||
};
|
|
||||||
|
|
||||||
static be_define_const_map(
|
|
||||||
m_libpath_map,
|
|
||||||
6
|
|
||||||
);
|
|
||||||
|
|
||||||
static be_define_const_module(
|
|
||||||
m_libpath,
|
|
||||||
"path"
|
|
||||||
);
|
|
|
@ -313,6 +313,7 @@ void be_load_baselib(bvm *vm)
|
||||||
extern const bclass be_class_list;
|
extern const bclass be_class_list;
|
||||||
extern const bclass be_class_map;
|
extern const bclass be_class_map;
|
||||||
extern const bclass be_class_range;
|
extern const bclass be_class_range;
|
||||||
|
extern const bclass be_class_bytes;
|
||||||
extern int be_nfunc_open(bvm *vm);
|
extern int be_nfunc_open(bvm *vm);
|
||||||
/* @const_object_info_begin
|
/* @const_object_info_begin
|
||||||
vartab m_builtin (scope: local) {
|
vartab m_builtin (scope: local) {
|
||||||
|
@ -337,6 +338,7 @@ vartab m_builtin (scope: local) {
|
||||||
list, class(be_class_list)
|
list, class(be_class_list)
|
||||||
map, class(be_class_map)
|
map, class(be_class_map)
|
||||||
range, class(be_class_range)
|
range, class(be_class_range)
|
||||||
|
bytes, class(be_class_bytes)
|
||||||
}
|
}
|
||||||
@const_object_info_end */
|
@const_object_info_end */
|
||||||
#include "../generate/be_fixed_m_builtin.h"
|
#include "../generate/be_fixed_m_builtin.h"
|
||||||
|
|
|
@ -0,0 +1,668 @@
|
||||||
|
/********************************************************************
|
||||||
|
** Copyright (c) 2018-2020 Guan Wenliang - Stephan Hadinger
|
||||||
|
** This file is part of the Berry default interpreter.
|
||||||
|
** skiars@qq.com, https://github.com/Skiars/berry
|
||||||
|
** See Copyright Notice in the LICENSE file or at
|
||||||
|
** https://github.com/Skiars/berry/blob/master/LICENSE
|
||||||
|
********************************************************************/
|
||||||
|
#include "be_object.h"
|
||||||
|
#include "be_string.h"
|
||||||
|
#include "be_strlib.h"
|
||||||
|
#include "be_list.h"
|
||||||
|
#include "be_func.h"
|
||||||
|
#include "be_exec.h"
|
||||||
|
#include "be_vm.h"
|
||||||
|
#include "be_mem.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#define BYTES_DEFAULT_SIZE 28 // default pre-reserved size for buffer (keep 4 bytes for len/size)
|
||||||
|
#define BYTES_MAX_SIZE (32*1024) // max 32Kb
|
||||||
|
#define BYTES_OVERHEAD 4 // bytes overhead to be added when allocating (used to store len and size)
|
||||||
|
#define BYTES_HEADROOM 8 // keep a natural headroom of 8 bytes when resizing
|
||||||
|
|
||||||
|
typedef struct buf_impl {
|
||||||
|
uint16_t size; // size in bytes of the buffer
|
||||||
|
uint16_t len; // current size of the data in buffer. Invariant: len <= size
|
||||||
|
uint8_t buf[]; // the actual data
|
||||||
|
} buf_impl;
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Buffer low-level implementation
|
||||||
|
**
|
||||||
|
** Extracted from Tasmota SBuffer lib
|
||||||
|
********************************************************************/
|
||||||
|
static inline uint8_t* buf_get_buf(buf_impl* buf) {
|
||||||
|
return &buf->buf[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// shrink or increase. If increase, fill with zeores. Cannot go beyond `size`
|
||||||
|
static void buf_set_len(buf_impl* buf, const size_t len) {
|
||||||
|
uint16_t old_len = buf->len;
|
||||||
|
buf->len = (len <= buf->size) ? len : buf->size;
|
||||||
|
if (old_len < buf->len) {
|
||||||
|
memset((void*) &buf->buf[old_len], 0, buf->len - old_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void buf_set1(buf_impl* buf, const size_t offset, const uint8_t data) {
|
||||||
|
if (offset < buf->len) {
|
||||||
|
buf->buf[offset] = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static size_t buf_add1(buf_impl* buf, const uint8_t data) { // append 8 bits value
|
||||||
|
if (buf->len < buf->size) { // do we have room for 1 byte
|
||||||
|
buf->buf[buf->len++] = data;
|
||||||
|
}
|
||||||
|
return buf->len;
|
||||||
|
}
|
||||||
|
static size_t buf_add2_le(buf_impl* buf, const uint16_t data) { // append 16 bits value
|
||||||
|
if (buf->len < buf->size - 1) { // do we have room for 2 bytes
|
||||||
|
buf->buf[buf->len++] = data;
|
||||||
|
buf->buf[buf->len++] = data >> 8;
|
||||||
|
}
|
||||||
|
return buf->len;
|
||||||
|
}
|
||||||
|
static size_t buf_add2_be(buf_impl* buf, const uint16_t data) { // append 16 bits value
|
||||||
|
if (buf->len < buf->size - 1) { // do we have room for 2 bytes
|
||||||
|
buf->buf[buf->len++] = data >> 8;
|
||||||
|
buf->buf[buf->len++] = data;
|
||||||
|
}
|
||||||
|
return buf->len;
|
||||||
|
}
|
||||||
|
static size_t buf_add4_le(buf_impl* buf, const uint32_t data) { // append 32 bits value
|
||||||
|
if (buf->len < buf->size - 3) { // do we have room for 4 bytes
|
||||||
|
buf->buf[buf->len++] = data;
|
||||||
|
buf->buf[buf->len++] = data >> 8;
|
||||||
|
buf->buf[buf->len++] = data >> 16;
|
||||||
|
buf->buf[buf->len++] = data >> 24;
|
||||||
|
}
|
||||||
|
return buf->len;
|
||||||
|
}
|
||||||
|
size_t buf_add4_be(buf_impl* buf, const uint32_t data) { // append 32 bits value
|
||||||
|
if (buf->len < buf->size - 3) { // do we have room for 4 bytes
|
||||||
|
buf->buf[buf->len++] = data >> 24;
|
||||||
|
buf->buf[buf->len++] = data >> 16;
|
||||||
|
buf->buf[buf->len++] = data >> 8;
|
||||||
|
buf->buf[buf->len++] = data;
|
||||||
|
}
|
||||||
|
return buf->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t buf_add_buf(buf_impl* buf, buf_impl* buf2) {
|
||||||
|
if (buf->len + buf2->len <= buf->size) {
|
||||||
|
for (uint32_t i = 0; i < buf2->len; i++) {
|
||||||
|
buf->buf[buf->len++] = buf2->buf[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t buf_get1(buf_impl* buf, int offset) {
|
||||||
|
if ((offset >= 0) && (offset < buf->len)) {
|
||||||
|
return buf->buf[offset];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static uint16_t buf_get2_le(buf_impl* buf, int offset) {
|
||||||
|
if ((offset >= 0) && (offset < buf->len - 1)) {
|
||||||
|
return buf->buf[offset] | (buf->buf[offset+1] << 8);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static uint16_t buf_get2_be(buf_impl* buf, int offset) {
|
||||||
|
if (offset < buf->len - 1) {
|
||||||
|
return buf->buf[offset+1] | (buf->buf[offset] << 8);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static uint32_t buf_get4_le(buf_impl* buf, int offset) {
|
||||||
|
if ((offset >= 0) && (offset < buf->len - 3)) {
|
||||||
|
return buf->buf[offset] | (buf->buf[offset+1] << 8) |
|
||||||
|
(buf->buf[offset+2] << 16) | (buf->buf[offset+3] << 24);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static uint32_t buf_get4_be(buf_impl* buf, int offset) {
|
||||||
|
if (offset < buf->len - 3) {
|
||||||
|
return buf->buf[offset+3] | (buf->buf[offset+2] << 8) |
|
||||||
|
(buf->buf[offset+1] << 16) | (buf->buf[offset] << 24);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nullptr accepted
|
||||||
|
static bbool buf_equals(buf_impl* buf1, buf_impl* buf2) {
|
||||||
|
if (buf1 == buf2) { return btrue; }
|
||||||
|
if (!buf1 || !buf2) { return bfalse; } // at least one buf is not empty
|
||||||
|
// we know that both buf1 and buf2 are non-null
|
||||||
|
if (buf1->len != buf2->len) { return bfalse; }
|
||||||
|
size_t len = buf1->len;
|
||||||
|
for (uint32_t i=0; i<len; i++) {
|
||||||
|
if (buf_get1(buf1, i) != buf_get1(buf2, i)) { return bfalse; }
|
||||||
|
}
|
||||||
|
return btrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t asc2byte(char chr) {
|
||||||
|
uint8_t rVal = 0;
|
||||||
|
if (isdigit(chr)) { rVal = chr - '0'; }
|
||||||
|
else if (chr >= 'A' && chr <= 'F') { rVal = chr + 10 - 'A'; }
|
||||||
|
else if (chr >= 'a' && chr <= 'f') { rVal = chr + 10 - 'a'; }
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
// does not check if there is enough room before hand, truncated if buffer too small
|
||||||
|
static void buf_add_hex(buf_impl* buf, const char *hex, size_t len) {
|
||||||
|
uint8_t val;
|
||||||
|
for (; len > 1; len -= 2) {
|
||||||
|
val = asc2byte(*hex++) << 4;
|
||||||
|
val |= asc2byte(*hex++);
|
||||||
|
buf_add1(buf, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Wrapping into lib
|
||||||
|
********************************************************************/
|
||||||
|
// typedef int (*bntvfunc)(bvm*); /* native function pointer */
|
||||||
|
int free_bytes_buf(bvm* vm) {
|
||||||
|
int argc = be_top(vm);
|
||||||
|
if (argc > 0) {
|
||||||
|
buf_impl * buf = (buf_impl*) be_tocomptr(vm, 1);
|
||||||
|
if (buf != NULL) {
|
||||||
|
be_os_free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_impl * bytes_alloc(int32_t size)
|
||||||
|
{
|
||||||
|
if (size < 4) { size = 4; }
|
||||||
|
if (size > BYTES_MAX_SIZE) { size = BYTES_MAX_SIZE; }
|
||||||
|
buf_impl * next = (buf_impl*) be_os_malloc(size + BYTES_OVERHEAD);
|
||||||
|
next->size = size;
|
||||||
|
next->len = 0;
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a new `bytes` object with pre-allocated size */
|
||||||
|
static void bytes_new_object(bvm *vm, size_t size)
|
||||||
|
{
|
||||||
|
be_getglobal(vm, "bytes"); /* eventually change with be_getbuiltin */
|
||||||
|
be_call(vm, 0); /* stack has only instance */
|
||||||
|
be_getmember(vm, -1, "init");
|
||||||
|
be_pushvalue(vm, -2);
|
||||||
|
be_pushint(vm, size); /* stack: instance, init func, instance, size */
|
||||||
|
be_call(vm, 2); /* stack: instance, ret, instance, size */
|
||||||
|
be_pop(vm, 3); /* remove ret, instance, size */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m_init(bvm *vm)
|
||||||
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
|
int size = BYTES_DEFAULT_SIZE;
|
||||||
|
const char * hex_in = NULL;
|
||||||
|
if (argc > 1 && be_isint(vm, 2)) {
|
||||||
|
int new_size = be_toint(vm, 2) + BYTES_HEADROOM;
|
||||||
|
if (new_size > size) {
|
||||||
|
size = new_size;
|
||||||
|
}
|
||||||
|
} else if (argc > 1 && be_isstring(vm, 2)) {
|
||||||
|
hex_in = be_tostring(vm, 2);
|
||||||
|
if (hex_in) {
|
||||||
|
size = strlen(hex_in) / 2 + BYTES_HEADROOM; // allocate headroom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf_impl * buf = bytes_alloc(size);
|
||||||
|
if (!buf) {
|
||||||
|
be_throw(vm, BE_MALLOC_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hex_in) {
|
||||||
|
buf_add_hex(buf, hex_in, strlen(hex_in));
|
||||||
|
}
|
||||||
|
be_newcomobj(vm, buf, &free_bytes_buf);
|
||||||
|
be_setmember(vm, 1, ".p");
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* grow or shrink to the exact value */
|
||||||
|
/* stack item 1 must contain the instance */
|
||||||
|
static buf_impl * _bytes_resize(bvm *vm, buf_impl * buf, size_t new_size) {
|
||||||
|
buf_impl * new_buf = bytes_alloc(new_size);
|
||||||
|
if (!new_buf) {
|
||||||
|
be_throw(vm, BE_MALLOC_FAIL);
|
||||||
|
}
|
||||||
|
memmove(buf_get_buf(new_buf), buf_get_buf(buf), buf->len);
|
||||||
|
new_buf->len = buf->len;
|
||||||
|
/* replace the .p attribute */
|
||||||
|
be_newcomobj(vm, new_buf, &free_bytes_buf);
|
||||||
|
be_setmember(vm, 1, ".p");
|
||||||
|
be_pop(vm, 1); /* remove comobj from stack */
|
||||||
|
/* the old buffer will be garbage collected later */
|
||||||
|
return new_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* grow if needed but don't shrink */
|
||||||
|
/* if grow, then add some headroom */
|
||||||
|
/* stack item 1 must contain the instance */
|
||||||
|
static buf_impl * bytes_resize(bvm *vm, buf_impl * buf, size_t new_size) {
|
||||||
|
if (buf->size >= new_size) { return buf; } /* no resize needed */
|
||||||
|
return _bytes_resize(vm, buf, new_size + BYTES_HEADROOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static buf_impl * bytes_check_data(bvm *vm, size_t add_size) {
|
||||||
|
be_getmember(vm, 1, ".p");
|
||||||
|
buf_impl * buf = be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 1); /* remove member from stack */
|
||||||
|
/* check if the `size` is big enough */
|
||||||
|
if (buf->len + add_size > buf->size) {
|
||||||
|
/* it does not fit so we need to realocate the buffer */
|
||||||
|
buf = bytes_resize(vm, buf, buf->len + add_size);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t tohex(char * out, size_t outsz, const uint8_t * in, size_t insz) {
|
||||||
|
static const char * hex = "0123456789ABCDEF";
|
||||||
|
const uint8_t * pin = in;
|
||||||
|
char * pout = out;
|
||||||
|
for (; pin < in + insz; pout += 2, pin++) {
|
||||||
|
pout[0] = hex[((*pin)>>4) & 0xF];
|
||||||
|
pout[1] = hex[ (*pin) & 0xF];
|
||||||
|
if (pout + 3 > out + outsz) { break; } /* check overflow */
|
||||||
|
}
|
||||||
|
pout[0] = 0; /* terminating Nul char */
|
||||||
|
return pout - out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m_tostring(bvm *vm)
|
||||||
|
{
|
||||||
|
buf_impl * buf = bytes_check_data(vm, 0);
|
||||||
|
size_t len = buf->len;
|
||||||
|
size_t hex_len = len * 2 + 5 + 2 + 2 + 1; /* reserve size for `bytes("")\0` - 9 chars */
|
||||||
|
|
||||||
|
char * hex_out = be_pushbuffer(vm, hex_len);
|
||||||
|
size_t l = strlcpy(hex_out, "bytes('", hex_len);
|
||||||
|
l += tohex(&hex_out[l], hex_len - l, buf_get_buf(buf), buf->len);
|
||||||
|
l += strlcpy(&hex_out[l], "')", hex_len - l);
|
||||||
|
|
||||||
|
be_pushnstring(vm, hex_out, l); /* make escape string from buffer */
|
||||||
|
be_remove(vm, -2); /* remove buffer */
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the buffer into a string without any changes
|
||||||
|
*/
|
||||||
|
static int m_asstring(bvm *vm)
|
||||||
|
{
|
||||||
|
buf_impl * buf = bytes_check_data(vm, 0);
|
||||||
|
be_pushnstring(vm, (const char*) buf_get_buf(buf), buf->len);
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
static int m_fromstring(bvm *vm)
|
||||||
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
|
if (argc >= 2 && be_isstring(vm, 2)) {
|
||||||
|
const char *s = be_tostring(vm, 2);
|
||||||
|
size_t len = strlen(s);
|
||||||
|
buf_impl * buf = bytes_check_data(vm, 0);
|
||||||
|
buf = bytes_resize(vm, buf, len); /* resize if needed */
|
||||||
|
if (len > buf->size) { len = buf->size; } /* avoid overflow */
|
||||||
|
memmove(buf_get_buf(buf), s, len);
|
||||||
|
buf->len = len;
|
||||||
|
be_pop(vm, 1); /* remove arg to leave instance */
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
be_raise(vm, "type_error", "operand must be a string");
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add an int made of 1, 2 or 4 bytes, in little or big endian
|
||||||
|
* `add(value:int[, size:int = 1]) -> instance`
|
||||||
|
*
|
||||||
|
* size: may be 1, 2, 4 (little endian), or -1, -2, -4 (big endian)
|
||||||
|
* obvisouly -1 is idntical to 1
|
||||||
|
* size==0 does nothing
|
||||||
|
*/
|
||||||
|
static int m_add(bvm *vm)
|
||||||
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
|
buf_impl * buf = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */
|
||||||
|
if (argc >= 2 && be_isint(vm, 2)) {
|
||||||
|
int32_t v = be_toint(vm, 2);
|
||||||
|
int vsize = 1;
|
||||||
|
if (argc >= 3 && be_isint(vm, 3)) {
|
||||||
|
vsize = be_toint(vm, 3);
|
||||||
|
}
|
||||||
|
switch (vsize) {
|
||||||
|
case 0: break;
|
||||||
|
case -1: /* fallback below */
|
||||||
|
case 1: buf_add1(buf, v); break;
|
||||||
|
case 2: buf_add2_le(buf, v); break;
|
||||||
|
case 4: buf_add4_le(buf, v); break;
|
||||||
|
case -2: buf_add2_be(buf, v); break;
|
||||||
|
case -4: buf_add4_be(buf, v); break;
|
||||||
|
default: be_raise(vm, "type_error", "size must be -4, -2, -1, 0, 1, 2 or 4.");
|
||||||
|
}
|
||||||
|
be_pop(vm, argc - 1);
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get an int made of 1, 2 or 4 bytes, in little or big endian
|
||||||
|
* `get(index:int[, size:int = 1]) -> instance`
|
||||||
|
*
|
||||||
|
* size: may be 1, 2, 4 (little endian), or -1, -2, -4 (big endian)
|
||||||
|
* obvisouly -1 is idntical to 1
|
||||||
|
* 0 returns nil
|
||||||
|
*/
|
||||||
|
static int m_get(bvm *vm)
|
||||||
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
|
buf_impl * buf = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||||
|
if (argc >=2 && be_isint(vm, 2)) {
|
||||||
|
int32_t idx = be_toint(vm, 2);
|
||||||
|
int vsize = 1;
|
||||||
|
if (argc >= 3 && be_isint(vm, 3)) {
|
||||||
|
vsize = be_toint(vm, 3);
|
||||||
|
}
|
||||||
|
int ret = 0;
|
||||||
|
switch (vsize) {
|
||||||
|
case 0: break;
|
||||||
|
case -1: /* fallback below */
|
||||||
|
case 1: ret = buf_get1(buf, idx); break;
|
||||||
|
case 2: ret = buf_get2_le(buf, idx); break;
|
||||||
|
case 4: ret = buf_get4_le(buf, idx); break;
|
||||||
|
case -2: ret = buf_get2_be(buf, idx); break;
|
||||||
|
case -4: ret = buf_get4_be(buf, idx); break;
|
||||||
|
default: be_raise(vm, "type_error", "size must be -4, -2, -1, 0, 1, 2 or 4.");
|
||||||
|
}
|
||||||
|
be_pop(vm, argc - 1);
|
||||||
|
if (vsize != 0) {
|
||||||
|
be_pushint(vm, ret);
|
||||||
|
} else {
|
||||||
|
be_pushnil(vm);
|
||||||
|
}
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int m_setitem(bvm *vm)
|
||||||
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
|
buf_impl * buf = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||||
|
if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
|
||||||
|
int index = be_toint(vm, 2);
|
||||||
|
int val = be_toint(vm, 3);
|
||||||
|
if (index >= 0 && index < buf->len) {
|
||||||
|
buf_set1(buf, index, val);
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_raise(vm, "index_error", "bytes index out of range or value non int");
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m_item(bvm *vm)
|
||||||
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
|
buf_impl * buf = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
|
||||||
|
if (argc >=2 && be_isint(vm, 2)) {
|
||||||
|
int index = be_toint(vm,2);
|
||||||
|
if (index >= 0 && index < buf->len) {
|
||||||
|
be_pushint(vm, buf_get1(buf, index));
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argc >= 2 && be_isinstance(vm, 2)) {
|
||||||
|
const char *cname = be_classname(vm, 2);
|
||||||
|
if (!strcmp(cname, "range")) {
|
||||||
|
bint lower, upper;
|
||||||
|
bint size = buf->len;
|
||||||
|
/* get index range */
|
||||||
|
be_getmember(vm, 2, "__lower__");
|
||||||
|
lower = be_toint(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_getmember(vm, 2, "__upper__");
|
||||||
|
upper = be_toint(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
/* protection scope */
|
||||||
|
upper = upper < size ? upper : size - 1;
|
||||||
|
lower = lower < 0 ? 0 : lower;
|
||||||
|
/* construction result list instance */
|
||||||
|
bytes_new_object(vm, upper > lower ? upper-lower : 0);
|
||||||
|
be_getmember(vm, -1, ".p");
|
||||||
|
buf_impl * buf2 = be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 1); /* remove .p and leave bytes instance */
|
||||||
|
for (; lower <= upper; ++lower) {
|
||||||
|
buf_add1(buf2, buf->buf[lower]);
|
||||||
|
}
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_raise(vm, "index_error", "bytes index out of range");
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m_size(bvm *vm)
|
||||||
|
{
|
||||||
|
buf_impl * buf = bytes_check_data(vm, 0);
|
||||||
|
be_pushint(vm, buf->len);
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m_resize(bvm *vm)
|
||||||
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
|
be_getmember(vm, 1, ".p");
|
||||||
|
buf_impl * buf = be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
if (argc <= 1 || !be_isint(vm, 2)) {
|
||||||
|
be_raise(vm, "type_error", "size must be of type 'int'");
|
||||||
|
}
|
||||||
|
int new_len = be_toint(vm, 2);
|
||||||
|
if (new_len < 0) {
|
||||||
|
new_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = bytes_resize(vm, buf, new_len);
|
||||||
|
buf_set_len(buf, new_len);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m_clear(bvm *vm)
|
||||||
|
{
|
||||||
|
buf_impl * buf = bytes_check_data(vm, 0);
|
||||||
|
buf->len = 0;
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m_merge(bvm *vm)
|
||||||
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
|
buf_impl * buf1 = bytes_check_data(vm, 0); /* no resize yet */
|
||||||
|
if (argc >= 2 && be_isinstance(vm, 2)) {
|
||||||
|
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
|
||||||
|
if (be_isderived(vm, 2)) {
|
||||||
|
be_getmember(vm, 2, ".p");
|
||||||
|
buf_impl * buf2 = be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 4); /* remove class, member, and 2 operands */
|
||||||
|
|
||||||
|
/* allocate new object */
|
||||||
|
bytes_new_object(vm, buf1->len + buf2->len);
|
||||||
|
be_getmember(vm, -1, ".p");
|
||||||
|
/* .p is on top of stack, then instance */
|
||||||
|
buf_impl * buf3 = be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
buf_add_buf(buf3, buf1);
|
||||||
|
buf_add_buf(buf3, buf2);
|
||||||
|
|
||||||
|
be_return(vm); /* return self */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_raise(vm, "type_error", "operand must be bytes");
|
||||||
|
be_return_nil(vm); /* return self */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m_copy(bvm *vm)
|
||||||
|
{
|
||||||
|
buf_impl * buf1 = bytes_check_data(vm, 0); /* no resize */
|
||||||
|
bytes_new_object(vm, buf1->len);
|
||||||
|
be_getmember(vm, -1, ".p");
|
||||||
|
buf_impl * buf2 = be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
buf_add_buf(buf2, buf1);
|
||||||
|
be_return(vm); /* return self */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* accept bytes or int as operand */
|
||||||
|
static int m_connect(bvm *vm)
|
||||||
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
|
buf_impl * buf1 = bytes_check_data(vm, 0); /* don't resize yet */
|
||||||
|
if (argc >= 2 && (be_isinstance(vm, 2) || be_isint(vm, 2))) {
|
||||||
|
if (be_isint(vm, 2)) {
|
||||||
|
buf1 = bytes_resize(vm, buf1, buf1->len + 1); /* resize */
|
||||||
|
buf_add1(buf1, be_toint(vm, 2));
|
||||||
|
be_pop(vm, 1); /* remove operand */
|
||||||
|
be_return(vm); /* return self */
|
||||||
|
} else {
|
||||||
|
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
|
||||||
|
if (be_isderived(vm, 2)) {
|
||||||
|
be_getmember(vm, 2, ".p");
|
||||||
|
buf_impl * buf2 = be_tocomptr(vm, -1);
|
||||||
|
buf1 = bytes_resize(vm, buf1, buf1->len + buf2->len); /* resize buf1 for total size */
|
||||||
|
buf_add_buf(buf1, buf2);
|
||||||
|
be_pop(vm, 3); /* remove class, member, and last operand */
|
||||||
|
be_return(vm); /* return self */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_raise(vm, "type_error", "operand must be bytes or int");
|
||||||
|
be_return_nil(vm); /* return self */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bytes_equal(bvm *vm, bbool iseq)
|
||||||
|
{
|
||||||
|
be_getmember(vm, 1, ".p");
|
||||||
|
buf_impl * buf1 = be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
be_getmember(vm, 2, ".p");
|
||||||
|
buf_impl * buf2 = be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
bbool ret;
|
||||||
|
if (buf_equals(buf1, buf2)) {
|
||||||
|
ret = iseq;
|
||||||
|
} else {
|
||||||
|
ret = !iseq;
|
||||||
|
}
|
||||||
|
be_pushbool(vm, ret);
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m_equal(bvm *vm)
|
||||||
|
{
|
||||||
|
return bytes_equal(vm, btrue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m_nequal(bvm *vm)
|
||||||
|
{
|
||||||
|
return bytes_equal(vm, bfalse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External API
|
||||||
|
*/
|
||||||
|
BERRY_API void be_pushbytes(bvm *vm, const void * bytes, size_t len)
|
||||||
|
{
|
||||||
|
bytes_new_object(vm, len);
|
||||||
|
be_getmember(vm, -1, ".p");
|
||||||
|
buf_impl * buf = be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 1); /* remove .p1 and leave instance */
|
||||||
|
if (len > buf->size) { len = buf->size; } /* double check if the buffer allocated was smaller */
|
||||||
|
memmove((void*)buf_get_buf(buf), bytes, len);
|
||||||
|
buf->len = len;
|
||||||
|
/* bytes instance is on top of stack */
|
||||||
|
}
|
||||||
|
|
||||||
|
BERRY_API const void *be_tobytes(bvm *vm, int rel_index, size_t *len)
|
||||||
|
{
|
||||||
|
int index = be_absindex(vm, rel_index);
|
||||||
|
if (be_isinstance(vm, index)) {
|
||||||
|
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
|
||||||
|
if (be_isderived(vm, index)) {
|
||||||
|
be_getmember(vm, index, ".p");
|
||||||
|
buf_impl * buf = be_tocomptr(vm, -1);
|
||||||
|
be_pop(vm, 2); /* class and .p */
|
||||||
|
if (len) { *len = buf->len; }
|
||||||
|
return (void*) buf_get_buf(buf);
|
||||||
|
} else {
|
||||||
|
be_pop(vm, 1); /* remove class */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len) { *len = 0; }
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !BE_USE_PRECOMPILED_OBJECT
|
||||||
|
void be_load_byteslib(bvm *vm)
|
||||||
|
{
|
||||||
|
static const bnfuncinfo members[] = {
|
||||||
|
{ ".p", NULL },
|
||||||
|
{ "init", m_init },
|
||||||
|
{ "tostring", m_tostring },
|
||||||
|
{ "asstring", m_asstring },
|
||||||
|
{ "fromstring", m_fromstring },
|
||||||
|
{ "add", m_add },
|
||||||
|
{ "get", m_get },
|
||||||
|
{ "item", m_item },
|
||||||
|
{ "setitem", m_setitem },
|
||||||
|
{ "size", m_size },
|
||||||
|
{ "resize", m_resize },
|
||||||
|
{ "clear", m_clear },
|
||||||
|
{ "copy", m_copy },
|
||||||
|
{ "+", m_merge },
|
||||||
|
{ "..", m_connect },
|
||||||
|
{ "==", m_equal },
|
||||||
|
{ "!=", m_nequal },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
be_regclass(vm, "bytes", members);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* @const_object_info_begin
|
||||||
|
class be_class_bytes (scope: global, name: bytes) {
|
||||||
|
.p, var
|
||||||
|
init, func(m_init)
|
||||||
|
tostring, func(m_tostring)
|
||||||
|
asstring, func(m_asstring)
|
||||||
|
fromstring, func(m_fromstring)
|
||||||
|
add, func(m_add)
|
||||||
|
get, func(m_get)
|
||||||
|
item, func(m_item)
|
||||||
|
setitem, func(m_setitem)
|
||||||
|
size, func(m_size)
|
||||||
|
resize, func(m_resize)
|
||||||
|
clear, func(m_clear)
|
||||||
|
copy, func(m_copy)
|
||||||
|
+, func(m_merge)
|
||||||
|
.., func(m_connect)
|
||||||
|
==, func(m_equal)
|
||||||
|
!=, func(m_nequal)
|
||||||
|
}
|
||||||
|
@const_object_info_end */
|
||||||
|
#include "../generate/be_fixed_be_class_bytes.h"
|
||||||
|
#endif
|
|
@ -13,6 +13,9 @@ extern void be_load_maplib(bvm *vm);
|
||||||
extern void be_load_rangelib(bvm *vm);
|
extern void be_load_rangelib(bvm *vm);
|
||||||
extern void be_load_filelib(bvm *vm);
|
extern void be_load_filelib(bvm *vm);
|
||||||
|
|
||||||
|
extern void be_load_tasmota_ntvlib(bvm *vm);
|
||||||
|
extern void be_load_wirelib(bvm *vm);
|
||||||
|
|
||||||
void be_loadlibs(bvm *vm)
|
void be_loadlibs(bvm *vm)
|
||||||
{
|
{
|
||||||
be_load_baselib(vm);
|
be_load_baselib(vm);
|
||||||
|
@ -21,5 +24,8 @@ void be_loadlibs(bvm *vm)
|
||||||
be_load_maplib(vm);
|
be_load_maplib(vm);
|
||||||
be_load_rangelib(vm);
|
be_load_rangelib(vm);
|
||||||
be_load_filelib(vm);
|
be_load_filelib(vm);
|
||||||
|
be_load_byteslib(vm);
|
||||||
#endif
|
#endif
|
||||||
|
be_load_tasmota_ntvlib(vm);
|
||||||
|
be_load_wirelib(vm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,6 +207,19 @@ static int m_item(bvm *vm)
|
||||||
be_return_nil(vm);
|
be_return_nil(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int m_find(bvm *vm)
|
||||||
|
{
|
||||||
|
be_getmember(vm, 1, ".p");
|
||||||
|
list_check_data(vm, 2);
|
||||||
|
if (be_isint(vm, 2)) {
|
||||||
|
be_pushvalue(vm, 2);
|
||||||
|
if (be_getindex(vm, -2)) {
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
static int m_setitem(bvm *vm)
|
static int m_setitem(bvm *vm)
|
||||||
{
|
{
|
||||||
be_getmember(vm, 1, ".p");
|
be_getmember(vm, 1, ".p");
|
||||||
|
@ -291,13 +304,15 @@ static int m_merge(bvm *vm)
|
||||||
{
|
{
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
if (argc >= 2) {
|
if (argc >= 2) {
|
||||||
|
be_newobject(vm, "list"); /* stack contains instance and .p */
|
||||||
be_getmember(vm, 1, ".p");
|
be_getmember(vm, 1, ".p");
|
||||||
|
be_data_merge(vm, -2);
|
||||||
be_getmember(vm, 2, ".p");
|
be_getmember(vm, 2, ".p");
|
||||||
if (!be_islist(vm, -1)) {
|
if (!be_islist(vm, -1)) {
|
||||||
be_raise(vm, "type_error", "operand must be a list");
|
be_raise(vm, "type_error", "operand must be a list");
|
||||||
}
|
}
|
||||||
be_data_merge(vm, -2);
|
be_data_merge(vm, -3);
|
||||||
be_pop(vm, argc + 1);
|
be_pop(vm, 3);
|
||||||
}
|
}
|
||||||
be_return(vm); /* return self */
|
be_return(vm); /* return self */
|
||||||
}
|
}
|
||||||
|
@ -423,6 +438,7 @@ void be_load_listlib(bvm *vm)
|
||||||
{ "insert", m_insert },
|
{ "insert", m_insert },
|
||||||
{ "remove", m_remove },
|
{ "remove", m_remove },
|
||||||
{ "item", m_item },
|
{ "item", m_item },
|
||||||
|
{ "find", m_find },
|
||||||
{ "setitem", m_setitem },
|
{ "setitem", m_setitem },
|
||||||
{ "size", m_size },
|
{ "size", m_size },
|
||||||
{ "resize", m_resize },
|
{ "resize", m_resize },
|
||||||
|
@ -450,6 +466,7 @@ class be_class_list (scope: global, name: list) {
|
||||||
insert, func(m_insert)
|
insert, func(m_insert)
|
||||||
remove, func(m_remove)
|
remove, func(m_remove)
|
||||||
item, func(m_item)
|
item, func(m_item)
|
||||||
|
find, func(m_find)
|
||||||
setitem, func(m_setitem)
|
setitem, func(m_setitem)
|
||||||
size, func(m_size)
|
size, func(m_size)
|
||||||
resize, func(m_resize)
|
resize, func(m_resize)
|
||||||
|
|
|
@ -429,6 +429,10 @@ BERRY_API int be_savecode(bvm *vm, const char *name);
|
||||||
BERRY_API void be_module_path(bvm *vm);
|
BERRY_API void be_module_path(bvm *vm);
|
||||||
BERRY_API void be_module_path_set(bvm *vm, const char *path);
|
BERRY_API void be_module_path_set(bvm *vm, const char *path);
|
||||||
|
|
||||||
|
/* bytes operations */
|
||||||
|
BERRY_API void be_pushbytes(bvm *vm, const void *buf, size_t len);
|
||||||
|
BERRY_API const void *be_tobytes(bvm *vm, int index, size_t *len);
|
||||||
|
|
||||||
/* registry operation */
|
/* registry operation */
|
||||||
BERRY_API int be_register(bvm *vm, int index);
|
BERRY_API int be_register(bvm *vm, int index);
|
||||||
BERRY_API void be_unregister(bvm *vm, int id);
|
BERRY_API void be_unregister(bvm *vm, int id);
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/********************************************************************
|
||||||
|
* Tasmota lib
|
||||||
|
*
|
||||||
|
* To use: `import power`
|
||||||
|
*
|
||||||
|
* read power values
|
||||||
|
*******************************************************************/
|
||||||
|
#include "be_object.h"
|
||||||
|
|
||||||
|
extern int b_nrg_read(bvm *vm);
|
||||||
|
|
||||||
|
// #if !BE_USE_PRECOMPILED_OBJECT
|
||||||
|
#if 1 // TODO we will do pre-compiled later
|
||||||
|
be_native_module_attr_table(energy) {
|
||||||
|
be_native_module_function("read", b_nrg_read),
|
||||||
|
};
|
||||||
|
|
||||||
|
be_define_native_module(energy, NULL);
|
||||||
|
#else
|
||||||
|
/* @const_object_info_begin
|
||||||
|
module tasmota (scope: global, depend: 1) {
|
||||||
|
getfreeheap, func(l_getFreeHeap)
|
||||||
|
}
|
||||||
|
@const_object_info_end */
|
||||||
|
#include "../generate/be_fixed_tasmota.h"
|
||||||
|
#endif
|
|
@ -20,8 +20,9 @@ be_extern_native_module(debug);
|
||||||
be_extern_native_module(gc);
|
be_extern_native_module(gc);
|
||||||
|
|
||||||
/* Tasmota specific */
|
/* Tasmota specific */
|
||||||
be_extern_native_module(tasmota_ntv);
|
// be_extern_native_module(tasmota_ntv);
|
||||||
be_extern_native_module(wire);
|
be_extern_native_module(wire);
|
||||||
|
be_extern_native_module(energy);
|
||||||
|
|
||||||
/* user-defined modules declare start */
|
/* user-defined modules declare start */
|
||||||
|
|
||||||
|
@ -56,8 +57,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
|
||||||
#endif
|
#endif
|
||||||
/* user-defined modules register start */
|
/* user-defined modules register start */
|
||||||
|
|
||||||
&be_native_module(tasmota_ntv),
|
&be_native_module(energy),
|
||||||
&be_native_module(wire),
|
|
||||||
|
|
||||||
/* user-defined modules register end */
|
/* user-defined modules register end */
|
||||||
NULL /* do not remove */
|
NULL /* do not remove */
|
||||||
|
|
|
@ -13,6 +13,7 @@ extern int l_millis(bvm *vm);
|
||||||
extern int l_timereached(bvm *vm);
|
extern int l_timereached(bvm *vm);
|
||||||
extern int l_yield(bvm *vm);
|
extern int l_yield(bvm *vm);
|
||||||
extern int l_delay(bvm *vm);
|
extern int l_delay(bvm *vm);
|
||||||
|
extern int l_scaleuint(bvm *vm);
|
||||||
|
|
||||||
extern int l_respCmnd(bvm *vm);
|
extern int l_respCmnd(bvm *vm);
|
||||||
extern int l_respCmndStr(bvm *vm);
|
extern int l_respCmndStr(bvm *vm);
|
||||||
|
@ -22,33 +23,49 @@ extern int l_respCmndFailed(bvm *vm);
|
||||||
extern int l_resolveCmnd(bvm *vm);
|
extern int l_resolveCmnd(bvm *vm);
|
||||||
|
|
||||||
extern int l_getlight(bvm *vm);
|
extern int l_getlight(bvm *vm);
|
||||||
|
extern int l_getpower(bvm *vm);
|
||||||
|
extern int l_setlight(bvm *vm);
|
||||||
|
extern int l_setpower(bvm *vm);
|
||||||
|
|
||||||
// #if !BE_USE_PRECOMPILED_OBJECT
|
// #if !BE_USE_PRECOMPILED_OBJECT
|
||||||
#if 1 // TODO we will do pre-compiled later
|
#if 1 // TODO we will do pre-compiled later
|
||||||
|
// Class definition
|
||||||
|
void be_load_tasmota_ntvlib(bvm *vm)
|
||||||
|
{
|
||||||
|
static const bnfuncinfo members[] = {
|
||||||
|
{ "_op", NULL },
|
||||||
|
{ "_opf", NULL },
|
||||||
|
{ "_operators", NULL },
|
||||||
|
{ "_rules", NULL },
|
||||||
|
{ "_timers", NULL },
|
||||||
|
{ "_cmd", NULL },
|
||||||
|
{ "getfreeheap", l_getFreeHeap },
|
||||||
|
{ "publish", l_publish },
|
||||||
|
{ "cmd", l_cmd },
|
||||||
|
{ "getoption", l_getoption },
|
||||||
|
{ "millis", l_millis },
|
||||||
|
{ "timereached", l_timereached },
|
||||||
|
{ "yield", l_yield },
|
||||||
|
{ "delay", l_delay },
|
||||||
|
{ "scaleuint", l_scaleuint },
|
||||||
|
|
||||||
be_native_module_attr_table(tasmota_ntv) {
|
{ "respcmnd", l_respCmnd },
|
||||||
be_native_module_function("getfreeheap", l_getFreeHeap),
|
{ "respcmndstr", l_respCmndStr },
|
||||||
be_native_module_function("publish", l_publish),
|
{ "respcmnd_done", l_respCmndDone },
|
||||||
be_native_module_function("cmd", l_cmd),
|
{ "respcmnd_error", l_respCmndError },
|
||||||
be_native_module_function("getoption", l_getoption),
|
{ "respcmnd_failed", l_respCmndFailed },
|
||||||
be_native_module_function("millis", l_millis),
|
{ "resolvecmnd", l_resolveCmnd },
|
||||||
be_native_module_function("timereached", l_timereached),
|
|
||||||
be_native_module_function("yield", l_yield),
|
|
||||||
be_native_module_function("delay", l_delay),
|
|
||||||
|
|
||||||
be_native_module_function("respcmnd", l_respCmnd),
|
{ "getlight", l_getlight },
|
||||||
be_native_module_function("respcmndstr", l_respCmndStr),
|
{ "getpower", l_getpower },
|
||||||
be_native_module_function("respcmnd_done", l_respCmndDone),
|
{ "setlight", l_setlight },
|
||||||
be_native_module_function("respcmnd_error", l_respCmndError),
|
{ "setpower", l_setpower },
|
||||||
be_native_module_function("respcmnd_failed", l_respCmndFailed),
|
|
||||||
be_native_module_function("resolvecmnd", l_resolveCmnd),
|
|
||||||
|
|
||||||
be_native_module_function("getlight", l_getlight),
|
{ NULL, NULL }
|
||||||
|
|
||||||
be_native_module_str("_operators", "=<>!|"),
|
|
||||||
};
|
};
|
||||||
|
be_regclass(vm, "Tasmota_ntv", members);
|
||||||
|
}
|
||||||
|
|
||||||
be_define_native_module(tasmota_ntv, NULL);
|
|
||||||
#else
|
#else
|
||||||
/* @const_object_info_begin
|
/* @const_object_info_begin
|
||||||
module tasmota (scope: global, depend: 1) {
|
module tasmota (scope: global, depend: 1) {
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
#include "be_object.h"
|
#include "be_object.h"
|
||||||
|
|
||||||
|
extern int b_wire_init(bvm *vm);
|
||||||
|
|
||||||
extern int b_wire_begintransmission(bvm *vm);
|
extern int b_wire_begintransmission(bvm *vm);
|
||||||
extern int b_wire_endtransmission(bvm *vm);
|
extern int b_wire_endtransmission(bvm *vm);
|
||||||
extern int b_wire_requestfrom(bvm *vm);
|
extern int b_wire_requestfrom(bvm *vm);
|
||||||
|
@ -21,19 +23,25 @@ extern int b_wire_validread(bvm *vm);
|
||||||
|
|
||||||
// #if !BE_USE_PRECOMPILED_OBJECT
|
// #if !BE_USE_PRECOMPILED_OBJECT
|
||||||
#if 1 // TODO we will do pre-compiled later
|
#if 1 // TODO we will do pre-compiled later
|
||||||
be_native_module_attr_table(wire) {
|
void be_load_wirelib(bvm *vm)
|
||||||
be_native_module_function("_begintransmission", b_wire_begintransmission),
|
{
|
||||||
be_native_module_function("_endtransmission", b_wire_endtransmission),
|
static const bnfuncinfo members[] = {
|
||||||
be_native_module_function("_requestfrom", b_wire_requestfrom),
|
{ "_bus", NULL }, // bus number
|
||||||
be_native_module_function("_available", b_wire_available),
|
{ "init", b_wire_init },
|
||||||
be_native_module_function("_write", b_wire_write),
|
{ "_begintransmission", b_wire_begintransmission },
|
||||||
be_native_module_function("_read", b_wire_read),
|
{ "_endtransmission", b_wire_endtransmission },
|
||||||
be_native_module_function("scan", b_wire_scan),
|
{ "_requestfrom", b_wire_requestfrom },
|
||||||
be_native_module_function("write", b_wire_validwrite),
|
{ "_available", b_wire_available },
|
||||||
be_native_module_function("read", b_wire_validread),
|
{ "_write", b_wire_write },
|
||||||
};
|
{ "_read", b_wire_read },
|
||||||
|
{ "scan", b_wire_scan },
|
||||||
|
{ "write", b_wire_validwrite },
|
||||||
|
{ "read", b_wire_validread },
|
||||||
|
|
||||||
be_define_native_module(wire, NULL);
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
be_regclass(vm, "Wire", members);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
/* @const_object_info_begin
|
/* @const_object_info_begin
|
||||||
module tasmota (scope: global, depend: 1) {
|
module tasmota (scope: global, depend: 1) {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
load('denky.be')
|
|
@ -0,0 +1,21 @@
|
||||||
|
#-
|
||||||
|
# example of using Berry script to change the led color
|
||||||
|
# accordingly to power consumption
|
||||||
|
# using Denky (French Teleinfo reader)
|
||||||
|
-#
|
||||||
|
|
||||||
|
#- define the global symbol for reference -#
|
||||||
|
runcolor = nil
|
||||||
|
|
||||||
|
def runcolor()
|
||||||
|
var pwr = energy.read().find('activepower',0)
|
||||||
|
print(pwr)
|
||||||
|
var red = tasmota.scaleuint(int(pwr), 0, 2500, 0, 255)
|
||||||
|
var green = 255 - red
|
||||||
|
var channels = [red, green, 0]
|
||||||
|
tasmota.setlight({"channels":channels, "bri":64, "power":true})
|
||||||
|
tasmota.settimer(2000, runcolor)
|
||||||
|
end
|
||||||
|
|
||||||
|
#- run animation -#
|
||||||
|
runcolor()
|
|
@ -1812,27 +1812,37 @@ const uint8_t I2C_RETRY_COUNTER = 3;
|
||||||
uint32_t i2c_active[4] = { 0 };
|
uint32_t i2c_active[4] = { 0 };
|
||||||
uint32_t i2c_buffer = 0;
|
uint32_t i2c_buffer = 0;
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size, uint32_t bus = 0);
|
||||||
|
bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size, uint32_t bus)
|
||||||
|
#else
|
||||||
bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size)
|
bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
uint8_t retry = I2C_RETRY_COUNTER;
|
uint8_t retry = I2C_RETRY_COUNTER;
|
||||||
bool status = false;
|
bool status = false;
|
||||||
|
#ifdef ESP32
|
||||||
|
TwoWire & myWire = (bus == 0) ? Wire : Wire1;
|
||||||
|
#else
|
||||||
|
TwoWire & myWire = Wire;
|
||||||
|
#endif
|
||||||
|
|
||||||
i2c_buffer = 0;
|
i2c_buffer = 0;
|
||||||
while (!status && retry) {
|
while (!status && retry) {
|
||||||
Wire.beginTransmission(addr); // start transmission to device
|
myWire.beginTransmission(addr); // start transmission to device
|
||||||
Wire.write(reg); // sends register address to read from
|
myWire.write(reg); // sends register address to read from
|
||||||
if (0 == Wire.endTransmission(false)) { // Try to become I2C Master, send data and collect bytes, keep master status for next request...
|
if (0 == myWire.endTransmission(false)) { // Try to become I2C Master, send data and collect bytes, keep master status for next request...
|
||||||
Wire.requestFrom((int)addr, (int)size); // send data n-bytes read
|
myWire.requestFrom((int)addr, (int)size); // send data n-bytes read
|
||||||
if (Wire.available() == size) {
|
if (myWire.available() == size) {
|
||||||
for (uint32_t i = 0; i < size; i++) {
|
for (uint32_t i = 0; i < size; i++) {
|
||||||
i2c_buffer = i2c_buffer << 8 | Wire.read(); // receive DATA
|
i2c_buffer = i2c_buffer << 8 | myWire.read(); // receive DATA
|
||||||
}
|
}
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
retry--;
|
retry--;
|
||||||
}
|
}
|
||||||
if (!retry) Wire.endTransmission();
|
if (!retry) myWire.endTransmission();
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1916,19 +1926,30 @@ int32_t I2cRead24(uint8_t addr, uint8_t reg)
|
||||||
return i2c_buffer;
|
return i2c_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size, uint32_t bus = 0);
|
||||||
|
bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size, uint32_t bus)
|
||||||
|
#else
|
||||||
bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size)
|
bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
uint8_t x = I2C_RETRY_COUNTER;
|
uint8_t x = I2C_RETRY_COUNTER;
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
TwoWire & myWire = (bus == 0) ? Wire : Wire1;
|
||||||
|
#else
|
||||||
|
TwoWire & myWire = Wire;
|
||||||
|
#endif
|
||||||
|
|
||||||
do {
|
do {
|
||||||
Wire.beginTransmission((uint8_t)addr); // start transmission to device
|
myWire.beginTransmission((uint8_t)addr); // start transmission to device
|
||||||
Wire.write(reg); // sends register address to write to
|
myWire.write(reg); // sends register address to write to
|
||||||
uint8_t bytes = size;
|
uint8_t bytes = size;
|
||||||
while (bytes--) {
|
while (bytes--) {
|
||||||
Wire.write((val >> (8 * bytes)) & 0xFF); // write data
|
myWire.write((val >> (8 * bytes)) & 0xFF); // write data
|
||||||
}
|
}
|
||||||
x--;
|
x--;
|
||||||
} while (Wire.endTransmission(true) != 0 && x != 0); // end transmission
|
} while (myWire.endTransmission(true) != 0 && x != 0); // end transmission
|
||||||
return (x);
|
return (x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
|
||||||
|
#include <berry.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
const char kTypeError[] PROGMEM = "type_error";
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void be_dumpstack(bvm *vm) {
|
||||||
|
int32_t top = be_top(vm);
|
||||||
|
AddLog(LOG_LEVEL_INFO, "BRY: top=%d", top);
|
||||||
|
for (uint32_t i = 1; i <= top; i++) {
|
||||||
|
const char * tname = be_typename(vm, i);
|
||||||
|
const char * cname = be_classname(vm, i);
|
||||||
|
AddLog(LOG_LEVEL_INFO, "BRY: stack[%d] = type='%s' (%s)", i, (tname != nullptr) ? tname : "", (cname != nullptr) ? cname : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert to unsigned 8 bits
|
||||||
|
static uint8_t to_u8(int32_t v) {
|
||||||
|
if (v < 0) { return 0; }
|
||||||
|
if (v > 0xFF) { return 0xFF; }
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
static void map_insert_int(bvm *vm, const char *key, int value)
|
||||||
|
{
|
||||||
|
be_pushstring(vm, key);
|
||||||
|
be_pushint(vm, value);
|
||||||
|
be_data_insert(vm, -3);
|
||||||
|
be_pop(vm, 2);
|
||||||
|
}
|
||||||
|
static void map_insert_bool(bvm *vm, const char *key, bool value)
|
||||||
|
{
|
||||||
|
be_pushstring(vm, key);
|
||||||
|
be_pushbool(vm, value);
|
||||||
|
be_data_insert(vm, -3);
|
||||||
|
be_pop(vm, 2);
|
||||||
|
}
|
||||||
|
// if value == NAN, ignore
|
||||||
|
static void map_insert_float(bvm *vm, const char *key, float value)
|
||||||
|
{
|
||||||
|
if (!isnan(value)) {
|
||||||
|
be_pushstring(vm, key);
|
||||||
|
be_pushreal(vm, value);
|
||||||
|
be_data_insert(vm, -3);
|
||||||
|
be_pop(vm, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void map_insert_str(bvm *vm, const char *key, const char *value)
|
||||||
|
{
|
||||||
|
be_pushstring(vm, key);
|
||||||
|
be_pushstring(vm, value);
|
||||||
|
be_data_insert(vm, -3);
|
||||||
|
be_pop(vm, 2);
|
||||||
|
}
|
||||||
|
static void map_insert_list_uint8(bvm *vm, const char *key, const uint8_t *value, size_t size)
|
||||||
|
{
|
||||||
|
be_pushstring(vm, key);
|
||||||
|
|
||||||
|
be_newobject(vm, "list");
|
||||||
|
for (uint32_t i=0; i < size; i++) {
|
||||||
|
be_pushint(vm, value[i]);
|
||||||
|
be_data_push(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
}
|
||||||
|
be_pop(vm, 1); // now list is on top
|
||||||
|
|
||||||
|
be_data_insert(vm, -3); // insert into map, key/value
|
||||||
|
be_pop(vm, 2); // pop both key and value
|
||||||
|
}
|
||||||
|
static bool map_find(bvm *vm, const char *key)
|
||||||
|
{
|
||||||
|
be_getmethod(vm, -1, "find"); // look for "find" method of "Map" instance
|
||||||
|
be_pushvalue(vm, -2); // put back instance as first argument (implicit instance)
|
||||||
|
be_pushstring(vm, key); // push string as second argument
|
||||||
|
be_call(vm, 2); // call wirn 2 parameters (implicit instance and key)
|
||||||
|
be_pop(vm, 2); // pop 2 arguments, the function is replaced by result
|
||||||
|
return !be_isnil(vm, -1); // true if not 'nil'
|
||||||
|
}
|
||||||
|
static int32_t get_list_size(bvm *vm) {
|
||||||
|
be_getmethod(vm, -1, "size"); // look for "size" method of "list" instance
|
||||||
|
be_pushvalue(vm, -2); // put back instance as first argument (implicit instance)
|
||||||
|
be_call(vm, 1); // call wirn 2 parameters (implicit instance and key)
|
||||||
|
int32_t ret = be_toint(vm, -2);
|
||||||
|
be_pop(vm, 2); // pop 1 argument and return value
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// get item number `index` from list, index must be valid or raises an exception
|
||||||
|
static void get_list_item(bvm *vm, int32_t index) {
|
||||||
|
be_getmethod(vm, -1, "item"); // look for "size" method of "list" instance
|
||||||
|
be_pushvalue(vm, -2); // put back instance as first argument (implicit instance)
|
||||||
|
be_pushint(vm, index);
|
||||||
|
// be_dumpstack(vm);
|
||||||
|
be_call(vm, 2); // call wirn 2 parameters (implicit instance and key)
|
||||||
|
be_pop(vm, 2); // pop 2 arguments and return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_BERRY
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
|
||||||
|
#include <berry.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Native functions mapped to Berry functions
|
||||||
|
*
|
||||||
|
* import power
|
||||||
|
*
|
||||||
|
* power.read() -> map
|
||||||
|
*
|
||||||
|
\*********************************************************************************************/
|
||||||
|
extern "C" {
|
||||||
|
#ifdef USE_ENERGY_SENSOR
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
#else // USE_ENERGY_SENSOR
|
||||||
|
//
|
||||||
|
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'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// define weak aliases
|
||||||
|
int32_t b_nrg_read(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_energymissing")));
|
||||||
|
#endif // USE_ENERGY_SENSOR
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // USE_BERRY
|
|
@ -1,534 +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
|
|
||||||
|
|
||||||
#include <berry.h>
|
|
||||||
#include <Wire.h>
|
|
||||||
|
|
||||||
const char kTypeError[] PROGMEM = "type_error";
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Native functions mapped to Berry functions
|
|
||||||
*
|
|
||||||
* log(msg:string [,log_level:int]) ->nil
|
|
||||||
*
|
|
||||||
* import tasmota
|
|
||||||
*
|
|
||||||
* tasmota.getfreeheap() -> int
|
|
||||||
* tasmota.publish(topic:string, payload:string[, retain:bool]) -> nil
|
|
||||||
* tasmota.cmd(command:string) -> string
|
|
||||||
* tasmota.getoption(index:int) -> int
|
|
||||||
* tasmota.millis([delay:int]) -> int
|
|
||||||
* tasmota.timereached(timer:int) -> bool
|
|
||||||
* tasmota.yield() -> nil
|
|
||||||
*
|
|
||||||
\*********************************************************************************************/
|
|
||||||
extern "C" {
|
|
||||||
// Berry: `tasmota.publish(topic, payload [,retain]) -> nil``
|
|
||||||
//
|
|
||||||
int32_t l_publish(struct bvm *vm);
|
|
||||||
int32_t l_publish(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) { // 2 mandatory string arguments
|
|
||||||
if (top == 2 || (top == 3 && be_isbool(vm, 3))) { // 3rd optional argument must be bool
|
|
||||||
const char * topic = be_tostring(vm, 1);
|
|
||||||
const char * payload = be_tostring(vm, 2);
|
|
||||||
bool retain = false;
|
|
||||||
if (top == 3) {
|
|
||||||
retain = be_tobool(vm, 3);
|
|
||||||
}
|
|
||||||
strlcpy(TasmotaGlobal.mqtt_data, payload, sizeof(TasmotaGlobal.mqtt_data));
|
|
||||||
MqttPublish(topic, retain);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `tasmota.cmd(command:string) -> string`
|
|
||||||
//
|
|
||||||
int32_t l_cmd(struct bvm *vm);
|
|
||||||
int32_t l_cmd(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted
|
|
||||||
const char * command = be_tostring(vm, 1);
|
|
||||||
ExecuteCommand(command, SRC_BERRY);
|
|
||||||
be_pushstring(vm, TasmotaGlobal.mqtt_data);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: tasmota.millis([delay:int]) -> int
|
|
||||||
//
|
|
||||||
int32_t l_millis(struct bvm *vm);
|
|
||||||
int32_t l_millis(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 0 || (top == 1 && be_isint(vm, 1))) { // only 1 argument of type string accepted
|
|
||||||
uint32_t delay = 0;
|
|
||||||
if (top == 1) {
|
|
||||||
delay = be_toint(vm, 1);
|
|
||||||
}
|
|
||||||
uint32_t ret_millis = millis() + delay;
|
|
||||||
be_pushint(vm, ret_millis);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: tasmota.getoption(index:int) -> int
|
|
||||||
//
|
|
||||||
int32_t l_getoption(struct bvm *vm);
|
|
||||||
int32_t l_getoption(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 1 && be_isint(vm, 1)) {
|
|
||||||
uint32_t opt = GetOption(be_toint(vm, 1));
|
|
||||||
be_pushint(vm, opt);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: tasmota.timereached(timer:int) -> bool
|
|
||||||
//
|
|
||||||
int32_t l_timereached(struct bvm *vm);
|
|
||||||
int32_t l_timereached(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted
|
|
||||||
uint32_t timer = be_toint(vm, 1);
|
|
||||||
bool reached = TimeReached(timer);
|
|
||||||
be_pushbool(vm, reached);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: tasmota.delay(timer:int) -> nil
|
|
||||||
//
|
|
||||||
int32_t l_delay(struct bvm *vm);
|
|
||||||
int32_t l_delay(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted
|
|
||||||
uint32_t timer = be_toint(vm, 1);
|
|
||||||
delay(timer);
|
|
||||||
be_return_nil(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `yield() -> nil`
|
|
||||||
// ESP object
|
|
||||||
int32_t l_yield(bvm *vm);
|
|
||||||
int32_t l_yield(bvm *vm) {
|
|
||||||
optimistic_yield(10);
|
|
||||||
be_return(vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `save(file:string, f:closure) -> bool`
|
|
||||||
int32_t l_save(struct bvm *vm);
|
|
||||||
int32_t l_save(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top ==2 && be_isstring(vm, 1) && be_isclosure(vm, 2)) { // only 1 argument of type string accepted
|
|
||||||
const char *fname = be_tostring(vm, 1);
|
|
||||||
int32_t ret = be_savecode(vm, fname);
|
|
||||||
be_pushint(vm, ret);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t l_respCmnd(bvm *vm);
|
|
||||||
int32_t l_respCmnd(bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 1) {
|
|
||||||
const char *msg = be_tostring(vm, 1);
|
|
||||||
Response_P("%s", msg);
|
|
||||||
be_return_nil(vm); // Return nil when something goes wrong
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t l_respCmndStr(bvm *vm);
|
|
||||||
int32_t l_respCmndStr(bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 1) {
|
|
||||||
const char *msg = be_tostring(vm, 1);
|
|
||||||
ResponseCmndChar(msg);
|
|
||||||
be_return_nil(vm); // Return nil when something goes wrong
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t l_respCmndDone(bvm *vm);
|
|
||||||
int32_t l_respCmndDone(bvm *vm) {
|
|
||||||
ResponseCmndDone();
|
|
||||||
be_return_nil(vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t l_respCmndError(bvm *vm);
|
|
||||||
int32_t l_respCmndError(bvm *vm) {
|
|
||||||
ResponseCmndError();
|
|
||||||
be_return_nil(vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t l_respCmndFailed(bvm *vm);
|
|
||||||
int32_t l_respCmndFailed(bvm *vm) {
|
|
||||||
ResponseCmndFailed();
|
|
||||||
be_return_nil(vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update XdrvMailbox.command with actual command
|
|
||||||
int32_t l_resolveCmnd(bvm *vm);
|
|
||||||
int32_t l_resolveCmnd(bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 1 && be_isstring(vm, 1)) {
|
|
||||||
const char *msg = be_tostring(vm, 1);
|
|
||||||
strlcpy(XdrvMailbox.command, msg, CMDSZ);
|
|
||||||
be_return_nil(vm); // Return nil when something goes wrong
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void map_insert_int(bvm *vm, const char *key, int value)
|
|
||||||
{
|
|
||||||
be_pushstring(vm, key);
|
|
||||||
be_pushint(vm, value);
|
|
||||||
be_data_insert(vm, -3);
|
|
||||||
be_pop(vm, 2);
|
|
||||||
}
|
|
||||||
static void map_insert_bool(bvm *vm, const char *key, bool value)
|
|
||||||
{
|
|
||||||
be_pushstring(vm, key);
|
|
||||||
be_pushbool(vm, value);
|
|
||||||
be_data_insert(vm, -3);
|
|
||||||
be_pop(vm, 2);
|
|
||||||
}
|
|
||||||
static void map_insert_str(bvm *vm, const char *key, const char *value)
|
|
||||||
{
|
|
||||||
be_pushstring(vm, key);
|
|
||||||
be_pushstring(vm, value);
|
|
||||||
be_data_insert(vm, -3);
|
|
||||||
be_pop(vm, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get light
|
|
||||||
int32_t l_getlight(bvm *vm);
|
|
||||||
int32_t l_getlight(bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 0 || (top == 1 && be_isint(vm, 1))) {
|
|
||||||
int32_t light_num = 0;
|
|
||||||
if (top > 0) {
|
|
||||||
light_num = be_toint(vm, 1);
|
|
||||||
}
|
|
||||||
bool data_present = false; // do we have relevant data
|
|
||||||
be_newobject(vm, "map");
|
|
||||||
// check if the light exist
|
|
||||||
// TasmotaGlobal.devices_present
|
|
||||||
// Light.device
|
|
||||||
// Light.subtype
|
|
||||||
// Light.pwm_multi_channels
|
|
||||||
// light_controller.isCTRGBLinked()
|
|
||||||
|
|
||||||
if (Light.device > 0) {
|
|
||||||
// we have a light
|
|
||||||
|
|
||||||
uint8_t channels[LST_MAX];
|
|
||||||
uint8_t channelsb[LST_MAX];
|
|
||||||
char rgbcw[12] = {0};
|
|
||||||
char rgbcwb[12] = {0};
|
|
||||||
light_state.getChannelsRaw(channels);
|
|
||||||
light_state.getChannels(channelsb);
|
|
||||||
|
|
||||||
// map_insert_int(vm, "_devices_present", TasmotaGlobal.devices_present);
|
|
||||||
// map_insert_int(vm, "_light_device", Light.device);
|
|
||||||
// map_insert_int(vm, "_light_subtype", Light.subtype);
|
|
||||||
// map_insert_int(vm, "_light_multi", Light.pwm_multi_channels);
|
|
||||||
// map_insert_int(vm, "_light_linked", light_controller.isCTRGBLinked());
|
|
||||||
|
|
||||||
if (!Light.pwm_multi_channels) {
|
|
||||||
uint32_t subtype = Light.subtype; // virtual sub-type, for SO37 128
|
|
||||||
uint32_t chanidx = 0; // channel offset, for SO37 128
|
|
||||||
|
|
||||||
|
|
||||||
if (light_controller.isCTRGBLinked() && (light_num == 0)) {
|
|
||||||
data_present = true; // valid combination
|
|
||||||
}
|
|
||||||
if (!light_controller.isCTRGBLinked()) {
|
|
||||||
if (light_num == 0) {
|
|
||||||
data_present = true; // valid combination
|
|
||||||
if (subtype > LST_RGB) { subtype = LST_RGB; } // limit to RGB
|
|
||||||
}
|
|
||||||
if ((light_num == 1) && subtype > LST_RGB) {
|
|
||||||
data_present = true; // valid combination
|
|
||||||
subtype = subtype - LST_RGB;
|
|
||||||
chanidx = 3; // skip first 3 channels
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data_present) {
|
|
||||||
// see ResponseLightState()
|
|
||||||
map_insert_bool(vm, "power", (bool)(Light.power & 1));
|
|
||||||
map_insert_int(vm, "bri", light_state.getBri());
|
|
||||||
|
|
||||||
|
|
||||||
if (subtype >= LST_RGB) {
|
|
||||||
uint16_t hue;
|
|
||||||
uint8_t sat, bri;
|
|
||||||
light_state.getHSB(&hue, &sat, &bri);
|
|
||||||
map_insert_int(vm, "hue", hue);
|
|
||||||
map_insert_int(vm, "sat", sat);
|
|
||||||
}
|
|
||||||
if ((LST_COLDWARM == subtype) || (LST_RGBW <= subtype)) {
|
|
||||||
map_insert_int(vm, "ct", light_state.getCT());
|
|
||||||
}
|
|
||||||
if (subtype > LST_NONE) {
|
|
||||||
for (uint32_t i=0; i < subtype; i++) {
|
|
||||||
snprintf_P(rgbcw, sizeof(rgbcw), PSTR("%s%02X"), rgbcw, channels[i+chanidx]);
|
|
||||||
snprintf_P(rgbcwb, sizeof(rgbcwb), PSTR("%s%02X"), rgbcwb, channelsb[i+chanidx]);
|
|
||||||
}
|
|
||||||
map_insert_str(vm, "channels", rgbcw);
|
|
||||||
map_insert_str(vm, "channelsb", rgbcwb);
|
|
||||||
// map_insert_bool(vm, "gamma", Settings.light_correction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // Light.pwm_multi_channels
|
|
||||||
if ((light_num >= 0) && (light_num < LST_MAX)) {
|
|
||||||
data_present = true;
|
|
||||||
map_insert_bool(vm, "power", Light.power & (1 << light_num));
|
|
||||||
map_insert_int(vm, "bri", Light.current_color[light_num]);
|
|
||||||
snprintf_P(rgbcw, sizeof(rgbcw), PSTR("%02X"), channels[light_num]);
|
|
||||||
snprintf_P(rgbcwb, sizeof(rgbcwb), PSTR("%02X"), channelsb[light_num]);
|
|
||||||
map_insert_str(vm, "channels", rgbcw);
|
|
||||||
map_insert_str(vm, "channelsb", rgbcwb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
be_pop(vm, 1);
|
|
||||||
if (data_present) {
|
|
||||||
be_return(vm); // Return
|
|
||||||
} else {
|
|
||||||
be_return_nil(vm); // no data, return nil instead of empty map
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
be_return_nil(vm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Native functions mapped to Berry functions
|
|
||||||
*
|
|
||||||
* import wire
|
|
||||||
*
|
|
||||||
* wire.getfreeheap() -> int
|
|
||||||
*
|
|
||||||
\*********************************************************************************************/
|
|
||||||
extern "C" {
|
|
||||||
// Berry: `begintransmission(address:int) -> nil`
|
|
||||||
int32_t b_wire_begintransmission(struct bvm *vm);
|
|
||||||
int32_t b_wire_begintransmission(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted
|
|
||||||
int32_t address = be_toint(vm, 1);
|
|
||||||
Wire.beginTransmission(address);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `endtransmission([stop:bool]) -> nil`
|
|
||||||
int32_t b_wire_endtransmission(struct bvm *vm);
|
|
||||||
int32_t b_wire_endtransmission(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 0 || (top == 1 && be_isbool(vm, 1))) { // only 1 argument of type string accepted
|
|
||||||
bool stop = true;
|
|
||||||
if (top == 1) {
|
|
||||||
stop = be_tobool(vm, 1);
|
|
||||||
}
|
|
||||||
uint32_t ret = Wire.endTransmission(stop);
|
|
||||||
be_pushint(vm, ret);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `requestfrom(address:int, quantity:int [stop:bool = true]) -> nil`
|
|
||||||
int32_t b_wire_requestfrom(struct bvm *vm);
|
|
||||||
int32_t b_wire_requestfrom(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if ( (top == 2 || (top == 3 && be_isbool(vm, 3)))
|
|
||||||
&& be_isint(vm, 1) && be_isint(vm, 2) ) {
|
|
||||||
int32_t address = be_toint(vm, 1);
|
|
||||||
int32_t quantity = be_toint(vm, 2);
|
|
||||||
bool stop = true;
|
|
||||||
if (top == 3) {
|
|
||||||
stop = be_tobool(vm, 3);
|
|
||||||
}
|
|
||||||
Wire.requestFrom((uint16_t)address, (uint8_t)quantity, stop);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `available() -> bool`
|
|
||||||
int32_t b_wire_available(struct bvm *vm);
|
|
||||||
int32_t b_wire_available(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 0) {
|
|
||||||
size_t available = Wire.available();
|
|
||||||
be_pushint(vm, available);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `write(value:int | s:string) -> nil`
|
|
||||||
int32_t b_wire_write(struct bvm *vm);
|
|
||||||
int32_t b_wire_write(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 1 && (be_isint(vm, 1) || be_isstring(vm, 1))) {
|
|
||||||
if (be_isint(vm, 1)) {
|
|
||||||
int32_t value = be_toint(vm, 1);
|
|
||||||
Wire.write(value);
|
|
||||||
} else if (be_isstring(vm, 1)) {
|
|
||||||
const char * s = be_tostring(vm, 1);
|
|
||||||
Wire.write(s);
|
|
||||||
} else {
|
|
||||||
be_return_nil(vm);
|
|
||||||
}
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `read() -> int`
|
|
||||||
int32_t b_wire_read(struct bvm *vm);
|
|
||||||
int32_t b_wire_read(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 0) {
|
|
||||||
int32_t value = Wire.read();
|
|
||||||
be_pushint(vm, value);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t b_wire_scan(struct bvm *vm);
|
|
||||||
int32_t b_wire_scan(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 0) {
|
|
||||||
be_newobject(vm, "list");
|
|
||||||
for (uint8_t address = 1; address <= 127; address++) {
|
|
||||||
Wire.beginTransmission(address);
|
|
||||||
int32_t error = Wire.endTransmission();
|
|
||||||
if (0 == error) {
|
|
||||||
be_pushint(vm, address);
|
|
||||||
be_data_push(vm, -2);
|
|
||||||
be_pop(vm, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
be_pop(vm, 1);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `validwrite(address:int, reg:int, val:int, size:int) -> bool or nil`
|
|
||||||
int32_t b_wire_validwrite(struct bvm *vm);
|
|
||||||
int32_t b_wire_validwrite(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 4 && be_isint(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4)) {
|
|
||||||
uint8_t addr = be_toint(vm, 1);
|
|
||||||
uint8_t reg = be_toint(vm, 2);
|
|
||||||
uint8_t val = be_toint(vm, 3);
|
|
||||||
uint8_t size = be_toint(vm, 4);
|
|
||||||
bool ok = I2cWrite(addr, reg, val, size);
|
|
||||||
be_pushbool(vm, ok);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `validread(address:int, reg:int, size:int) -> int or nil`
|
|
||||||
int32_t b_wire_validread(struct bvm *vm);
|
|
||||||
int32_t b_wire_validread(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top == 3 && be_isint(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3)) {
|
|
||||||
uint8_t addr = be_toint(vm, 1);
|
|
||||||
uint8_t reg = be_toint(vm, 2);
|
|
||||||
uint8_t size = be_toint(vm, 3);
|
|
||||||
bool ok = I2cValidRead(addr, reg, size);
|
|
||||||
if (ok) {
|
|
||||||
be_pushint(vm, i2c_buffer);
|
|
||||||
} else {
|
|
||||||
be_pushnil(vm);
|
|
||||||
}
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Native functions mapped to Berry functions
|
|
||||||
*
|
|
||||||
* log(msg:string [,log_level:int]) ->nil
|
|
||||||
*
|
|
||||||
\*********************************************************************************************/
|
|
||||||
extern "C" {
|
|
||||||
// Berry: `log(msg:string [,log_level:int]) ->nil`
|
|
||||||
// Logs the string at LOG_LEVEL_INFO (loglevel=2)
|
|
||||||
int32_t l_logInfo(struct bvm *vm);
|
|
||||||
int32_t l_logInfo(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top >= 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted
|
|
||||||
const char * msg = be_tostring(vm, 1);
|
|
||||||
uint32_t log_level = LOG_LEVEL_INFO;
|
|
||||||
if (top >= 2 && be_isint(vm, 2)) {
|
|
||||||
log_level = be_toint(vm, 2);
|
|
||||||
if (log_level > LOG_LEVEL_DEBUG_MORE) { log_level = LOG_LEVEL_DEBUG_MORE; }
|
|
||||||
}
|
|
||||||
AddLog(log_level, PSTR("%s"), msg);
|
|
||||||
be_return(vm); // Return
|
|
||||||
}
|
|
||||||
be_return_nil(vm); // Return nil when something goes wrong
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `getFreeHeap() -> int`
|
|
||||||
// ESP object
|
|
||||||
int32_t l_getFreeHeap(bvm *vm);
|
|
||||||
int32_t l_getFreeHeap(bvm *vm) {
|
|
||||||
be_pushint(vm, ESP.getFreeHeap());
|
|
||||||
be_return(vm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// called as a replacement to Berry `print()`
|
|
||||||
void berry_log(const char * berry_buf);
|
|
||||||
void berry_log(const char * berry_buf) {
|
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // USE_BERRY
|
|
|
@ -0,0 +1,529 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
|
||||||
|
#include <berry.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Native functions mapped to Berry functions
|
||||||
|
*
|
||||||
|
* log(msg:string [,log_level:int]) ->nil
|
||||||
|
*
|
||||||
|
* import tasmota
|
||||||
|
*
|
||||||
|
* tasmota.getfreeheap() -> int
|
||||||
|
* tasmota.publish(topic:string, payload:string[, retain:bool]) -> nil
|
||||||
|
* tasmota.cmd(command:string) -> string
|
||||||
|
* tasmota.getoption(index:int) -> int
|
||||||
|
* tasmota.millis([delay:int]) -> int
|
||||||
|
* tasmota.timereached(timer:int) -> bool
|
||||||
|
* tasmota.yield() -> nil
|
||||||
|
*
|
||||||
|
* tasmota.getlight([index:int = 0]) -> map
|
||||||
|
* tasmota.getpower([index:int = 0]) -> bool
|
||||||
|
* tasmota.setpower(idx:int, power:bool) -> bool or nil
|
||||||
|
* tasmota.setlight(idx:int, values:map) -> map
|
||||||
|
*
|
||||||
|
\*********************************************************************************************/
|
||||||
|
extern "C" {
|
||||||
|
// Berry: `tasmota.publish(topic, payload [,retain]) -> nil``
|
||||||
|
//
|
||||||
|
int32_t l_publish(struct bvm *vm);
|
||||||
|
int32_t l_publish(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top >= 3 && be_isstring(vm, 2) && be_isstring(vm, 3)) { // 2 mandatory string arguments
|
||||||
|
if (top == 3 || (top == 4 && be_isbool(vm, 4))) { // 3rd optional argument must be bool
|
||||||
|
const char * topic = be_tostring(vm, 2);
|
||||||
|
const char * payload = be_tostring(vm, 3);
|
||||||
|
bool retain = false;
|
||||||
|
if (top == 4) {
|
||||||
|
retain = be_tobool(vm, 4);
|
||||||
|
}
|
||||||
|
strlcpy(TasmotaGlobal.mqtt_data, payload, sizeof(TasmotaGlobal.mqtt_data));
|
||||||
|
MqttPublish(topic, retain);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `tasmota.cmd(command:string) -> string`
|
||||||
|
//
|
||||||
|
int32_t l_cmd(struct bvm *vm);
|
||||||
|
int32_t l_cmd(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 2 && be_isstring(vm, 2)) { // only 1 argument of type string accepted
|
||||||
|
const char * command = be_tostring(vm, 2);
|
||||||
|
ExecuteCommand(command, SRC_BERRY);
|
||||||
|
be_pushstring(vm, TasmotaGlobal.mqtt_data);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: tasmota.millis([delay:int]) -> int
|
||||||
|
//
|
||||||
|
int32_t l_millis(struct bvm *vm);
|
||||||
|
int32_t l_millis(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 1 || (top == 2 && be_isint(vm, 2))) { // only 1 argument of type string accepted
|
||||||
|
uint32_t delay = 0;
|
||||||
|
if (top == 2) {
|
||||||
|
delay = be_toint(vm, 2);
|
||||||
|
}
|
||||||
|
uint32_t ret_millis = millis() + delay;
|
||||||
|
be_pushint(vm, ret_millis);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: tasmota.getoption(index:int) -> int
|
||||||
|
//
|
||||||
|
int32_t l_getoption(struct bvm *vm);
|
||||||
|
int32_t l_getoption(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 2 && be_isint(vm, 2)) {
|
||||||
|
uint32_t opt = GetOption(be_toint(vm, 2));
|
||||||
|
be_pushint(vm, opt);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: tasmota.timereached(timer:int) -> bool
|
||||||
|
//
|
||||||
|
int32_t l_timereached(struct bvm *vm);
|
||||||
|
int32_t l_timereached(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 2 && be_isint(vm, 2)) { // only 1 argument of type string accepted
|
||||||
|
uint32_t timer = be_toint(vm, 2);
|
||||||
|
bool reached = TimeReached(timer);
|
||||||
|
be_pushbool(vm, reached);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: tasmota.delay(timer:int) -> nil
|
||||||
|
//
|
||||||
|
int32_t l_delay(struct bvm *vm);
|
||||||
|
int32_t l_delay(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 2 && be_isint(vm, 2)) { // only 1 argument of type string accepted
|
||||||
|
uint32_t timer = be_toint(vm, 2);
|
||||||
|
delay(timer);
|
||||||
|
be_return_nil(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `yield() -> nil`
|
||||||
|
// ESP object
|
||||||
|
int32_t l_yield(bvm *vm);
|
||||||
|
int32_t l_yield(bvm *vm) {
|
||||||
|
optimistic_yield(10);
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: tasmota.scaleuint(int * 5) -> int
|
||||||
|
//
|
||||||
|
int32_t l_scaleuint(struct bvm *vm);
|
||||||
|
int32_t l_scaleuint(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 6 && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4) && be_isint(vm, 5) && be_isint(vm, 6)) { // only 1 argument of type string accepted
|
||||||
|
int32_t v = be_toint(vm, 2);
|
||||||
|
int32_t from1 = be_toint(vm, 3);
|
||||||
|
int32_t from2 = be_toint(vm, 4);
|
||||||
|
int32_t to1 = be_toint(vm, 5);
|
||||||
|
int32_t to2 = be_toint(vm, 6);
|
||||||
|
|
||||||
|
int32_t ret = changeUIntScale(v, from1, from2, to1, to2);
|
||||||
|
be_pushint(vm, ret);
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t l_respCmnd(bvm *vm);
|
||||||
|
int32_t l_respCmnd(bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 2) {
|
||||||
|
const char *msg = be_tostring(vm, 2);
|
||||||
|
Response_P("%s", msg);
|
||||||
|
be_return_nil(vm); // Return nil when something goes wrong
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t l_respCmndStr(bvm *vm);
|
||||||
|
int32_t l_respCmndStr(bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 2) {
|
||||||
|
const char *msg = be_tostring(vm, 2);
|
||||||
|
ResponseCmndChar(msg);
|
||||||
|
be_return_nil(vm); // Return nil when something goes wrong
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t l_respCmndDone(bvm *vm);
|
||||||
|
int32_t l_respCmndDone(bvm *vm) {
|
||||||
|
ResponseCmndDone();
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t l_respCmndError(bvm *vm);
|
||||||
|
int32_t l_respCmndError(bvm *vm) {
|
||||||
|
ResponseCmndError();
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t l_respCmndFailed(bvm *vm);
|
||||||
|
int32_t l_respCmndFailed(bvm *vm) {
|
||||||
|
ResponseCmndFailed();
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update XdrvMailbox.command with actual command
|
||||||
|
int32_t l_resolveCmnd(bvm *vm);
|
||||||
|
int32_t l_resolveCmnd(bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 2 && be_isstring(vm, 2)) {
|
||||||
|
const char *msg = be_tostring(vm, 2);
|
||||||
|
strlcpy(XdrvMailbox.command, msg, CMDSZ);
|
||||||
|
be_return_nil(vm); // Return nil when something goes wrong
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// push the light status object on the vm stack
|
||||||
|
void push_getlight(bvm *vm, uint32_t light_num) {
|
||||||
|
bool data_present = false; // do we have relevant data
|
||||||
|
be_newobject(vm, "map");
|
||||||
|
// check if the light exist
|
||||||
|
// TasmotaGlobal.devices_present
|
||||||
|
// Light.device
|
||||||
|
// Light.subtype
|
||||||
|
// Light.pwm_multi_channels
|
||||||
|
// light_controller.isCTRGBLinked()
|
||||||
|
|
||||||
|
if (Light.device > 0) {
|
||||||
|
// we have a light
|
||||||
|
|
||||||
|
uint8_t channels[LST_MAX];
|
||||||
|
char s_rgb[8] = {0}; // RGB raw levels
|
||||||
|
light_controller.calcLevels(channels);
|
||||||
|
uint8_t bri = light_state.getBri();
|
||||||
|
|
||||||
|
// map_insert_int(vm, "_devices_present", TasmotaGlobal.devices_present);
|
||||||
|
// map_insert_int(vm, "_light_device", Light.device);
|
||||||
|
// map_insert_int(vm, "_light_subtype", Light.subtype);
|
||||||
|
// map_insert_int(vm, "_light_multi", Light.pwm_multi_channels);
|
||||||
|
// map_insert_int(vm, "_light_linked", light_controller.isCTRGBLinked());
|
||||||
|
|
||||||
|
if (!Light.pwm_multi_channels) {
|
||||||
|
uint32_t subtype = Light.subtype; // virtual sub-type, for SO37 128
|
||||||
|
uint32_t chanidx = 0; // channel offset, for SO37 128
|
||||||
|
|
||||||
|
|
||||||
|
if (light_controller.isCTRGBLinked() && (light_num == 0)) {
|
||||||
|
data_present = true; // valid combination
|
||||||
|
if (subtype >= LST_RGBW) {
|
||||||
|
map_insert_str(vm, "colormode", (light_state.getColorMode() & LCM_RGB ? "rgb" : "ct"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!light_controller.isCTRGBLinked()) {
|
||||||
|
if (light_num == 0) {
|
||||||
|
data_present = true; // valid combination
|
||||||
|
if (subtype > LST_RGB) { subtype = LST_RGB; } // limit to RGB
|
||||||
|
bri = light_state.getBriRGB();
|
||||||
|
}
|
||||||
|
if ((light_num == 1) && subtype > LST_RGB) {
|
||||||
|
data_present = true; // valid combination
|
||||||
|
subtype = subtype - LST_RGB;
|
||||||
|
chanidx = 3; // skip first 3 channels
|
||||||
|
bri = light_state.getBriCT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_present) {
|
||||||
|
// see ResponseLightState()
|
||||||
|
map_insert_bool(vm, "power", bitRead(TasmotaGlobal.power, light_num));
|
||||||
|
map_insert_int(vm, "bri", bri);
|
||||||
|
|
||||||
|
if (subtype >= LST_RGB) {
|
||||||
|
uint16_t hue;
|
||||||
|
uint8_t sat, bri;
|
||||||
|
light_state.getHSB(&hue, &sat, &bri);
|
||||||
|
map_insert_int(vm, "hue", hue);
|
||||||
|
map_insert_int(vm, "sat", sat);
|
||||||
|
}
|
||||||
|
if ((LST_COLDWARM == subtype) || (LST_RGBW <= subtype)) {
|
||||||
|
map_insert_int(vm, "ct", light_state.getCT());
|
||||||
|
}
|
||||||
|
if (subtype >= LST_RGB) {
|
||||||
|
snprintf(s_rgb, sizeof(s_rgb), PSTR("%02X%02X%02X"), channels[0], channels[1], channels[2]);
|
||||||
|
map_insert_str(vm, "rgb", s_rgb);
|
||||||
|
}
|
||||||
|
if (subtype > LST_NONE) {
|
||||||
|
map_insert_list_uint8(vm, "channels", &channels[chanidx], subtype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // Light.pwm_multi_channels
|
||||||
|
if ((light_num >= 0) && (light_num < LST_MAX)) {
|
||||||
|
data_present = true;
|
||||||
|
map_insert_bool(vm, "power", Light.power & (1 << light_num));
|
||||||
|
map_insert_int(vm, "bri", Light.current_color[light_num]);
|
||||||
|
map_insert_list_uint8(vm, "channels", &channels[light_num], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
be_pop(vm, 1);
|
||||||
|
if (!data_present) {
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_pushnil(vm);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_pushnil(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get light
|
||||||
|
int32_t l_getlight(bvm *vm);
|
||||||
|
int32_t l_getlight(bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 1 || (top == 2 && be_isint(vm, 2))) {
|
||||||
|
int32_t light_num = 0;
|
||||||
|
if (top > 0) {
|
||||||
|
light_num = be_toint(vm, 2);
|
||||||
|
}
|
||||||
|
push_getlight(vm, light_num);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set light
|
||||||
|
int32_t l_setlight(bvm *vm);
|
||||||
|
int32_t l_setlight(bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top >= 2 && be_isinstance(vm, 2) && (top != 3 || be_isint(vm, 3))) {
|
||||||
|
int32_t idx = 0;
|
||||||
|
if (top >= 3) {
|
||||||
|
idx = be_toint(vm, 3);
|
||||||
|
be_pop(vm, 1); // remove last argument to have the map at the top of stack
|
||||||
|
}
|
||||||
|
|
||||||
|
// power
|
||||||
|
if (map_find(vm, "power")) {
|
||||||
|
bool power = be_tobool(vm, -1);
|
||||||
|
bool current_power = bitRead(TasmotaGlobal.power, idx);
|
||||||
|
if (power != current_power) { // only send command if needed
|
||||||
|
ExecuteCommandPower(Light.device + idx, (power) ? POWER_ON : POWER_OFF, SRC_BERRY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
// ct
|
||||||
|
if (map_find(vm, "ct")) {
|
||||||
|
int32_t ct = be_toint(vm, -1);
|
||||||
|
light_controller.changeCTB(ct, light_state.getBriCT());
|
||||||
|
}
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
// hue
|
||||||
|
if (map_find(vm, "hue")) {
|
||||||
|
int32_t hue = be_toint(vm, -1);
|
||||||
|
uint8_t sat;
|
||||||
|
uint8_t bri;
|
||||||
|
light_state.getHSB(nullptr, &sat, &bri);
|
||||||
|
light_controller.changeHSB(hue, sat, bri);
|
||||||
|
}
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
// sat
|
||||||
|
if (map_find(vm, "sat")) {
|
||||||
|
int32_t sat = be_toint(vm, -1);
|
||||||
|
uint16_t hue;
|
||||||
|
uint8_t bri;
|
||||||
|
light_state.getHSB(&hue, nullptr, &bri);
|
||||||
|
light_controller.changeHSB(hue, sat, bri);
|
||||||
|
}
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
// rgb
|
||||||
|
if (map_find(vm, "rgb")) {
|
||||||
|
const char * rgb_s = be_tostring(vm, -1);
|
||||||
|
SBuffer buf = SBuffer::SBufferFromHex(rgb_s, strlen(rgb_s));
|
||||||
|
uint8_t channels[LST_MAX] = {};
|
||||||
|
memcpy(channels, buf.buf(), buf.len() > LST_MAX ? LST_MAX : buf.len());
|
||||||
|
bool on = false; // if all are zero, then only set power off
|
||||||
|
for (uint32_t i = 0; i < LST_MAX; i++) {
|
||||||
|
if (channels[i] != 0) { on = true; }
|
||||||
|
}
|
||||||
|
if (on) {
|
||||||
|
light_controller.changeChannels(channels);
|
||||||
|
} else {
|
||||||
|
ExecuteCommandPower(idx + 1, POWER_OFF, SRC_BERRY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
// channels
|
||||||
|
if (map_find(vm, "channels")) {
|
||||||
|
if (be_isinstance(vm, -1)) {
|
||||||
|
be_getbuiltin(vm, "list"); // add "list" class
|
||||||
|
if (be_isderived(vm, -2)) {
|
||||||
|
be_pop(vm, 1); // remove "list" class from top
|
||||||
|
int32_t list_size = get_list_size(vm);
|
||||||
|
// AddLog(LOG_LEVEL_INFO, "Instance is list size = %d", list_size);
|
||||||
|
|
||||||
|
uint8_t channels[LST_MAX] = {}; // initialized with all zeroes
|
||||||
|
if (list_size > LST_MAX) { list_size = LST_MAX; } // no more than 5 channels, no need to test for positive, any negative will be discarded by loop
|
||||||
|
for (uint32_t i = 0; i < list_size; i++) {
|
||||||
|
// be_dumpstack(vm);
|
||||||
|
get_list_item(vm, i);
|
||||||
|
// be_dumpstack(vm);
|
||||||
|
int32_t val = be_toint(vm, -1);
|
||||||
|
be_pop(vm, 1); // remove result from stack
|
||||||
|
channels[i] = to_u8(val);
|
||||||
|
|
||||||
|
bool on = false; // if all are zero, then only set power off
|
||||||
|
for (uint32_t i = 0; i < LST_MAX; i++) {
|
||||||
|
if (channels[i] != 0) { on = true; }
|
||||||
|
}
|
||||||
|
if (on) {
|
||||||
|
light_controller.changeChannels(channels);
|
||||||
|
} else {
|
||||||
|
ExecuteCommandPower(idx + 1, POWER_OFF, SRC_BERRY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
be_pop(vm, 1); // remove "list" class from top
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
// bri is done after channels and rgb
|
||||||
|
// bri
|
||||||
|
if (map_find(vm, "bri")) {
|
||||||
|
int32_t bri = be_toint(vm, -1);
|
||||||
|
light_controller.changeBri(bri);
|
||||||
|
}
|
||||||
|
be_pop(vm, 1);
|
||||||
|
|
||||||
|
push_getlight(vm, idx);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
} // TODO
|
||||||
|
|
||||||
|
// get power
|
||||||
|
int32_t l_getpower(bvm *vm);
|
||||||
|
int32_t l_getpower(bvm *vm) {
|
||||||
|
be_newobject(vm, "list");
|
||||||
|
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) {
|
||||||
|
be_pushbool(vm, bitRead(TasmotaGlobal.power, i));
|
||||||
|
be_data_push(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
}
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t l_setpower(bvm *vm);
|
||||||
|
int32_t l_setpower(bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 3 && be_isint(vm, 2) && be_isbool(vm, 3)) {
|
||||||
|
int32_t idx = be_toint(vm, 2);
|
||||||
|
bool power = be_tobool(vm, 3);
|
||||||
|
if ((idx >= 0) && (idx < TasmotaGlobal.devices_present)) {
|
||||||
|
ExecuteCommandPower(idx + 1, (power) ? POWER_ON : POWER_OFF, SRC_BERRY);
|
||||||
|
be_pushbool(vm, power);
|
||||||
|
be_return(vm); // Return
|
||||||
|
} else {
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Native functions mapped to Berry functions
|
||||||
|
*
|
||||||
|
* log(msg:string [,log_level:int]) ->nil
|
||||||
|
*
|
||||||
|
\*********************************************************************************************/
|
||||||
|
extern "C" {
|
||||||
|
// Berry: `log(msg:string [,log_level:int]) ->nil`
|
||||||
|
// Logs the string at LOG_LEVEL_INFO (loglevel=2)
|
||||||
|
int32_t l_logInfo(struct bvm *vm);
|
||||||
|
int32_t l_logInfo(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top >= 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted
|
||||||
|
const char * msg = be_tostring(vm, 1);
|
||||||
|
uint32_t log_level = LOG_LEVEL_INFO;
|
||||||
|
if (top >= 2 && be_isint(vm, 2)) {
|
||||||
|
log_level = be_toint(vm, 2);
|
||||||
|
if (log_level > LOG_LEVEL_DEBUG_MORE) { log_level = LOG_LEVEL_DEBUG_MORE; }
|
||||||
|
}
|
||||||
|
AddLog(log_level, PSTR("%s"), msg);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_return_nil(vm); // Return nil when something goes wrong
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `getFreeHeap() -> int`
|
||||||
|
// ESP object
|
||||||
|
int32_t l_getFreeHeap(bvm *vm);
|
||||||
|
int32_t l_getFreeHeap(bvm *vm) {
|
||||||
|
be_pushint(vm, ESP.getFreeHeap());
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `save(file:string, f:closure) -> bool`
|
||||||
|
int32_t l_save(struct bvm *vm);
|
||||||
|
int32_t l_save(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top == 2 && be_isstring(vm, 1) && be_isclosure(vm, 2)) { // only 1 argument of type string accepted
|
||||||
|
const char *fname = be_tostring(vm, 1);
|
||||||
|
int32_t ret = be_savecode(vm, fname);
|
||||||
|
be_pushint(vm, ret);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// called as a replacement to Berry `print()`
|
||||||
|
void berry_log(const char * berry_buf);
|
||||||
|
void berry_log(const char * berry_buf) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // USE_BERRY
|
|
@ -0,0 +1,245 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
|
||||||
|
#include <berry.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
// read the `_bus` attribute and return `Wire` or `Wire1`
|
||||||
|
TwoWire & getWire(bvm *vm);
|
||||||
|
TwoWire & getWire(bvm *vm) {
|
||||||
|
be_getmember(vm, 1, "_bus");
|
||||||
|
int32_t bus = be_toint(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
if (0 == bus) {
|
||||||
|
return Wire;
|
||||||
|
} else {
|
||||||
|
return Wire1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int32_t getBus(bvm *vm);
|
||||||
|
int32_t getBus(bvm *vm) {
|
||||||
|
be_getmember(vm, 1, "_bus");
|
||||||
|
int32_t bus = be_toint(vm, -1);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
return bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Native functions mapped to Berry functions
|
||||||
|
*
|
||||||
|
* import wire
|
||||||
|
*
|
||||||
|
* wire.getfreeheap() -> int
|
||||||
|
*
|
||||||
|
\*********************************************************************************************/
|
||||||
|
extern "C" {
|
||||||
|
#ifdef USE_I2C
|
||||||
|
// Berry: `init([bus:int = 0]) -> nil
|
||||||
|
int32_t b_wire_init(struct bvm *vm);
|
||||||
|
int32_t b_wire_init(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
int32_t bus = 0;
|
||||||
|
if (top > 1 && be_isint(vm, 2)) {
|
||||||
|
bus = be_toint(vm, 2);
|
||||||
|
if (bus < 0) { bus = 0; }
|
||||||
|
if (bus > 1) { bus = 1; }
|
||||||
|
}
|
||||||
|
// store bus in instance
|
||||||
|
be_pushint(vm, bus);
|
||||||
|
be_setmember(vm, 1, "_bus");
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `begintransmission(address:int) -> nil`
|
||||||
|
int32_t b_wire_begintransmission(struct bvm *vm);
|
||||||
|
int32_t b_wire_begintransmission(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
TwoWire & myWire = getWire(vm);
|
||||||
|
if (top == 2 && be_isint(vm, 2)) { // only 1 argument of type string accepted
|
||||||
|
int32_t address = be_toint(vm, 2);
|
||||||
|
myWire.beginTransmission(address);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `endtransmission([stop:bool]) -> nil`
|
||||||
|
int32_t b_wire_endtransmission(struct bvm *vm);
|
||||||
|
int32_t b_wire_endtransmission(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
TwoWire & myWire = getWire(vm);
|
||||||
|
if (top == 1 || (top == 2 && be_isbool(vm, 2))) { // only 1 argument of type string accepted
|
||||||
|
bool stop = true;
|
||||||
|
if (top == 1) {
|
||||||
|
stop = be_tobool(vm, 2);
|
||||||
|
}
|
||||||
|
uint32_t ret = myWire.endTransmission(stop);
|
||||||
|
be_pushint(vm, ret);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `requestfrom(address:int, quantity:int [stop:bool = true]) -> nil`
|
||||||
|
int32_t b_wire_requestfrom(struct bvm *vm);
|
||||||
|
int32_t b_wire_requestfrom(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
TwoWire & myWire = getWire(vm);
|
||||||
|
if ( (top == 3 || (top == 4 && be_isbool(vm, 4)))
|
||||||
|
&& be_isint(vm, 2) && be_isint(vm, 3) ) {
|
||||||
|
int32_t address = be_toint(vm, 2);
|
||||||
|
int32_t quantity = be_toint(vm, 3);
|
||||||
|
bool stop = true;
|
||||||
|
if (top == 4) {
|
||||||
|
stop = be_tobool(vm, 4);
|
||||||
|
}
|
||||||
|
myWire.requestFrom((uint16_t)address, (uint8_t)quantity, stop);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `available() -> bool`
|
||||||
|
int32_t b_wire_available(struct bvm *vm);
|
||||||
|
int32_t b_wire_available(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
TwoWire & myWire = getWire(vm);
|
||||||
|
if (top == 1) {
|
||||||
|
size_t available = myWire.available();
|
||||||
|
be_pushint(vm, available);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `write(value:int | s:string) -> nil`
|
||||||
|
int32_t b_wire_write(struct bvm *vm);
|
||||||
|
int32_t b_wire_write(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
TwoWire & myWire = getWire(vm);
|
||||||
|
if (top == 2 && (be_isint(vm, 2) || be_isstring(vm, 2))) {
|
||||||
|
if (be_isint(vm, 2)) {
|
||||||
|
int32_t value = be_toint(vm, 2);
|
||||||
|
myWire.write(value);
|
||||||
|
} else if (be_isstring(vm, 2)) {
|
||||||
|
const char * s = be_tostring(vm, 1);
|
||||||
|
myWire.write(s);
|
||||||
|
} else {
|
||||||
|
be_return_nil(vm);
|
||||||
|
}
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `read() -> int`
|
||||||
|
int32_t b_wire_read(struct bvm *vm);
|
||||||
|
int32_t b_wire_read(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
TwoWire & myWire = getWire(vm);
|
||||||
|
if (top == 1) {
|
||||||
|
int32_t value = myWire.read();
|
||||||
|
be_pushint(vm, value);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t b_wire_scan(struct bvm *vm);
|
||||||
|
int32_t b_wire_scan(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
TwoWire & myWire = getWire(vm);
|
||||||
|
if (top == 1) {
|
||||||
|
be_newobject(vm, "list");
|
||||||
|
for (uint8_t address = 1; address <= 127; address++) {
|
||||||
|
myWire.beginTransmission(address);
|
||||||
|
int32_t error = myWire.endTransmission();
|
||||||
|
if (0 == error) {
|
||||||
|
be_pushint(vm, address);
|
||||||
|
be_data_push(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `validwrite(address:int, reg:int, val:int, size:int) -> bool or nil`
|
||||||
|
int32_t b_wire_validwrite(struct bvm *vm);
|
||||||
|
int32_t b_wire_validwrite(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
int32_t bus = getBus(vm);
|
||||||
|
if (top == 5 && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4) && be_isint(vm, 5)) {
|
||||||
|
uint8_t addr = be_toint(vm, 2);
|
||||||
|
uint8_t reg = be_toint(vm, 3);
|
||||||
|
uint8_t val = be_toint(vm, 4);
|
||||||
|
uint8_t size = be_toint(vm, 5);
|
||||||
|
bool ok = I2cWrite(addr, reg, val, size, bus);
|
||||||
|
be_pushbool(vm, ok);
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Berry: `validread(address:int, reg:int, size:int) -> int or nil`
|
||||||
|
int32_t b_wire_validread(struct bvm *vm);
|
||||||
|
int32_t b_wire_validread(struct bvm *vm) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
int32_t bus = getBus(vm);
|
||||||
|
if (top == 4 && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4)) {
|
||||||
|
uint8_t addr = be_toint(vm, 2);
|
||||||
|
uint8_t reg = be_toint(vm, 3);
|
||||||
|
uint8_t size = be_toint(vm, 4);
|
||||||
|
bool ok = I2cValidRead(addr, reg, size); // TODO
|
||||||
|
if (ok) {
|
||||||
|
be_pushint(vm, i2c_buffer);
|
||||||
|
} else {
|
||||||
|
be_pushnil(vm);
|
||||||
|
}
|
||||||
|
be_return(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
#else // USE_I2C
|
||||||
|
//
|
||||||
|
int32_t b_wire_i2cmissing(struct bvm *vm);
|
||||||
|
int32_t b_wire_i2cmissing(struct bvm *vm) {
|
||||||
|
be_raise(vm, "feature_error", "I2C is not enabled, use '#define USE_I2C'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// define weak aliases
|
||||||
|
int32_t b_wire_init(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||||
|
int32_t b_wire_begintransmission(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||||
|
int32_t b_wire_endtransmission(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||||
|
int32_t b_wire_requestfrom(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||||
|
int32_t b_wire_available(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||||
|
int32_t b_wire_write(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||||
|
int32_t b_wire_read(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||||
|
int32_t b_wire_scan(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||||
|
int32_t b_wire_validwrite(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||||
|
int32_t b_wire_validread(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||||
|
#endif // USE_I2C
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_BERRY
|
|
@ -32,60 +32,33 @@ const char berry_prog[] =
|
||||||
//"def noop() log('noop before'); yield(); log('middle after'); yield(); log('noop after'); end "
|
//"def noop() log('noop before'); yield(); log('middle after'); yield(); log('noop after'); end "
|
||||||
//"log(\"foobar\") "
|
//"log(\"foobar\") "
|
||||||
|
|
||||||
|
// create a 'ntv' module to allow functions to be registered in a safe namespace
|
||||||
|
"ntv = module('ntv') "
|
||||||
|
|
||||||
// auto-import modules
|
// auto-import modules
|
||||||
// // import alias
|
// // import alias
|
||||||
"import wire "
|
"import energy "
|
||||||
|
|
||||||
// Phase 1
|
// Phase 1
|
||||||
// Prepare the super class that will be eventually in Flash
|
"class Tasmota: Tasmota_ntv "
|
||||||
"class Tasmota_ntv "
|
// for now the variables are built, need to find a way to push in Flash
|
||||||
"var _op, _operators, _rules, _timers, _cmd "
|
|
||||||
|
|
||||||
// Map all native functions to methods
|
|
||||||
// Again, this will be eventually pre-compiled
|
|
||||||
"var getfreeheap, publish, cmd, getoption, millis, timereached, yield "
|
|
||||||
"var respcmnd, respcmndstr, respcmnd_done, respcmnd_error, respcmnd_failed, resolvecmnd "
|
|
||||||
"var getlight "
|
|
||||||
"def init_ntv() "
|
|
||||||
"import tasmota_ntv "
|
|
||||||
"self.getfreeheap = tasmota_ntv.getfreeheap "
|
|
||||||
"self.publish = tasmota_ntv.publish "
|
|
||||||
"self.cmd = tasmota_ntv.cmd "
|
|
||||||
"self.getoption = tasmota_ntv.getoption "
|
|
||||||
"self.millis = tasmota_ntv.millis "
|
|
||||||
"self.timereached = tasmota_ntv.timereached "
|
|
||||||
"self.yield = tasmota_ntv.yield "
|
|
||||||
"self._operators = tasmota_ntv._operators "
|
|
||||||
|
|
||||||
"self.respcmnd = tasmota_ntv.respcmnd "
|
|
||||||
"self.respcmndstr = tasmota_ntv.respcmndstr "
|
|
||||||
"self.respcmnd_done = tasmota_ntv.respcmnd_done "
|
|
||||||
"self.respcmnd_error = tasmota_ntv.respcmnd_error "
|
|
||||||
"self.respcmnd_failed = tasmota_ntv.respcmnd_failed "
|
|
||||||
"self.resolvecmnd = tasmota_ntv.resolvecmnd "
|
|
||||||
|
|
||||||
"self.getlight = tasmota_ntv.getlight "
|
|
||||||
"end "
|
|
||||||
|
|
||||||
"def init() "
|
"def init() "
|
||||||
"self._op = [ "
|
"self._op = ['==', '!==', '=', '!=', '>=', '<=', '>', '<'] "
|
||||||
"['==', /s1,s2-> str(s1) == str(s2)],"
|
"self._opf = [ "
|
||||||
"['!==',/s1,s2-> str(s1) != str(s2)],"
|
"/s1,s2-> str(s1) == str(s2),"
|
||||||
"['=', /f1,f2-> real(f1) == real(f2)],"
|
"/s1,s2-> str(s1) != str(s2),"
|
||||||
"['!=', /f1,f2-> real(f1) != real(f2)],"
|
"/f1,f2-> real(f1) == real(f2),"
|
||||||
"['>=', /f1,f2-> real(f1) >= real(f2)],"
|
"/f1,f2-> real(f1) != real(f2),"
|
||||||
"['<=', /f1,f2-> real(f1) <= real(f2)],"
|
"/f1,f2-> real(f1) >= real(f2),"
|
||||||
"['>', /f1,f2-> real(f1) > real(f2)],"
|
"/f1,f2-> real(f1) <= real(f2),"
|
||||||
"['<', /f1,f2-> real(f1) < real(f2)],"
|
"/f1,f2-> real(f1) > real(f2),"
|
||||||
|
"/f1,f2-> real(f1) < real(f2),"
|
||||||
"] "
|
"] "
|
||||||
|
"self._operators = \"=<>!|\" "
|
||||||
"self._rules = {} "
|
"self._rules = {} "
|
||||||
"self._timers = [] "
|
"self._timers = [] "
|
||||||
"self._cmd = {} "
|
"self._cmd = {} "
|
||||||
"self.init_ntv() "
|
|
||||||
"end "
|
"end "
|
||||||
"end "
|
|
||||||
|
|
||||||
"class Tasmota: Tasmota_ntv "
|
|
||||||
// add `charsinstring(s:string,c:string) -> int``
|
// add `charsinstring(s:string,c:string) -> int``
|
||||||
// looks for any char in c, and return the position of the first chat
|
// looks for any char in c, and return the position of the first chat
|
||||||
// or -1 if not found
|
// or -1 if not found
|
||||||
|
@ -125,10 +98,11 @@ const char berry_prog[] =
|
||||||
"var op_left = op_split[0] "
|
"var op_left = op_split[0] "
|
||||||
"var op_rest = op_split[1] "
|
"var op_rest = op_split[1] "
|
||||||
// # iterate through operators
|
// # iterate through operators
|
||||||
"for op: self._op "
|
"for i: 0..size(self._op)-1 "
|
||||||
"if string.find(op_rest,op[0]) == 0 "
|
"var op = self._op[i] "
|
||||||
"var op_func = op[1] "
|
"if string.find(op_rest,op) == 0 "
|
||||||
"var op_right = string.split(op_rest,size(op[0]))[1] "
|
"var op_func = self._opf[i] "
|
||||||
|
"var op_right = string.split(op_rest,size(op))[1] "
|
||||||
"return [op_left,op_func,op_right] "
|
"return [op_left,op_func,op_right] "
|
||||||
"end "
|
"end "
|
||||||
"end "
|
"end "
|
||||||
|
@ -137,7 +111,6 @@ const char berry_prog[] =
|
||||||
"end "
|
"end "
|
||||||
|
|
||||||
// Rules trigger if match. return true if match, false if not
|
// Rules trigger if match. return true if match, false if not
|
||||||
// Note: condition is not yet managed
|
|
||||||
"def try_rule(ev, rule, f) "
|
"def try_rule(ev, rule, f) "
|
||||||
"import string "
|
"import string "
|
||||||
"var rl_list = self.find_op(rule) "
|
"var rl_list = self.find_op(rule) "
|
||||||
|
@ -229,6 +202,8 @@ const char berry_prog[] =
|
||||||
|
|
||||||
// Instantiate tasmota object
|
// Instantiate tasmota object
|
||||||
"tasmota = Tasmota() "
|
"tasmota = Tasmota() "
|
||||||
|
"wire = Wire(0) "
|
||||||
|
"wire1 = Wire(1) "
|
||||||
|
|
||||||
// Not sure how to run call methods from C
|
// Not sure how to run call methods from C
|
||||||
"def _exec_rules(e) return tasmota.exec_rules(e) end "
|
"def _exec_rules(e) return tasmota.exec_rules(e) end "
|
||||||
|
@ -253,19 +228,30 @@ const char berry_prog[] =
|
||||||
"var c = compile(f,'file') "
|
"var c = compile(f,'file') "
|
||||||
// save the compiled bytecode
|
// save the compiled bytecode
|
||||||
"if !native "
|
"if !native "
|
||||||
|
"try "
|
||||||
"save(f+'c', c) "
|
"save(f+'c', c) "
|
||||||
|
"except .. as e "
|
||||||
|
"log(string.format('BRY: could not save compiled file %s (%s)',f+'c',e)) "
|
||||||
|
"end "
|
||||||
"end "
|
"end "
|
||||||
// call the compiled code
|
// call the compiled code
|
||||||
"c() "
|
"c() "
|
||||||
|
"log(string.format(\"BRY: sucessfully loaded '%s'\",f)) "
|
||||||
"except .. as e "
|
"except .. as e "
|
||||||
"log(string.format(\"BRY: could not load file '%s' - %s\",f,e)) "
|
"raise \"io_error\",string.format(\"Could not load file '%s'\",f) "
|
||||||
"end "
|
"end "
|
||||||
"end "
|
"end "
|
||||||
|
|
||||||
// try to load "/autoexec.be"
|
// try to load "/autoexec.be"
|
||||||
// "try compile('/autoexec.be','file')() except .. log('BRY: no /autoexec.bat file') end "
|
// "try compile('/autoexec.be','file')() except .. log('BRY: no /autoexec.bat file') end "
|
||||||
|
|
||||||
// Wire
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
const char berry_autoexec[] =
|
||||||
|
// load "autoexec.be" using import, which loads either .be or .bec file
|
||||||
|
"try "
|
||||||
|
"load('autoexec.be') "
|
||||||
|
"except .. "
|
||||||
|
"log(\"BRY: No 'autoexec.be' file\") "
|
||||||
|
"end "
|
||||||
|
;
|
||||||
#endif // USE_BERRY
|
#endif // USE_BERRY
|
||||||
|
|
|
@ -36,8 +36,7 @@ class BerrySupport {
|
||||||
public:
|
public:
|
||||||
bvm *vm = nullptr; // berry vm
|
bvm *vm = nullptr; // berry vm
|
||||||
bool rules_busy = false; // are we already processing rules, avoid infinite loop
|
bool rules_busy = false; // are we already processing rules, avoid infinite loop
|
||||||
const char *fname = nullptr; // name of berry function to call
|
bool autoexec_done = false; // do we still need to load 'autoexec.be'
|
||||||
int32_t fret = 0;
|
|
||||||
};
|
};
|
||||||
BerrySupport berry;
|
BerrySupport berry;
|
||||||
|
|
||||||
|
@ -59,10 +58,6 @@ void checkBeTop(void) {
|
||||||
*
|
*
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
// // call a function (if exists) of type void -> void
|
// // call a function (if exists) of type void -> void
|
||||||
// void callBerryFunctionVoid_berry(const char * fname) {
|
|
||||||
// berry.fret = 0;
|
|
||||||
// callBerryFunctionVoid(berry.fname);
|
|
||||||
// }
|
|
||||||
|
|
||||||
bool callBerryRule(void) {
|
bool callBerryRule(void) {
|
||||||
if (berry.rules_busy) { return false; }
|
if (berry.rules_busy) { return false; }
|
||||||
|
@ -244,7 +239,7 @@ void BrReset(void) {
|
||||||
ret_code2 = be_pcall(berry.vm, 0);
|
ret_code2 = be_pcall(berry.vm, 0);
|
||||||
if (ret_code1 != 0) {
|
if (ret_code1 != 0) {
|
||||||
AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_pcall [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
|
AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_pcall [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
|
||||||
be_pop(berry.vm, 2);
|
be_pop(berry.vm, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM used=%u"), be_gc_memcount(berry.vm));
|
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM used=%u"), be_gc_memcount(berry.vm));
|
||||||
|
@ -268,6 +263,32 @@ void BrReset(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BrAutoexec(void) {
|
||||||
|
if (berry.vm == nullptr) { return; }
|
||||||
|
|
||||||
|
int32_t ret_code1, ret_code2;
|
||||||
|
bool berry_init_ok = false;
|
||||||
|
|
||||||
|
// load 'autoexec.be' or 'autoexec.bec'
|
||||||
|
ret_code1 = be_loadstring(berry.vm, berry_autoexec);
|
||||||
|
// be_dumpstack(berry.vm);
|
||||||
|
if (ret_code1 != 0) {
|
||||||
|
be_pop(berry.vm, 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret_code2 = be_pcall(berry.vm, 0);
|
||||||
|
// be_dumpstack(berry.vm);
|
||||||
|
if (ret_code1 != 0) {
|
||||||
|
// AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_pcall [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
|
||||||
|
be_pop(berry.vm, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM used=%u"), be_gc_memcount(berry.vm));
|
||||||
|
be_pop(berry.vm, 1);
|
||||||
|
// be_dumpstack(berry.vm);
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Tasmota Commands
|
* Tasmota Commands
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
@ -304,11 +325,11 @@ void CmndBrRun(void) {
|
||||||
// AddLog(LOG_LEVEL_INFO, "run: type(2)=%s", be_typename(berry.vm, 2));
|
// AddLog(LOG_LEVEL_INFO, "run: type(2)=%s", be_typename(berry.vm, 2));
|
||||||
|
|
||||||
// code taken from REPL, look first at top, and if nil, look at return value
|
// code taken from REPL, look first at top, and if nil, look at return value
|
||||||
if (!be_isnil(berry.vm, 1)) {
|
// if (!be_isnil(berry.vm, 1)) {
|
||||||
ret_val = be_tostring(berry.vm, 1);
|
ret_val = be_tostring(berry.vm, 1);
|
||||||
} else {
|
// } else {
|
||||||
ret_val = be_tostring(berry.vm, 2);
|
// ret_val = be_tostring(berry.vm, 2);
|
||||||
}
|
// }
|
||||||
Response_P("{\"" D_PRFX_BR "\":\"%s\"}", EscapeJSONString(ret_val).c_str()); // can't use XdrvMailbox.command as it may have been overwritten by subcommand
|
Response_P("{\"" D_PRFX_BR "\":\"%s\"}", EscapeJSONString(ret_val).c_str()); // can't use XdrvMailbox.command as it may have been overwritten by subcommand
|
||||||
be_pop(berry.vm, 1);
|
be_pop(berry.vm, 1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -340,6 +361,12 @@ bool Xdrv52(uint8_t function)
|
||||||
case FUNC_INIT:
|
case FUNC_INIT:
|
||||||
BrReset();
|
BrReset();
|
||||||
break;
|
break;
|
||||||
|
case FUNC_LOOP:
|
||||||
|
if (!berry.autoexec_done) {
|
||||||
|
BrAutoexec();
|
||||||
|
berry.autoexec_done = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case FUNC_EVERY_50_MSECOND:
|
case FUNC_EVERY_50_MSECOND:
|
||||||
callBerryFunctionVoid(PSTR("_run_deferred"));
|
callBerryFunctionVoid(PSTR("_run_deferred"));
|
||||||
break;
|
break;
|
||||||
|
@ -383,8 +410,6 @@ bool Xdrv52(uint8_t function)
|
||||||
case FUNC_BUTTON_PRESSED:
|
case FUNC_BUTTON_PRESSED:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FUNC_LOOP:
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in New Issue