mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-23 02:36:35 +00:00
Berry 'tasmota.defer()' (#22976)
This commit is contained in:
parent
5a6b219971
commit
ff5b4956c8
@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
### Added
|
### Added
|
||||||
- Formatter `%_U` for `ext_snprintf_P()` to print uint64_t variable as decimal equivalent to `%llu`
|
- Formatter `%_U` for `ext_snprintf_P()` to print uint64_t variable as decimal equivalent to `%llu`
|
||||||
- Support for RC-switch decoding of 64-bit received data
|
- Support for RC-switch decoding of 64-bit received data
|
||||||
|
- Berry `tasmota.defer()`
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ class be_class_tasmota (scope: global, name: Tasmota) {
|
|||||||
_fl, var // list of active fast-loop object (faster than drivers)
|
_fl, var // list of active fast-loop object (faster than drivers)
|
||||||
_rules, var // list of active rules
|
_rules, var // list of active rules
|
||||||
_timers, var // list of active timers
|
_timers, var // list of active timers
|
||||||
|
_defer, var // list of deferred functions to be called at next millisecond
|
||||||
_crons, var // list of active crons
|
_crons, var // list of active crons
|
||||||
_ccmd, var // list of active Tasmota commands implemented in Berry
|
_ccmd, var // list of active Tasmota commands implemented in Berry
|
||||||
_drivers, var // list of active drivers
|
_drivers, var // list of active drivers
|
||||||
@ -173,6 +174,8 @@ class be_class_tasmota (scope: global, name: Tasmota) {
|
|||||||
exec_rules, closure(class_Tasmota_exec_rules_closure)
|
exec_rules, closure(class_Tasmota_exec_rules_closure)
|
||||||
exec_tele, closure(class_Tasmota_exec_tele_closure)
|
exec_tele, closure(class_Tasmota_exec_tele_closure)
|
||||||
set_timer, closure(class_Tasmota_set_timer_closure)
|
set_timer, closure(class_Tasmota_set_timer_closure)
|
||||||
|
run_timers, closure(class_Tasmota_run_timers_closure)
|
||||||
|
defer, closure(class_Tasmota_defer_closure)
|
||||||
run_deferred, closure(class_Tasmota_run_deferred_closure)
|
run_deferred, closure(class_Tasmota_run_deferred_closure)
|
||||||
remove_timer, closure(class_Tasmota_remove_timer_closure)
|
remove_timer, closure(class_Tasmota_remove_timer_closure)
|
||||||
add_cmd, closure(class_Tasmota_add_cmd_closure)
|
add_cmd, closure(class_Tasmota_add_cmd_closure)
|
||||||
|
@ -9,6 +9,7 @@ class Tasmota
|
|||||||
var _fl # list of fast_loop registered closures
|
var _fl # list of fast_loop registered closures
|
||||||
var _rules
|
var _rules
|
||||||
var _timers # holds both timers and cron
|
var _timers # holds both timers and cron
|
||||||
|
var _defer # holds functions to be called at next millisecond
|
||||||
var _crons
|
var _crons
|
||||||
var _ccmd
|
var _ccmd
|
||||||
var _drivers
|
var _drivers
|
||||||
@ -273,13 +274,39 @@ class Tasmota
|
|||||||
def set_timer(delay,f,id)
|
def set_timer(delay,f,id)
|
||||||
self.check_not_method(f)
|
self.check_not_method(f)
|
||||||
if self._timers == nil
|
if self._timers == nil
|
||||||
self._timers=[]
|
self._timers = []
|
||||||
end
|
end
|
||||||
self._timers.push(Trigger(self.millis(delay),f,id))
|
self._timers.push(Trigger(self.millis(delay),f,id))
|
||||||
end
|
end
|
||||||
|
|
||||||
# run every 50ms tick
|
# special version to push a function that will be called immediately after
|
||||||
|
def defer(f)
|
||||||
|
if self._defer == nil
|
||||||
|
self._defer = []
|
||||||
|
end
|
||||||
|
self._defer.push(f)
|
||||||
|
tasmota.global.deferred_ready = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# run any immediate function
|
||||||
def run_deferred()
|
def run_deferred()
|
||||||
|
if self._defer
|
||||||
|
var sz = size(self._defer) # make sure to run only those present at first, and not those inserted in between
|
||||||
|
while sz > 0
|
||||||
|
var f = self._defer[0]
|
||||||
|
self._defer.remove(0)
|
||||||
|
sz -= 1
|
||||||
|
f()
|
||||||
|
end
|
||||||
|
if size(self._defer) == 0
|
||||||
|
tasmota.global.deferred_ready = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# run every 50ms tick
|
||||||
|
def run_timers()
|
||||||
|
self.run_deferred() # run immediate functions first
|
||||||
if self._timers
|
if self._timers
|
||||||
var i=0
|
var i=0
|
||||||
while i < self._timers.size()
|
while i < self._timers.size()
|
||||||
@ -699,7 +726,7 @@ class Tasmota
|
|||||||
def event(event_type, cmd, idx, payload, raw)
|
def event(event_type, cmd, idx, payload, raw)
|
||||||
import introspect
|
import introspect
|
||||||
if event_type=='every_50ms'
|
if event_type=='every_50ms'
|
||||||
self.run_deferred()
|
self.run_timers()
|
||||||
end #- first run deferred events -#
|
end #- first run deferred events -#
|
||||||
|
|
||||||
if event_type=='every_250ms'
|
if event_type=='every_250ms'
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -383,6 +383,7 @@ struct TasmotaGlobal_t {
|
|||||||
#endif // PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
|
#endif // PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
|
||||||
|
|
||||||
#ifdef USE_BERRY
|
#ifdef USE_BERRY
|
||||||
|
bool berry_deferred_ready = false; // is there an deferred Berry function to be called at next millisecond
|
||||||
bool berry_fast_loop_enabled = false; // is Berry fast loop enabled, i.e. control is passed at each loop iteration
|
bool berry_fast_loop_enabled = false; // is Berry fast loop enabled, i.e. control is passed at each loop iteration
|
||||||
#endif // USE_BERRY
|
#endif // USE_BERRY
|
||||||
} TasmotaGlobal = { 0 };
|
} TasmotaGlobal = { 0 };
|
||||||
|
@ -33,10 +33,11 @@ extern "C" {
|
|||||||
|
|
||||||
extern const be_ctypes_structure_t be_tasmota_global_struct = {
|
extern const be_ctypes_structure_t be_tasmota_global_struct = {
|
||||||
sizeof(TasmotaGlobal), /* size in bytes */
|
sizeof(TasmotaGlobal), /* size in bytes */
|
||||||
11, /* number of elements */
|
12, /* number of elements */
|
||||||
nullptr,
|
nullptr,
|
||||||
(const be_ctypes_structure_item_t[11]) {
|
(const be_ctypes_structure_item_t[12]) {
|
||||||
// Warning: fields below need to be in alphabetical order
|
// Warning: fields below need to be in alphabetical order
|
||||||
|
{ "deferred_ready", offsetof(TasmotaGlobal_t, berry_deferred_ready), 0, 0, ctypes_u8, 0 },
|
||||||
{ "devices_present", offsetof(TasmotaGlobal_t, devices_present), 0, 0, ctypes_u8, 0 },
|
{ "devices_present", offsetof(TasmotaGlobal_t, devices_present), 0, 0, ctypes_u8, 0 },
|
||||||
{ "energy_driver", offsetof(TasmotaGlobal_t, energy_driver), 0, 0, ctypes_u8, 0 },
|
{ "energy_driver", offsetof(TasmotaGlobal_t, energy_driver), 0, 0, ctypes_u8, 0 },
|
||||||
{ "fast_loop_enabled", offsetof(TasmotaGlobal_t, berry_fast_loop_enabled), 0, 0, ctypes_u8, 0 },
|
{ "fast_loop_enabled", offsetof(TasmotaGlobal_t, berry_fast_loop_enabled), 0, 0, ctypes_u8, 0 },
|
||||||
|
@ -176,6 +176,26 @@ int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// simple wrapper to call `tasmota.<method_name>()`
|
||||||
|
static void callBerryTasmotaFunc(const char * method_name) {
|
||||||
|
bvm *vm = berry.vm;
|
||||||
|
if (be_getglobal(vm, "tasmota")) {
|
||||||
|
if (be_getmethod(vm, -1, method_name)) {
|
||||||
|
be_pushvalue(vm, -2); // add instance as first arg
|
||||||
|
BrTimeoutStart();
|
||||||
|
int32_t ret = be_pcall(vm, 1);
|
||||||
|
if (ret != 0) {
|
||||||
|
be_error_pop_all(berry.vm); // clear Berry stack
|
||||||
|
}
|
||||||
|
BrTimeoutReset();
|
||||||
|
be_pop(vm, 1);
|
||||||
|
}
|
||||||
|
be_pop(vm, 1); // remove method
|
||||||
|
}
|
||||||
|
be_pop(vm, 1); // remove instance object
|
||||||
|
be_pop(vm, be_top(vm)); // clean
|
||||||
|
}
|
||||||
|
|
||||||
// Simplified version of event loop. Just call `tasmota.fast_loop()`
|
// Simplified version of event loop. Just call `tasmota.fast_loop()`
|
||||||
// `every_5ms` is a flag to wait at least 5ms between calss to `tasmota.fast_loop()`
|
// `every_5ms` is a flag to wait at least 5ms between calss to `tasmota.fast_loop()`
|
||||||
void callBerryFastLoop(bool every_5ms) {
|
void callBerryFastLoop(bool every_5ms) {
|
||||||
@ -191,21 +211,13 @@ void callBerryFastLoop(bool every_5ms) {
|
|||||||
fast_loop_last_call = now;
|
fast_loop_last_call = now;
|
||||||
|
|
||||||
// TODO - can we make this dereferencing once for all?
|
// TODO - can we make this dereferencing once for all?
|
||||||
if (be_getglobal(vm, "tasmota")) {
|
callBerryTasmotaFunc("fast_loop");
|
||||||
if (be_getmethod(vm, -1, "fast_loop")) {
|
}
|
||||||
be_pushvalue(vm, -2); // add instance as first arg
|
|
||||||
BrTimeoutStart();
|
// call `tasmota.run_immediate()`
|
||||||
int32_t ret = be_pcall(vm, 1);
|
void callBerryRunDeferred(void) {
|
||||||
if (ret != 0) {
|
if (nullptr == berry.vm) { return; }
|
||||||
be_error_pop_all(berry.vm); // clear Berry stack
|
callBerryTasmotaFunc("run_deferred");
|
||||||
}
|
|
||||||
BrTimeoutReset();
|
|
||||||
be_pop(vm, 1);
|
|
||||||
}
|
|
||||||
be_pop(vm, 1); // remove method
|
|
||||||
}
|
|
||||||
be_pop(vm, 1); // remove instance object
|
|
||||||
be_pop(vm, be_top(vm)); // clean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
@ -888,6 +900,9 @@ bool Xdrv52(uint32_t function)
|
|||||||
|
|
||||||
switch (function) {
|
switch (function) {
|
||||||
case FUNC_SLEEP_LOOP:
|
case FUNC_SLEEP_LOOP:
|
||||||
|
if (TasmotaGlobal.berry_deferred_ready) { // there are immediate functions registered, call them first
|
||||||
|
callBerryRunDeferred(); // call `tasmota.run_immediate()`
|
||||||
|
}
|
||||||
if (TasmotaGlobal.berry_fast_loop_enabled) { // call only if enabled at global level
|
if (TasmotaGlobal.berry_fast_loop_enabled) { // call only if enabled at global level
|
||||||
callBerryFastLoop(true); // call `tasmota.fast_loop()` optimized for minimal performance impact
|
callBerryFastLoop(true); // call `tasmota.fast_loop()` optimized for minimal performance impact
|
||||||
}
|
}
|
||||||
@ -914,6 +929,9 @@ bool Xdrv52(uint32_t function)
|
|||||||
}
|
}
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
}
|
}
|
||||||
|
if (TasmotaGlobal.berry_deferred_ready) { // there are immediate functions registered, call them first
|
||||||
|
callBerryRunDeferred(); // call `tasmota.run_immediate()`
|
||||||
|
}
|
||||||
if (TasmotaGlobal.berry_fast_loop_enabled) { // call only if enabled at global level
|
if (TasmotaGlobal.berry_fast_loop_enabled) { // call only if enabled at global level
|
||||||
callBerryFastLoop(false); // call `tasmota.fast_loop()` optimized for minimal performance impact
|
callBerryFastLoop(false); // call `tasmota.fast_loop()` optimized for minimal performance impact
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user