mirror of https://github.com/arendst/Tasmota.git
Merge branch 'development' of github.com:arendst/Tasmota into pr_tm1638
This commit is contained in:
commit
9af3ec2118
|
@ -16,9 +16,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Crash protection in ext_vnsprintf_P (#11202)
|
||||
- Extent compile time SetOptions support (#11204)
|
||||
- ESP32 Extent BLE (#11212)
|
||||
|
||||
- ESP32 support for WS2812 hardware driver via RMT or I2S
|
||||
|
||||
- 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_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_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_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_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_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_setitem;
|
||||
extern const bcstring be_const_str_def;
|
||||
extern const bcstring be_const_str_except;
|
||||
extern const bcstring be_const_str_classname;
|
||||
extern const bcstring be_const_str_isinstance;
|
||||
extern const bcstring be_const_str_cosh;
|
||||
extern const bcstring be_const_str_elif;
|
||||
extern const bcstring be_const_str_item;
|
||||
extern const bcstring be_const_str_push;
|
||||
extern const bcstring be_const_str_concat;
|
||||
extern const bcstring be_const_str_traceback;
|
||||
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(asin, "asin", 4272848550u, 0, 4, &be_const_str_list);
|
||||
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(remove, "remove", 3683784189u, 0, 6, &be_const_str_false);
|
||||
be_define_const_str(false, "false", 184981848u, 62, 5, &be_const_str_raise);
|
||||
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(assert, "assert", 2774883451u, 0, 6, &be_const_str_item);
|
||||
be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_reverse);
|
||||
be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_sin);
|
||||
be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_super);
|
||||
be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_try);
|
||||
be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_dot_p);
|
||||
be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_calldepth);
|
||||
be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, NULL);
|
||||
be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, &be_const_str_break);
|
||||
be_define_const_str(break, "break", 3378807160u, 58, 5, NULL);
|
||||
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(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(compile, "compile", 1000265118u, 0, 7, &be_const_str_false);
|
||||
be_define_const_str(false, "false", 184981848u, 62, 5, NULL);
|
||||
be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL);
|
||||
be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL);
|
||||
be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_true);
|
||||
be_define_const_str(true, "true", 1303515621u, 61, 4, NULL);
|
||||
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(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_hex);
|
||||
be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_resize);
|
||||
be_define_const_str(resize, "resize", 3514612129u, 0, 6, &be_const_str_as);
|
||||
be_define_const_str(as, "as", 1579491469u, 67, 2, NULL);
|
||||
be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_codedump);
|
||||
be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_cosh);
|
||||
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[] = {
|
||||
(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,
|
||||
NULL,
|
||||
(const bstring *)&be_const_str_int,
|
||||
NULL,
|
||||
(const bstring *)&be_const_str_iter,
|
||||
(const bstring *)&be_const_str_fromstring,
|
||||
(const bstring *)&be_const_str_opt_eq,
|
||||
(const bstring *)&be_const_str_floor,
|
||||
(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,
|
||||
NULL,
|
||||
(const bstring *)&be_const_str_classof,
|
||||
(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_deg,
|
||||
(const bstring *)&be_const_str_allocated,
|
||||
(const bstring *)&be_const_str_attrdump,
|
||||
(const bstring *)&be_const_str_for,
|
||||
(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_reverse,
|
||||
(const bstring *)&be_const_str_assert,
|
||||
(const bstring *)&be_const_str_imax,
|
||||
(const bstring *)&be_const_str_codedump,
|
||||
(const bstring *)&be_const_str_def,
|
||||
(const bstring *)&be_const_str_classname,
|
||||
(const bstring *)&be_const_str_cosh
|
||||
(const bstring *)&be_const_str_opt_neq,
|
||||
(const bstring *)&be_const_str___upper__,
|
||||
(const bstring *)&be_const_str_abs,
|
||||
(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 = {
|
||||
.size = 45,
|
||||
.count = 90,
|
||||
.size = 47,
|
||||
.count = 95,
|
||||
.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"
|
||||
|
||||
static be_define_const_map_slots(be_class_list_map) {
|
||||
{ be_const_key(pop, -1), be_const_func(m_pop) },
|
||||
{ be_const_key(reverse, -1), be_const_func(m_reverse) },
|
||||
{ be_const_key(concat, -1), be_const_func(m_concat) },
|
||||
{ be_const_key(push, -1), be_const_func(m_push) },
|
||||
{ be_const_key(init, -1), be_const_func(m_init) },
|
||||
{ be_const_key(copy, 8), be_const_func(m_copy) },
|
||||
{ be_const_key(opt_connect, 13), be_const_func(m_connect) },
|
||||
{ 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(insert, 1), be_const_func(m_insert) },
|
||||
{ be_const_key(find, -1), be_const_func(m_find) },
|
||||
{ be_const_key(remove, 9), be_const_func(m_remove) },
|
||||
{ be_const_key(clear, -1), be_const_func(m_clear) },
|
||||
{ be_const_key(opt_eq, 3), be_const_func(m_equal) },
|
||||
{ be_const_key(insert, 12), be_const_func(m_insert) },
|
||||
{ be_const_key(concat, 2), be_const_func(m_concat) },
|
||||
{ be_const_key(dot_p, -1), be_const_int(0) },
|
||||
{ be_const_key(iter, 18), be_const_func(m_iter) },
|
||||
{ be_const_key(size, -1), be_const_func(m_size) },
|
||||
{ be_const_key(resize, 13), be_const_func(m_resize) },
|
||||
{ be_const_key(copy, -1), be_const_func(m_copy) },
|
||||
{ be_const_key(pop, -1), be_const_func(m_pop) },
|
||||
{ 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(
|
||||
be_class_list_map,
|
||||
20
|
||||
21
|
||||
);
|
||||
|
||||
BE_EXPORT_VARIABLE be_define_const_class(
|
||||
|
|
|
@ -1,37 +1,39 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(m_builtin_map) {
|
||||
{ be_const_key(map, 11), be_const_int(10) },
|
||||
{ be_const_key(str, 14), be_const_int(18) },
|
||||
{ be_const_key(int, -1), be_const_int(6) },
|
||||
{ be_const_key(type, -1), be_const_int(20) },
|
||||
{ be_const_key(assert, -1), be_const_int(1) },
|
||||
{ be_const_key(issubclass, -1), be_const_int(8) },
|
||||
{ be_const_key(number, 7), be_const_int(12) },
|
||||
{ be_const_key(compile, 8), be_const_int(4) },
|
||||
{ be_const_key(module, 18), be_const_int(11) },
|
||||
{ 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(print, 19), be_const_int(15) },
|
||||
{ be_const_key(isinstance, -1), be_const_int(8) },
|
||||
{ be_const_key(classname, -1), be_const_int(3) },
|
||||
{ be_const_key(module, -1), be_const_int(12) },
|
||||
{ be_const_key(size, -1), be_const_int(18) },
|
||||
{ be_const_key(type, 9), be_const_int(21) },
|
||||
{ be_const_key(compile, -1), be_const_int(5) },
|
||||
{ be_const_key(open, -1), be_const_int(14) },
|
||||
{ be_const_key(real, -1), be_const_int(17) },
|
||||
{ be_const_key(__iterator__, -1), be_const_int(0) },
|
||||
{ be_const_key(real, 10), be_const_int(16) },
|
||||
{ be_const_key(list, 20), be_const_int(9) },
|
||||
{ be_const_key(isinstance, -1), be_const_int(7) },
|
||||
{ be_const_key(range, -1), be_const_int(15) },
|
||||
{ be_const_key(size, -1), be_const_int(17) },
|
||||
{ be_const_key(classname, -1), be_const_int(2) },
|
||||
{ be_const_key(print, -1), be_const_int(14) },
|
||||
{ be_const_key(super, -1), be_const_int(20) },
|
||||
{ be_const_key(issubclass, -1), be_const_int(9) },
|
||||
{ be_const_key(classof, -1), be_const_int(4) },
|
||||
{ be_const_key(map, 8), be_const_int(11) },
|
||||
{ be_const_key(int, 2), be_const_int(7) },
|
||||
{ be_const_key(input, 3), be_const_int(6) },
|
||||
{ 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(
|
||||
m_builtin_map,
|
||||
21
|
||||
22
|
||||
);
|
||||
|
||||
static const bvalue __vlist_array[] = {
|
||||
be_const_func(l_iterator),
|
||||
be_const_func(l_assert),
|
||||
be_const_class(be_class_bytes),
|
||||
be_const_func(l_classname),
|
||||
be_const_func(l_classof),
|
||||
be_const_func(l_compile),
|
||||
|
@ -56,5 +58,5 @@ static const bvalue __vlist_array[] = {
|
|||
static be_define_const_vector(
|
||||
m_builtin_vector,
|
||||
__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_map;
|
||||
extern const bclass be_class_range;
|
||||
extern const bclass be_class_bytes;
|
||||
extern int be_nfunc_open(bvm *vm);
|
||||
/* @const_object_info_begin
|
||||
vartab m_builtin (scope: local) {
|
||||
|
@ -337,6 +338,7 @@ vartab m_builtin (scope: local) {
|
|||
list, class(be_class_list)
|
||||
map, class(be_class_map)
|
||||
range, class(be_class_range)
|
||||
bytes, class(be_class_bytes)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#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_filelib(bvm *vm);
|
||||
|
||||
extern void be_load_tasmota_ntvlib(bvm *vm);
|
||||
extern void be_load_wirelib(bvm *vm);
|
||||
|
||||
void be_loadlibs(bvm *vm)
|
||||
{
|
||||
be_load_baselib(vm);
|
||||
|
@ -21,5 +24,8 @@ void be_loadlibs(bvm *vm)
|
|||
be_load_maplib(vm);
|
||||
be_load_rangelib(vm);
|
||||
be_load_filelib(vm);
|
||||
be_load_byteslib(vm);
|
||||
#endif
|
||||
be_load_tasmota_ntvlib(vm);
|
||||
be_load_wirelib(vm);
|
||||
}
|
||||
|
|
|
@ -207,6 +207,19 @@ static int m_item(bvm *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)
|
||||
{
|
||||
be_getmember(vm, 1, ".p");
|
||||
|
@ -291,13 +304,15 @@ static int m_merge(bvm *vm)
|
|||
{
|
||||
int argc = be_top(vm);
|
||||
if (argc >= 2) {
|
||||
be_newobject(vm, "list"); /* stack contains instance and .p */
|
||||
be_getmember(vm, 1, ".p");
|
||||
be_data_merge(vm, -2);
|
||||
be_getmember(vm, 2, ".p");
|
||||
if (!be_islist(vm, -1)) {
|
||||
be_raise(vm, "type_error", "operand must be a list");
|
||||
}
|
||||
be_data_merge(vm, -2);
|
||||
be_pop(vm, argc + 1);
|
||||
be_data_merge(vm, -3);
|
||||
be_pop(vm, 3);
|
||||
}
|
||||
be_return(vm); /* return self */
|
||||
}
|
||||
|
@ -423,6 +438,7 @@ void be_load_listlib(bvm *vm)
|
|||
{ "insert", m_insert },
|
||||
{ "remove", m_remove },
|
||||
{ "item", m_item },
|
||||
{ "find", m_find },
|
||||
{ "setitem", m_setitem },
|
||||
{ "size", m_size },
|
||||
{ "resize", m_resize },
|
||||
|
@ -450,6 +466,7 @@ class be_class_list (scope: global, name: list) {
|
|||
insert, func(m_insert)
|
||||
remove, func(m_remove)
|
||||
item, func(m_item)
|
||||
find, func(m_find)
|
||||
setitem, func(m_setitem)
|
||||
size, func(m_size)
|
||||
resize, func(m_resize)
|
||||
|
|
|
@ -1060,4 +1060,4 @@ BERRY_API void be_set_obs_hook(bvm *vm, beobshook hook)
|
|||
#if BE_USE_OBSERVABILITY_HOOK
|
||||
vm->obshook = hook;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_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 */
|
||||
BERRY_API int be_register(bvm *vm, int index);
|
||||
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);
|
||||
|
||||
/* Tasmota specific */
|
||||
be_extern_native_module(tasmota_ntv);
|
||||
// be_extern_native_module(tasmota_ntv);
|
||||
be_extern_native_module(wire);
|
||||
be_extern_native_module(energy);
|
||||
|
||||
/* user-defined modules declare start */
|
||||
|
||||
|
@ -56,8 +57,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
|
|||
#endif
|
||||
/* user-defined modules register start */
|
||||
|
||||
&be_native_module(tasmota_ntv),
|
||||
&be_native_module(wire),
|
||||
&be_native_module(energy),
|
||||
|
||||
/* user-defined modules register end */
|
||||
NULL /* do not remove */
|
||||
|
|
|
@ -13,6 +13,7 @@ extern int l_millis(bvm *vm);
|
|||
extern int l_timereached(bvm *vm);
|
||||
extern int l_yield(bvm *vm);
|
||||
extern int l_delay(bvm *vm);
|
||||
extern int l_scaleuint(bvm *vm);
|
||||
|
||||
extern int l_respCmnd(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_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 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) {
|
||||
be_native_module_function("getfreeheap", l_getFreeHeap),
|
||||
be_native_module_function("publish", l_publish),
|
||||
be_native_module_function("cmd", l_cmd),
|
||||
be_native_module_function("getoption", l_getoption),
|
||||
be_native_module_function("millis", l_millis),
|
||||
be_native_module_function("timereached", l_timereached),
|
||||
be_native_module_function("yield", l_yield),
|
||||
be_native_module_function("delay", l_delay),
|
||||
{ "respcmnd", l_respCmnd },
|
||||
{ "respcmndstr", l_respCmndStr },
|
||||
{ "respcmnd_done", l_respCmndDone },
|
||||
{ "respcmnd_error", l_respCmndError },
|
||||
{ "respcmnd_failed", l_respCmndFailed },
|
||||
{ "resolvecmnd", l_resolveCmnd },
|
||||
|
||||
be_native_module_function("respcmnd", l_respCmnd),
|
||||
be_native_module_function("respcmndstr", l_respCmndStr),
|
||||
be_native_module_function("respcmnd_done", l_respCmndDone),
|
||||
be_native_module_function("respcmnd_error", l_respCmndError),
|
||||
be_native_module_function("respcmnd_failed", l_respCmndFailed),
|
||||
be_native_module_function("resolvecmnd", l_resolveCmnd),
|
||||
{ "getlight", l_getlight },
|
||||
{ "getpower", l_getpower },
|
||||
{ "setlight", l_setlight },
|
||||
{ "setpower", l_setpower },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
be_regclass(vm, "Tasmota_ntv", members);
|
||||
}
|
||||
|
||||
be_native_module_function("getlight", l_getlight),
|
||||
|
||||
be_native_module_str("_operators", "=<>!|"),
|
||||
};
|
||||
|
||||
be_define_native_module(tasmota_ntv, NULL);
|
||||
#else
|
||||
/* @const_object_info_begin
|
||||
module tasmota (scope: global, depend: 1) {
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
*******************************************************************/
|
||||
#include "be_object.h"
|
||||
|
||||
extern int b_wire_init(bvm *vm);
|
||||
|
||||
extern int b_wire_begintransmission(bvm *vm);
|
||||
extern int b_wire_endtransmission(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 1 // TODO we will do pre-compiled later
|
||||
be_native_module_attr_table(wire) {
|
||||
be_native_module_function("_begintransmission", b_wire_begintransmission),
|
||||
be_native_module_function("_endtransmission", b_wire_endtransmission),
|
||||
be_native_module_function("_requestfrom", b_wire_requestfrom),
|
||||
be_native_module_function("_available", b_wire_available),
|
||||
be_native_module_function("_write", b_wire_write),
|
||||
be_native_module_function("_read", b_wire_read),
|
||||
be_native_module_function("scan", b_wire_scan),
|
||||
be_native_module_function("write", b_wire_validwrite),
|
||||
be_native_module_function("read", b_wire_validread),
|
||||
};
|
||||
|
||||
be_define_native_module(wire, NULL);
|
||||
void be_load_wirelib(bvm *vm)
|
||||
{
|
||||
static const bnfuncinfo members[] = {
|
||||
{ "_bus", NULL }, // bus number
|
||||
{ "init", b_wire_init },
|
||||
{ "_begintransmission", b_wire_begintransmission },
|
||||
{ "_endtransmission", b_wire_endtransmission },
|
||||
{ "_requestfrom", b_wire_requestfrom },
|
||||
{ "_available", b_wire_available },
|
||||
{ "_write", b_wire_write },
|
||||
{ "_read", b_wire_read },
|
||||
{ "scan", b_wire_scan },
|
||||
{ "write", b_wire_validwrite },
|
||||
{ "read", b_wire_validread },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
be_regclass(vm, "Wire", members);
|
||||
}
|
||||
#else
|
||||
/* @const_object_info_begin
|
||||
module tasmota (scope: global, depend: 1) {
|
||||
|
|
155
lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.c → lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.cpp
Normal file → Executable file
155
lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.c → lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.cpp
Normal file → Executable file
|
@ -21,25 +21,169 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <string.h>
|
||||
#include <FS.h>
|
||||
|
||||
#define HAP_PLATFORM_DEF_NVS_PARTITION "nvs"
|
||||
#define HAP_PLATFORM_DEF_FACTORY_NVS_PARTITION "factory_nvs"
|
||||
|
||||
extern "C" {
|
||||
|
||||
static const char *TAG = "hap_platform_keystore";
|
||||
|
||||
char * hap_platform_keystore_get_nvs_partition_name()
|
||||
{
|
||||
const char * hap_platform_keystore_get_nvs_partition_name() {
|
||||
return HAP_PLATFORM_DEF_NVS_PARTITION;
|
||||
}
|
||||
|
||||
char * hap_platform_keystore_get_factory_nvs_partition_name()
|
||||
{
|
||||
const char * hap_platform_keystore_get_factory_nvs_partition_name() {
|
||||
return HAP_PLATFORM_DEF_FACTORY_NVS_PARTITION;
|
||||
}
|
||||
|
||||
#define HAP_USE_LITTLEFS
|
||||
|
||||
#ifdef HAP_USE_LITTLEFS
|
||||
|
||||
#include <LITTLEFS.h>
|
||||
|
||||
extern FS *ffsp;
|
||||
|
||||
int hap_platform_keystore_init_partition(const char *part_name, bool read_only) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hap_platform_keystore_get(const char *part_name, const char *name_space, const char *key, uint8_t *val, size_t *val_size) {
|
||||
char path[48];
|
||||
strcpy(path, "/");
|
||||
strcat(path, part_name);
|
||||
|
||||
File fp = ffsp->open(path, "r");
|
||||
if (!fp) {
|
||||
ffsp->mkdir(path);
|
||||
return -1;
|
||||
}
|
||||
fp.close();
|
||||
|
||||
strcat(path, "/");
|
||||
strcat(path, name_space);
|
||||
fp = ffsp->open(path, "r");
|
||||
if (!fp) {
|
||||
ffsp->mkdir(path);
|
||||
return -1;
|
||||
}
|
||||
fp.close();
|
||||
|
||||
strcat(path, "/");
|
||||
strcat(path, key);
|
||||
fp = ffsp->open(path, "r");
|
||||
if (fp) {
|
||||
fp.read(val, *val_size);
|
||||
fp.close();
|
||||
} else {
|
||||
*val_size = 0;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hap_platform_keystore_set(const char *part_name, const char *name_space, const char *key, const uint8_t *val, const size_t val_len) {
|
||||
char path[48];
|
||||
strcpy(path, "/");
|
||||
strcat(path, part_name);
|
||||
|
||||
File fp = ffsp->open(path, "r");
|
||||
if (!fp) {
|
||||
ffsp->mkdir(path);
|
||||
}
|
||||
fp.close();
|
||||
|
||||
strcat(path, "/");
|
||||
strcat(path, name_space);
|
||||
fp = ffsp->open(path, "r");
|
||||
if (!fp) {
|
||||
ffsp->mkdir(path);
|
||||
}
|
||||
fp.close();
|
||||
|
||||
strcat(path, "/");
|
||||
strcat(path, key);
|
||||
fp = ffsp->open(path, "w");
|
||||
if (fp) {
|
||||
fp.write(val, val_len);
|
||||
fp.close();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hap_platform_keystore_delete(const char *part_name, const char *name_space, const char *key) {
|
||||
char path[48];
|
||||
strcpy(path, "/");
|
||||
strcat(path, part_name);
|
||||
strcat(path, "/");
|
||||
strcat(path, name_space);
|
||||
strcat(path, "/");
|
||||
strcat(path, key);
|
||||
ffsp->remove(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// should
|
||||
int hap_platform_keystore_delete_namespace(const char *part_name, const char *name_space) {
|
||||
char path[48];
|
||||
strcpy(path, "/");
|
||||
strcat(path, part_name);
|
||||
strcat(path, "/");
|
||||
strcat(path, name_space);
|
||||
File fp = ffsp->open(path, "r");
|
||||
if (fp.isDirectory()) {
|
||||
while (true) {
|
||||
File entry = fp.openNextFile();
|
||||
if (!entry) break;
|
||||
char fp[48];
|
||||
strcpy(fp,path);
|
||||
strcat(fp, "/");
|
||||
strcat(fp, entry.name());
|
||||
ffsp->remove(fp);
|
||||
entry.close();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// last resort only
|
||||
int hap_platfrom_keystore_erase_partition(const char *part_name) {
|
||||
// LITTLEFS.format();
|
||||
char path[48];
|
||||
strcpy(path, "/");
|
||||
strcat(path, part_name);
|
||||
File fp = ffsp->open(path, "r");
|
||||
if (fp.isDirectory()) {
|
||||
while (true) {
|
||||
File entry = fp.openNextFile();
|
||||
if (!entry) break;
|
||||
char fp[48];
|
||||
strcpy(fp,path);
|
||||
strcat(fp, "/");
|
||||
strcat(fp, entry.name());
|
||||
if (entry.isDirectory()) {
|
||||
hap_platform_keystore_delete_namespace(part_name, entry.name());
|
||||
ffsp->rmdir(fp);
|
||||
} else {
|
||||
ffsp->remove(fp);
|
||||
}
|
||||
entry.close();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_NVS_ENCRYPTION
|
||||
int hap_platform_keystore_init_partition(const char *part_name, bool read_only)
|
||||
{
|
||||
|
@ -185,3 +329,6 @@ int hap_platfrom_keystore_erase_partition(const char *part_name)
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
#endif // USE_LITTLEFS
|
||||
|
||||
}
|
|
@ -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()
|
|
@ -24,6 +24,9 @@
|
|||
/* HomeKit Smart Outlet Example
|
||||
*/
|
||||
|
||||
//#define USE_HOMEKIT
|
||||
|
||||
|
||||
#ifdef USE_HOMEKIT
|
||||
#ifdef ESP32
|
||||
|
||||
|
@ -49,6 +52,7 @@
|
|||
static const char *TAG = "HAP outlet";
|
||||
char *hk_desc;
|
||||
char hk_code[12];
|
||||
uint8_t hk_services;
|
||||
|
||||
extern void Ext_Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize);
|
||||
extern uint32_t Ext_UpdVar(char *vname, float *fvar, uint32_t mode);
|
||||
|
@ -194,6 +198,8 @@ static int sensor_read(hap_char_t *hc, hap_status_t *status_code, void *serv_pri
|
|||
|
||||
const char *hcp = hap_char_get_type_uuid(hc);
|
||||
|
||||
printf("read values %s\n", hcp );
|
||||
|
||||
if (!strcmp(hcp, HAP_CHAR_UUID_CURRENT_TEMPERATURE)
|
||||
|| !strcmp(hcp, HAP_CHAR_UUID_CURRENT_RELATIVE_HUMIDITY)
|
||||
|| !strcmp(hcp, HAP_CHAR_UUID_CURRENT_AMBIENT_LIGHT_LEVEL)
|
||||
|
@ -228,6 +234,24 @@ static int sensor_read(hap_char_t *hc, hap_status_t *status_code, void *serv_pri
|
|||
hap_char_update_val(hc, &new_val);
|
||||
*status_code = HAP_STATUS_SUCCESS;
|
||||
}
|
||||
if (!strcmp(hcp, HAP_CHAR_UUID_BATTERY_LEVEL)) {
|
||||
Ext_UpdVar(hap_devs[index].var_name, &fvar, 0);
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
*status_code = HAP_STATUS_SUCCESS;
|
||||
}
|
||||
if (!strcmp(hcp, HAP_CHAR_UUID_STATUS_LOW_BATTERY)) {
|
||||
Ext_UpdVar(hap_devs[index].var2_name, &fvar, 0);
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
*status_code = HAP_STATUS_SUCCESS;
|
||||
}
|
||||
if (!strcmp(hcp, HAP_CHAR_UUID_CHARGING_STATE)) {
|
||||
Ext_UpdVar(hap_devs[index].var3_name, &fvar, 0);
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
*status_code = HAP_STATUS_SUCCESS;
|
||||
}
|
||||
return HAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -324,6 +348,7 @@ uint32_t cnt;
|
|||
return cnt;
|
||||
}
|
||||
|
||||
float tsim = 20;
|
||||
|
||||
uint32_t str2c(char **sp, char *vp, uint32_t len) {
|
||||
char *lp = *sp;
|
||||
|
@ -440,7 +465,8 @@ static void smart_outlet_thread_entry(void *p) {
|
|||
uint8_t product_data[] = {'E','S','P','3','2','H','A','P'};
|
||||
hap_acc_add_product_data(hap_devs[index].accessory, product_data, sizeof(product_data));
|
||||
|
||||
int ret = hap_serv_add_char(hap_devs[index].service, hap_char_name_create(hap_devs[index].hap_name));
|
||||
int ret;
|
||||
|
||||
switch (hap_cfg.cid) {
|
||||
case HAP_CID_LIGHTING:
|
||||
{ float fvar = 0;
|
||||
|
@ -467,13 +493,22 @@ static void smart_outlet_thread_entry(void *p) {
|
|||
case 0: hap_devs[index].service = hap_serv_temperature_sensor_create(fvar); break;
|
||||
case 1: hap_devs[index].service = hap_serv_humidity_sensor_create(fvar); break;
|
||||
case 2: hap_devs[index].service = hap_serv_light_sensor_create(fvar); break;
|
||||
case 3:
|
||||
{ float fvar1 = 0, fvar2 = 0;
|
||||
Ext_UpdVar(hap_devs[index].var2_name, &fvar1, 0);
|
||||
Ext_UpdVar(hap_devs[index].var3_name, &fvar2, 0);
|
||||
hap_devs[index].service = hap_serv_battery_service_create(fvar, fvar1, fvar2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
hap_devs[index].service = hap_serv_outlet_create(true, true);
|
||||
}
|
||||
|
||||
hap_serv_add_char(hap_devs[index].service, hap_char_name_create(hap_devs[index].hap_name));
|
||||
hap_set_read(hap_devs[index].service, index);
|
||||
hap_set_write(hap_devs[index].service, index);
|
||||
|
||||
|
@ -497,7 +532,7 @@ nextline:
|
|||
lp++;
|
||||
}
|
||||
}
|
||||
|
||||
hk_services = index;
|
||||
|
||||
/* Initialize the appliance specific hardware. This enables out-in-use detection */
|
||||
smart_outlet_hardware_init(OUTLET_IN_USE_GPIO);
|
||||
|
@ -538,7 +573,7 @@ nextline:
|
|||
/* Start Wi-Fi */
|
||||
//app_wifi_start(portMAX_DELAY);
|
||||
|
||||
uint32_t io_num = OUTLET_IN_USE_GPIO;
|
||||
int32_t io_num = OUTLET_IN_USE_GPIO;
|
||||
if (io_num >= 0) {
|
||||
hap_val_t appliance_value = {
|
||||
.b = true,
|
||||
|
@ -561,25 +596,112 @@ nextline:
|
|||
}
|
||||
}
|
||||
} else {
|
||||
while (1) {
|
||||
// vTaskDelete(NULL);
|
||||
// update values every 100 ms
|
||||
while (1) {
|
||||
delay(100);
|
||||
float fvar;
|
||||
hap_char_t *hc;
|
||||
hap_val_t new_val;
|
||||
for (uint32_t cnt = 0; cnt < hk_services; cnt++) {
|
||||
switch (hap_devs[cnt].hap_cid) {
|
||||
case HAP_CID_SENSOR:
|
||||
switch (hap_devs[cnt].type) {
|
||||
case 0:
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_CURRENT_TEMPERATURE);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) {
|
||||
new_val.f = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_CURRENT_RELATIVE_HUMIDITY);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) {
|
||||
new_val.f = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_CURRENT_AMBIENT_LIGHT_LEVEL);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) {
|
||||
new_val.f = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_BATTERY_LEVEL);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) {
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_STATUS_LOW_BATTERY);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var2_name, &fvar, 0)) {
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_STATUS_LOW_BATTERY);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var3_name, &fvar, 0)) {
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HAP_CID_OUTLET:
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_ON);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) {
|
||||
new_val.b = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
break;
|
||||
case HAP_CID_LIGHTING:
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_ON);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) {
|
||||
new_val.b = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_HUE);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var2_name, &fvar, 0)) {
|
||||
new_val.f = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_SATURATION);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var3_name, &fvar, 0)) {
|
||||
new_val.f = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_BRIGHTNESS);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var4_name, &fvar, 0)) {
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define HK_MAXSIZE 1024
|
||||
#define HK_PASSCODE "111-11-111"
|
||||
|
||||
void homekit_main(char *desc) {
|
||||
void homekit_main(char *desc, uint32_t flag ) {
|
||||
if (desc) {
|
||||
char *cp = desc;
|
||||
cp += 2;
|
||||
while (*cp == ' ') cp++;
|
||||
// "111-11-111"
|
||||
uint32_t cnt;
|
||||
for (cnt = 0; cnt < 10; cnt++) {
|
||||
hk_code[cnt] = *cp++;
|
||||
|
||||
if (*cp == '*') {
|
||||
strlcpy(hk_code, HK_PASSCODE, 10);
|
||||
cp++;
|
||||
} else {
|
||||
uint32_t cnt;
|
||||
for (cnt = 0; cnt < 10; cnt++) {
|
||||
hk_code[cnt] = *cp++;
|
||||
}
|
||||
hk_code[cnt] = 0;
|
||||
}
|
||||
hk_code[cnt] = 0;
|
||||
if (*cp != '\n') {
|
||||
printf("init error\n");
|
||||
return;
|
||||
|
@ -587,7 +709,12 @@ void homekit_main(char *desc) {
|
|||
cp++;
|
||||
hk_desc = cp;
|
||||
} else {
|
||||
hap_platfrom_keystore_erase_partition("nvs");
|
||||
if (flag == 99) {
|
||||
hap_reset_to_factory();
|
||||
} else {
|
||||
// not yet implemented
|
||||
hap_stop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -595,7 +722,8 @@ void homekit_main(char *desc) {
|
|||
|
||||
/* Create the application thread */
|
||||
xTaskCreate(smart_outlet_thread_entry, SMART_OUTLET_TASK_NAME, SMART_OUTLET_TASK_STACKSIZE, NULL, SMART_OUTLET_TASK_PRIORITY, NULL);
|
||||
|
||||
}
|
||||
|
||||
#endif // ESP32
|
||||
#endif // USE_HOMEKIT
|
||||
#endif // USE_HOMEKIT
|
||||
|
|
|
@ -1812,27 +1812,37 @@ const uint8_t I2C_RETRY_COUNTER = 3;
|
|||
uint32_t i2c_active[4] = { 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)
|
||||
#endif
|
||||
{
|
||||
uint8_t retry = I2C_RETRY_COUNTER;
|
||||
bool status = false;
|
||||
#ifdef ESP32
|
||||
TwoWire & myWire = (bus == 0) ? Wire : Wire1;
|
||||
#else
|
||||
TwoWire & myWire = Wire;
|
||||
#endif
|
||||
|
||||
i2c_buffer = 0;
|
||||
while (!status && retry) {
|
||||
Wire.beginTransmission(addr); // start transmission to device
|
||||
Wire.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...
|
||||
Wire.requestFrom((int)addr, (int)size); // send data n-bytes read
|
||||
if (Wire.available() == size) {
|
||||
myWire.beginTransmission(addr); // start transmission to device
|
||||
myWire.write(reg); // sends register address to read from
|
||||
if (0 == myWire.endTransmission(false)) { // Try to become I2C Master, send data and collect bytes, keep master status for next request...
|
||||
myWire.requestFrom((int)addr, (int)size); // send data n-bytes read
|
||||
if (myWire.available() == size) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
retry--;
|
||||
}
|
||||
if (!retry) Wire.endTransmission();
|
||||
if (!retry) myWire.endTransmission();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1916,19 +1926,30 @@ int32_t I2cRead24(uint8_t addr, uint8_t reg)
|
|||
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)
|
||||
#endif
|
||||
{
|
||||
uint8_t x = I2C_RETRY_COUNTER;
|
||||
|
||||
#ifdef ESP32
|
||||
TwoWire & myWire = (bus == 0) ? Wire : Wire1;
|
||||
#else
|
||||
TwoWire & myWire = Wire;
|
||||
#endif
|
||||
|
||||
do {
|
||||
Wire.beginTransmission((uint8_t)addr); // start transmission to device
|
||||
Wire.write(reg); // sends register address to write to
|
||||
myWire.beginTransmission((uint8_t)addr); // start transmission to device
|
||||
myWire.write(reg); // sends register address to write to
|
||||
uint8_t bytes = size;
|
||||
while (bytes--) {
|
||||
Wire.write((val >> (8 * bytes)) & 0xFF); // write data
|
||||
myWire.write((val >> (8 * bytes)) & 0xFF); // write data
|
||||
}
|
||||
x--;
|
||||
} while (Wire.endTransmission(true) != 0 && x != 0); // end transmission
|
||||
} while (myWire.endTransmission(true) != 0 && x != 0); // end transmission
|
||||
return (x);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,9 @@ keywords if then else endif, or, and are better readable for beginners (others m
|
|||
#define MAXFILT 5
|
||||
#endif
|
||||
#define SCRIPT_SVARSIZE 20
|
||||
#ifndef SCRIPT_MAXSSIZE
|
||||
#define SCRIPT_MAXSSIZE 48
|
||||
#endif
|
||||
#define SCRIPT_EOL '\n'
|
||||
#define SCRIPT_FLOAT_PRECISION 2
|
||||
#define PMEM_SIZE sizeof(Settings.script_pram)
|
||||
|
@ -221,7 +223,7 @@ extern FS *ufsp;
|
|||
|
||||
#endif // USE_UFILESYS
|
||||
|
||||
extern "C" void homekit_main(char *);
|
||||
extern "C" void homekit_main(char *, uint32_t);
|
||||
|
||||
#ifdef SUPPORT_MQTT_EVENT
|
||||
#include <LinkedList.h> // Import LinkedList library
|
||||
|
@ -244,7 +246,7 @@ extern VButton *buttons[MAX_TOUCH_BUTTONS];
|
|||
#endif
|
||||
|
||||
typedef union {
|
||||
#ifdef USE_SCRIPT_GLOBVARS
|
||||
#if defined(USE_SCRIPT_GLOBVARS) || defined(USE_HOMEKIT)
|
||||
uint16_t data;
|
||||
#else
|
||||
uint8_t data;
|
||||
|
@ -260,6 +262,9 @@ typedef union {
|
|||
uint8_t constant : 1;
|
||||
#ifdef USE_SCRIPT_GLOBVARS
|
||||
uint8_t global : 1;
|
||||
#endif
|
||||
#ifdef USE_SCRIPT_GLOBVARS
|
||||
uint8_t hchanged : 1;
|
||||
#endif
|
||||
};
|
||||
} SCRIPT_TYPE;
|
||||
|
@ -490,7 +495,7 @@ void ScriptEverySecond(void) {
|
|||
uint8_t homekit_found = Run_Scripter(">h", -2, 0);
|
||||
if (homekit_found == 99) {
|
||||
if (!TasmotaGlobal.global_state.wifi_down) {
|
||||
homekit_main(glob_script_mem.section_ptr);
|
||||
homekit_main(glob_script_mem.section_ptr, 0);
|
||||
glob_script_mem.homekit_running = true;
|
||||
}
|
||||
}
|
||||
|
@ -504,6 +509,15 @@ void RulesTeleperiod(void) {
|
|||
if (bitRead(Settings.rule_enabled, 0) && TasmotaGlobal.mqtt_data[0]) Run_Scripter(">T", 2, TasmotaGlobal.mqtt_data);
|
||||
}
|
||||
|
||||
void SetChanged(uint32_t index) {
|
||||
glob_script_mem.type[index].bits.changed = 1;
|
||||
#ifdef USE_HOMEKIT
|
||||
glob_script_mem.type[index].bits.hchanged = 1;
|
||||
#endif
|
||||
//AddLog(LOG_LEVEL_INFO, PSTR("Change: %d"), index);
|
||||
}
|
||||
|
||||
|
||||
#define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++;
|
||||
#define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++;
|
||||
|
||||
|
@ -1015,7 +1029,7 @@ void Script_PollUdp(void) {
|
|||
if (res) {
|
||||
// mark changed
|
||||
glob_script_mem.last_udp_ip = glob_script_mem.Script_PortUdp.remoteIP();
|
||||
glob_script_mem.type[index].bits.changed = 1;
|
||||
SetChanged(index);
|
||||
if (glob_script_mem.glob_script == 99) {
|
||||
Run_Scripter(">G", 2, 0);
|
||||
}
|
||||
|
@ -2497,14 +2511,16 @@ chknext:
|
|||
#endif //USE_LIGHT
|
||||
|
||||
#ifdef USE_HOMEKIT
|
||||
if (!strncmp(vname, "hki", 3)) {
|
||||
if (!strncmp(vname, "hki(", 4)) {
|
||||
if (!TasmotaGlobal.global_state.wifi_down) {
|
||||
// erase nvs
|
||||
homekit_main(0);
|
||||
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv);
|
||||
homekit_main(0, fvar);
|
||||
// restart homekit
|
||||
glob_script_mem.homekit_running = false;
|
||||
TasmotaGlobal.restart_flag = 2;
|
||||
}
|
||||
fvar = 0;
|
||||
lp++;
|
||||
len = 0;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
@ -3568,32 +3584,40 @@ char *ForceStringVar(char *lp, char *dstr) {
|
|||
return lp;
|
||||
}
|
||||
|
||||
#ifdef USE_HOMEKIT
|
||||
extern "C" {
|
||||
uint32_t Ext_UpdVar(char *vname, float *fvar, uint32_t mode) {
|
||||
return UpdVar(vname, fvar, mode);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t UpdVar(char *vname, float *fvar, uint32_t mode) {
|
||||
int32_t UpdVar(char *vname, float *fvar, uint32_t mode) {
|
||||
struct T_INDEX ind;
|
||||
uint8_t vtype;
|
||||
float res = *fvar;
|
||||
uint8_t index;
|
||||
isvar(vname, &vtype, &ind, fvar, 0, 0);
|
||||
if (vtype != VAR_NV) {
|
||||
// found variable as result
|
||||
if (vtype == NUM_RES || (vtype & STYPE) == 0) {
|
||||
if (mode) {
|
||||
// set var
|
||||
uint8_t index = glob_script_mem.type[ind.index].index;
|
||||
index = glob_script_mem.type[ind.index].index;
|
||||
glob_script_mem.fvars[index] = res;
|
||||
glob_script_mem.type[index].bits.changed = 1;
|
||||
SetChanged(ind.index);
|
||||
return 0;
|
||||
} else {
|
||||
// get var
|
||||
//index = glob_script_mem.type[ind.index].index;
|
||||
int32_t ret = glob_script_mem.type[ind.index].bits.hchanged;
|
||||
glob_script_mem.type[ind.index].bits.hchanged = 0;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
// break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3602,6 +3626,9 @@ extern "C" {
|
|||
Replace_Cmd_Vars(srcbuf, srcsize, dstbuf, dstsize);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_HOMEKIT
|
||||
|
||||
// replace vars in cmd %var%
|
||||
void Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize) {
|
||||
char *cp;
|
||||
|
@ -4575,7 +4602,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) {
|
|||
break;
|
||||
}
|
||||
// var was changed
|
||||
glob_script_mem.type[globvindex].bits.changed = 1;
|
||||
SetChanged(globvindex);
|
||||
#ifdef USE_SCRIPT_GLOBVARS
|
||||
if (glob_script_mem.type[globvindex].bits.global) {
|
||||
script_udp_sendvar(varname, dfvar, 0);
|
||||
|
@ -4633,7 +4660,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) {
|
|||
|
||||
if (!glob_script_mem.var_not_found) {
|
||||
// var was changed
|
||||
glob_script_mem.type[globvindex].bits.changed = 1;
|
||||
SetChanged(globvindex);
|
||||
#ifdef USE_SCRIPT_GLOBVARS
|
||||
if (glob_script_mem.type[globvindex].bits.global) {
|
||||
script_udp_sendvar(varname, 0, str);
|
||||
|
@ -5631,7 +5658,7 @@ void Script_Handle_Hue(String *path) {
|
|||
glob_script_mem.fvars[hue_script[index].index[0] - 1] = 1;
|
||||
response.replace("{re", "true");
|
||||
}
|
||||
glob_script_mem.type[hue_script[index].vindex[0]].bits.changed = 1;
|
||||
SetChanged(hue_script[index].vindex[0]);
|
||||
resp = true;
|
||||
}
|
||||
|
||||
|
@ -5647,7 +5674,7 @@ void Script_Handle_Hue(String *path) {
|
|||
response.replace("{cm", "bri");
|
||||
response.replace("{re", String(tmp));
|
||||
glob_script_mem.fvars[hue_script[index].index[1] - 1] = bri;
|
||||
glob_script_mem.type[hue_script[index].vindex[1]].bits.changed = 1;
|
||||
SetChanged(hue_script[index].vindex[1]);
|
||||
resp = true;
|
||||
}
|
||||
|
||||
|
@ -5670,9 +5697,9 @@ void Script_Handle_Hue(String *path) {
|
|||
response.replace("{cm", "xy");
|
||||
response.replace("{re", "[" + x_str + "," + y_str + "]");
|
||||
glob_script_mem.fvars[hue_script[index].index[2]-1] = hue;
|
||||
glob_script_mem.type[hue_script[index].vindex[2]].bits.changed = 1;
|
||||
SetChanged(hue_script[index].vindex[2]);
|
||||
glob_script_mem.fvars[hue_script[index].index[3]-1] = sat;
|
||||
glob_script_mem.type[hue_script[index].vindex[3]].bits.changed = 1;
|
||||
SetChanged(hue_script[index].vindex[3]);
|
||||
resp = true;
|
||||
}
|
||||
|
||||
|
@ -5688,7 +5715,7 @@ void Script_Handle_Hue(String *path) {
|
|||
response.replace("{cm", "hue");
|
||||
response.replace("{re", String(tmp));
|
||||
glob_script_mem.fvars[hue_script[index].index[2] - 1] = hue;
|
||||
glob_script_mem.type[hue_script[index].vindex[2]].bits.changed = 1;
|
||||
SetChanged(hue_script[index].vindex[2]);
|
||||
resp = true;
|
||||
}
|
||||
|
||||
|
@ -5703,7 +5730,7 @@ void Script_Handle_Hue(String *path) {
|
|||
response.replace("{cm", "sat");
|
||||
response.replace("{re", String(tmp));
|
||||
glob_script_mem.fvars[hue_script[index].index[3] - 1] = sat;
|
||||
glob_script_mem.type[hue_script[index].vindex[3]].bits.changed = 1;
|
||||
SetChanged(hue_script[index].vindex[3]);
|
||||
resp = true;
|
||||
}
|
||||
|
||||
|
@ -5716,7 +5743,7 @@ void Script_Handle_Hue(String *path) {
|
|||
response.replace("{cm", "ct");
|
||||
response.replace("{re", String(ct));
|
||||
glob_script_mem.fvars[hue_script[index].index[4] - 1] = ct;
|
||||
glob_script_mem.type[hue_script[index].vindex[4]].bits.changed = 1;
|
||||
SetChanged(hue_script[index].vindex[4]);
|
||||
resp = true;
|
||||
}
|
||||
response += "]";
|
||||
|
|
|
@ -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 "
|
||||
//"log(\"foobar\") "
|
||||
|
||||
// create a 'ntv' module to allow functions to be registered in a safe namespace
|
||||
"ntv = module('ntv') "
|
||||
|
||||
// auto-import modules
|
||||
// // import alias
|
||||
"import wire "
|
||||
"import energy "
|
||||
|
||||
// Phase 1
|
||||
// Prepare the super class that will be eventually in Flash
|
||||
"class Tasmota_ntv "
|
||||
"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 "
|
||||
|
||||
"class Tasmota: Tasmota_ntv "
|
||||
// for now the variables are built, need to find a way to push in Flash
|
||||
"def init() "
|
||||
"self._op = [ "
|
||||
"['==', /s1,s2-> str(s1) == str(s2)],"
|
||||
"['!==',/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)],"
|
||||
"self._op = ['==', '!==', '=', '!=', '>=', '<=', '>', '<'] "
|
||||
"self._opf = [ "
|
||||
"/s1,s2-> str(s1) == str(s2),"
|
||||
"/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),"
|
||||
"] "
|
||||
"self._operators = \"=<>!|\" "
|
||||
"self._rules = {} "
|
||||
"self._timers = [] "
|
||||
"self._cmd = {} "
|
||||
"self.init_ntv() "
|
||||
"end "
|
||||
"end "
|
||||
|
||||
"class Tasmota: Tasmota_ntv "
|
||||
// add `charsinstring(s:string,c:string) -> int``
|
||||
// looks for any char in c, and return the position of the first chat
|
||||
// or -1 if not found
|
||||
|
@ -125,10 +98,11 @@ const char berry_prog[] =
|
|||
"var op_left = op_split[0] "
|
||||
"var op_rest = op_split[1] "
|
||||
// # iterate through operators
|
||||
"for op: self._op "
|
||||
"if string.find(op_rest,op[0]) == 0 "
|
||||
"var op_func = op[1] "
|
||||
"var op_right = string.split(op_rest,size(op[0]))[1] "
|
||||
"for i: 0..size(self._op)-1 "
|
||||
"var op = self._op[i] "
|
||||
"if string.find(op_rest,op) == 0 "
|
||||
"var op_func = self._opf[i] "
|
||||
"var op_right = string.split(op_rest,size(op))[1] "
|
||||
"return [op_left,op_func,op_right] "
|
||||
"end "
|
||||
"end "
|
||||
|
@ -137,7 +111,6 @@ const char berry_prog[] =
|
|||
"end "
|
||||
|
||||
// Rules trigger if match. return true if match, false if not
|
||||
// Note: condition is not yet managed
|
||||
"def try_rule(ev, rule, f) "
|
||||
"import string "
|
||||
"var rl_list = self.find_op(rule) "
|
||||
|
@ -229,6 +202,8 @@ const char berry_prog[] =
|
|||
|
||||
// Instantiate tasmota object
|
||||
"tasmota = Tasmota() "
|
||||
"wire = Wire(0) "
|
||||
"wire1 = Wire(1) "
|
||||
|
||||
// Not sure how to run call methods from C
|
||||
"def _exec_rules(e) return tasmota.exec_rules(e) end "
|
||||
|
@ -253,19 +228,30 @@ const char berry_prog[] =
|
|||
"var c = compile(f,'file') "
|
||||
// save the compiled bytecode
|
||||
"if !native "
|
||||
"save(f+'c', c) "
|
||||
"try "
|
||||
"save(f+'c', c) "
|
||||
"except .. as e "
|
||||
"log(string.format('BRY: could not save compiled file %s (%s)',f+'c',e)) "
|
||||
"end "
|
||||
"end "
|
||||
// call the compiled code
|
||||
"c() "
|
||||
"log(string.format(\"BRY: sucessfully loaded '%s'\",f)) "
|
||||
"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 "
|
||||
|
||||
// try to load "/autoexec.be"
|
||||
// "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
|
||||
|
|
|
@ -36,8 +36,7 @@ class BerrySupport {
|
|||
public:
|
||||
bvm *vm = nullptr; // berry vm
|
||||
bool rules_busy = false; // are we already processing rules, avoid infinite loop
|
||||
const char *fname = nullptr; // name of berry function to call
|
||||
int32_t fret = 0;
|
||||
bool autoexec_done = false; // do we still need to load 'autoexec.be'
|
||||
};
|
||||
BerrySupport berry;
|
||||
|
||||
|
@ -59,10 +58,6 @@ void checkBeTop(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) {
|
||||
if (berry.rules_busy) { return false; }
|
||||
|
@ -244,7 +239,7 @@ void BrReset(void) {
|
|||
ret_code2 = be_pcall(berry.vm, 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));
|
||||
be_pop(berry.vm, 2);
|
||||
be_pop(berry.vm, 1);
|
||||
break;
|
||||
}
|
||||
// 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
|
||||
\*********************************************************************************************/
|
||||
|
@ -304,11 +325,11 @@ void CmndBrRun(void) {
|
|||
// 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
|
||||
if (!be_isnil(berry.vm, 1)) {
|
||||
// if (!be_isnil(berry.vm, 1)) {
|
||||
ret_val = be_tostring(berry.vm, 1);
|
||||
} else {
|
||||
ret_val = be_tostring(berry.vm, 2);
|
||||
}
|
||||
// } else {
|
||||
// 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
|
||||
be_pop(berry.vm, 1);
|
||||
} else {
|
||||
|
@ -340,6 +361,12 @@ bool Xdrv52(uint8_t function)
|
|||
case FUNC_INIT:
|
||||
BrReset();
|
||||
break;
|
||||
case FUNC_LOOP:
|
||||
if (!berry.autoexec_done) {
|
||||
BrAutoexec();
|
||||
berry.autoexec_done = true;
|
||||
}
|
||||
break;
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
callBerryFunctionVoid(PSTR("_run_deferred"));
|
||||
break;
|
||||
|
@ -383,8 +410,6 @@ bool Xdrv52(uint8_t function)
|
|||
case FUNC_BUTTON_PRESSED:
|
||||
break;
|
||||
|
||||
case FUNC_LOOP:
|
||||
break;
|
||||
|
||||
}
|
||||
return result;
|
||||
|
|
Loading…
Reference in New Issue