mirror of https://github.com/arendst/Tasmota.git
Merge pull request #15487 from s-hadinger/berry_mqtt_subscribe
Berry easier MQTT subscribe
This commit is contained in:
commit
33142a7071
|
@ -258,6 +258,7 @@ extern const bcstring be_const_str__rules;
|
|||
extern const bcstring be_const_str__settings_def;
|
||||
extern const bcstring be_const_str__settings_ptr;
|
||||
extern const bcstring be_const_str__splash;
|
||||
extern const bcstring be_const_str__subscribe;
|
||||
extern const bcstring be_const_str__t;
|
||||
extern const bcstring be_const_str__timers;
|
||||
extern const bcstring be_const_str__validate;
|
||||
|
@ -667,6 +668,9 @@ extern const bcstring be_const_str_model;
|
|||
extern const bcstring be_const_str_module;
|
||||
extern const bcstring be_const_str_month;
|
||||
extern const bcstring be_const_str_montserrat_font;
|
||||
extern const bcstring be_const_str_mqtt;
|
||||
extern const bcstring be_const_str_mqtt_data;
|
||||
extern const bcstring be_const_str_mqtt_listener;
|
||||
extern const bcstring be_const_str_name;
|
||||
extern const bcstring be_const_str_nan;
|
||||
extern const bcstring be_const_str_next;
|
||||
|
@ -934,6 +938,7 @@ extern const bcstring be_const_str_toint;
|
|||
extern const bcstring be_const_str_tolower;
|
||||
extern const bcstring be_const_str_tomap;
|
||||
extern const bcstring be_const_str_top;
|
||||
extern const bcstring be_const_str_topic;
|
||||
extern const bcstring be_const_str_toptr;
|
||||
extern const bcstring be_const_str_tostring;
|
||||
extern const bcstring be_const_str_touch_update;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +1,15 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(m_libmqtt_map) {
|
||||
{ be_const_key(unsubscribe, -1), be_const_ctype_func(be_mqtt_unsubscribe) },
|
||||
{ be_const_key(subscribe, -1), be_const_ctype_func(be_mqtt_subscribe) },
|
||||
{ be_const_key(publish, 1), be_const_func(be_mqtt_publish) },
|
||||
{ be_const_key(publish, -1), be_const_func(be_mqtt_publish) },
|
||||
{ be_const_key(_subscribe, -1), be_const_ctype_func(be_mqtt_subscribe) },
|
||||
{ be_const_key(unsubscribe, 1), be_const_ctype_func(be_mqtt_unsubscribe) },
|
||||
{ be_const_key(subscribe, -1), be_const_closure(subscribe_closure) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
m_libmqtt_map,
|
||||
3
|
||||
4
|
||||
);
|
||||
|
||||
static be_define_const_module(
|
||||
|
|
|
@ -0,0 +1,288 @@
|
|||
/********************************************************************
|
||||
* Berry module `mqtt`
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#include "be_constobj.h"
|
||||
#include "be_mapping.h"
|
||||
|
||||
/* Embedded code */
|
||||
|
||||
/*
|
||||
|
||||
def subscribe(topic, closure)
|
||||
class mqtt_listener
|
||||
var topic
|
||||
var closure
|
||||
|
||||
def init(topic, closure)
|
||||
import string
|
||||
self.topic = string.split(topic, '/')
|
||||
self.closure = closure
|
||||
tasmota.add_driver(self)
|
||||
end
|
||||
|
||||
def mqtt_data(topic, idx, payload_s, payload_b)
|
||||
# check if the topic matches the patter
|
||||
import string
|
||||
var topic_elts = string.split(topic, '/')
|
||||
var topic_sz = size(topic_elts)
|
||||
var pat = self.topic
|
||||
var pat_sz = size(pat)
|
||||
var i = 0
|
||||
while i < pat_sz
|
||||
var pat_elt = pat[i]
|
||||
|
||||
if pat_elt == '#'
|
||||
# joker, munch whatever is left
|
||||
# '#' is supposed to be the last character of the topic (we don't check it)
|
||||
break
|
||||
elif i >= topic_sz
|
||||
# the topic is too short - no match
|
||||
return false
|
||||
elif pat_elt == '+'
|
||||
# pass
|
||||
elif pat_elt != topic_elts[i]
|
||||
# topic element are different - no match
|
||||
return false
|
||||
end
|
||||
|
||||
i += 1
|
||||
end
|
||||
|
||||
if i >= pat_sz && pat_sz != topic_sz
|
||||
# the topic is too long and the pattern did not finish with '#' - no match
|
||||
return false
|
||||
end
|
||||
|
||||
var cl = self.closure
|
||||
var ret = cl(topic, idx, payload_s, payload_b)
|
||||
if ret == nil ret = true end # return true if the return value is forgotten
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
import mqtt
|
||||
mqtt._subscribe(topic)
|
||||
if type(closure) == 'function'
|
||||
tasmota.check_not_method(closure)
|
||||
mqtt_listener(topic, closure)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: mqtt_data
|
||||
********************************************************************/
|
||||
be_local_closure(mqtt_listener_mqtt_data, /* name */
|
||||
be_nested_proto(
|
||||
17, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 9]) { /* constants */
|
||||
/* K0 */ be_nested_str(string),
|
||||
/* K1 */ be_nested_str(split),
|
||||
/* K2 */ be_nested_str(_X2F),
|
||||
/* K3 */ be_nested_str(topic),
|
||||
/* K4 */ be_const_int(0),
|
||||
/* K5 */ be_nested_str(_X23),
|
||||
/* K6 */ be_nested_str(_X2B),
|
||||
/* K7 */ be_const_int(1),
|
||||
/* K8 */ be_nested_str(closure),
|
||||
}),
|
||||
&be_const_str_mqtt_data,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[53]) { /* code */
|
||||
0xA4160000, // 0000 IMPORT R5 K0
|
||||
0x8C180B01, // 0001 GETMET R6 R5 K1
|
||||
0x5C200200, // 0002 MOVE R8 R1
|
||||
0x58240002, // 0003 LDCONST R9 K2
|
||||
0x7C180600, // 0004 CALL R6 3
|
||||
0x601C000C, // 0005 GETGBL R7 G12
|
||||
0x5C200C00, // 0006 MOVE R8 R6
|
||||
0x7C1C0200, // 0007 CALL R7 1
|
||||
0x88200103, // 0008 GETMBR R8 R0 K3
|
||||
0x6024000C, // 0009 GETGBL R9 G12
|
||||
0x5C281000, // 000A MOVE R10 R8
|
||||
0x7C240200, // 000B CALL R9 1
|
||||
0x58280004, // 000C LDCONST R10 K4
|
||||
0x142C1409, // 000D LT R11 R10 R9
|
||||
0x782E0013, // 000E JMPF R11 #0023
|
||||
0x942C100A, // 000F GETIDX R11 R8 R10
|
||||
0x1C301705, // 0010 EQ R12 R11 K5
|
||||
0x78320001, // 0011 JMPF R12 #0014
|
||||
0x7002000F, // 0012 JMP #0023
|
||||
0x7002000C, // 0013 JMP #0021
|
||||
0x28301407, // 0014 GE R12 R10 R7
|
||||
0x78320002, // 0015 JMPF R12 #0019
|
||||
0x50300000, // 0016 LDBOOL R12 0 0
|
||||
0x80041800, // 0017 RET 1 R12
|
||||
0x70020007, // 0018 JMP #0021
|
||||
0x1C301706, // 0019 EQ R12 R11 K6
|
||||
0x78320000, // 001A JMPF R12 #001C
|
||||
0x70020004, // 001B JMP #0021
|
||||
0x94300C0A, // 001C GETIDX R12 R6 R10
|
||||
0x2030160C, // 001D NE R12 R11 R12
|
||||
0x78320001, // 001E JMPF R12 #0021
|
||||
0x50300000, // 001F LDBOOL R12 0 0
|
||||
0x80041800, // 0020 RET 1 R12
|
||||
0x00281507, // 0021 ADD R10 R10 K7
|
||||
0x7001FFE9, // 0022 JMP #000D
|
||||
0x282C1409, // 0023 GE R11 R10 R9
|
||||
0x782E0003, // 0024 JMPF R11 #0029
|
||||
0x202C1207, // 0025 NE R11 R9 R7
|
||||
0x782E0001, // 0026 JMPF R11 #0029
|
||||
0x502C0000, // 0027 LDBOOL R11 0 0
|
||||
0x80041600, // 0028 RET 1 R11
|
||||
0x882C0108, // 0029 GETMBR R11 R0 K8
|
||||
0x5C301600, // 002A MOVE R12 R11
|
||||
0x5C340200, // 002B MOVE R13 R1
|
||||
0x5C380400, // 002C MOVE R14 R2
|
||||
0x5C3C0600, // 002D MOVE R15 R3
|
||||
0x5C400800, // 002E MOVE R16 R4
|
||||
0x7C300800, // 002F CALL R12 4
|
||||
0x4C340000, // 0030 LDNIL R13
|
||||
0x1C34180D, // 0031 EQ R13 R12 R13
|
||||
0x78360000, // 0032 JMPF R13 #0034
|
||||
0x50300200, // 0033 LDBOOL R12 1 0
|
||||
0x80041800, // 0034 RET 1 R12
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: init
|
||||
********************************************************************/
|
||||
be_local_closure(mqtt_listener_init, /* name */
|
||||
be_nested_proto(
|
||||
8, /* nstack */
|
||||
3, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 7]) { /* constants */
|
||||
/* K0 */ be_nested_str(string),
|
||||
/* K1 */ be_nested_str(topic),
|
||||
/* K2 */ be_nested_str(split),
|
||||
/* K3 */ be_nested_str(_X2F),
|
||||
/* K4 */ be_nested_str(closure),
|
||||
/* K5 */ be_nested_str(tasmota),
|
||||
/* K6 */ be_nested_str(add_driver),
|
||||
}),
|
||||
&be_const_str_init,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[12]) { /* code */
|
||||
0xA40E0000, // 0000 IMPORT R3 K0
|
||||
0x8C100702, // 0001 GETMET R4 R3 K2
|
||||
0x5C180200, // 0002 MOVE R6 R1
|
||||
0x581C0003, // 0003 LDCONST R7 K3
|
||||
0x7C100600, // 0004 CALL R4 3
|
||||
0x90020204, // 0005 SETMBR R0 K1 R4
|
||||
0x90020802, // 0006 SETMBR R0 K4 R2
|
||||
0xB8120A00, // 0007 GETNGBL R4 K5
|
||||
0x8C100906, // 0008 GETMET R4 R4 K6
|
||||
0x5C180000, // 0009 MOVE R6 R0
|
||||
0x7C100400, // 000A CALL R4 2
|
||||
0x80000000, // 000B RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: mqtt_listener
|
||||
********************************************************************/
|
||||
be_local_class(mqtt_listener,
|
||||
2,
|
||||
NULL,
|
||||
be_nested_map(4,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key(topic, 1), be_const_var(0) },
|
||||
{ be_const_key(mqtt_data, -1), be_const_closure(mqtt_listener_mqtt_data_closure) },
|
||||
{ be_const_key(closure, -1), be_const_var(1) },
|
||||
{ be_const_key(init, -1), be_const_closure(mqtt_listener_init_closure) },
|
||||
})),
|
||||
(bstring*) &be_const_str_mqtt_listener
|
||||
);
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: subscribe
|
||||
********************************************************************/
|
||||
be_local_closure(subscribe, /* name */
|
||||
be_nested_proto(
|
||||
7, /* nstack */
|
||||
2, /* argc */
|
||||
0, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 6]) { /* constants */
|
||||
/* K0 */ be_const_class(be_class_mqtt_listener),
|
||||
/* K1 */ be_nested_str(mqtt),
|
||||
/* K2 */ be_nested_str(_subscribe),
|
||||
/* K3 */ be_nested_str(function),
|
||||
/* K4 */ be_nested_str(tasmota),
|
||||
/* K5 */ be_nested_str(check_not_method),
|
||||
}),
|
||||
&be_const_str_subscribe,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[20]) { /* code */
|
||||
0x58080000, // 0000 LDCONST R2 K0
|
||||
0xB4000000, // 0001 CLASS K0
|
||||
0xA40E0200, // 0002 IMPORT R3 K1
|
||||
0x8C100702, // 0003 GETMET R4 R3 K2
|
||||
0x5C180000, // 0004 MOVE R6 R0
|
||||
0x7C100400, // 0005 CALL R4 2
|
||||
0x60100004, // 0006 GETGBL R4 G4
|
||||
0x5C140200, // 0007 MOVE R5 R1
|
||||
0x7C100200, // 0008 CALL R4 1
|
||||
0x1C100903, // 0009 EQ R4 R4 K3
|
||||
0x78120007, // 000A JMPF R4 #0013
|
||||
0xB8120800, // 000B GETNGBL R4 K4
|
||||
0x8C100905, // 000C GETMET R4 R4 K5
|
||||
0x5C180200, // 000D MOVE R6 R1
|
||||
0x7C100400, // 000E CALL R4 2
|
||||
0x5C100400, // 000F MOVE R4 R2
|
||||
0x5C140000, // 0010 MOVE R5 R0
|
||||
0x5C180200, // 0011 MOVE R6 R1
|
||||
0x7C100400, // 0012 CALL R4 2
|
||||
0x80000000, // 0013 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
extern int be_mqtt_publish(bvm *vm);
|
||||
|
||||
extern void be_mqtt_subscribe(const char* topic); BE_FUNC_CTYPE_DECLARE(be_mqtt_subscribe, "", "s")
|
||||
extern void be_mqtt_unsubscribe(const char* topic); BE_FUNC_CTYPE_DECLARE(be_mqtt_unsubscribe, "", "s")
|
||||
|
||||
/* @const_object_info_begin
|
||||
module mqtt (scope: global) {
|
||||
publish, func(be_mqtt_publish)
|
||||
subscribe, closure(subscribe_closure)
|
||||
_subscribe, ctype_func(be_mqtt_subscribe)
|
||||
unsubscribe, ctype_func(be_mqtt_unsubscribe)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "be_fixed_mqtt.h"
|
|
@ -1,21 +0,0 @@
|
|||
/********************************************************************
|
||||
* Berry module `mqtt`
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#include "be_constobj.h"
|
||||
#include "be_mapping.h"
|
||||
|
||||
extern int be_mqtt_publish(bvm *vm);
|
||||
|
||||
extern void be_mqtt_subscribe(const char* topic); BE_FUNC_CTYPE_DECLARE(be_mqtt_subscribe, "", "s")
|
||||
extern void be_mqtt_unsubscribe(const char* topic); BE_FUNC_CTYPE_DECLARE(be_mqtt_unsubscribe, "", "s")
|
||||
|
||||
/* @const_object_info_begin
|
||||
module mqtt (scope: global) {
|
||||
publish, func(be_mqtt_publish)
|
||||
subscribe, ctype_func(be_mqtt_subscribe)
|
||||
unsubscribe, ctype_func(be_mqtt_unsubscribe)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "be_fixed_mqtt.h"
|
|
@ -741,7 +741,7 @@ be_local_closure(Tasmota_add_fast_loop, /* name */
|
|||
********************************************************************/
|
||||
be_local_closure(Tasmota_event, /* name */
|
||||
be_nested_proto(
|
||||
20, /* nstack */
|
||||
21, /* nstack */
|
||||
6, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
|
@ -749,37 +749,38 @@ be_local_closure(Tasmota_event, /* name */
|
|||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[26]) { /* constants */
|
||||
( &(const bvalue[27]) { /* 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(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),
|
||||
/* K6 */ be_nested_str(mqtt_data),
|
||||
/* K7 */ be_nested_str(cmd),
|
||||
/* K8 */ be_nested_str(exec_cmd),
|
||||
/* K9 */ be_nested_str(tele),
|
||||
/* K10 */ be_nested_str(exec_tele),
|
||||
/* K11 */ be_nested_str(rule),
|
||||
/* K12 */ be_nested_str(exec_rules),
|
||||
/* K13 */ be_nested_str(gc),
|
||||
/* K14 */ be_nested_str(_drivers),
|
||||
/* K15 */ be_const_int(0),
|
||||
/* K16 */ be_nested_str(get),
|
||||
/* K17 */ be_nested_str(function),
|
||||
/* K18 */ be_nested_str(format),
|
||||
/* K19 */ be_nested_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s),
|
||||
/* K20 */ be_nested_str(_debug_present),
|
||||
/* K21 */ be_nested_str(debug),
|
||||
/* K22 */ be_nested_str(traceback),
|
||||
/* K23 */ be_const_int(1),
|
||||
/* K24 */ be_nested_str(save_before_restart),
|
||||
/* K25 */ be_nested_str(persist),
|
||||
/* K26 */ be_nested_str(save),
|
||||
}),
|
||||
&be_const_str_event,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[97]) { /* code */
|
||||
( &(const binstruction[106]) { /* code */
|
||||
0xA41A0000, // 0000 IMPORT R6 K0
|
||||
0xA41E0200, // 0001 IMPORT R7 K1
|
||||
0x1C200302, // 0002 EQ R8 R1 K2
|
||||
|
@ -791,92 +792,101 @@ be_local_closure(Tasmota_event, /* name */
|
|||
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
|
||||
0x50240000, // 000B LDBOOL R9 0 0
|
||||
0x1C280306, // 000C EQ R10 R1 K6
|
||||
0x782A0000, // 000D JMPF R10 #000F
|
||||
0x50240200, // 000E LDBOOL R9 1 0
|
||||
0x1C280307, // 000F EQ R10 R1 K7
|
||||
0x782A0006, // 0010 JMPF R10 #0018
|
||||
0x8C280108, // 0011 GETMET R10 R0 K8
|
||||
0x5C300400, // 0012 MOVE R12 R2
|
||||
0x5C340600, // 0013 MOVE R13 R3
|
||||
0x5C380800, // 0014 MOVE R14 R4
|
||||
0x7C280800, // 0015 CALL R10 4
|
||||
0x80041400, // 0016 RET 1 R10
|
||||
0x7002004B, // 0017 JMP #0064
|
||||
0x1C280309, // 0018 EQ R10 R1 K9
|
||||
0x782A0004, // 0019 JMPF R10 #001F
|
||||
0x8C28010A, // 001A GETMET R10 R0 K10
|
||||
0x5C300800, // 001B MOVE R12 R4
|
||||
0x7C280400, // 001C CALL R10 2
|
||||
0x80041400, // 001D RET 1 R10
|
||||
0x70020044, // 001E JMP #0064
|
||||
0x1C28030B, // 001F EQ R10 R1 K11
|
||||
0x782A0004, // 0020 JMPF R10 #0026
|
||||
0x8C28010C, // 0021 GETMET R10 R0 K12
|
||||
0x5C300800, // 0022 MOVE R12 R4
|
||||
0x7C280400, // 0023 CALL R10 2
|
||||
0x80041400, // 0024 RET 1 R10
|
||||
0x7002003D, // 0025 JMP #0064
|
||||
0x1C28030D, // 0026 EQ R10 R1 K13
|
||||
0x782A0003, // 0027 JMPF R10 #002C
|
||||
0x8C28010D, // 0028 GETMET R10 R0 K13
|
||||
0x7C280200, // 0029 CALL R10 1
|
||||
0x80041400, // 002A RET 1 R10
|
||||
0x70020037, // 002B JMP #0064
|
||||
0x8828010E, // 002C GETMBR R10 R0 K14
|
||||
0x782A0035, // 002D JMPF R10 #0064
|
||||
0x5828000F, // 002E LDCONST R10 K15
|
||||
0x602C000C, // 002F GETGBL R11 G12
|
||||
0x8830010E, // 0030 GETMBR R12 R0 K14
|
||||
0x7C2C0200, // 0031 CALL R11 1
|
||||
0x142C140B, // 0032 LT R11 R10 R11
|
||||
0x782E002F, // 0033 JMPF R11 #0064
|
||||
0x882C010E, // 0034 GETMBR R11 R0 K14
|
||||
0x942C160A, // 0035 GETIDX R11 R11 R10
|
||||
0x8C300D10, // 0036 GETMET R12 R6 K16
|
||||
0x5C381600, // 0037 MOVE R14 R11
|
||||
0x5C3C0200, // 0038 MOVE R15 R1
|
||||
0x7C300600, // 0039 CALL R12 3
|
||||
0x60340004, // 003A GETGBL R13 G4
|
||||
0x5C381800, // 003B MOVE R14 R12
|
||||
0x7C340200, // 003C CALL R13 1
|
||||
0x1C341B11, // 003D EQ R13 R13 K17
|
||||
0x78360022, // 003E JMPF R13 #0062
|
||||
0xA8020011, // 003F EXBLK 0 #0052
|
||||
0x5C341800, // 0040 MOVE R13 R12
|
||||
0x5C381600, // 0041 MOVE R14 R11
|
||||
0x5C3C0400, // 0042 MOVE R15 R2
|
||||
0x5C400600, // 0043 MOVE R16 R3
|
||||
0x5C440800, // 0044 MOVE R17 R4
|
||||
0x5C480A00, // 0045 MOVE R18 R5
|
||||
0x7C340A00, // 0046 CALL R13 5
|
||||
0x74360001, // 0047 JMPT R13 #004A
|
||||
0x74220000, // 0048 JMPT R8 #004A
|
||||
0x50200001, // 0049 LDBOOL R8 0 1
|
||||
0x50200200, // 004A LDBOOL R8 1 0
|
||||
0x78220003, // 004B JMPF R8 #0050
|
||||
0x5C341200, // 004C MOVE R13 R9
|
||||
0x74360001, // 004D JMPT R13 #0050
|
||||
0xA8040001, // 004E EXBLK 1 1
|
||||
0x70020013, // 004F JMP #0064
|
||||
0xA8040001, // 0050 EXBLK 1 1
|
||||
0x7002000F, // 0051 JMP #0062
|
||||
0xAC340002, // 0052 CATCH R13 0 2
|
||||
0x7002000C, // 0053 JMP #0061
|
||||
0x603C0001, // 0054 GETGBL R15 G1
|
||||
0x8C400F12, // 0055 GETMET R16 R7 K18
|
||||
0x58480013, // 0056 LDCONST R18 K19
|
||||
0x5C4C1A00, // 0057 MOVE R19 R13
|
||||
0x5C501C00, // 0058 MOVE R20 R14
|
||||
0x7C400800, // 0059 CALL R16 4
|
||||
0x7C3C0200, // 005A CALL R15 1
|
||||
0x883C0114, // 005B GETMBR R15 R0 K20
|
||||
0x783E0002, // 005C JMPF R15 #0060
|
||||
0xA43E2A00, // 005D IMPORT R15 K21
|
||||
0x8C401F16, // 005E GETMET R16 R15 K22
|
||||
0x7C400200, // 005F CALL R16 1
|
||||
0x70020000, // 0060 JMP #0062
|
||||
0xB0080000, // 0061 RAISE 2 R0 R0
|
||||
0x00281517, // 0062 ADD R10 R10 K23
|
||||
0x7001FFCA, // 0063 JMP #002F
|
||||
0x1C280318, // 0064 EQ R10 R1 K24
|
||||
0x782A0002, // 0065 JMPF R10 #0069
|
||||
0xA42A3200, // 0066 IMPORT R10 K25
|
||||
0x8C2C151A, // 0067 GETMET R11 R10 K26
|
||||
0x7C2C0200, // 0068 CALL R11 1
|
||||
0x80041000, // 0069 RET 1 R8
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
|
@ -633,6 +633,12 @@ class Tasmota
|
|||
end
|
||||
|
||||
var done = false
|
||||
var keep_going = false # if true, we continue dispatch event if done == true (for mqtt_data)
|
||||
|
||||
if event_type == 'mqtt_data'
|
||||
keep_going = true
|
||||
end
|
||||
|
||||
if event_type=='cmd' return self.exec_cmd(cmd, idx, payload)
|
||||
elif event_type=='tele' return self.exec_tele(payload)
|
||||
elif event_type=='rule' return self.exec_rules(payload)
|
||||
|
@ -640,13 +646,12 @@ class Tasmota
|
|||
elif self._drivers
|
||||
var i = 0
|
||||
while i < size(self._drivers)
|
||||
#for d:self._drivers
|
||||
var d = self._drivers[i]
|
||||
var f = introspect.get(d, event_type) # try to match a function or method with the same name
|
||||
if type(f) == 'function'
|
||||
try
|
||||
done = f(d, cmd, idx, payload, raw)
|
||||
if done break end
|
||||
done = f(d, cmd, idx, payload, raw) || done
|
||||
if done && !keep_going break end
|
||||
except .. as e,m
|
||||
print(string.format("BRY: Exception> '%s' - %s", e, m))
|
||||
if self._debug_present
|
||||
|
|
|
@ -0,0 +1,510 @@
|
|||
#######################################################################
|
||||
# Partition manager for ESP32 - ESP32C3 - ESP32S2
|
||||
#
|
||||
# use : `import partition_core`
|
||||
#
|
||||
# To solidify:
|
||||
#-
|
||||
import solidify load("partition_core.be") solidify.dump(partition_core)
|
||||
-#
|
||||
# Provides low-level objects and a Web UI
|
||||
#######################################################################
|
||||
|
||||
var partition_core2 = module('partition_core2')
|
||||
|
||||
#######################################################################
|
||||
# Class for a partition table entry
|
||||
#
|
||||
# typedef struct {
|
||||
# uint16_t magic;
|
||||
# uint8_t type;
|
||||
# uint8_t subtype;
|
||||
# uint32_t offset;
|
||||
# uint32_t size;
|
||||
# uint8_t label[16];
|
||||
# uint32_t flags;
|
||||
# } esp_partition_info_t_simplified;
|
||||
#
|
||||
#######################################################################
|
||||
class Partition_info
|
||||
var type
|
||||
var subtype
|
||||
var start
|
||||
var size
|
||||
var label
|
||||
var flags
|
||||
|
||||
#- remove trailing NULL chars from a bytes buffer before converting to string -#
|
||||
#- Berry strings can contain NULL, but this messes up C-Berry interface -#
|
||||
static def remove_trailing_zeroes(b)
|
||||
var sz = size(b)
|
||||
var i = 0
|
||||
while i < sz
|
||||
if b[-1-i] != 0 break end
|
||||
i += 1
|
||||
end
|
||||
if i > 0
|
||||
b.resize(size(b)-i)
|
||||
end
|
||||
return b
|
||||
end
|
||||
|
||||
# Init the Parition information structure, either from a bytes() buffer or an empty if no buffer is provided
|
||||
def init(raw)
|
||||
self.type = 0
|
||||
self.subtype = 0
|
||||
self.start = 0
|
||||
self.size = 0
|
||||
self.label = ''
|
||||
self.flags = 0
|
||||
|
||||
if !issubclass(bytes, raw) # no payload, empty partition information
|
||||
return
|
||||
end
|
||||
|
||||
#- we have a payload, parse it -#
|
||||
var magic = raw.get(0,2)
|
||||
if magic == 0x50AA #- partition entry -#
|
||||
|
||||
self.type = raw.get(2,1)
|
||||
self.subtype = raw.get(3,1)
|
||||
self.start = raw.get(4,4)
|
||||
self.size = raw.get(8,4)
|
||||
print("size", self.size)
|
||||
self.label = self.remove_trailing_zeroes(raw[12..27]).asstring()
|
||||
self.flags = raw.get(28,4)
|
||||
|
||||
# elif magic == 0xEBEB #- MD5 -#
|
||||
else
|
||||
import string
|
||||
raise "internal_error", string.format("invalid magic number %02X", magic)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# check if the parition is an OTA partition
|
||||
# if yes, return OTA number (starting at 0)
|
||||
# if no, return nil
|
||||
def is_ota()
|
||||
var sub_type = self.subtype
|
||||
if self.type == 0 && (sub_type >= 0x10 && sub_type < 0x20)
|
||||
return sub_type - 0x10
|
||||
end
|
||||
end
|
||||
|
||||
# check if the parition is a SPIFFS partition
|
||||
# returns bool
|
||||
def is_spiffs()
|
||||
return self.type == 1 && self.subtype == 130
|
||||
end
|
||||
|
||||
# get the actual image size give of the partition
|
||||
# returns -1 if the partition is not an app ota partition
|
||||
def get_image_size()
|
||||
import flash
|
||||
if self.is_ota() == nil return -1 end
|
||||
try
|
||||
var addr = self.start
|
||||
var magic_byte = flash.read(addr, 1).get(0, 1)
|
||||
if magic_byte != 0xE9 return -1 end
|
||||
|
||||
var seg_count = flash.read(addr+1, 1).get(0, 1)
|
||||
# print("Segment count", seg_count)
|
||||
|
||||
var seg_offset = addr + 0x20 # sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) = 24 + 8
|
||||
|
||||
var seg_num = 0
|
||||
while seg_num < seg_count
|
||||
# print(string.format("Reading 0x%08X", seg_offset))
|
||||
var segment_header = flash.read(seg_offset - 8, 8)
|
||||
var seg_start_addr = segment_header.get(0, 4)
|
||||
var seg_size = segment_header.get(4,4)
|
||||
# print(string.format("Segment %i: flash_offset=0x%08X start_addr=0x%08X size=0x%08X", seg_num, seg_offset, seg_start_addr, seg_size))
|
||||
|
||||
seg_offset += seg_size + 8 # add segment_length + sizeof(esp_image_segment_header_t)
|
||||
|
||||
seg_num += 1
|
||||
end
|
||||
var total_size = seg_offset - addr + 1 # add 1KB for safety
|
||||
|
||||
# print(string.format("Total size = %i KB", total_size/1024))
|
||||
|
||||
return total_size
|
||||
except .. as e, m
|
||||
tasmota.log("BRY: Exception> '" + e + "' - " + m, 2)
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
# Human readable version of Partition information
|
||||
# this method is not included in the solidified version to save space,
|
||||
# it is included only in the optional application `tapp` version
|
||||
def tostring()
|
||||
import string
|
||||
var type_s = ""
|
||||
var subtype_s = ""
|
||||
if self.type == 0 type_s = "app"
|
||||
if self.subtype == 0 subtype_s = "factory"
|
||||
elif self.subtype >= 0x10 && self.subtype < 0x20 subtype_s = "ota" + str(self.subtype - 0x10)
|
||||
elif self.subtype == 0x20 subtype_s = "test"
|
||||
end
|
||||
elif self.type == 1 type_s = "data"
|
||||
if self.subtype == 0x00 subtype_s = "otadata"
|
||||
elif self.subtype == 0x01 subtype_s = "phy"
|
||||
elif self.subtype == 0x02 subtype_s = "nvs"
|
||||
elif self.subtype == 0x03 subtype_s = "coredump"
|
||||
elif self.subtype == 0x04 subtype_s = "nvskeys"
|
||||
elif self.subtype == 0x05 subtype_s = "efuse_em"
|
||||
elif self.subtype == 0x80 subtype_s = "esphttpd"
|
||||
elif self.subtype == 0x81 subtype_s = "fat"
|
||||
elif self.subtype == 0x82 subtype_s = "spiffs"
|
||||
end
|
||||
end
|
||||
|
||||
# reformat strings
|
||||
if type_s != "" type_s = " (" + type_s + ")" end
|
||||
if subtype_s != "" subtype_s = " (" + subtype_s + ")" end
|
||||
return string.format("<instance: Partition_info(%d%s,%d%s,0x%08X,0x%08X,'%s',0x%X)>",
|
||||
self.type, type_s,
|
||||
self.subtype, subtype_s,
|
||||
self.start, self.size,
|
||||
self.label, self.flags)
|
||||
end
|
||||
|
||||
def tobytes()
|
||||
#- convert to raw bytes -#
|
||||
var b = bytes('AA50') #- set magic number -#
|
||||
b.resize(32).resize(2) #- pre-reserve 32 bytes -#
|
||||
b.add(self.type, 1)
|
||||
b.add(self.subtype, 1)
|
||||
b.add(self.start, 4)
|
||||
b.add(self.size, 4)
|
||||
var label = bytes().fromstring(self.label)
|
||||
label.resize(16)
|
||||
b = b + label
|
||||
b.add(self.flags, 4)
|
||||
return b
|
||||
end
|
||||
|
||||
end
|
||||
partition_core2.Partition_info = Partition_info
|
||||
|
||||
#-------------------------------------------------------------
|
||||
- OTA Data
|
||||
-
|
||||
- Selection of the active OTA partition
|
||||
-
|
||||
typedef struct {
|
||||
uint32_t ota_seq;
|
||||
uint8_t seq_label[20];
|
||||
uint32_t ota_state;
|
||||
uint32_t crc; /* CRC32 of ota_seq field only */
|
||||
} esp_ota_select_entry_t;
|
||||
|
||||
- Excerp from esp_ota_ops.c
|
||||
esp32_idf use two sector for store information about which partition is running
|
||||
it defined the two sector as ota data partition,two structure esp_ota_select_entry_t is saved in the two sector
|
||||
named data in first sector as otadata[0], second sector data as otadata[1]
|
||||
e.g.
|
||||
if otadata[0].ota_seq == otadata[1].ota_seq == 0xFFFFFFFF,means ota info partition is in init status
|
||||
so it will boot factory application(if there is),if there's no factory application,it will boot ota[0] application
|
||||
if otadata[0].ota_seq != 0 and otadata[1].ota_seq != 0,it will choose a max seq ,and get value of max_seq%max_ota_app_number
|
||||
and boot a subtype (mask 0x0F) value is (max_seq - 1)%max_ota_app_number,so if want switch to run ota[x],can use next formulas.
|
||||
for example, if otadata[0].ota_seq = 4, otadata[1].ota_seq = 5, and there are 8 ota application,
|
||||
current running is (5-1)%8 = 4,running ota[4],so if we want to switch to run ota[7],
|
||||
we should add otadata[0].ota_seq (is 4) to 4 ,(8-1)%8=7,then it will boot ota[7]
|
||||
if A=(B - C)%D
|
||||
then B=(A + C)%D + D*n ,n= (0,1,2...)
|
||||
so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
|
||||
seq will add (x + n*1 + 1 - seq)%n
|
||||
-------------------------------------------------------------#
|
||||
class Partition_otadata
|
||||
var maxota #- number of highest OTA partition, default 1 (double ota0/ota1) -#
|
||||
var offset #- offset of the otadata partition (0x2000 in length), default 0xE000 -#
|
||||
var active_otadata #- which otadata block is active, 0 or 1, i.e. 0xE000 or 0xF000 -#
|
||||
var seq0 #- ota_seq of first block -#
|
||||
var seq1 #- ota_seq of second block -#
|
||||
|
||||
#- crc32 for ota_seq as 32 bits unsigned, with init vector -1 -#
|
||||
static def crc32_ota_seq(seq)
|
||||
import crc
|
||||
return crc.crc32(0xFFFFFFFF, bytes().add(seq, 4))
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------#
|
||||
# Rest of the class
|
||||
#---------------------------------------------------------------------#
|
||||
def init(maxota, offset)
|
||||
self.maxota = maxota
|
||||
if self.maxota == nil self.maxota = 1 end
|
||||
self.offset = offset
|
||||
if self.offset == nil self.offset = 0xE000 end
|
||||
self.active_otadata = 0
|
||||
self.load()
|
||||
end
|
||||
|
||||
#- update ota_max, needs to recompute everything -#
|
||||
def set_ota_max(n)
|
||||
self.maxota = n
|
||||
end
|
||||
|
||||
# change the active OTA partition
|
||||
def set_active(n)
|
||||
var seq_max = 0 #- current highest seq number -#
|
||||
var block_act = 0 #- block number containing the highest seq number -#
|
||||
|
||||
if self.seq0 != nil
|
||||
seq_max = self.seq0
|
||||
block_act = 0
|
||||
end
|
||||
if self.seq1 != nil && self.seq1 > seq_max
|
||||
seq_max = self.seq1
|
||||
block_act = 1
|
||||
end
|
||||
|
||||
#- compute the next sequence number -#
|
||||
var actual_ota = (seq_max - 1) % (self.maxota + 1)
|
||||
if actual_ota != n #- change only if different -#
|
||||
if n > actual_ota seq_max += n - actual_ota
|
||||
else seq_max += (self.maxota + 1) - actual_ota + n
|
||||
end
|
||||
|
||||
#- update internal structure -#
|
||||
if block_act == 1 #- current block is 1, so update block 0 -#
|
||||
self.seq0 = seq_max
|
||||
else #- or write to block 1 -#
|
||||
self.seq1 = seq_max
|
||||
end
|
||||
self._validate()
|
||||
end
|
||||
end
|
||||
|
||||
#- load otadata from SPI Flash -#
|
||||
def load()
|
||||
import flash
|
||||
var otadata0 = flash.read(0xE000, 32)
|
||||
var otadata1 = flash.read(0xF000, 32)
|
||||
self.seq0 = otadata0.get(0, 4) #- ota_seq for block 1 -#
|
||||
self.seq1 = otadata1.get(0, 4) #- ota_seq for block 2 -#
|
||||
var valid0 = otadata0.get(28, 4) == self.crc32_ota_seq(self.seq0) #- is CRC32 valid? -#
|
||||
var valid1 = otadata1.get(28, 4) == self.crc32_ota_seq(self.seq1) #- is CRC32 valid? -#
|
||||
if !valid0 self.seq0 = nil end
|
||||
if !valid1 self.seq1 = nil end
|
||||
|
||||
self._validate()
|
||||
end
|
||||
|
||||
#- internally used, validate data -#
|
||||
def _validate()
|
||||
self.active_otadata = 0 #- if none is valid, default to OTA0 -#
|
||||
if self.seq0 != nil
|
||||
self.active_otadata = (self.seq0 - 1) % (self.maxota + 1)
|
||||
end
|
||||
if self.seq1 != nil && (self.seq0 == nil || self.seq1 > self.seq0)
|
||||
self.active_otadata = (self.seq1 - 1) % (self.maxota + 1)
|
||||
end
|
||||
end
|
||||
|
||||
# Save partition information to SPI Flash
|
||||
def save()
|
||||
import flash
|
||||
#- check the block number to save, 0 or 1. Choose the highest ota_seq -#
|
||||
var block_to_save = -1 #- invalid -#
|
||||
var seq_to_save = -1 #- invalid value -#
|
||||
|
||||
# check seq0
|
||||
if self.seq0 != nil
|
||||
seq_to_save = self.seq0
|
||||
block_to_save = 0
|
||||
end
|
||||
if (self.seq1 != nil) && (self.seq1 > seq_to_save)
|
||||
seq_to_save = self.seq1
|
||||
block_to_save = 1
|
||||
end
|
||||
# if none was good
|
||||
if block_to_save < 0 block_to_save = 0 end
|
||||
if seq_to_save < 0 seq_to_save = 1 end
|
||||
|
||||
var offset_to_save = self.offset + 0x1000 * block_to_save #- default 0xE000 or 0xF000 -#
|
||||
|
||||
var bytes_to_save = bytes()
|
||||
bytes_to_save.add(seq_to_save, 4)
|
||||
bytes_to_save += bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
|
||||
bytes_to_save.add(self.crc32_ota_seq(seq_to_save), 4)
|
||||
|
||||
#- erase flash area and write -#
|
||||
flash.erase(offset_to_save, 0x1000)
|
||||
flash.write(offset_to_save, bytes_to_save)
|
||||
end
|
||||
|
||||
# Produce a human-readable representation of the object with relevant information
|
||||
def tostring()
|
||||
import string
|
||||
return string.format("<instance: Partition_otadata(ota_active:%d, ota_seq=[%d,%d], ota_max=%d)>",
|
||||
self.active_otadata, self.seq0, self.seq1, self.maxota)
|
||||
end
|
||||
end
|
||||
partition_core2.Partition_otadata = Partition_otadata
|
||||
|
||||
#-------------------------------------------------------------
|
||||
- Class for a partition table entry
|
||||
-------------------------------------------------------------#
|
||||
class Partition
|
||||
var raw #- raw bytes of the partition table in flash -#
|
||||
var md5 #- md5 hash of partition list -#
|
||||
var slots
|
||||
var otadata #- instance of Partition_otadata() -#
|
||||
|
||||
def init()
|
||||
self.slots = []
|
||||
self.load()
|
||||
self.parse()
|
||||
self.load_otadata()
|
||||
end
|
||||
|
||||
# Load partition information from SPI Flash
|
||||
def load()
|
||||
import flash
|
||||
self.raw = flash.read(0x8000,0x1000)
|
||||
end
|
||||
|
||||
#- parse the raw bytes to a structured list of partition items -#
|
||||
def parse()
|
||||
for i:0..94 # there are maximum 95 slots + md5 (0xC00)
|
||||
var item_raw = self.raw[i*32..(i+1)*32-1]
|
||||
print(item_raw)
|
||||
var magic = item_raw.get(0,2)
|
||||
if magic == 0x50AA #- partition entry -#
|
||||
var slot = partition_core2.Partition_info(item_raw)
|
||||
self.slots.push(slot)
|
||||
elif magic == 0xEBEB #- MD5 -#
|
||||
self.md5 = self.raw[i*32+16..i*33-1]
|
||||
break
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_ota_slot(n)
|
||||
for slot: self.slots
|
||||
if slot.is_ota() == n return slot end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
#- compute the highest ota<x> partition -#
|
||||
def ota_max()
|
||||
var ota_max = 0
|
||||
for slot:self.slots
|
||||
if slot.type == 0 && (slot.subtype >= 0x10 && slot.subtype < 0x20)
|
||||
var ota_num = slot.subtype - 0x10
|
||||
if ota_num > ota_max ota_max = ota_num end
|
||||
end
|
||||
end
|
||||
return ota_max
|
||||
end
|
||||
|
||||
def load_otadata()
|
||||
#- look for otadata partition offset, and max_ota -#
|
||||
var otadata_offset = 0xE000 #- default value -#
|
||||
var ota_max = self.ota_max()
|
||||
for slot:self.slots
|
||||
if slot.type == 1 && slot.subtype == 0 #- otadata -#
|
||||
otadata_offset = slot.start
|
||||
end
|
||||
end
|
||||
|
||||
self.otadata = partition_core2.Partition_otadata(ota_max, otadata_offset)
|
||||
end
|
||||
|
||||
# get the active OTA app partition number
|
||||
def get_active()
|
||||
return self.otadata.active_otadata
|
||||
end
|
||||
|
||||
#- change the active partition -#
|
||||
def set_active(n)
|
||||
if n < 0 || n > self.ota_max() raise "value_error", "Invalid ota partition number" end
|
||||
self.otadata.set_ota_max(self.ota_max()) #- update ota_max if it changed -#
|
||||
self.otadata.set_active(n)
|
||||
end
|
||||
|
||||
# Human readable version of Partition information
|
||||
# this method is not included in the solidified version to save space,
|
||||
# it is included only in the optional application `tapp` version
|
||||
#- convert to human readble -#
|
||||
def tostring()
|
||||
var ret = "<instance: Partition([\n"
|
||||
for slot: self.slots
|
||||
ret += " "
|
||||
ret += slot.tostring()
|
||||
ret += "\n"
|
||||
end
|
||||
ret += "],\n "
|
||||
ret += self.otadata.tostring()
|
||||
ret += "\n)>"
|
||||
return ret
|
||||
end
|
||||
|
||||
#- convert the slots to raw bytes, ready to falsh to parition page -#
|
||||
def tobytes()
|
||||
if size(self.slots) > 95 raise "value_error", "Too many partiition slots" end
|
||||
var b = bytes()
|
||||
for slot: self.slots
|
||||
b += slot.tobytes()
|
||||
end
|
||||
#- compute MD5 -#
|
||||
var md5 = MD5()
|
||||
md5.update(b)
|
||||
#- add the last segment -#
|
||||
b += bytes("EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
|
||||
b += md5.finish()
|
||||
#- complete -#
|
||||
return b
|
||||
end
|
||||
|
||||
#- write back to flash -#
|
||||
def save()
|
||||
import flash
|
||||
var b = self.tobytes()
|
||||
#- erase flash area and write -#
|
||||
flash.erase(0x8000, 0x1000)
|
||||
flash.write(0x8000, b)
|
||||
self.otadata.save()
|
||||
end
|
||||
|
||||
#- invalidate SPIFFS partition to force format at next boot -#
|
||||
#- we simply erase the first byte of the first 2 blocks in the SPIFFS partition -#
|
||||
def invalidate_spiffs()
|
||||
import flash
|
||||
#- we expect the SPIFFS partition to be the last one -#
|
||||
var spiffs = self.slots[-1]
|
||||
if !spiffs.is_spiffs() raise 'value_error', 'No SPIFFS partition found' end
|
||||
|
||||
var b = bytes("00") #- flash memory: we can turn bits from '1' to '0' -#
|
||||
flash.write(spiffs.start , b) #- block #0 -#
|
||||
flash.write(spiffs.start + 0x1000, b) #- block #1 -#
|
||||
end
|
||||
end
|
||||
partition_core2.Partition = Partition
|
||||
|
||||
# init method to force the global `partition_core` is defined even if the import is done within a function
|
||||
def init(m)
|
||||
import global
|
||||
global.partition_core2 = m
|
||||
return m
|
||||
end
|
||||
partition_core2.init = init
|
||||
|
||||
return partition_core2
|
||||
|
||||
#- Example
|
||||
|
||||
import partition_core2
|
||||
|
||||
# read
|
||||
p = partition_core2.Partition()
|
||||
print(p)
|
||||
|
||||
-#
|
|
@ -70,20 +70,20 @@ extern "C" {
|
|||
int32_t l_publish(struct bvm *vm) {
|
||||
return be_mqtt_publish(vm, true);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t be_mqtt_publish(struct bvm *vm) {
|
||||
return be_mqtt_publish(vm, false);
|
||||
}
|
||||
int32_t be_mqtt_publish(struct bvm *vm) {
|
||||
return be_mqtt_publish(vm, false);
|
||||
}
|
||||
|
||||
void be_mqtt_subscribe(const char* topic) {
|
||||
if (!topic) { return; }
|
||||
MqttSubscribe(topic);
|
||||
}
|
||||
void be_mqtt_subscribe(const char* topic) {
|
||||
if (!topic) { return; }
|
||||
MqttSubscribe(topic);
|
||||
}
|
||||
|
||||
void be_mqtt_unsubscribe(const char* topic) {
|
||||
if (!topic) { return; }
|
||||
MqttUnsubscribe(topic);
|
||||
void be_mqtt_unsubscribe(const char* topic) {
|
||||
if (!topic) { return; }
|
||||
MqttUnsubscribe(topic);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_BERRY
|
||||
|
|
Loading…
Reference in New Issue