Merge pull request #14937 from s-hadinger/berry_cron

Berry add cron timers
This commit is contained in:
s-hadinger 2022-02-21 22:47:30 +01:00 committed by GitHub
commit 7f6818f9f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 3925 additions and 1332 deletions

View File

@ -167,6 +167,7 @@ extern void be_load_webclient_lib(bvm *vm);
extern void be_load_tcpclient_lib(bvm *vm);
extern void be_load_udp_lib(bvm *vm);
extern void be_load_crypto_lib(bvm *vm);
extern void be_load_ccronexpr_class(bvm *vm);
extern void be_load_Leds_ntv_class(bvm *vm);
extern void be_load_Leds_class(bvm *vm);
extern void be_load_Leds_animator_class(bvm *vm);
@ -207,6 +208,7 @@ BERRY_API void be_load_custom_libs(bvm *vm)
be_load_md5_lib(vm);
be_load_serial_lib(vm);
be_load_ctypes_lib(vm);
be_load_ccronexpr_class(vm);
#ifdef USE_LIGHT
be_load_light_state_class(vm);
#endif

View File

@ -199,6 +199,7 @@ extern const bcstring be_const_str__buffer;
extern const bcstring be_const_str__ccmd;
extern const bcstring be_const_str__class;
extern const bcstring be_const_str__cmd;
extern const bcstring be_const_str__crons;
extern const bcstring be_const_str__debug_present;
extern const bcstring be_const_str__def;
extern const bcstring be_const_str__dirty;
@ -228,6 +229,7 @@ extern const bcstring be_const_str_acos;
extern const bcstring be_const_str_add;
extern const bcstring be_const_str_add_anim;
extern const bcstring be_const_str_add_cmd;
extern const bcstring be_const_str_add_cron;
extern const bcstring be_const_str_add_driver;
extern const bcstring be_const_str_add_event_cb;
extern const bcstring be_const_str_add_fast_loop;
@ -283,6 +285,7 @@ extern const bcstring be_const_str_cb;
extern const bcstring be_const_str_cb_do_nothing;
extern const bcstring be_const_str_cb_event_closure;
extern const bcstring be_const_str_cb_obj;
extern const bcstring be_const_str_ccronexpr;
extern const bcstring be_const_str_ceil;
extern const bcstring be_const_str_char;
extern const bcstring be_const_str_chars_in_string;
@ -385,6 +388,7 @@ extern const bcstring be_const_str_event;
extern const bcstring be_const_str_event_cb;
extern const bcstring be_const_str_event_send;
extern const bcstring be_const_str_every_100ms;
extern const bcstring be_const_str_every_250ms;
extern const bcstring be_const_str_every_50ms;
extern const bcstring be_const_str_every_second;
extern const bcstring be_const_str_except;
@ -577,10 +581,13 @@ extern const bcstring be_const_str_month;
extern const bcstring be_const_str_montserrat_font;
extern const bcstring be_const_str_name;
extern const bcstring be_const_str_nan;
extern const bcstring be_const_str_next;
extern const bcstring be_const_str_next_cron;
extern const bcstring be_const_str_nil;
extern const bcstring be_const_str_no_X20GPIO_X20specified_X20for_X20neopixelbus;
extern const bcstring be_const_str_null_cb;
extern const bcstring be_const_str_number;
extern const bcstring be_const_str_o;
extern const bcstring be_const_str_obj_class_create_obj;
extern const bcstring be_const_str_obj_event_base;
extern const bcstring be_const_str_offset;
@ -647,6 +654,7 @@ extern const bcstring be_const_str_remote_ip;
extern const bcstring be_const_str_remote_port;
extern const bcstring be_const_str_remove;
extern const bcstring be_const_str_remove_cmd;
extern const bcstring be_const_str_remove_cron;
extern const bcstring be_const_str_remove_driver;
extern const bcstring be_const_str_remove_light;
extern const bcstring be_const_str_remove_rule;
@ -673,6 +681,7 @@ extern const bcstring be_const_str_rtc;
extern const bcstring be_const_str_rule;
extern const bcstring be_const_str_run;
extern const bcstring be_const_str_run_bat;
extern const bcstring be_const_str_run_cron;
extern const bcstring be_const_str_run_deferred;
extern const bcstring be_const_str_running;
extern const bcstring be_const_str_sat;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
#include "be_constobj.h"
static be_define_const_map_slots(be_class_ccronexpr_map) {
{ be_const_key(deinit, 2), be_const_ctype_func(ccronexpr_init) },
{ be_const_key(_X2Ep, -1), be_const_var(0) },
{ be_const_key(next, -1), be_const_ctype_func(ccronexpr_next) },
{ be_const_key(init, 1), be_const_ctype_func(ccronexpr_init) },
};
static be_define_const_map(
be_class_ccronexpr_map,
4
);
BE_EXPORT_VARIABLE be_define_const_class(
be_class_ccronexpr,
1,
NULL,
ccronexpr
);

View File

@ -1,97 +1,102 @@
#include "be_constobj.h"
static be_define_const_map_slots(be_class_tasmota_map) {
{ be_const_key(get_power, -1), be_const_func(l_getpower) },
{ be_const_key(gc, -1), be_const_closure(Tasmota_gc_closure) },
{ be_const_key(response_append, -1), be_const_func(l_respAppend) },
{ be_const_key(resp_cmnd_done, 29), be_const_func(l_respCmndDone) },
{ be_const_key(try_rule, -1), be_const_closure(Tasmota_try_rule_closure) },
{ be_const_key(get_light, 8), be_const_closure(Tasmota_get_light_closure) },
{ be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) },
{ be_const_key(eth, 76), be_const_func(l_eth) },
{ be_const_key(time_dump, -1), be_const_func(l_time_dump) },
{ be_const_key(cmd_res, -1), be_const_var(0) },
{ be_const_key(_drivers, 18), be_const_var(1) },
{ be_const_key(find_key_i, -1), be_const_closure(Tasmota_find_key_i_closure) },
{ be_const_key(set_timer, -1), be_const_closure(Tasmota_set_timer_closure) },
{ be_const_key(load, 9), be_const_closure(Tasmota_load_closure) },
{ be_const_key(set_light, 15), be_const_closure(Tasmota_set_light_closure) },
{ be_const_key(fast_loop, -1), be_const_closure(Tasmota_fast_loop_closure) },
{ be_const_key(settings, -1), be_const_var(2) },
{ be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) },
{ be_const_key(strptime, -1), be_const_func(l_strptime) },
{ be_const_key(init, 20), be_const_closure(Tasmota_init_closure) },
{ be_const_key(get_option, -1), be_const_func(l_getoption) },
{ be_const_key(memory, 37), be_const_func(l_memory) },
{ be_const_key(find_op, -1), be_const_closure(Tasmota_find_op_closure) },
{ be_const_key(yield, -1), be_const_func(l_yield) },
{ be_const_key(publish_result, 19), be_const_func(l_publish_result) },
{ be_const_key(_timers, 33), be_const_var(3) },
{ be_const_key(_ccmd, 75), be_const_var(4) },
{ be_const_key(read_sensors, 26), be_const_func(l_read_sensors) },
{ be_const_key(rtc, -1), be_const_func(l_rtc) },
{ be_const_key(delay, 73), be_const_func(l_delay) },
{ be_const_key(event, 35), be_const_closure(Tasmota_event_closure) },
{ be_const_key(web_send, 12), be_const_func(l_webSend) },
{ be_const_key(i2c_enabled, 78), be_const_func(l_i2cenabled) },
{ be_const_key(resp_cmnd_done, -1), be_const_func(l_respCmndDone) },
{ be_const_key(web_send, 33), be_const_func(l_webSend) },
{ be_const_key(add_driver, 21), be_const_closure(Tasmota_add_driver_closure) },
{ be_const_key(wd, 16), be_const_var(0) },
{ be_const_key(resp_cmnd_error, 25), be_const_func(l_respCmndError) },
{ be_const_key(publish, 71), be_const_func(l_publish) },
{ be_const_key(gen_cb, 0), be_const_closure(Tasmota_gen_cb_closure) },
{ be_const_key(_settings_ptr, -1), be_const_comptr(&Settings) },
{ be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) },
{ be_const_key(cmd, -1), be_const_closure(Tasmota_cmd_closure) },
{ be_const_key(_cmd, 62), be_const_func(l_cmd) },
{ be_const_key(wifi, 71), be_const_func(l_wifi) },
{ be_const_key(wire_scan, -1), be_const_closure(Tasmota_wire_scan_closure) },
{ be_const_key(resp_cmnd, 17), be_const_func(l_respCmnd) },
{ be_const_key(wire2, -1), be_const_var(5) },
{ be_const_key(get_switch, 51), be_const_func(l_getswitch) },
{ be_const_key(chars_in_string, -1), be_const_closure(Tasmota_chars_in_string_closure) },
{ be_const_key(remove_cmd, 7), be_const_closure(Tasmota_remove_cmd_closure) },
{ be_const_key(_fl, 1), be_const_var(6) },
{ be_const_key(hs2rgb, -1), be_const_closure(Tasmota_hs2rgb_closure) },
{ be_const_key(wd, 38), be_const_var(7) },
{ be_const_key(get_free_heap, -1), be_const_func(l_getFreeHeap) },
{ be_const_key(strftime, -1), be_const_func(l_strftime) },
{ be_const_key(_global_addr, 65), be_const_comptr(&TasmotaGlobal) },
{ be_const_key(exec_tele, -1), be_const_closure(Tasmota_exec_tele_closure) },
{ be_const_key(time_reached, -1), be_const_func(l_timereached) },
{ be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) },
{ be_const_key(remove_rule, 67), be_const_closure(Tasmota_remove_rule_closure) },
{ be_const_key(gen_cb, -1), be_const_closure(Tasmota_gen_cb_closure) },
{ be_const_key(exec_cmd, -1), be_const_closure(Tasmota_exec_cmd_closure) },
{ be_const_key(time_str, 14), be_const_closure(Tasmota_time_str_closure) },
{ be_const_key(exec_rules, -1), be_const_closure(Tasmota_exec_rules_closure) },
{ be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) },
{ be_const_key(global, 4), be_const_var(8) },
{ be_const_key(kv, 2), be_const_closure(Tasmota_kv_closure) },
{ be_const_key(add_fast_loop, -1), be_const_closure(Tasmota_add_fast_loop_closure) },
{ be_const_key(resp_cmnd_failed, -1), be_const_func(l_respCmndFailed) },
{ be_const_key(log, -1), be_const_func(l_logInfo) },
{ be_const_key(add_cmd, -1), be_const_closure(Tasmota_add_cmd_closure) },
{ be_const_key(remove_timer, -1), be_const_closure(Tasmota_remove_timer_closure) },
{ be_const_key(millis, 58), be_const_func(l_millis) },
{ be_const_key(scale_uint, -1), be_const_func(l_scaleuint) },
{ be_const_key(run_deferred, -1), be_const_closure(Tasmota_run_deferred_closure) },
{ be_const_key(_debug_present, 30), be_const_var(9) },
{ be_const_key(remove_driver, -1), be_const_closure(Tasmota_remove_driver_closure) },
{ be_const_key(try_rule, -1), be_const_closure(Tasmota_try_rule_closure) },
{ be_const_key(set_timer, -1), be_const_closure(Tasmota_set_timer_closure) },
{ be_const_key(time_dump, -1), be_const_func(l_time_dump) },
{ be_const_key(cmd_res, -1), be_const_var(1) },
{ be_const_key(millis, 35), be_const_func(l_millis) },
{ be_const_key(chars_in_string, 82), be_const_closure(Tasmota_chars_in_string_closure) },
{ be_const_key(get_power, -1), be_const_func(l_getpower) },
{ be_const_key(set_light, 40), be_const_closure(Tasmota_set_light_closure) },
{ be_const_key(set_power, -1), be_const_func(l_setpower) },
{ be_const_key(check_not_method, -1), be_const_closure(Tasmota_check_not_method_closure) },
{ be_const_key(resolvecmnd, 74), be_const_func(l_resolveCmnd) },
{ be_const_key(arch, -1), be_const_func(l_arch) },
{ be_const_key(fast_loop, -1), be_const_closure(Tasmota_fast_loop_closure) },
{ be_const_key(get_option, -1), be_const_func(l_getoption) },
{ be_const_key(add_cron, -1), be_const_closure(Tasmota_add_cron_closure) },
{ be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) },
{ be_const_key(init, 41), be_const_closure(Tasmota_init_closure) },
{ be_const_key(add_rule, 19), be_const_closure(Tasmota_add_rule_closure) },
{ be_const_key(resp_cmnd_failed, -1), be_const_func(l_respCmndFailed) },
{ be_const_key(exec_tele, -1), be_const_closure(Tasmota_exec_tele_closure) },
{ be_const_key(add_fast_loop, -1), be_const_closure(Tasmota_add_fast_loop_closure) },
{ be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) },
{ be_const_key(yield, 73), be_const_func(l_yield) },
{ be_const_key(next_cron, -1), be_const_closure(Tasmota_next_cron_closure) },
{ be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) },
{ be_const_key(time_reached, 11), be_const_func(l_timereached) },
{ be_const_key(delay, -1), be_const_func(l_delay) },
{ be_const_key(rtc, -1), be_const_func(l_rtc) },
{ be_const_key(wire2, -1), be_const_var(2) },
{ be_const_key(add_cmd, 75), be_const_closure(Tasmota_add_cmd_closure) },
{ be_const_key(exec_rules, 12), be_const_closure(Tasmota_exec_rules_closure) },
{ be_const_key(strptime, 74), be_const_func(l_strptime) },
{ be_const_key(wire_scan, -1), be_const_closure(Tasmota_wire_scan_closure) },
{ be_const_key(run_cron, 10), be_const_closure(Tasmota_run_cron_closure) },
{ be_const_key(get_light, 46), be_const_closure(Tasmota_get_light_closure) },
{ be_const_key(cmd, -1), be_const_closure(Tasmota_cmd_closure) },
{ be_const_key(remove_cmd, -1), be_const_closure(Tasmota_remove_cmd_closure) },
{ be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) },
{ be_const_key(_fl, -1), be_const_var(3) },
{ be_const_key(i2c_enabled, -1), be_const_func(l_i2cenabled) },
{ be_const_key(global, -1), be_const_var(4) },
{ be_const_key(_debug_present, 39), be_const_var(5) },
{ be_const_key(run_deferred, 18), be_const_closure(Tasmota_run_deferred_closure) },
{ be_const_key(load, -1), be_const_closure(Tasmota_load_closure) },
{ be_const_key(get_switch, 56), be_const_func(l_getswitch) },
{ be_const_key(_ccmd, -1), be_const_var(6) },
{ be_const_key(kv, 14), be_const_closure(Tasmota_kv_closure) },
{ be_const_key(event, 22), be_const_closure(Tasmota_event_closure) },
{ be_const_key(get_free_heap, -1), be_const_func(l_getFreeHeap) },
{ be_const_key(_rules, 20), be_const_var(7) },
{ be_const_key(_timers, -1), be_const_var(8) },
{ be_const_key(remove_timer, 5), be_const_closure(Tasmota_remove_timer_closure) },
{ be_const_key(eth, -1), be_const_func(l_eth) },
{ be_const_key(arch, 65), be_const_func(l_arch) },
{ be_const_key(remove_driver, -1), be_const_closure(Tasmota_remove_driver_closure) },
{ be_const_key(response_append, -1), be_const_func(l_respAppend) },
{ be_const_key(wifi, -1), be_const_func(l_wifi) },
{ be_const_key(log, -1), be_const_func(l_logInfo) },
{ be_const_key(find_op, 78), be_const_closure(Tasmota_find_op_closure) },
{ be_const_key(hs2rgb, -1), be_const_closure(Tasmota_hs2rgb_closure) },
{ be_const_key(find_key_i, -1), be_const_closure(Tasmota_find_key_i_closure) },
{ be_const_key(_global_addr, -1), be_const_comptr(&TasmotaGlobal) },
{ be_const_key(save, -1), be_const_func(l_save) },
{ be_const_key(add_rule, -1), be_const_closure(Tasmota_add_rule_closure) },
{ be_const_key(publish, -1), be_const_func(l_publish) },
{ be_const_key(wire1, 77), be_const_var(10) },
{ be_const_key(_rules, 28), be_const_var(11) },
{ be_const_key(add_driver, -1), be_const_closure(Tasmota_add_driver_closure) },
{ be_const_key(exec_cmd, 37), be_const_closure(Tasmota_exec_cmd_closure) },
{ be_const_key(remove_rule, -1), be_const_closure(Tasmota_remove_rule_closure) },
{ be_const_key(publish_result, -1), be_const_func(l_publish_result) },
{ be_const_key(settings, -1), be_const_var(9) },
{ be_const_key(time_str, -1), be_const_closure(Tasmota_time_str_closure) },
{ be_const_key(wire1, -1), be_const_var(10) },
{ be_const_key(_drivers, -1), be_const_var(11) },
{ be_const_key(scale_uint, 43), be_const_func(l_scaleuint) },
{ be_const_key(strftime, 9), be_const_func(l_strftime) },
{ be_const_key(_cmd, -1), be_const_func(l_cmd) },
{ be_const_key(check_not_method, -1), be_const_closure(Tasmota_check_not_method_closure) },
{ be_const_key(remove_cron, -1), be_const_closure(Tasmota_remove_cron_closure) },
{ be_const_key(resolvecmnd, 51), be_const_func(l_resolveCmnd) },
{ be_const_key(resp_cmnd, -1), be_const_func(l_respCmnd) },
{ be_const_key(_crons, 63), be_const_var(12) },
{ be_const_key(memory, -1), be_const_func(l_memory) },
{ be_const_key(read_sensors, 54), be_const_func(l_read_sensors) },
};
static be_define_const_map(
be_class_tasmota_map,
81
86
);
BE_EXPORT_VARIABLE be_define_const_class(
be_class_tasmota,
12,
13,
NULL,
Tasmota
);

View File

@ -157,6 +157,7 @@ int be_find_global_or_module_member(bvm *vm, const char * name) {
* '~': send the length of the previous bytes() buffer (or raise an exception if no length known)
* 'lv_obj' be_instance of type or subtype
* '^lv_event_cb^' callback of a named class - will call `_lvgl.gen_cb(arg_type, closure, self)` and expects a callback address in return
* '@': pass a pointer to the Berry VM (virtual parameter added, must be the first argument)
*
* Ex: ".ii" takes 3 arguments, first one is any type, followed by 2 ints
\*********************************************************************************************/
@ -301,6 +302,13 @@ int be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type, i
uint32_t p_idx = 0; // index in p[], is incremented with each parameter except '-'
int32_t buf_len = -1; // stores the length of a bytes() buffer to be used as '~' attribute
// special case when first parameter is '@', pass pointer to VM
if (NULL != arg_type && arg_type[arg_idx] == '@') {
arg_idx++;
p[p_idx] = vm;
p_idx++;
}
// special case when no parameters are passed but all are optional
if (NULL != arg_type && arg_type[arg_idx] == '[') {
arg_optional = btrue;

View File

@ -0,0 +1,66 @@
/********************************************************************
* Light_state class - abstract light state
*
* Handles all states and events for a virtual light.
* Can be eventually subclassed to handle a physical light.
*
*******************************************************************/
#ifdef USE_LIGHT
#include "be_constobj.h"
#include "be_mapping.h"
#include "ccronexpr.h"
// create
static cron_expr* ccronexpr_init(struct bvm* vm, char* expr) {
cron_expr* cron = new cron_expr();
const char* error = nullptr;
cron_parse_expr(expr, cron, &error);
if (error) {
be_raise(vm, "value_error", error); // TODO any way to pass VM?
}
return cron;
}
BE_FUNC_CTYPE_DECLARE(ccronexpr_init, "+.p", "@s")
// deinit
static void ccronexpr_deinit(cron_expr* cron) {
delete cron;
}
BE_FUNC_CTYPE_DECLARE(ccronexpr_deinit, "", ".")
// next
static uint32_t ccronexpr_next(cron_expr* cron, uint32_t date) {
return cron_next(cron, date);
}
BE_FUNC_CTYPE_DECLARE(ccronexpr_next, "i", ".i")
// prev
static uint32_t ccronexpr_prev(cron_expr* cron, uint32_t date) {
return cron_prev(cron, date);
}
BE_FUNC_CTYPE_DECLARE(ccronexpr_prev, "i", ".i")
#include "be_fixed_be_class_ccronexpr.h"
extern "C" void be_load_ccronexpr_class(bvm *vm) {
be_pushntvclass(vm, &be_class_ccronexpr);
be_setglobal(vm, "ccronexpr");
be_pop(vm, 1);
}
/* @const_object_info_begin
class be_class_ccronexpr (scope: global, name: ccronexpr) {
.p, var // pointer to cron_expr*
init, ctype_func(ccronexpr_init)
deinit, ctype_func(ccronexpr_init)
next, ctype_func(ccronexpr_next)
}
@const_object_info_end */
#endif // USE_LIGHT

View File

@ -546,7 +546,7 @@ be_local_closure(Tasmota_exec_tele, /* name */
********************************************************************/
be_local_closure(Tasmota_run_deferred, /* name */
be_nested_proto(
6, /* nstack */
7, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
@ -566,34 +566,32 @@ be_local_closure(Tasmota_run_deferred, /* name */
}),
&be_const_str_run_deferred,
&be_const_str_solidified,
( &(const binstruction[27]) { /* code */
( &(const binstruction[25]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060017, // 0001 JMPF R1 #001A
0x78060015, // 0001 JMPF R1 #0018
0x58040001, // 0002 LDCONST R1 K1
0x88080100, // 0003 GETMBR R2 R0 K0
0x8C080502, // 0004 GETMET R2 R2 K2
0x7C080200, // 0005 CALL R2 1
0x14080202, // 0006 LT R2 R1 R2
0x780A0011, // 0007 JMPF R2 #001A
0x8C080103, // 0008 GETMET R2 R0 K3
0x88100100, // 0009 GETMBR R4 R0 K0
0x94100801, // 000A GETIDX R4 R4 R1
0x88100904, // 000B GETMBR R4 R4 K4
0x7C080400, // 000C CALL R2 2
0x780A0009, // 000D JMPF R2 #0018
0x88080100, // 000E GETMBR R2 R0 K0
0x94080401, // 000F GETIDX R2 R2 R1
0x88080505, // 0010 GETMBR R2 R2 K5
0x880C0100, // 0011 GETMBR R3 R0 K0
0x8C0C0706, // 0012 GETMET R3 R3 K6
0x5C140200, // 0013 MOVE R5 R1
0x7C0C0400, // 0014 CALL R3 2
0x5C0C0400, // 0015 MOVE R3 R2
0x7C0C0000, // 0016 CALL R3 0
0x70020000, // 0017 JMP #0019
0x00040307, // 0018 ADD R1 R1 K7
0x7001FFE8, // 0019 JMP #0003
0x80000000, // 001A RET 0
0x780A000F, // 0007 JMPF R2 #0018
0x88080100, // 0008 GETMBR R2 R0 K0
0x94080401, // 0009 GETIDX R2 R2 R1
0x8C0C0103, // 000A GETMET R3 R0 K3
0x88140504, // 000B GETMBR R5 R2 K4
0x7C0C0400, // 000C CALL R3 2
0x780E0007, // 000D JMPF R3 #0016
0x880C0505, // 000E GETMBR R3 R2 K5
0x88100100, // 000F GETMBR R4 R0 K0
0x8C100906, // 0010 GETMET R4 R4 K6
0x5C180200, // 0011 MOVE R6 R1
0x7C100400, // 0012 CALL R4 2
0x5C100600, // 0013 MOVE R4 R3
0x7C100000, // 0014 CALL R4 0
0x70020000, // 0015 JMP #0017
0x00040307, // 0016 ADD R1 R1 K7
0x7001FFEA, // 0017 JMP #0003
0x80000000, // 0018 RET 0
})
)
);
@ -749,125 +747,134 @@ be_local_closure(Tasmota_event, /* name */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[23]) { /* constants */
( &(const bvalue[26]) { /* constants */
/* K0 */ be_nested_str(introspect),
/* K1 */ be_nested_str(string),
/* K2 */ be_nested_str(every_50ms),
/* K3 */ be_nested_str(run_deferred),
/* K4 */ be_nested_str(cmd),
/* K5 */ be_nested_str(exec_cmd),
/* K6 */ be_nested_str(tele),
/* K7 */ be_nested_str(exec_tele),
/* K8 */ be_nested_str(rule),
/* K9 */ be_nested_str(exec_rules),
/* K10 */ be_nested_str(gc),
/* K11 */ be_nested_str(_drivers),
/* K12 */ be_const_int(0),
/* K13 */ be_nested_str(get),
/* K14 */ be_nested_str(function),
/* K15 */ be_nested_str(format),
/* K16 */ be_nested_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s),
/* K17 */ be_nested_str(debug),
/* K18 */ be_nested_str(traceback),
/* K19 */ be_const_int(1),
/* K20 */ be_nested_str(save_before_restart),
/* K21 */ be_nested_str(persist),
/* K22 */ be_nested_str(save),
/* K4 */ be_nested_str(every_250ms),
/* K5 */ be_nested_str(run_cron),
/* K6 */ be_nested_str(cmd),
/* K7 */ be_nested_str(exec_cmd),
/* K8 */ be_nested_str(tele),
/* K9 */ be_nested_str(exec_tele),
/* K10 */ be_nested_str(rule),
/* K11 */ be_nested_str(exec_rules),
/* K12 */ be_nested_str(gc),
/* K13 */ be_nested_str(_drivers),
/* K14 */ be_const_int(0),
/* K15 */ be_nested_str(get),
/* K16 */ be_nested_str(function),
/* K17 */ be_nested_str(format),
/* K18 */ be_nested_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s),
/* K19 */ be_nested_str(_debug_present),
/* K20 */ be_nested_str(debug),
/* K21 */ be_nested_str(traceback),
/* K22 */ be_const_int(1),
/* K23 */ be_nested_str(save_before_restart),
/* K24 */ be_nested_str(persist),
/* K25 */ be_nested_str(save),
}),
&be_const_str_event,
&be_const_str_solidified,
( &(const binstruction[91]) { /* code */
( &(const binstruction[97]) { /* code */
0xA41A0000, // 0000 IMPORT R6 K0
0xA41E0200, // 0001 IMPORT R7 K1
0x1C200302, // 0002 EQ R8 R1 K2
0x78220001, // 0003 JMPF R8 #0006
0x8C200103, // 0004 GETMET R8 R0 K3
0x7C200200, // 0005 CALL R8 1
0x50200000, // 0006 LDBOOL R8 0 0
0x1C240304, // 0007 EQ R9 R1 K4
0x78260006, // 0008 JMPF R9 #0010
0x8C240105, // 0009 GETMET R9 R0 K5
0x5C2C0400, // 000A MOVE R11 R2
0x5C300600, // 000B MOVE R12 R3
0x5C340800, // 000C MOVE R13 R4
0x7C240800, // 000D CALL R9 4
0x80041200, // 000E RET 1 R9
0x70020044, // 000F JMP #0055
0x1C240306, // 0010 EQ R9 R1 K6
0x78260004, // 0011 JMPF R9 #0017
0x8C240107, // 0012 GETMET R9 R0 K7
0x5C2C0800, // 0013 MOVE R11 R4
0x7C240400, // 0014 CALL R9 2
0x80041200, // 0015 RET 1 R9
0x7002003D, // 0016 JMP #0055
0x1C240308, // 0017 EQ R9 R1 K8
0x78260004, // 0018 JMPF R9 #001E
0x8C240109, // 0019 GETMET R9 R0 K9
0x5C2C0800, // 001A MOVE R11 R4
0x7C240400, // 001B CALL R9 2
0x80041200, // 001C RET 1 R9
0x70020036, // 001D JMP #0055
0x1C24030A, // 001E EQ R9 R1 K10
0x78260003, // 001F JMPF R9 #0024
0x8C24010A, // 0020 GETMET R9 R0 K10
0x7C240200, // 0021 CALL R9 1
0x80041200, // 0022 RET 1 R9
0x70020030, // 0023 JMP #0055
0x8824010B, // 0024 GETMBR R9 R0 K11
0x7826002E, // 0025 JMPF R9 #0055
0x5824000C, // 0026 LDCONST R9 K12
0x6028000C, // 0027 GETGBL R10 G12
0x882C010B, // 0028 GETMBR R11 R0 K11
0x7C280200, // 0029 CALL R10 1
0x1428120A, // 002A LT R10 R9 R10
0x782A0028, // 002B JMPF R10 #0055
0x8828010B, // 002C GETMBR R10 R0 K11
0x94281409, // 002D GETIDX R10 R10 R9
0x8C2C0D0D, // 002E GETMET R11 R6 K13
0x5C341400, // 002F MOVE R13 R10
0x5C380200, // 0030 MOVE R14 R1
0x7C2C0600, // 0031 CALL R11 3
0x60300004, // 0032 GETGBL R12 G4
0x5C341600, // 0033 MOVE R13 R11
0x7C300200, // 0034 CALL R12 1
0x1C30190E, // 0035 EQ R12 R12 K14
0x7832001B, // 0036 JMPF R12 #0053
0xA802000C, // 0037 EXBLK 0 #0045
0x5C301600, // 0038 MOVE R12 R11
0x5C341400, // 0039 MOVE R13 R10
0x5C380400, // 003A MOVE R14 R2
0x5C3C0600, // 003B MOVE R15 R3
0x5C400800, // 003C MOVE R16 R4
0x5C440A00, // 003D MOVE R17 R5
0x7C300A00, // 003E CALL R12 5
0x5C201800, // 003F MOVE R8 R12
0x78220001, // 0040 JMPF R8 #0043
0xA8040001, // 0041 EXBLK 1 1
0x70020011, // 0042 JMP #0055
0xA8040001, // 0043 EXBLK 1 1
0x7002000D, // 0044 JMP #0053
0xAC300002, // 0045 CATCH R12 0 2
0x7002000A, // 0046 JMP #0052
0x60380001, // 0047 GETGBL R14 G1
0x8C3C0F0F, // 0048 GETMET R15 R7 K15
0x58440010, // 0049 LDCONST R17 K16
0x5C481800, // 004A MOVE R18 R12
0x5C4C1A00, // 004B MOVE R19 R13
0x7C3C0800, // 004C CALL R15 4
0x7C380200, // 004D CALL R14 1
0xA43A2200, // 004E IMPORT R14 K17
0x8C3C1D12, // 004F GETMET R15 R14 K18
0x7C3C0200, // 0050 CALL R15 1
0x70020000, // 0051 JMP #0053
0xB0080000, // 0052 RAISE 2 R0 R0
0x00241313, // 0053 ADD R9 R9 K19
0x7001FFD1, // 0054 JMP #0027
0x1C240314, // 0055 EQ R9 R1 K20
0x78260002, // 0056 JMPF R9 #005A
0xA4262A00, // 0057 IMPORT R9 K21
0x8C281316, // 0058 GETMET R10 R9 K22
0x7C280200, // 0059 CALL R10 1
0x80041000, // 005A RET 1 R8
0x1C200304, // 0006 EQ R8 R1 K4
0x78220001, // 0007 JMPF R8 #000A
0x8C200105, // 0008 GETMET R8 R0 K5
0x7C200200, // 0009 CALL R8 1
0x50200000, // 000A LDBOOL R8 0 0
0x1C240306, // 000B EQ R9 R1 K6
0x78260006, // 000C JMPF R9 #0014
0x8C240107, // 000D GETMET R9 R0 K7
0x5C2C0400, // 000E MOVE R11 R2
0x5C300600, // 000F MOVE R12 R3
0x5C340800, // 0010 MOVE R13 R4
0x7C240800, // 0011 CALL R9 4
0x80041200, // 0012 RET 1 R9
0x70020046, // 0013 JMP #005B
0x1C240308, // 0014 EQ R9 R1 K8
0x78260004, // 0015 JMPF R9 #001B
0x8C240109, // 0016 GETMET R9 R0 K9
0x5C2C0800, // 0017 MOVE R11 R4
0x7C240400, // 0018 CALL R9 2
0x80041200, // 0019 RET 1 R9
0x7002003F, // 001A JMP #005B
0x1C24030A, // 001B EQ R9 R1 K10
0x78260004, // 001C JMPF R9 #0022
0x8C24010B, // 001D GETMET R9 R0 K11
0x5C2C0800, // 001E MOVE R11 R4
0x7C240400, // 001F CALL R9 2
0x80041200, // 0020 RET 1 R9
0x70020038, // 0021 JMP #005B
0x1C24030C, // 0022 EQ R9 R1 K12
0x78260003, // 0023 JMPF R9 #0028
0x8C24010C, // 0024 GETMET R9 R0 K12
0x7C240200, // 0025 CALL R9 1
0x80041200, // 0026 RET 1 R9
0x70020032, // 0027 JMP #005B
0x8824010D, // 0028 GETMBR R9 R0 K13
0x78260030, // 0029 JMPF R9 #005B
0x5824000E, // 002A LDCONST R9 K14
0x6028000C, // 002B GETGBL R10 G12
0x882C010D, // 002C GETMBR R11 R0 K13
0x7C280200, // 002D CALL R10 1
0x1428120A, // 002E LT R10 R9 R10
0x782A002A, // 002F JMPF R10 #005B
0x8828010D, // 0030 GETMBR R10 R0 K13
0x94281409, // 0031 GETIDX R10 R10 R9
0x8C2C0D0F, // 0032 GETMET R11 R6 K15
0x5C341400, // 0033 MOVE R13 R10
0x5C380200, // 0034 MOVE R14 R1
0x7C2C0600, // 0035 CALL R11 3
0x60300004, // 0036 GETGBL R12 G4
0x5C341600, // 0037 MOVE R13 R11
0x7C300200, // 0038 CALL R12 1
0x1C301910, // 0039 EQ R12 R12 K16
0x7832001D, // 003A JMPF R12 #0059
0xA802000C, // 003B EXBLK 0 #0049
0x5C301600, // 003C MOVE R12 R11
0x5C341400, // 003D MOVE R13 R10
0x5C380400, // 003E MOVE R14 R2
0x5C3C0600, // 003F MOVE R15 R3
0x5C400800, // 0040 MOVE R16 R4
0x5C440A00, // 0041 MOVE R17 R5
0x7C300A00, // 0042 CALL R12 5
0x5C201800, // 0043 MOVE R8 R12
0x78220001, // 0044 JMPF R8 #0047
0xA8040001, // 0045 EXBLK 1 1
0x70020013, // 0046 JMP #005B
0xA8040001, // 0047 EXBLK 1 1
0x7002000F, // 0048 JMP #0059
0xAC300002, // 0049 CATCH R12 0 2
0x7002000C, // 004A JMP #0058
0x60380001, // 004B GETGBL R14 G1
0x8C3C0F11, // 004C GETMET R15 R7 K17
0x58440012, // 004D LDCONST R17 K18
0x5C481800, // 004E MOVE R18 R12
0x5C4C1A00, // 004F MOVE R19 R13
0x7C3C0800, // 0050 CALL R15 4
0x7C380200, // 0051 CALL R14 1
0x88380113, // 0052 GETMBR R14 R0 K19
0x783A0002, // 0053 JMPF R14 #0057
0xA43A2800, // 0054 IMPORT R14 K20
0x8C3C1D15, // 0055 GETMET R15 R14 K21
0x7C3C0200, // 0056 CALL R15 1
0x70020000, // 0057 JMP #0059
0xB0080000, // 0058 RAISE 2 R0 R0
0x00241316, // 0059 ADD R9 R9 K22
0x7001FFCF, // 005A JMP #002B
0x1C240317, // 005B EQ R9 R1 K23
0x78260002, // 005C JMPF R9 #0060
0xA4263000, // 005D IMPORT R9 K24
0x8C281319, // 005E GETMET R10 R9 K25
0x7C280200, // 005F CALL R10 1
0x80041000, // 0060 RET 1 R8
})
)
);
@ -1949,6 +1956,185 @@ be_local_closure(Tasmota_set_timer, /* name */
** Solidified function: remove_timer
********************************************************************/
be_local_closure(Tasmota_remove_timer, /* name */
be_nested_proto(
7, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_nested_str(_timers),
/* K1 */ be_const_int(0),
/* K2 */ be_nested_str(size),
/* K3 */ be_nested_str(id),
/* K4 */ be_nested_str(remove),
/* K5 */ be_const_int(1),
}),
&be_const_str_remove_timer,
&be_const_str_solidified,
( &(const binstruction[18]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x780A000E, // 0001 JMPF R2 #0011
0x580C0001, // 0002 LDCONST R3 K1
0x8C100502, // 0003 GETMET R4 R2 K2
0x7C100200, // 0004 CALL R4 1
0x14100604, // 0005 LT R4 R3 R4
0x78120009, // 0006 JMPF R4 #0011
0x94100403, // 0007 GETIDX R4 R2 R3
0x88100903, // 0008 GETMBR R4 R4 K3
0x1C100801, // 0009 EQ R4 R4 R1
0x78120003, // 000A JMPF R4 #000F
0x8C100504, // 000B GETMET R4 R2 K4
0x5C180600, // 000C MOVE R6 R3
0x7C100400, // 000D CALL R4 2
0x70020000, // 000E JMP #0010
0x000C0705, // 000F ADD R3 R3 K5
0x7001FFF1, // 0010 JMP #0003
0x80000000, // 0011 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: add_cron
********************************************************************/
be_local_closure(Tasmota_add_cron, /* name */
be_nested_proto(
13, /* nstack */
4, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 8]) { /* constants */
/* K0 */ be_nested_str(check_not_method),
/* K1 */ be_nested_str(_crons),
/* K2 */ be_nested_str(ccronexpr),
/* K3 */ be_nested_str(next),
/* K4 */ be_nested_str(rtc),
/* K5 */ be_nested_str(local),
/* K6 */ be_nested_str(push),
/* K7 */ be_nested_str(Trigger),
}),
&be_const_str_add_cron,
&be_const_str_solidified,
( &(const binstruction[28]) { /* code */
0x8C100100, // 0000 GETMET R4 R0 K0
0x5C180400, // 0001 MOVE R6 R2
0x7C100400, // 0002 CALL R4 2
0x88100101, // 0003 GETMBR R4 R0 K1
0x74120002, // 0004 JMPT R4 #0008
0x60100012, // 0005 GETGBL R4 G18
0x7C100000, // 0006 CALL R4 0
0x90020204, // 0007 SETMBR R0 K1 R4
0xB8120400, // 0008 GETNGBL R4 K2
0x60140008, // 0009 GETGBL R5 G8
0x5C180200, // 000A MOVE R6 R1
0x7C140200, // 000B CALL R5 1
0x7C100200, // 000C CALL R4 1
0x8C140903, // 000D GETMET R5 R4 K3
0x8C1C0104, // 000E GETMET R7 R0 K4
0x7C1C0200, // 000F CALL R7 1
0x941C0F05, // 0010 GETIDX R7 R7 K5
0x7C140400, // 0011 CALL R5 2
0x88180101, // 0012 GETMBR R6 R0 K1
0x8C180D06, // 0013 GETMET R6 R6 K6
0xB8220E00, // 0014 GETNGBL R8 K7
0x5C240A00, // 0015 MOVE R9 R5
0x5C280400, // 0016 MOVE R10 R2
0x5C2C0600, // 0017 MOVE R11 R3
0x5C300800, // 0018 MOVE R12 R4
0x7C200800, // 0019 CALL R8 4
0x7C180400, // 001A CALL R6 2
0x80000000, // 001B RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: run_cron
********************************************************************/
be_local_closure(Tasmota_run_cron, /* name */
be_nested_proto(
9, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[10]) { /* constants */
/* K0 */ be_nested_str(_crons),
/* K1 */ be_const_int(0),
/* K2 */ be_nested_str(rtc),
/* K3 */ be_nested_str(local),
/* K4 */ be_nested_str(size),
/* K5 */ be_nested_str(trig),
/* K6 */ be_nested_str(f),
/* K7 */ be_nested_str(next),
/* K8 */ be_nested_str(remove),
/* K9 */ be_const_int(1),
}),
&be_const_str_run_cron,
&be_const_str_solidified,
( &(const binstruction[37]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060021, // 0001 JMPF R1 #0024
0x58040001, // 0002 LDCONST R1 K1
0x8C080102, // 0003 GETMET R2 R0 K2
0x7C080200, // 0004 CALL R2 1
0x94080503, // 0005 GETIDX R2 R2 K3
0x880C0100, // 0006 GETMBR R3 R0 K0
0x8C0C0704, // 0007 GETMET R3 R3 K4
0x7C0C0200, // 0008 CALL R3 1
0x140C0203, // 0009 LT R3 R1 R3
0x780E0018, // 000A JMPF R3 #0024
0x880C0100, // 000B GETMBR R3 R0 K0
0x940C0601, // 000C GETIDX R3 R3 R1
0x88100705, // 000D GETMBR R4 R3 K5
0x18100802, // 000E LE R4 R4 R2
0x78120011, // 000F JMPF R4 #0022
0x88100706, // 0010 GETMBR R4 R3 K6
0x8C140707, // 0011 GETMET R5 R3 K7
0x5C1C0400, // 0012 MOVE R7 R2
0x7C140400, // 0013 CALL R5 2
0x5C180A00, // 0014 MOVE R6 R5
0x741A0004, // 0015 JMPT R6 #001B
0x88180100, // 0016 GETMBR R6 R0 K0
0x8C180D08, // 0017 GETMET R6 R6 K8
0x5C200200, // 0018 MOVE R8 R1
0x7C180400, // 0019 CALL R6 2
0x70020001, // 001A JMP #001D
0x900E0A05, // 001B SETMBR R3 K5 R5
0x00040309, // 001C ADD R1 R1 K9
0x5C180800, // 001D MOVE R6 R4
0x5C1C0400, // 001E MOVE R7 R2
0x5C200A00, // 001F MOVE R8 R5
0x7C180400, // 0020 CALL R6 2
0x70020000, // 0021 JMP #0023
0x00040309, // 0022 ADD R1 R1 K9
0x7001FFE1, // 0023 JMP #0006
0x80000000, // 0024 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: next_cron
********************************************************************/
be_local_closure(Tasmota_next_cron, /* name */
be_nested_proto(
6, /* nstack */
2, /* argc */
@ -1958,41 +2144,80 @@ be_local_closure(Tasmota_remove_timer, /* name */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 7]) { /* constants */
/* K0 */ be_nested_str(tasmota),
/* K1 */ be_nested_str(_timers),
/* K2 */ be_const_int(0),
/* K3 */ be_nested_str(size),
/* K4 */ be_nested_str(id),
/* K5 */ be_nested_str(remove),
/* K6 */ be_const_int(1),
( &(const bvalue[ 5]) { /* constants */
/* K0 */ be_nested_str(_crons),
/* K1 */ be_const_int(0),
/* K2 */ be_nested_str(size),
/* K3 */ be_nested_str(id),
/* K4 */ be_nested_str(trig),
}),
&be_const_str_remove_timer,
&be_const_str_next_cron,
&be_const_str_solidified,
( &(const binstruction[23]) { /* code */
0xB80A0000, // 0000 GETNGBL R2 K0
0x88080501, // 0001 GETMBR R2 R2 K1
0x780A0012, // 0002 JMPF R2 #0016
0x58080002, // 0003 LDCONST R2 K2
0xB80E0000, // 0004 GETNGBL R3 K0
0x880C0701, // 0005 GETMBR R3 R3 K1
0x8C0C0703, // 0006 GETMET R3 R3 K3
0x7C0C0200, // 0007 CALL R3 1
0x140C0403, // 0008 LT R3 R2 R3
0x780E000B, // 0009 JMPF R3 #0016
0x880C0101, // 000A GETMBR R3 R0 K1
0x940C0602, // 000B GETIDX R3 R3 R2
0x880C0704, // 000C GETMBR R3 R3 K4
0x1C0C0601, // 000D EQ R3 R3 R1
0x780E0004, // 000E JMPF R3 #0014
0x880C0101, // 000F GETMBR R3 R0 K1
0x8C0C0705, // 0010 GETMET R3 R3 K5
0x5C140400, // 0011 MOVE R5 R2
0x7C0C0400, // 0012 CALL R3 2
0x70020000, // 0013 JMP #0015
0x00080506, // 0014 ADD R2 R2 K6
0x7001FFED, // 0015 JMP #0004
0x80000000, // 0016 RET 0
( &(const binstruction[16]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x780A000C, // 0001 JMPF R2 #000F
0x580C0001, // 0002 LDCONST R3 K1
0x8C100502, // 0003 GETMET R4 R2 K2
0x7C100200, // 0004 CALL R4 1
0x14100604, // 0005 LT R4 R3 R4
0x78120007, // 0006 JMPF R4 #000F
0x94100403, // 0007 GETIDX R4 R2 R3
0x88100903, // 0008 GETMBR R4 R4 K3
0x1C100801, // 0009 EQ R4 R4 R1
0x78120002, // 000A JMPF R4 #000E
0x94100403, // 000B GETIDX R4 R2 R3
0x88100904, // 000C GETMBR R4 R4 K4
0x80040800, // 000D RET 1 R4
0x7001FFF3, // 000E JMP #0003
0x80000000, // 000F RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: remove_cron
********************************************************************/
be_local_closure(Tasmota_remove_cron, /* name */
be_nested_proto(
7, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_nested_str(_crons),
/* K1 */ be_const_int(0),
/* K2 */ be_nested_str(size),
/* K3 */ be_nested_str(id),
/* K4 */ be_nested_str(remove),
/* K5 */ be_const_int(1),
}),
&be_const_str_remove_cron,
&be_const_str_solidified,
( &(const binstruction[18]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x780A000E, // 0001 JMPF R2 #0011
0x580C0001, // 0002 LDCONST R3 K1
0x8C100502, // 0003 GETMET R4 R2 K2
0x7C100200, // 0004 CALL R4 1
0x14100604, // 0005 LT R4 R3 R4
0x78120009, // 0006 JMPF R4 #0011
0x94100403, // 0007 GETIDX R4 R2 R3
0x88100903, // 0008 GETMBR R4 R4 K3
0x1C100801, // 0009 EQ R4 R4 R1
0x78120003, // 000A JMPF R4 #000F
0x8C100504, // 000B GETMET R4 R2 K4
0x5C180600, // 000C MOVE R6 R3
0x7C100400, // 000D CALL R4 2
0x70020000, // 000E JMP #0010
0x000C0705, // 000F ADD R3 R3 K5
0x7001FFF1, // 0010 JMP #0003
0x80000000, // 0011 RET 0
})
)
);
@ -2157,6 +2382,7 @@ class be_class_tasmota (scope: global, name: Tasmota) {
_fl, var
_rules, var
_timers, var
_crons, var
_ccmd, var
_drivers, var
wire1, var
@ -2240,6 +2466,11 @@ class be_class_tasmota (scope: global, name: Tasmota) {
wire_scan, closure(Tasmota_wire_scan_closure)
time_str, closure(Tasmota_time_str_closure)
add_cron, closure(Tasmota_add_cron_closure)
run_cron, closure(Tasmota_run_cron_closure)
next_cron, closure(Tasmota_next_cron_closure)
remove_cron, closure(Tasmota_remove_cron_closure)
check_not_method, closure(Tasmota_check_not_method_closure)
hs2rgb, closure(Tasmota_hs2rgb_closure)

View File

@ -59,26 +59,62 @@ be_local_closure(Trigger_tostring, /* name */
********************************************************************/
be_local_closure(Trigger_init, /* name */
be_nested_proto(
4, /* nstack */
4, /* argc */
5, /* nstack */
5, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 3]) { /* constants */
( &(const bvalue[ 4]) { /* constants */
/* K0 */ be_nested_str(trig),
/* K1 */ be_nested_str(f),
/* K2 */ be_nested_str(id),
/* K3 */ be_nested_str(o),
}),
&be_const_str_init,
&be_const_str_solidified,
( &(const binstruction[ 4]) { /* code */
( &(const binstruction[ 5]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x90020202, // 0001 SETMBR R0 K1 R2
0x90020403, // 0002 SETMBR R0 K2 R3
0x80000000, // 0003 RET 0
0x90020604, // 0003 SETMBR R0 K3 R4
0x80000000, // 0004 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: next
********************************************************************/
be_local_closure(Trigger_next, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 2]) { /* constants */
/* K0 */ be_nested_str(o),
/* K1 */ be_nested_str(next),
}),
&be_const_str_next,
&be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x780A0004, // 0001 JMPF R2 #0007
0x88080100, // 0002 GETMBR R2 R0 K0
0x8C080501, // 0003 GETMET R2 R2 K1
0x5C100200, // 0004 MOVE R4 R1
0x7C080400, // 0005 CALL R2 2
0x80040400, // 0006 RET 1 R2
0x80000000, // 0007 RET 0
})
)
);
@ -89,15 +125,17 @@ be_local_closure(Trigger_init, /* name */
** Solidified class: Trigger
********************************************************************/
be_local_class(Trigger,
3,
4,
NULL,
be_nested_map(5,
be_nested_map(7,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key(tostring, 3), be_const_closure(Trigger_tostring_closure) },
{ be_const_key(id, 2), be_const_var(2) },
{ be_const_key(f, -1), be_const_var(1) },
{ be_const_key(f, 1), be_const_var(1) },
{ be_const_key(o, -1), be_const_var(3) },
{ be_const_key(init, -1), be_const_closure(Trigger_init_closure) },
{ be_const_key(trig, -1), be_const_var(0) },
{ be_const_key(id, 4), be_const_var(2) },
{ be_const_key(tostring, -1), be_const_closure(Trigger_tostring_closure) },
{ be_const_key(trig, 2), be_const_var(0) },
{ be_const_key(next, -1), be_const_closure(Trigger_next_closure) },
})),
be_str_literal("Trigger")
);

View File

@ -3,23 +3,32 @@
class Trigger
var trig, f, id
def init(trig, f, id)
var o # optional object
def init(trig, f, id, o)
self.trig = trig
self.f = f
self.id = id
self.o = o
end
def tostring()
import string
return string.format("<instance: %s(%s, %s, %s)", str(classof(self)),
str(self.trig), str(self.f), str(self.id))
end
# next(now) returns the next trigger, or nil if no more
def next(now)
if self.o
return self.o.next(now)
end
end
end
tasmota = nil
class Tasmota
var _fl # list of fast_loop registered closures
var _rules
var _timers
var _timers # holds both timers and cron
var _crons
var _ccmd
var _drivers
var wire1
@ -245,10 +254,50 @@ class Tasmota
if self._timers
var i=0
while i < self._timers.size()
if self.time_reached(self._timers[i].trig)
var f=self._timers[i].f
self._timers.remove(i)
var trigger = self._timers[i]
if self.time_reached(trigger.trig)
var f = trigger.f
self._timers.remove(i) # one shot event
f()
else
i += 1
end
end
end
end
def run_cron()
if self._crons
var i=0
var now = self.rtc()['local'] # now in epoch seconds
while i < self._crons.size()
var trigger = self._crons[i]
if trigger.trig <= now
var f = trigger.f
var next_time = trigger.next(now)
if !next_time
self._crons.remove(i) # one shot event
else
trigger.trig = next_time # recurring event
i += 1
end
f(now, next_time)
else
i += 1
end
end
end
end
def remove_timer(id)
var timers = self._timers
if timers
var i=0
while i < timers.size()
if timers[i].id == id
timers.remove(i)
else
i=i+1
end
@ -256,13 +305,24 @@ class Tasmota
end
end
# remove timers by id
def remove_timer(id)
if tasmota._timers
# crontab style recurring events
def add_cron(pattern,f,id)
self.check_not_method(f)
if !self._crons self._crons=[] end
var cron = ccronexpr(str(pattern)) # can fail, throwing an exception
var next_time = cron.next(self.rtc()['local'])
self._crons.push(Trigger(next_time, f, id, cron))
end
# remove cron by id
def remove_cron(id)
var crons = self._crons
if crons
var i=0
while i<tasmota._timers.size()
if self._timers[i].id == id
self._timers.remove(i)
while i < crons.size()
if crons[i].id == id
crons.remove(i)
else
i=i+1
end
@ -270,6 +330,19 @@ class Tasmota
end
end
# get next timestamp for cron
def next_cron(id)
var crons = self._crons
if crons
var i=0
while i < crons.size()
if crons[i].id == id
return crons[i].trig
end
end
end
end
# Add command to list
def add_cmd(c,f)
self.check_not_method(f)
@ -454,7 +527,13 @@ class Tasmota
def event(event_type, cmd, idx, payload, raw)
import introspect
import string
if event_type=='every_50ms' self.run_deferred() end #- first run deferred events -#
if event_type=='every_50ms'
self.run_deferred()
end #- first run deferred events -#
if event_type=='every_250ms'
self.run_cron()
end
var done = false
if event_type=='cmd' return self.exec_cmd(cmd, idx, payload)

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2015, staticlibs.net
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,97 @@
Cron expression parsing in ANSI C
=================================
[![travis](https://travis-ci.org/staticlibs/ccronexpr.svg?branch=master)](https://travis-ci.org/staticlibs/ccronexpr)
[![appveyor](https://ci.appveyor.com/api/projects/status/github/staticlibs/ccronexpr?svg=true)](https://ci.appveyor.com/project/staticlibs/ccronexpr)
Given a cron expression and a date, you can get the next date which satisfies the cron expression.
Supports cron expressions with `seconds` field. Based on implementation of [CronSequenceGenerator](https://github.com/spring-projects/spring-framework/blob/babbf6e8710ab937cd05ece20270f51490299270/spring-context/src/main/java/org/springframework/scheduling/support/CronSequenceGenerator.java) from Spring Framework.
Compiles and should work on Linux (GCC/Clang), Mac OS (Clang), Windows (MSVC), Android NDK, iOS and possibly on other platforms with `time.h` support.
Supports compilation in C (89) and in C++ modes.
Usage example
-------------
#include "ccronexpr.h"
cron_expr expr;
const char* err = NULL;
memset(&expr, 0, sizeof(expr));
cron_parse_expr("0 */2 1-4 * * *", &expr, &err);
if (err) ... /* invalid expression */
time_t cur = time(NULL);
time_t next = cron_next(&expr, cur);
Compilation and tests run examples
----------------------------------
gcc ccronexpr.c ccronexpr_test.c -I. -Wall -Wextra -std=c89 -DCRON_TEST_MALLOC -o a.out && ./a.out
g++ ccronexpr.c ccronexpr_test.c -I. -Wall -Wextra -std=c++11 -DCRON_TEST_MALLOC -o a.out && ./a.out
g++ ccronexpr.c ccronexpr_test.c -I. -Wall -Wextra -std=c++11 -DCRON_TEST_MALLOC -DCRON_COMPILE_AS_CXX -o a.out && ./a.out
clang ccronexpr.c ccronexpr_test.c -I. -Wall -Wextra -std=c89 -DCRON_TEST_MALLOC -o a.out && ./a.out
clang++ ccronexpr.c ccronexpr_test.c -I. -Wall -Wextra -std=c++11 -DCRON_TEST_MALLOC -o a.out && ./a.out
clang++ ccronexpr.c ccronexpr_test.c -I. -Wall -Wextra -std=c++11 -DCRON_TEST_MALLOC -DCRON_COMPILE_AS_CXX -o a.out && ./a.out
cl ccronexpr.c ccronexpr_test.c /W4 /D_CRT_SECURE_NO_WARNINGS && ccronexpr.exe
Examples of supported expressions
---------------------------------
Expression, input date, next date:
"*/15 * 1-4 * * *", "2012-07-01_09:53:50", "2012-07-02_01:00:00"
"0 */2 1-4 * * *", "2012-07-01_09:00:00", "2012-07-02_01:00:00"
"0 0 7 ? * MON-FRI", "2009-09-26_00:42:55", "2009-09-28_07:00:00"
"0 30 23 30 1/3 ?", "2011-04-30_23:30:00", "2011-07-30_23:30:00"
See more examples in [tests](https://github.com/staticlibs/ccronexpr/blob/a1343bc5a546b13430bd4ac72f3b047ac08f8192/ccronexpr_test.c#L251).
Timezones
---------
This implementation does not support explicit timezones handling. By default all dates are
processed as UTC (GMT) dates without timezone infomation.
To use local dates (current system timezone) instead of GMT compile with `-DCRON_USE_LOCAL_TIME`, example:
gcc -DCRON_USE_LOCAL_TIME ccronexpr.c ccronexpr_test.c -I. -Wall -Wextra -std=c89 -DCRON_TEST_MALLOC -o a.out && TZ="America/Toronto" ./a.out
License information
-------------------
This project is released under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
Changelog
---------
**2019-03-27**
* `CRON_USE_LOCAL_TIME` usage fixes
**2018-05-23**
* merged [#8](https://github.com/staticlibs/ccronexpr/pull/8)
* merged [#9](https://github.com/staticlibs/ccronexpr/pull/9)
* minor cleanups
**2018-01-27**
* merged [#6](https://github.com/staticlibs/ccronexpr/pull/6)
* updated license file (to the one parse-able by github)
**2017-09-24**
* merged [#4](https://github.com/staticlibs/ccronexpr/pull/4)
**2016-06-17**
* use thread-safe versions of `gmtime` and `localtime`
**2015-02-28**
* initial public version

View File

@ -0,0 +1,29 @@
# Copyright 2017, alex at staticlibs.net
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
image: Visual Studio 2017
configuration: Release
build: off
build_script:
- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat"
- cl ccronexpr.c ccronexpr_test.c /W4 /D_CRT_SECURE_NO_WARNINGS /Feccronexpr_32.exe
- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
- cl ccronexpr.c ccronexpr_test.c /W4 /D_CRT_SECURE_NO_WARNINGS /Feccronexpr_64.exe
test_script:
- ccronexpr_32.exe
- ccronexpr_64.exe

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
/*
* Copyright 2015, alex at staticlibs.net
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* File: ccronexpr.h
* Author: alex
*
* Created on February 24, 2015, 9:35 AM
*/
#ifndef CCRONEXPR_H
#define CCRONEXPR_H
#define CRON_USE_LOCAL_TIME
#if defined(__cplusplus) && !defined(CRON_COMPILE_AS_CXX)
extern "C" {
#endif
#ifndef ANDROID
#include <time.h>
#else /* ANDROID */
#include <time64.h>
#endif /* ANDROID */
#include <stdint.h> /*added for use if uint*_t data types*/
/**
* Parsed cron expression
*/
typedef struct {
uint8_t seconds[8];
uint8_t minutes[8];
uint8_t hours[3];
uint8_t days_of_week[1];
uint8_t days_of_month[4];
uint8_t months[2];
} cron_expr;
/**
* Parses specified cron expression.
*
* @param expression cron expression as nul-terminated string,
* should be no longer that 256 bytes
* @param pointer to cron expression structure, it's client code responsibility
* to free/destroy it afterwards
* @param error output error message, will be set to string literal
* error message in case of error. Will be set to NULL on success.
* The error message should NOT be freed by client.
*/
void cron_parse_expr(const char* expression, cron_expr* target, const char** error);
/**
* Uses the specified expression to calculate the next 'fire' date after
* the specified date. All dates are processed as UTC (GMT) dates
* without timezones information. To use local dates (current system timezone)
* instead of GMT compile with '-DCRON_USE_LOCAL_TIME'
*
* @param expr parsed cron expression to use in next date calculation
* @param date start date to start calculation from
* @return next 'fire' date in case of success, '((time_t) -1)' in case of error.
*/
time_t cron_next(cron_expr* expr, time_t date);
/**
* Uses the specified expression to calculate the previous 'fire' date after
* the specified date. All dates are processed as UTC (GMT) dates
* without timezones information. To use local dates (current system timezone)
* instead of GMT compile with '-DCRON_USE_LOCAL_TIME'
*
* @param expr parsed cron expression to use in previous date calculation
* @param date start date to start calculation from
* @return previous 'fire' date in case of success, '((time_t) -1)' in case of error.
*/
time_t cron_prev(cron_expr* expr, time_t date);
#if defined(__cplusplus) && !defined(CRON_COMPILE_AS_CXX)
} /* extern "C"*/
#endif
#endif /* CCRONEXPR_H */

View File

@ -0,0 +1,409 @@
/*
* Copyright 2015, alex at staticlibs.net
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* File: CronExprParser_test.cpp
* Author: alex
*
* Created on February 24, 2015, 9:36 AM
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include "ccronexpr.h"
#define MAX_SECONDS 60
#define CRON_MAX_MINUTES 60
#define CRON_MAX_HOURS 24
#define CRON_MAX_DAYS_OF_WEEK 8
#define CRON_MAX_DAYS_OF_MONTH 32
#define CRON_MAX_MONTHS 12
#define INVALID_INSTANT ((time_t) -1)
#define DATE_FORMAT "%Y-%m-%d_%H:%M:%S"
#ifndef ARRAY_LEN
#define ARRAY_LEN(x) sizeof(x)/sizeof(x[0])
#endif
#ifdef CRON_TEST_MALLOC
static int cronAllocations = 0;
static int cronTotalAllocations = 0;
static int maxAlloc = 0;
void* cron_malloc(size_t n) {
cronAllocations++;
cronTotalAllocations++;
if (cronAllocations > maxAlloc) {
maxAlloc = cronAllocations;
}
return malloc(n);
}
void cron_free(void* p) {
cronAllocations--;
free(p);
}
#endif
#ifndef ANDROID
#ifndef _WIN32
time_t timegm(struct tm* __tp);
#else /* _WIN32 */
static time_t timegm(struct tm* tm) {
return _mkgmtime(tm);
}
#endif /* _WIN32 */
#else /* ANDROID */
static time_t timegm(struct tm * const t) {
/* time_t is signed on Android. */
static const time_t kTimeMax = ~(1L << (sizeof (time_t) * CHAR_BIT - 1));
static const time_t kTimeMin = (1L << (sizeof (time_t) * CHAR_BIT - 1));
time64_t result = timegm64(t);
if (result < kTimeMin || result > kTimeMax)
return -1;
return result;
}
#endif
/**
* uint8_t* replace char* for storing hit dates, set_bit and get_bit are used as handlers
*/
uint8_t cron_get_bit(uint8_t* rbyte, int idx);
void cron_set_bit(uint8_t* rbyte, int idx);
void cron_del_bit(uint8_t* rbyte, int idx);
static int crons_equal(cron_expr* cr1, cron_expr* cr2) {
unsigned int i;
for (i = 0; i < ARRAY_LEN(cr1->seconds); i++) {
if (cr1->seconds[i] != cr2->seconds[i]) {
printf("seconds not equal @%d %02x != %02x", i, cr1->seconds[i], cr2->seconds[i]);
return 0;
}
}
for (i = 0; i < ARRAY_LEN(cr1->minutes); i++) {
if (cr1->minutes[i] != cr2->minutes[i]) {
printf("minutes not equal @%d %02x != %02x", i, cr1->minutes[i], cr2->minutes[i]);
return 0;
}
}
for (i = 0; i < ARRAY_LEN(cr1->hours); i++) {
if (cr1->hours[i] != cr2->hours[i]) {
printf("hours not equal @%d %02x != %02x", i, cr1->hours[i], cr2->hours[i]);
return 0;
}
}
for (i = 0; i < ARRAY_LEN(cr1->days_of_week); i++) {
if (cr1->days_of_week[i] != cr2->days_of_week[i]) {
printf("days_of_week not equal @%d %02x != %02x", i, cr1->days_of_week[i], cr2->days_of_week[i]);
return 0;
}
}
for (i = 0; i < ARRAY_LEN(cr1->days_of_month); i++) {
if (cr1->days_of_month[i] != cr2->days_of_month[i]) {
printf("days_of_month not equal @%d %02x != %02x", i, cr1->days_of_month[i], cr2->days_of_month[i]);
return 0;
}
}
for (i = 0; i < ARRAY_LEN(cr1->months); i++) {
if (cr1->months[i] != cr2->months[i]) {
printf("months not equal @%d %02x != %02x", i, cr1->months[i], cr2->months[i]);
return 0;
}
}
return 1;
}
int one_dec_num(const char ch) {
switch (ch) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
default:
return -1;
}
}
int two_dec_num(const char* first) {
return one_dec_num(first[0]) * 10 + one_dec_num(first[1]);
}
int four_dec_num(const char *first) {
return ((one_dec_num(first[0]) * 1000)
+ (one_dec_num(first[1]) * 100)
+ (one_dec_num(first[2]) * 10)
+ (one_dec_num(first[3]) * 1));
}
/* strptime is not available in msvc */
/* 2012-07-01_09:53:50 */
/* 0123456789012345678 */
struct tm* poors_mans_strptime(const char* str) {
struct tm* cal = (struct tm*) malloc(sizeof(struct tm));
assert(cal != NULL);
memset(cal, 0, sizeof(struct tm));
cal->tm_year = four_dec_num(str) - 1900;
cal->tm_mon = two_dec_num(str + 5) - 1;
cal->tm_mday = two_dec_num(str + 8);
cal->tm_wday = 0;
cal->tm_yday = 0;
cal->tm_hour = two_dec_num(str + 11);
cal->tm_min = two_dec_num(str + 14);
cal->tm_sec = two_dec_num(str + 17);
return cal;
}
void check_next(const char* pattern, const char* initial, const char* expected) {
const char* err = NULL;
cron_expr parsed;
cron_parse_expr(pattern, &parsed, &err);
struct tm* calinit = poors_mans_strptime(initial);
#ifdef CRON_USE_LOCAL_TIME
time_t dateinit = mktime(calinit);
#else
time_t dateinit = timegm(calinit);
#endif
assert(-1 != dateinit);
time_t datenext = cron_next(&parsed, dateinit);
#ifdef CRON_USE_LOCAL_TIME
struct tm* calnext = localtime(&datenext);
#else
struct tm* calnext = gmtime(&datenext);
#endif
assert(calnext);
char* buffer = (char*) malloc(21);
memset(buffer, 0, 21);
strftime(buffer, 20, DATE_FORMAT, calnext);
if (0 != strcmp(expected, buffer)) {
printf("Pattern: %s\n", pattern);
printf("Initial: %s\n", initial);
printf("Expected: %s\n", expected);
printf("Actual: %s\n", buffer);
assert(0);
}
free(buffer);
free(calinit);
}
void check_same(const char* expr1, const char* expr2) {
cron_expr parsed1;
cron_parse_expr(expr1, &parsed1, NULL);
cron_expr parsed2;
cron_parse_expr(expr2, &parsed2, NULL);
assert(crons_equal(&parsed1, &parsed2));
}
void check_calc_invalid() {
cron_expr parsed;
cron_parse_expr("0 0 0 31 6 *", &parsed, NULL);
struct tm * calinit = poors_mans_strptime("2012-07-01_09:53:50");
time_t dateinit = timegm(calinit);
time_t res = cron_next(&parsed, dateinit);
assert(INVALID_INSTANT == res);
free(calinit);
}
void check_expr_invalid(const char* expr) {
const char* err = NULL;
cron_expr test;
cron_parse_expr(expr, &test, &err);
assert(err);
}
void test_expr() {
#ifdef CRON_USE_LOCAL_TIME
check_next("* 15 11 * * *", "2019-03-09_11:43:00", "2019-03-10_11:15:00");
#else
check_next("*/15 * 1-4 * * *", "2012-07-01_09:53:50", "2012-07-02_01:00:00");
check_next("*/15 * 1-4 * * *", "2012-07-01_09:53:00", "2012-07-02_01:00:00");
check_next("0 */2 1-4 * * *", "2012-07-01_09:00:00", "2012-07-02_01:00:00");
check_next("0 */2 * * * *", "2012-07-01_09:00:00", "2012-07-01_09:02:00");
check_next("0 */2 * * * *", "2013-07-01_09:00:00", "2013-07-01_09:02:00");
check_next("0 */2 * * * *", "2018-09-14_14:24:00", "2018-09-14_14:26:00");
check_next("0 */2 * * * *", "2018-09-14_14:25:00", "2018-09-14_14:26:00");
check_next("0 */20 * * * *", "2018-09-14_14:24:00", "2018-09-14_14:40:00");
check_next("* * * * * *", "2012-07-01_09:00:00", "2012-07-01_09:00:01");
check_next("* * * * * *", "2012-12-01_09:00:58", "2012-12-01_09:00:59");
check_next("10 * * * * *", "2012-12-01_09:42:09", "2012-12-01_09:42:10");
check_next("11 * * * * *", "2012-12-01_09:42:10", "2012-12-01_09:42:11");
check_next("10 * * * * *", "2012-12-01_09:42:10", "2012-12-01_09:43:10");
check_next("10-15 * * * * *", "2012-12-01_09:42:09", "2012-12-01_09:42:10");
check_next("10-15 * * * * *", "2012-12-01_21:42:14", "2012-12-01_21:42:15");
check_next("0 * * * * *", "2012-12-01_21:10:42", "2012-12-01_21:11:00");
check_next("0 * * * * *", "2012-12-01_21:11:00", "2012-12-01_21:12:00");
check_next("0 11 * * * *", "2012-12-01_21:10:42", "2012-12-01_21:11:00");
check_next("0 10 * * * *", "2012-12-01_21:11:00", "2012-12-01_22:10:00");
check_next("0 0 * * * *", "2012-09-30_11:01:00", "2012-09-30_12:00:00");
check_next("0 0 * * * *", "2012-09-30_12:00:00", "2012-09-30_13:00:00");
check_next("0 0 * * * *", "2012-09-10_23:01:00", "2012-09-11_00:00:00");
check_next("0 0 * * * *", "2012-09-11_00:00:00", "2012-09-11_01:00:00");
check_next("0 0 0 * * *", "2012-09-01_14:42:43", "2012-09-02_00:00:00");
check_next("0 0 0 * * *", "2012-09-02_00:00:00", "2012-09-03_00:00:00");
check_next("* * * 10 * *", "2012-10-09_15:12:42", "2012-10-10_00:00:00");
check_next("* * * 10 * *", "2012-10-11_15:12:42", "2012-11-10_00:00:00");
check_next("0 0 0 * * *", "2012-09-30_15:12:42", "2012-10-01_00:00:00");
check_next("0 0 0 * * *", "2012-10-01_00:00:00", "2012-10-02_00:00:00");
check_next("0 0 0 * * *", "2012-08-30_15:12:42", "2012-08-31_00:00:00");
check_next("0 0 0 * * *", "2012-08-31_00:00:00", "2012-09-01_00:00:00");
check_next("0 0 0 * * *", "2012-10-30_15:12:42", "2012-10-31_00:00:00");
check_next("0 0 0 * * *", "2012-10-31_00:00:00", "2012-11-01_00:00:00");
check_next("0 0 0 1 * *", "2012-10-30_15:12:42", "2012-11-01_00:00:00");
check_next("0 0 0 1 * *", "2012-11-01_00:00:00", "2012-12-01_00:00:00");
check_next("0 0 0 1 * *", "2010-12-31_15:12:42", "2011-01-01_00:00:00");
check_next("0 0 0 1 * *", "2011-01-01_00:00:00", "2011-02-01_00:00:00");
check_next("0 0 0 31 * *", "2011-10-30_15:12:42", "2011-10-31_00:00:00");
check_next("0 0 0 1 * *", "2011-10-30_15:12:42", "2011-11-01_00:00:00");
check_next("* * * * * 2", "2010-10-25_15:12:42", "2010-10-26_00:00:00");
check_next("* * * * * 2", "2010-10-20_15:12:42", "2010-10-26_00:00:00");
check_next("* * * * * 2", "2010-10-27_15:12:42", "2010-11-02_00:00:00");
check_next("55 5 * * * *", "2010-10-27_15:04:54", "2010-10-27_15:05:55");
check_next("55 5 * * * *", "2010-10-27_15:05:55", "2010-10-27_16:05:55");
check_next("55 * 10 * * *", "2010-10-27_09:04:54", "2010-10-27_10:00:55");
check_next("55 * 10 * * *", "2010-10-27_10:00:55", "2010-10-27_10:01:55");
check_next("* 5 10 * * *", "2010-10-27_09:04:55", "2010-10-27_10:05:00");
check_next("* 5 10 * * *", "2010-10-27_10:05:00", "2010-10-27_10:05:01");
check_next("55 * * 3 * *", "2010-10-02_10:05:54", "2010-10-03_00:00:55");
check_next("55 * * 3 * *", "2010-10-03_00:00:55", "2010-10-03_00:01:55");
check_next("* * * 3 11 *", "2010-10-02_14:42:55", "2010-11-03_00:00:00");
check_next("* * * 3 11 *", "2010-11-03_00:00:00", "2010-11-03_00:00:01");
check_next("0 0 0 29 2 *", "2007-02-10_14:42:55", "2008-02-29_00:00:00");
check_next("0 0 0 29 2 *", "2008-02-29_00:00:00", "2012-02-29_00:00:00");
check_next("0 0 7 ? * MON-FRI", "2009-09-26_00:42:55", "2009-09-28_07:00:00");
check_next("0 0 7 ? * MON-FRI", "2009-09-28_07:00:00", "2009-09-29_07:00:00");
check_next("0 30 23 30 1/3 ?", "2010-12-30_00:00:00", "2011-01-30_23:30:00");
check_next("0 30 23 30 1/3 ?", "2011-01-30_23:30:00", "2011-04-30_23:30:00");
check_next("0 30 23 30 1/3 ?", "2011-04-30_23:30:00", "2011-07-30_23:30:00");
#endif
}
void test_parse() {
check_same("* * * 2 * *", "* * * 2 * ?");
check_same("57,59 * * * * *", "57/2 * * * * *");
check_same("1,3,5 * * * * *", "1-6/2 * * * * *");
check_same("* * 4,8,12,16,20 * * *", "* * 4/4 * * *");
check_same("* * * * * 0-6", "* * * * * TUE,WED,THU,FRI,SAT,SUN,MON");
check_same("* * * * * 0", "* * * * * SUN");
check_same("* * * * * 0", "* * * * * 7");
check_same("* * * * 1-12 *", "* * * * FEB,JAN,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC *");
check_same("* * * * 2 *", "* * * * Feb *");
check_same("* * * * 1 *", "* * * * 1 *");
check_expr_invalid("77 * * * * *");
check_expr_invalid("44-77 * * * * *");
check_expr_invalid("* 77 * * * *");
check_expr_invalid("* 44-77 * * * *");
check_expr_invalid("* * 27 * * *");
check_expr_invalid("* * 23-28 * * *");
check_expr_invalid("* * * 45 * *");
check_expr_invalid("* * * 28-45 * *");
check_expr_invalid("0 0 0 25 13 ?");
check_expr_invalid("0 0 0 25 0 ?");
check_expr_invalid("0 0 0 32 12 ?");
check_expr_invalid("* * * * 11-13 *");
check_expr_invalid("-5 * * * * *");
check_expr_invalid("3-2 */5 * * * *");
check_expr_invalid("/5 * * * * *");
check_expr_invalid("*/0 * * * * *");
check_expr_invalid("*/-0 * * * * *");
check_expr_invalid("* 1 1 0 * *");
}
void test_bits() {
uint8_t testbyte[8];
memset(testbyte, 0, 8);
int err = 0;
int i;
for (i = 0; i <= 63; i++) {
cron_set_bit(testbyte, i);
if (!cron_get_bit(testbyte, i)) {
printf("Bit set error! Bit: %d!\n", i);
err = 1;
}
cron_del_bit(testbyte, i);
if (cron_get_bit(testbyte, i)) {
printf("Bit clear error! Bit: %d!\n", i);
err = 1;
}
assert(!err);
}
for (i = 0; i < 12; i++) {
cron_set_bit(testbyte, i);
}
if (testbyte[0] != 0xff) {
err = 1;
}
if (testbyte[1] != 0x0f) {
err = 1;
}
assert(!err);
}
/* For this test to work you need to set "-DCRON_TEST_MALLOC=1"*/
#ifdef CRON_TEST_MALLOC
void test_memory() {
cron_expr cron;
const char* err;
cron_parse_expr("* * * * * *", &cron, &err);
if (cronAllocations != 0) {
printf("Allocations != 0 but %d", cronAllocations);
assert(0);
}
printf("Allocations: total: %d, max: %d", cronTotalAllocations, maxAlloc);
}
#endif
int main() {
test_bits();
test_expr();
test_parse();
check_calc_invalid();
#ifdef CRON_TEST_MALLOC
test_memory(); /* For this test to work you need to set "-DCRON_TEST_MALLOC=1"*/
#endif
printf("\nAll OK!");
return 0;
}

View File

@ -0,0 +1,17 @@
{
"name": "ccronexpr",
"frameworks": "arduino",
"keywords": "cron, Time, alarm, schedule, date, hour, minute, second, day, week, month, year",
"description": "Crontab parser",
"url": "https://github.com/Martin-Laclaustra/CronAlarms",
"authors":
{
"name": "alex@staticlibs.net"
},
"repository":
{
"type": "git",
"url": "https://github.com/staticlibs/ccronexpr"
},
"platforms": "espressif32"
}

View File

@ -26,6 +26,7 @@
#include "berry_tasmota.h"
#include "be_vm.h"
#include "ZipReadFS.h"
#include "ccronexpr.h"
extern "C" {
extern void be_load_custom_libs(bvm *vm);