Merge pull request #12779 from s-hadinger/berry_aes_gcm

Berry support for AES GCM and raw MQTT send/receive
This commit is contained in:
s-hadinger 2021-07-29 20:37:43 +02:00 committed by GitHub
commit 4926f7445e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1946 additions and 1644 deletions

View File

@ -0,0 +1,44 @@
/********************************************************************
* Berry module `webserver`
*
* To use: `import webserver`
*
* Allows to respond to HTTP request
*******************************************************************/
#include "be_constobj.h"
#ifdef USE_ALEXA_AVS
extern int m_aes_gcm_init(bvm *vm);
extern int m_aes_gcm_encryt(bvm *vm);
extern int m_aes_gcm_decryt(bvm *vm);
extern int m_aes_gcm_tag(bvm *vm);
#if BE_USE_PRECOMPILED_OBJECT
#include "../generate/be_fixed_be_class_aes_gcm.h"
#endif
void be_load_aes_gcm_lib(bvm *vm) {
// insert the class GCM in module AES
be_newmodule(vm);
be_setname(vm, -1, "AES");
be_setglobal(vm, "AES");
be_pushntvclass(vm, &be_class_aes_gcm);
be_setmember(vm, -2, "GCM");
be_pop(vm, 2);
}
/* @const_object_info_begin
class be_class_aes_gcm (scope: global, name: GCM) {
.p1, var
.p2, var
init, func(m_aes_gcm_init)
encrypt, func(m_aes_gcm_encryt)
decrypt, func(m_aes_gcm_decryt)
tag, func(m_aes_gcm_tag)
}
@const_object_info_end */
#endif // USE_ALEXA_AVS

View File

@ -103,6 +103,7 @@ extern void be_load_wirelib(bvm *vm);
extern void be_load_Driver_class(bvm *vm); extern void be_load_Driver_class(bvm *vm);
extern void be_load_driver_i2c_lib(bvm *vm); extern void be_load_driver_i2c_lib(bvm *vm);
extern void be_load_md5_lib(bvm *vm); extern void be_load_md5_lib(bvm *vm);
extern void be_load_aes_gcm_lib(bvm *vm);
#ifdef USE_I2S_AUDIO_BERRY #ifdef USE_I2S_AUDIO_BERRY
extern void be_load_driver_audio_lib(bvm *vm); extern void be_load_driver_audio_lib(bvm *vm);
@ -133,6 +134,9 @@ BERRY_API void be_load_custom_libs(bvm *vm)
be_load_tasmota_ntvlib(vm); be_load_tasmota_ntvlib(vm);
be_load_Driver_class(vm); be_load_Driver_class(vm);
be_load_md5_lib(vm); be_load_md5_lib(vm);
#ifdef USE_ALEXA_AVS
be_load_aes_gcm_lib(vm);
#endif
#ifdef USE_I2C #ifdef USE_I2C
be_load_wirelib(vm); be_load_wirelib(vm);
be_load_driver_i2c_lib(vm); be_load_driver_i2c_lib(vm);

View File

@ -1364,8 +1364,8 @@ be_local_closure(gc, /* name */
********************************************************************/ ********************************************************************/
be_local_closure(event, /* name */ be_local_closure(event, /* name */
be_nested_proto( be_nested_proto(
18, /* nstack */ 19, /* nstack */
5, /* argc */ 6, /* argc */
0, /* has upvals */ 0, /* has upvals */
NULL, /* no upvals */ NULL, /* no upvals */
0, /* has sup protos */ 0, /* has sup protos */
@ -1390,85 +1390,86 @@ be_local_closure(event, /* name */
}), }),
(be_nested_const_str("event", -30355297, 5)), (be_nested_const_str("event", -30355297, 5)),
(be_nested_const_str("input", -103256197, 5)), (be_nested_const_str("input", -103256197, 5)),
( &(const binstruction[78]) { /* code */ ( &(const binstruction[79]) { /* code */
0xA4160000, // 0000 IMPORT R5 R256 0xA41A0000, // 0000 IMPORT R6 R256
0x1C180301, // 0001 EQ R6 R1 R257 0x1C1C0301, // 0001 EQ R7 R1 R257
0x781A0001, // 0002 JMPF R6 #0005 0x781E0001, // 0002 JMPF R7 #0005
0x8C180102, // 0003 GETMET R6 R0 R258 0x8C1C0102, // 0003 GETMET R7 R0 R258
0x7C180200, // 0004 CALL R6 1 0x7C1C0200, // 0004 CALL R7 1
0x1C180303, // 0005 EQ R6 R1 R259 0x1C1C0303, // 0005 EQ R7 R1 R259
0x781A0006, // 0006 JMPF R6 #000E 0x781E0006, // 0006 JMPF R7 #000E
0x8C180104, // 0007 GETMET R6 R0 R260 0x8C1C0104, // 0007 GETMET R7 R0 R260
0x5C200400, // 0008 MOVE R8 R2 0x5C240400, // 0008 MOVE R9 R2
0x5C240600, // 0009 MOVE R9 R3 0x5C280600, // 0009 MOVE R10 R3
0x5C280800, // 000A MOVE R10 R4 0x5C2C0800, // 000A MOVE R11 R4
0x7C180800, // 000B CALL R6 4 0x7C1C0800, // 000B CALL R7 4
0x80040C00, // 000C RET 1 R6 0x80040E00, // 000C RET 1 R7
0x7002003E, // 000D JMP #004D 0x7002003F, // 000D JMP #004E
0x1C180305, // 000E EQ R6 R1 R261 0x1C1C0305, // 000E EQ R7 R1 R261
0x781A0004, // 000F JMPF R6 #0015 0x781E0004, // 000F JMPF R7 #0015
0x8C180106, // 0010 GETMET R6 R0 R262 0x8C1C0106, // 0010 GETMET R7 R0 R262
0x5C200800, // 0011 MOVE R8 R4 0x5C240800, // 0011 MOVE R9 R4
0x7C180400, // 0012 CALL R6 2 0x7C1C0400, // 0012 CALL R7 2
0x80040C00, // 0013 RET 1 R6 0x80040E00, // 0013 RET 1 R7
0x70020037, // 0014 JMP #004D 0x70020038, // 0014 JMP #004E
0x1C180307, // 0015 EQ R6 R1 R263 0x1C1C0307, // 0015 EQ R7 R1 R263
0x781A0003, // 0016 JMPF R6 #001B 0x781E0003, // 0016 JMPF R7 #001B
0x8C180107, // 0017 GETMET R6 R0 R263 0x8C1C0107, // 0017 GETMET R7 R0 R263
0x7C180200, // 0018 CALL R6 1 0x7C1C0200, // 0018 CALL R7 1
0x80040C00, // 0019 RET 1 R6 0x80040E00, // 0019 RET 1 R7
0x70020031, // 001A JMP #004D 0x70020032, // 001A JMP #004E
0x88180108, // 001B GETMBR R6 R0 R264 0x881C0108, // 001B GETMBR R7 R0 R264
0x781A002F, // 001C JMPF R6 #004D 0x781E0030, // 001C JMPF R7 #004E
0x60180000, // 001D GETGBL R6 G0 0x601C0000, // 001D GETGBL R7 G0
0x881C0108, // 001E GETMBR R7 R0 R264 0x88200108, // 001E GETMBR R8 R0 R264
0x7C180200, // 001F CALL R6 1 0x7C1C0200, // 001F CALL R7 1
0xA8020026, // 0020 EXBLK 0 #0048 0xA8020027, // 0020 EXBLK 0 #0049
0x5C1C0C00, // 0021 MOVE R7 R6 0x5C200E00, // 0021 MOVE R8 R7
0x7C1C0000, // 0022 CALL R7 0 0x7C200000, // 0022 CALL R8 0
0x8C200B09, // 0023 GETMET R8 R5 R265 0x8C240D09, // 0023 GETMET R9 R6 R265
0x5C280E00, // 0024 MOVE R10 R7 0x5C2C1000, // 0024 MOVE R11 R8
0x5C2C0200, // 0025 MOVE R11 R1 0x5C300200, // 0025 MOVE R12 R1
0x7C200600, // 0026 CALL R8 3 0x7C240600, // 0026 CALL R9 3
0x60240015, // 0027 GETGBL R9 G21 0x60280015, // 0027 GETGBL R10 G21
0x5C281000, // 0028 MOVE R10 R8 0x5C2C1200, // 0028 MOVE R11 R9
0x7C240200, // 0029 CALL R9 1 0x7C280200, // 0029 CALL R10 1
0x1C24130A, // 002A EQ R9 R9 R266 0x1C28150A, // 002A EQ R10 R10 R266
0x7826001A, // 002B JMPF R9 #0047 0x782A001B, // 002B JMPF R10 #0048
0xA802000D, // 002C EXBLK 0 #003B 0xA802000E, // 002C EXBLK 0 #003C
0x5C241000, // 002D MOVE R9 R8 0x5C281200, // 002D MOVE R10 R9
0x5C280E00, // 002E MOVE R10 R7 0x5C2C1000, // 002E MOVE R11 R8
0x5C2C0400, // 002F MOVE R11 R2 0x5C300400, // 002F MOVE R12 R2
0x5C300600, // 0030 MOVE R12 R3 0x5C340600, // 0030 MOVE R13 R3
0x5C340800, // 0031 MOVE R13 R4 0x5C380800, // 0031 MOVE R14 R4
0x7C240800, // 0032 CALL R9 4 0x5C3C0A00, // 0032 MOVE R15 R5
0x50280200, // 0033 LDBOOL R10 1 0 0x7C280A00, // 0033 CALL R10 5
0x1C28120A, // 0034 EQ R10 R9 R10 0x502C0200, // 0034 LDBOOL R11 1 0
0x782A0002, // 0035 JMPF R10 #0039 0x1C2C140B, // 0035 EQ R11 R10 R11
0x50280200, // 0036 LDBOOL R10 1 0 0x782E0002, // 0036 JMPF R11 #003A
0xA8040002, // 0037 EXBLK 1 2 0x502C0200, // 0037 LDBOOL R11 1 0
0x80041400, // 0038 RET 1 R10 0xA8040002, // 0038 EXBLK 1 2
0xA8040001, // 0039 EXBLK 1 1 0x80041600, // 0039 RET 1 R11
0x7002000B, // 003A JMP #0047 0xA8040001, // 003A EXBLK 1 1
0xAC240002, // 003B CATCH R9 0 2 0x7002000B, // 003B JMP #0048
0x70020008, // 003C JMP #0046 0xAC280002, // 003C CATCH R10 0 2
0xA42E1600, // 003D IMPORT R11 R267 0x70020008, // 003D JMP #0047
0x6030000F, // 003E GETGBL R12 G15 0xA4321600, // 003E IMPORT R12 R267
0x8C34170C, // 003F GETMET R13 R11 R268 0x6034000F, // 003F GETGBL R13 G15
0x583C000D, // 0040 LDCONST R15 K13 0x8C38190C, // 0040 GETMET R14 R12 R268
0x5C401200, // 0041 MOVE R16 R9 0x5840000D, // 0041 LDCONST R16 K13
0x5C441400, // 0042 MOVE R17 R10 0x5C441400, // 0042 MOVE R17 R10
0x7C340800, // 0043 CALL R13 4 0x5C481600, // 0043 MOVE R18 R11
0x7C300200, // 0044 CALL R12 1 0x7C380800, // 0044 CALL R14 4
0x70020000, // 0045 JMP #0047 0x7C340200, // 0045 CALL R13 1
0xB0080000, // 0046 RAISE 2 R0 R0 0x70020000, // 0046 JMP #0048
0x7001FFD8, // 0047 JMP #0021 0xB0080000, // 0047 RAISE 2 R0 R0
0x5818000E, // 0048 LDCONST R6 K14 0x7001FFD7, // 0048 JMP #0021
0xAC180200, // 0049 CATCH R6 1 0 0x581C000E, // 0049 LDCONST R7 K14
0xB0080000, // 004A RAISE 2 R0 R0 0xAC1C0200, // 004A CATCH R7 1 0
0x50180000, // 004B LDBOOL R6 0 0 0xB0080000, // 004B RAISE 2 R0 R0
0x80040C00, // 004C RET 1 R6 0x501C0000, // 004C LDBOOL R7 0 0
0x80000000, // 004D RET 0 R0 0x80040E00, // 004D RET 1 R7
0x80000000, // 004E RET 0 R0
}) })
) )
); );

View File

@ -241,7 +241,7 @@ class Tasmota
end end
def event(event_type, cmd, idx, payload) def event(event_type, cmd, idx, payload, raw)
import introspect import introspect
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 -#
@ -253,7 +253,7 @@ class Tasmota
var f = introspect.get(d, event_type) # try to match a function or method with the same name var f = introspect.get(d, event_type) # try to match a function or method with the same name
if type(f) == 'function' if type(f) == 'function'
try try
var done = f(d, cmd, idx, payload) var done = f(d, cmd, idx, payload, raw)
if done == true return true end if done == true return true end
except .. as e,m except .. as e,m
import string import string

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
#include "be_constobj.h"
static be_define_const_map_slots(be_class_aes_gcm_map) {
{ be_const_key(encrypt, 4), be_const_func(m_aes_gcm_encryt) },
{ be_const_key(dot_p2, -1), be_const_index(0) },
{ be_const_key(decrypt, -1), be_const_func(m_aes_gcm_decryt) },
{ be_const_key(init, -1), be_const_func(m_aes_gcm_init) },
{ be_const_key(dot_p1, -1), be_const_index(1) },
{ be_const_key(tag, -1), be_const_func(m_aes_gcm_tag) },
};
static be_define_const_map(
be_class_aes_gcm_map,
6
);
BE_EXPORT_VARIABLE be_define_const_class(
be_class_aes_gcm,
2,
NULL,
GCM
);

View File

@ -0,0 +1,196 @@
/*
xdrv_52_3_berry_md5.ino - Berry scripting language, Md5 class
Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BERRY
#ifdef USE_ALEXA_AVS
#include <berry.h>
#include "be_mem.h"
/*********************************************************************************************\
* AES class
*
\*********************************************************************************************/
extern "C" {
int free_br_obj(bvm* vm) {
int argc = be_top(vm);
if (argc > 0) {
void * obj = be_tocomptr(vm, 1);
if (obj != NULL) { be_os_free(obj); }
}
be_return_nil(vm);
}
// `AES_GCM.init(secret_key:bytes(32), iv:bytes(12)) -> instance`
int32_t m_aes_gcm_init(struct bvm *vm);
int32_t m_aes_gcm_init(struct bvm *vm) {
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 3 && be_isinstance(vm, 2) && be_isinstance(vm, 3)) {
do {
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
if (!be_isderived(vm, 2)) break;
size_t length = 0;
const void * bytes = be_tobytes(vm, 2, &length);
if (!bytes) break;
if (length != 32) {
be_raise(vm, "value_error", "Key size must be 32 bytes");
}
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
if (!be_isderived(vm, 3)) break;
size_t iv_length = 0;
const void * iv_bytes = be_tobytes(vm, 3, &iv_length);
if (!iv_bytes) break;
// Initialize an AES CTR structure with the secret key
br_aes_small_ctr_keys * ctr_ctx = (br_aes_small_ctr_keys *) be_os_malloc(sizeof(br_aes_small_ctr_keys));
if (!ctr_ctx) { be_throw(vm, BE_MALLOC_FAIL); }
br_aes_small_ctr_init(ctr_ctx, bytes, length);
be_newcomobj(vm, ctr_ctx, &free_br_obj);
be_setmember(vm, 1, ".p1");
// Initialize an AES GCM structure based on this CTR engine
br_gcm_context * gcm_ctx = (br_gcm_context *) be_os_malloc(sizeof(br_gcm_context));
if (!gcm_ctx) { be_throw(vm, BE_MALLOC_FAIL); }
br_gcm_init(gcm_ctx, &ctr_ctx->vtable, &br_ghash_ctmul32);
be_newcomobj(vm, gcm_ctx, &free_br_obj);
be_setmember(vm, 1, ".p2");
// Reset GCM context with provided IV
br_gcm_reset(gcm_ctx, iv_bytes, iv_length);
// We don't have any additional authenticated data so we flip instantly
br_gcm_flip(gcm_ctx);
be_return_nil(vm);
// success
} while (0);
}
be_raise(vm, kTypeError, nullptr);
}
int32_t m_aes_gcm_encryt(bvm *vm);
int32_t m_aes_gcm_decryt(bvm *vm);
int32_t m_aes_gcm_encrypt_or_decryt(bvm *vm, int encrypt) {
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 2 && be_isinstance(vm, 2)) {
do {
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
if (!be_isderived(vm, 2)) break;
// get GCM context
be_getmember(vm, 1, ".p2");
br_gcm_context * gcm_ctx = (br_gcm_context *) be_tocomptr(vm, -1);
be_pop(vm, 1);
// copy the input buffer
be_getmember(vm, 2, "copy"); // stack: bytes.copy()
be_pushvalue(vm, 2); // stack: bytes.copy(), bytes instance
be_call(vm, 1); // call copy with self parameter
be_pop(vm, 1); // stack: clone of input bytes
size_t length = 0;
// we are changing bytes in place
void * bytes = (void*) be_tobytes(vm, -1, &length);
if (!bytes) break;
br_gcm_run(gcm_ctx, encrypt, bytes, length);
be_return(vm);
// success
} while (0);
}
be_raise(vm, kTypeError, nullptr);
}
int32_t m_aes_gcm_encryt(bvm *vm) {
return m_aes_gcm_encrypt_or_decryt(vm, 1);
}
int32_t m_aes_gcm_decryt(bvm *vm) {
return m_aes_gcm_encrypt_or_decryt(vm, 0);
}
int32_t m_aes_gcm_tag(bvm *vm) {
do {
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
// get GCM context
be_getmember(vm, 1, ".p2");
br_gcm_context * gcm_ctx = (br_gcm_context *) be_tocomptr(vm, -1);
be_pop(vm, 1);
// create a bytes buffer of 16 bytes
uint8_t tag[16] = {0};
br_gcm_get_tag(gcm_ctx, tag);
be_pushbytes(vm, tag, sizeof(tag));
be_return(vm);
// success
} while (0);
be_raise(vm, kTypeError, nullptr);
}
// // `Md5.update(content:bytes()) -> nil`
// //
// // Add raw bytes to the MD5 calculation
// int32_t m_md5_update(struct bvm *vm);
// int32_t m_md5_update(struct bvm *vm) {
// int32_t argc = be_top(vm); // Get the number of arguments
// if (argc >= 2 && be_isinstance(vm, 2)) {
// do {
// be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
// if (!be_isderived(vm, 2)) break;
// size_t length = 0;
// const void * bytes = be_tobytes(vm, 2, &length);
// if (!bytes) break;
// be_getmember(vm, 1, ".p");
// struct MD5Context * ctx;
// ctx = (struct MD5Context *) be_tocomptr(vm, -1);
// if (!ctx) break;
// if (length > 0) {
// MD5Update(ctx, (const uint8_t*) bytes, length);
// }
// be_return_nil(vm);
// // success
// } while (0);
// }
// be_raise(vm, kTypeError, nullptr);
// }
// // `Md5.update(content:bytes()) -> nil`
// //
// // Add raw bytes to the MD5 calculation
// int32_t m_md5_finish(struct bvm *vm);
// int32_t m_md5_finish(struct bvm *vm) {
// be_getmember(vm, 1, ".p");
// struct MD5Context * ctx;
// ctx = (struct MD5Context *) be_tocomptr(vm, -1);
// uint8_t output[16];
// MD5Final(output, ctx);
// be_pushbytes(vm, output, sizeof(output));
// be_return(vm);
// }
}
#endif // USE_ALEXA_AVS
#endif // USE_BERRY

View File

@ -33,7 +33,8 @@ extern "C" {
int free_ctx(bvm* vm) { int free_ctx(bvm* vm) {
int argc = be_top(vm); int argc = be_top(vm);
if (argc > 0) { if (argc > 0) {
struct MD5Context * ctx = (struct MD5Context *) be_tocomptr(vm, 1); be_getmember(vm, 1, ".p");
struct MD5Context * ctx = (struct MD5Context *) be_tocomptr(vm, -1);
if (ctx != NULL) { if (ctx != NULL) {
be_os_free(ctx); be_os_free(ctx);
} }

View File

@ -72,17 +72,27 @@ extern "C" {
int32_t l_publish(struct bvm *vm); int32_t l_publish(struct bvm *vm);
int32_t l_publish(struct bvm *vm) { int32_t l_publish(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments int32_t top = be_top(vm); // Get the number of arguments
if (top >= 3 && be_isstring(vm, 2) && be_isstring(vm, 3)) { // 2 mandatory string arguments if (top >= 3 && be_isstring(vm, 2) && (be_isstring(vm, 3) || be_isinstance(vm, 3))) { // 2 mandatory string arguments
if (top == 3 || (top == 4 && be_isbool(vm, 4))) { // 3rd optional argument must be bool if (top == 3 || (top == 4 && be_isbool(vm, 4))) { // 3rd optional argument must be bool
const char * topic = be_tostring(vm, 2); const char * topic = be_tostring(vm, 2);
const char * payload = be_tostring(vm, 3); const char * payload = nullptr;
size_t payload_len = 0;
if (be_isstring(vm, 3)) {
payload = be_tostring(vm, 3);
payload_len = strlen(payload);
} else {
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
if (be_isderived(vm, 3)) {
payload = (const char *) be_tobytes(vm, 3, &payload_len);
}
}
bool retain = false; bool retain = false;
if (top == 4) { if (top == 4) {
retain = be_tobool(vm, 4); retain = be_tobool(vm, 4);
} }
Response_P(payload); if (!payload) { be_raise(vm, "value_error", "Empty payload"); }
MqttPublish(topic, retain); MqttPublishPayload(topic, payload, payload_len, retain);
be_return(vm); // Return be_return_nil(vm); // Return
} }
} }
be_raise(vm, kTypeError, nullptr); be_raise(vm, kTypeError, nullptr);

View File

@ -37,6 +37,8 @@ void (* const BerryCommand[])(void) PROGMEM = {
CmndBrRun, CmndBrRun,
}; };
int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, const char *payload, uint32_t data_len = 0);
// //
// Sanity Check for be_top() // Sanity Check for be_top()
// //
@ -191,7 +193,8 @@ bool callMethodObjectWithArgs(const char * objname, const char * method, size_t
// call the event dispatcher from Tasmota object // call the event dispatcher from Tasmota object
int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, const char *payload) { // if data_len is non-zero, the event is also sent as raw `bytes()` object because the string may lose data
int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, const char *payload, uint32_t data_len) {
int32_t ret = 0; int32_t ret = 0;
bvm *vm = berry.vm; bvm *vm = berry.vm;
@ -206,7 +209,13 @@ int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx,
be_pushstring(vm, cmd != nullptr ? cmd : ""); be_pushstring(vm, cmd != nullptr ? cmd : "");
be_pushint(vm, idx); be_pushint(vm, idx);
be_pushstring(vm, payload != nullptr ? payload : "{}"); // empty json be_pushstring(vm, payload != nullptr ? payload : "{}"); // empty json
ret = be_pcall(vm, 5); // 5 arguments if (data_len > 0) {
be_pushbytes(vm, payload, data_len); // if data_len is set, we also push raw bytes
ret = be_pcall(vm, 6); // 6 arguments
be_pop(vm, 1);
} else {
ret = be_pcall(vm, 5); // 5 arguments
}
if (ret != 0) { if (ret != 0) {
BerryDumpErrorAndClear(vm, false); // log in Tasmota console only BerryDumpErrorAndClear(vm, false); // log in Tasmota console only
return ret; return ret;
@ -725,7 +734,7 @@ bool Xdrv52(uint8_t function)
result = callBerryRule(); result = callBerryRule();
break; break;
case FUNC_MQTT_DATA: case FUNC_MQTT_DATA:
result = callBerryEventDispatcher(PSTR("mqtt_data"), XdrvMailbox.topic, 0, XdrvMailbox.data); result = callBerryEventDispatcher(PSTR("mqtt_data"), XdrvMailbox.topic, 0, XdrvMailbox.data, XdrvMailbox.data_len);
break; break;
case FUNC_EVERY_50_MSECOND: case FUNC_EVERY_50_MSECOND:
callBerryEventDispatcher(PSTR("every_50ms"), nullptr, 0, nullptr); callBerryEventDispatcher(PSTR("every_50ms"), nullptr, 0, nullptr);