Berry fix cron

This commit is contained in:
Stephan Hadinger 2022-02-25 21:52:35 +01:00
parent a67898e8b3
commit 4229cafa63
8 changed files with 182 additions and 116 deletions

View File

@ -586,6 +586,7 @@ 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_now;
extern const bcstring be_const_str_null_cb;
extern const bcstring be_const_str_number;
extern const bcstring be_const_str_o;

View File

@ -68,7 +68,7 @@ be_define_const_str(_X3D_X3C_X3E_X21, "=<>!", 2664470277u, 0, 4, &be_const_str_C
be_define_const_str(_X3D_X3D, "==", 2431966415u, 0, 2, NULL);
be_define_const_str(_X3E, ">", 990687777u, 0, 1, &be_const_str__def);
be_define_const_str(_X3E_X3D, ">=", 284975636u, 0, 2, &be_const_str_AudioGeneratorWAV);
be_define_const_str(_X3F, "?", 973910158u, 0, 1, &be_const_str_web_add_handler);
be_define_const_str(_X3F, "?", 973910158u, 0, 1, &be_const_str_now);
be_define_const_str(AES_GCM, "AES_GCM", 3832208678u, 0, 7, NULL);
be_define_const_str(AXP192, "AXP192", 757230128u, 0, 6, &be_const_str_depower);
be_define_const_str(Animate_X20pc_X20is_X20out_X20of_X20range, "Animate pc is out of range", 1854929421u, 0, 26, &be_const_str_debug);
@ -578,6 +578,7 @@ be_define_const_str(next, "next", 1555467752u, 0, 4, &be_const_str_resp_cmnd_str
be_define_const_str(next_cron, "next_cron", 3260705337u, 0, 9, &be_const_str_seti);
be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL);
be_define_const_str(no_X20GPIO_X20specified_X20for_X20neopixelbus, "no GPIO specified for neopixelbus", 42078528u, 0, 33, NULL);
be_define_const_str(now, "now", 682728183u, 0, 3, &be_const_str_web_add_handler);
be_define_const_str(null_cb, "null_cb", 2333536460u, 0, 7, NULL);
be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_p1);
be_define_const_str(o, "o", 3926667934u, 0, 1, NULL);
@ -1308,6 +1309,6 @@ static const bstring* const m_string_table[] = {
static const struct bconststrtab m_const_string_table = {
.size = 427,
.count = 877,
.count = 878,
.table = m_string_table
};

View File

@ -1,15 +1,17 @@
#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(now, -1), be_const_static_ctype_func(ccronexpr_now) },
{ 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) },
{ be_const_key(init, 0), be_const_ctype_func(ccronexpr_init) },
{ be_const_key(deinit, -1), be_const_ctype_func(ccronexpr_init) },
{ be_const_key(time_reached, -1), be_const_static_ctype_func(ccronexpr_time_reached) },
};
static be_define_const_map(
be_class_ccronexpr_map,
4
6
);
BE_EXPORT_VARIABLE be_define_const_class(

View File

@ -13,12 +13,21 @@
bvaldata((const void*) &ctype_func_def##_f), \
BE_CTYPE_FUNC \
}
#define be_const_static_ctype_func(_f) { \
bvaldata((const void*) &ctype_func_def##_f), \
BE_CTYPE_FUNC | BE_STATIC \
}
#else // __cplusplus
typedef const void* be_constptr;
#define be_const_ctype_func(_f) { \
.v.nf = (const void*) &ctype_func_def##_f, \
.type = BE_CTYPE_FUNC \
}
typedef const void* be_constptr;
#define be_const_static_ctype_func(_f) { \
.v.nf = (const void*) &ctype_func_def##_f, \
.type = BE_CTYPE_FUNC | BE_STATIC \
}
#endif // __cplusplus
#define BE_FUNC_CTYPE_DECLARE(_name, _ret_arg, _in_arg) \

View File

@ -12,6 +12,9 @@
#include "ccronexpr.h"
extern uint32_t LocalTime(void);
static const uint32_t START_VALID_TIME = 1451602800; // Time is synced and after 2016-01-01
// create
static cron_expr* ccronexpr_init(struct bvm* vm, char* expr) {
cron_expr* cron = new cron_expr();
@ -33,16 +36,28 @@ BE_FUNC_CTYPE_DECLARE(ccronexpr_deinit, "", ".")
// next
static uint32_t ccronexpr_next(cron_expr* cron, uint32_t date) {
return cron_next(cron, date);
// Returns the next trigger time, or 0 if rtc is invalid
static uint32_t ccronexpr_next(cron_expr* cron) {
uint32_t now_local = LocalTime();
return now_local > START_VALID_TIME ? cron_next(cron, now_local) : 0;
}
BE_FUNC_CTYPE_DECLARE(ccronexpr_next, "i", ".i")
BE_FUNC_CTYPE_DECLARE(ccronexpr_next, "i", ".")
// prev
static uint32_t ccronexpr_prev(cron_expr* cron, uint32_t date) {
return cron_prev(cron, date);
// time_reached
// Compares as uint32_t (Berry only handles int32_t) to avoid the 2038 bug
// Also prevents from triggering an event if the clock is not set (i.e. year is 1970)
static bool ccronexpr_time_reached(uint32_t date) {
uint32_t now_local = LocalTime();
bool reached = (date <= now_local);
return now_local > START_VALID_TIME ? reached : false;
}
BE_FUNC_CTYPE_DECLARE(ccronexpr_prev, "i", ".i")
BE_FUNC_CTYPE_DECLARE(ccronexpr_time_reached, "b", "i")
// now (local time)
static uint32_t ccronexpr_now(void) {
return LocalTime();
}
BE_FUNC_CTYPE_DECLARE(ccronexpr_now, "i", "")
#include "be_fixed_be_class_ccronexpr.h"
@ -60,6 +75,8 @@ class be_class_ccronexpr (scope: global, name: ccronexpr) {
deinit, ctype_func(ccronexpr_init)
next, ctype_func(ccronexpr_next)
time_reached, static_ctype_func(ccronexpr_time_reached)
now, static_ctype_func(ccronexpr_now)
}
@const_object_info_end */

View File

@ -2013,19 +2013,17 @@ be_local_closure(Tasmota_add_cron, /* name */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 8]) { /* constants */
( &(const bvalue[ 6]) { /* 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),
/* K4 */ be_nested_str(push),
/* K5 */ be_nested_str(Trigger),
}),
&be_const_str_add_cron,
&be_const_str_solidified,
( &(const binstruction[28]) { /* code */
( &(const binstruction[25]) { /* code */
0x8C100100, // 0000 GETMET R4 R0 K0
0x5C180400, // 0001 MOVE R6 R2
0x7C100400, // 0002 CALL R4 2
@ -2040,20 +2038,17 @@ be_local_closure(Tasmota_add_cron, /* name */
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
0x7C140200, // 000E CALL R5 1
0x88180101, // 000F GETMBR R6 R0 K1
0x8C180D04, // 0010 GETMET R6 R6 K4
0xB8220A00, // 0011 GETNGBL R8 K5
0x5C240A00, // 0012 MOVE R9 R5
0x5C280400, // 0013 MOVE R10 R2
0x5C2C0600, // 0014 MOVE R11 R3
0x5C300800, // 0015 MOVE R12 R4
0x7C200800, // 0016 CALL R8 4
0x7C180400, // 0017 CALL R6 2
0x80000000, // 0018 RET 0
})
)
);
@ -2076,55 +2071,52 @@ be_local_closure(Tasmota_run_cron, /* name */
( &(const bvalue[10]) { /* constants */
/* K0 */ be_nested_str(_crons),
/* K1 */ be_const_int(0),
/* K2 */ be_nested_str(rtc),
/* K3 */ be_nested_str(local),
/* K2 */ be_nested_str(ccronexpr),
/* K3 */ be_nested_str(now),
/* 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),
/* K6 */ be_nested_str(next),
/* K7 */ be_nested_str(time_reached),
/* K8 */ be_nested_str(f),
/* K9 */ be_const_int(1),
}),
&be_const_str_run_cron,
&be_const_str_solidified,
( &(const binstruction[37]) { /* code */
( &(const binstruction[34]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060021, // 0001 JMPF R1 #0024
0x7806001E, // 0001 JMPF R1 #0021
0x58040001, // 0002 LDCONST R1 K1
0x8C080102, // 0003 GETMET R2 R0 K2
0x7C080200, // 0004 CALL R2 1
0x94080503, // 0005 GETIDX R2 R2 K3
0xB80A0400, // 0003 GETNGBL R2 K2
0x8C080503, // 0004 GETMET R2 R2 K3
0x7C080200, // 0005 CALL R2 1
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
0x780E0015, // 000A JMPF R3 #0021
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
0x1C100901, // 000E EQ R4 R4 K1
0x78120003, // 000F JMPF R4 #0014
0x8C100706, // 0010 GETMET R4 R3 K6
0x7C100200, // 0011 CALL R4 1
0x900E0A04, // 0012 SETMBR R3 K5 R4
0x7002000A, // 0013 JMP #001F
0x8C100707, // 0014 GETMET R4 R3 K7
0x7C100200, // 0015 CALL R4 1
0x78120007, // 0016 JMPF R4 #001F
0x88100708, // 0017 GETMBR R4 R3 K8
0x8C140706, // 0018 GETMET R5 R3 K6
0x7C140200, // 0019 CALL R5 1
0x900E0A05, // 001A SETMBR R3 K5 R5
0x5C180800, // 001B MOVE R6 R4
0x5C1C0400, // 001C MOVE R7 R2
0x5C200A00, // 001D MOVE R8 R5
0x7C180400, // 001E CALL R6 2
0x00040309, // 001F ADD R1 R1 K9
0x7001FFE4, // 0020 JMP #0006
0x80000000, // 0021 RET 0
})
)
);

View File

@ -5,6 +5,39 @@
*******************************************************************/
#include "be_constobj.h"
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(Trigger_init, /* name */
be_nested_proto(
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[ 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[ 5]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x90020202, // 0001 SETMBR R0 K1 R2
0x90020403, // 0002 SETMBR R0 K2 R3
0x90020604, // 0003 SETMBR R0 K3 R4
0x80000000, // 0004 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: tostring
********************************************************************/
@ -55,12 +88,12 @@ be_local_closure(Trigger_tostring, /* name */
/********************************************************************
** Solidified function: init
** Solidified function: time_reached
********************************************************************/
be_local_closure(Trigger_init, /* name */
be_local_closure(Trigger_time_reached, /* name */
be_nested_proto(
5, /* nstack */
5, /* argc */
4, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
@ -68,19 +101,26 @@ be_local_closure(Trigger_init, /* name */
NULL, /* no sub protos */
1, /* has 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),
/* K0 */ be_nested_str(o),
/* K1 */ be_nested_str(trig),
/* K2 */ be_const_int(0),
/* K3 */ be_nested_str(time_reached),
}),
&be_const_str_init,
&be_const_str_time_reached,
&be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x90020202, // 0001 SETMBR R0 K1 R2
0x90020403, // 0002 SETMBR R0 K2 R3
0x90020604, // 0003 SETMBR R0 K3 R4
0x80000000, // 0004 RET 0
( &(const binstruction[12]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060007, // 0001 JMPF R1 #000A
0x88040101, // 0002 GETMBR R1 R0 K1
0x24040302, // 0003 GT R1 R1 K2
0x78060004, // 0004 JMPF R1 #000A
0x88040100, // 0005 GETMBR R1 R0 K0
0x8C040303, // 0006 GETMET R1 R1 K3
0x880C0101, // 0007 GETMBR R3 R0 K1
0x7C040400, // 0008 CALL R1 2
0x80040200, // 0009 RET 1 R1
0x50040000, // 000A LDBOOL R1 0 0
0x80040200, // 000B RET 1 R1
})
)
);
@ -92,8 +132,8 @@ be_local_closure(Trigger_init, /* name */
********************************************************************/
be_local_closure(Trigger_next, /* name */
be_nested_proto(
5, /* nstack */
2, /* argc */
3, /* nstack */
1, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
@ -106,15 +146,14 @@ be_local_closure(Trigger_next, /* name */
}),
&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
( &(const binstruction[ 7]) { /* code */
0x88040100, // 0000 GETMBR R1 R0 K0
0x78060003, // 0001 JMPF R1 #0006
0x88040100, // 0002 GETMBR R1 R0 K0
0x8C040301, // 0003 GETMET R1 R1 K1
0x7C040200, // 0004 CALL R1 1
0x80040200, // 0005 RET 1 R1
0x80000000, // 0006 RET 0
})
)
);
@ -127,15 +166,16 @@ be_local_closure(Trigger_next, /* name */
be_local_class(Trigger,
4,
NULL,
be_nested_map(7,
be_nested_map(8,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key(f, 1), be_const_var(1) },
{ be_const_key(id, 2), be_const_var(2) },
{ be_const_key(f, -1), be_const_var(1) },
{ be_const_key(next, -1), be_const_closure(Trigger_next_closure) },
{ be_const_key(trig, 7), be_const_var(0) },
{ be_const_key(time_reached, -1), be_const_closure(Trigger_time_reached_closure) },
{ be_const_key(tostring, 4), be_const_closure(Trigger_tostring_closure) },
{ be_const_key(o, -1), be_const_var(3) },
{ be_const_key(init, -1), be_const_closure(Trigger_init_closure) },
{ 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

@ -15,12 +15,19 @@ class Trigger
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)
# next() returns the next trigger, or 0 if rtc is invalid, or nil if no more
def next()
if self.o
return self.o.next(now)
return self.o.next()
end
end
def time_reached()
if self.o && self.trig > 0
return self.o.time_reached(self.trig)
end
return false
end
end
tasmota = nil
@ -270,23 +277,19 @@ class Tasmota
def run_cron()
if self._crons
var i=0
var now = self.rtc()['local'] # now in epoch seconds
var now = ccronexpr.now()
while i < self._crons.size()
var trigger = self._crons[i]
if trigger.trig <= now
if trigger.trig == 0 # trigger was created when RTC was invalid, try to recalculate
trigger.trig = trigger.next()
elif trigger.time_reached() # time has come
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
var next_time = trigger.next()
trigger.trig = next_time # update to next time
f(now, next_time)
else
i += 1
end
i += 1
end
end
end
@ -309,10 +312,11 @@ class Tasmota
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))
var cron_obj = ccronexpr(str(pattern)) # can fail, throwing an exception
var next_time = cron_obj.next()
self._crons.push(Trigger(next_time, f, id, cron_obj))
end
# remove cron by id