mirror of https://github.com/arendst/Tasmota.git
Merge pull request #14160 from s-hadinger/berry_udp
Berry add support for udp client/server
This commit is contained in:
commit
0039f5a8c3
|
@ -144,6 +144,7 @@ extern void be_load_AXP192_class(bvm *vm);
|
|||
extern void be_load_md5_lib(bvm *vm);
|
||||
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_Leds_ntv_class(bvm *vm);
|
||||
extern void be_load_Leds_class(bvm *vm);
|
||||
|
@ -197,6 +198,7 @@ BERRY_API void be_load_custom_libs(bvm *vm)
|
|||
#ifdef USE_WEBCLIENT
|
||||
be_load_webclient_lib(vm);
|
||||
be_load_tcpclient_lib(vm);
|
||||
be_load_udp_lib(vm);
|
||||
#endif // USE_WEBCLIENT
|
||||
#if defined(USE_ONEWIRE) || defined(USE_DS18x20)
|
||||
be_load_onewirelib(vm);
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/********************************************************************
|
||||
* UDP lib
|
||||
*
|
||||
* To use: `d = udp()`
|
||||
*
|
||||
*******************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
#ifdef USE_WEBCLIENT
|
||||
|
||||
// extern int be_udp_init(bvm *vm);
|
||||
// extern int be_udp_deinit(bvm *vm);
|
||||
// extern int be_udp_begin(bvm *vm);
|
||||
// extern int be_udp_begin_mcast(bvm *vm);
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <WiFiGeneric.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include "be_mapping.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
// init()
|
||||
WiFiUDP *be_udp_init_ntv(void) {
|
||||
return new WiFiUDP();
|
||||
}
|
||||
int32_t be_udp_init(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_udp_init_ntv, "+.p", "");
|
||||
}
|
||||
|
||||
// deinit()
|
||||
void *be_udp_deinit_ntv(WiFiUDP *udp) {
|
||||
if (udp != nullptr) { delete udp; }
|
||||
return nullptr;
|
||||
}
|
||||
int32_t be_udp_deinit(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_udp_deinit_ntv, "=.p", "");
|
||||
}
|
||||
|
||||
// udp.begin(address:string, port:int) -> nil
|
||||
int32_t be_udp_begin_ntv(WiFiUDP *udp, const char *host, int32_t port) {
|
||||
IPAddress addr(INADDR_ANY);
|
||||
// if no host or host is "" then we defult to INADDR_ANY (0.0.0.0)
|
||||
if(host && (*host != 0) && !WiFiGenericClass::hostByName(host, addr)){
|
||||
return 0;
|
||||
}
|
||||
return udp->begin(addr, port);
|
||||
}
|
||||
int32_t be_udp_begin(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_udp_begin_ntv, "b", ".si");
|
||||
}
|
||||
|
||||
// udp.begin_multicast(address:string, port:int) -> nil
|
||||
int32_t be_udp_begin_mcast_ntv(WiFiUDP *udp, const char *host, int32_t port) {
|
||||
IPAddress addr((uint32_t)0);
|
||||
if(!WiFiGenericClass::hostByName(host, addr)){
|
||||
return 0;
|
||||
}
|
||||
return udp->WiFiUDP::beginMulticast(addr, port);
|
||||
}
|
||||
int32_t be_udp_begin_mcast(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_udp_begin_mcast_ntv, "b", ".si");
|
||||
}
|
||||
|
||||
// udp.send(address:string, port:int, payload:bytes) -> bool
|
||||
int32_t be_udp_send_ntv(WiFiUDP *udp, const char *host, int32_t port, const uint8_t* buf, int32_t len) {
|
||||
IPAddress addr((uint32_t)0);
|
||||
if (!WiFiGenericClass::hostByName(host, addr)){
|
||||
return 0;
|
||||
}
|
||||
if (!udp->beginPacket(addr, port)) { return 0; }
|
||||
int bw = udp->write(buf, len);
|
||||
if (!bw) { return 0; }
|
||||
if (!udp->endPacket()) { return 0; }
|
||||
return btrue;
|
||||
}
|
||||
int32_t be_udp_send(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_udp_send_ntv, "b", ".si(bytes)~");
|
||||
}
|
||||
|
||||
// udp.send_multicast(payload:bytes) -> bool
|
||||
int32_t be_udp_send_mcast_ntv(WiFiUDP *udp, const uint8_t* buf, int32_t len) {
|
||||
if (!udp->beginMulticastPacket()) { return 0; }
|
||||
int bw = udp->write(buf, len);
|
||||
if (!bw) { return 0; }
|
||||
if (!udp->endPacket()) { return 0; }
|
||||
return btrue;
|
||||
}
|
||||
int32_t be_udp_send_mcast(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_udp_send_mcast_ntv, "b", ".(bytes)~");
|
||||
}
|
||||
|
||||
// udp.read() -> bytes or nil
|
||||
int32_t be_udp_read(struct bvm *vm) {
|
||||
WiFiUDP *udp = (WiFiUDP*) be_convert_single_elt(vm, 1, NULL, NULL);
|
||||
if (udp->parsePacket()) {
|
||||
int btr = udp->available();
|
||||
uint8_t * buf = (uint8_t*) be_pushbuffer(vm, btr);
|
||||
int32_t btr2 = udp->read(buf, btr);
|
||||
be_pushbytes(vm, buf, btr2);
|
||||
be_return(vm); /* return code */
|
||||
} else {
|
||||
be_return_nil(vm);
|
||||
}
|
||||
}
|
||||
|
||||
#include "../generate/be_fixed_be_class_udp.h"
|
||||
|
||||
void be_load_udp_lib(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_udp);
|
||||
be_setglobal(vm, "udp");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
}
|
||||
/* @const_object_info_begin
|
||||
|
||||
class be_class_udp (scope: global, name: udp) {
|
||||
.p, var
|
||||
init, func(be_udp_init)
|
||||
deinit, func(be_udp_deinit)
|
||||
|
||||
send, func(be_udp_send)
|
||||
send_multicast, func(be_udp_send_mcast)
|
||||
|
||||
begin, func(be_udp_begin)
|
||||
begin_multicast, func(be_udp_begin_mcast)
|
||||
read, func(be_udp_read)
|
||||
}
|
||||
@const_object_info_end */
|
||||
|
||||
#endif // USE_WEBCLIENT
|
|
@ -236,6 +236,7 @@ extern const bcstring be_const_str_back_forth;
|
|||
extern const bcstring be_const_str_base_class;
|
||||
extern const bcstring be_const_str_battery_present;
|
||||
extern const bcstring be_const_str_begin;
|
||||
extern const bcstring be_const_str_begin_multicast;
|
||||
extern const bcstring be_const_str_bool;
|
||||
extern const bcstring be_const_str_break;
|
||||
extern const bcstring be_const_str_bri;
|
||||
|
@ -595,6 +596,8 @@ extern const bcstring be_const_str_search;
|
|||
extern const bcstring be_const_str_sec;
|
||||
extern const bcstring be_const_str_seg7_font;
|
||||
extern const bcstring be_const_str_select;
|
||||
extern const bcstring be_const_str_send;
|
||||
extern const bcstring be_const_str_send_multicast;
|
||||
extern const bcstring be_const_str_serial;
|
||||
extern const bcstring be_const_str_set;
|
||||
extern const bcstring be_const_str_set_alternate;
|
||||
|
@ -680,6 +683,7 @@ extern const bcstring be_const_str_true;
|
|||
extern const bcstring be_const_str_try;
|
||||
extern const bcstring be_const_str_try_rule;
|
||||
extern const bcstring be_const_str_type;
|
||||
extern const bcstring be_const_str_udp;
|
||||
extern const bcstring be_const_str_unknown_X20instruction;
|
||||
extern const bcstring be_const_str_update;
|
||||
extern const bcstring be_const_str_upper;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,24 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(be_class_udp_map) {
|
||||
{ be_const_key(deinit, -1), be_const_func(be_udp_deinit) },
|
||||
{ be_const_key(begin_multicast, -1), be_const_func(be_udp_begin_mcast) },
|
||||
{ be_const_key(begin, -1), be_const_func(be_udp_begin) },
|
||||
{ be_const_key(_X2Ep, 4), be_const_var(0) },
|
||||
{ be_const_key(init, 1), be_const_func(be_udp_init) },
|
||||
{ be_const_key(read, -1), be_const_func(be_udp_read) },
|
||||
{ be_const_key(send_multicast, 2), be_const_func(be_udp_send_mcast) },
|
||||
{ be_const_key(send, -1), be_const_func(be_udp_send) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
be_class_udp_map,
|
||||
8
|
||||
);
|
||||
|
||||
BE_EXPORT_VARIABLE be_define_const_class(
|
||||
be_class_udp,
|
||||
1,
|
||||
NULL,
|
||||
udp
|
||||
);
|
|
@ -13,14 +13,6 @@
|
|||
#include "be_exec.h"
|
||||
#include <string.h>
|
||||
|
||||
// By default the cb generator is cb.gen_cb
|
||||
// This can be changed. Note: it is across all VMs
|
||||
static const char * be_gen_cb_name = "cb.gen_cb";
|
||||
|
||||
void be_set_gen_cb_name(bvm *vm, const char * gen_cb) {
|
||||
if (gen_cb) be_gen_cb_name = gen_cb;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Converision from real <-> int
|
||||
*
|
||||
|
@ -165,8 +157,8 @@ int be_find_global_or_module_member(bvm *vm, const char * name) {
|
|||
|
||||
// read a single value at stack position idx, convert to int.
|
||||
// if object instance, get `_p` member and convert it recursively
|
||||
intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, const char * gen_cb) {
|
||||
// berry_log_C("be_convert_single_elt(idx=%i, argtype='%s', gen_cb=%p, type=%s", idx, arg_type ? arg_type : "", gen_cb ? gen_cb : "", be_typename(vm, idx));
|
||||
intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, int *buf_len) {
|
||||
// berry_log_C("be_convert_single_elt(idx=%i, argtype='%s', type=%s", idx, arg_type ? arg_type : "", be_typename(vm, idx));
|
||||
int ret = 0;
|
||||
char provided_type = 0;
|
||||
idx = be_absindex(vm, idx); // make sure we have an absolute index
|
||||
|
@ -179,7 +171,7 @@ intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, const ch
|
|||
if (arg_type_len > 1 && arg_type[0] == '^') { // it is a callback
|
||||
arg_type++; // skip first character
|
||||
if (be_isclosure(vm, idx)) {
|
||||
ret = be_find_global_or_module_member(vm, gen_cb);
|
||||
ret = be_find_global_or_module_member(vm, "cb.make_cb");
|
||||
if (ret) {
|
||||
be_pushvalue(vm, idx);
|
||||
be_pushvalue(vm, 1);
|
||||
|
@ -191,7 +183,7 @@ intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, const ch
|
|||
// berry_log_C("func=%p", func);
|
||||
return (int32_t) func;
|
||||
} else {
|
||||
be_raisef(vm, "type_error", "Can't find callback generator: %s", gen_cb);
|
||||
be_raisef(vm, "type_error", "Can't find callback generator: 'cb.make_cb'");
|
||||
}
|
||||
} else {
|
||||
be_raise(vm, "type_error", "Closure expected for callback type");
|
||||
|
@ -228,17 +220,12 @@ intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, const ch
|
|||
// non-simple type
|
||||
if (be_isinstance(vm, idx)) {
|
||||
// check if the instance is a subclass of `bytes()``
|
||||
be_getbuiltin(vm, "bytes");
|
||||
if (be_isderived(vm, idx)) {
|
||||
be_pop(vm, 1);
|
||||
be_getmember(vm, idx, "_buffer");
|
||||
be_pushvalue(vm, idx);
|
||||
be_call(vm, 1);
|
||||
int32_t ret = (int32_t) be_tocomptr(vm, -2);
|
||||
be_pop(vm, 2);
|
||||
if (be_isbytes(vm, idx)) {
|
||||
size_t len;
|
||||
intptr_t ret = (intptr_t) be_tobytes(vm, idx, &len);
|
||||
if (buf_len) { *buf_len = (int) len; }
|
||||
return ret;
|
||||
} else {
|
||||
be_pop(vm, 1);
|
||||
// we accept either `_p` or `.p` attribute to retrieve a pointer
|
||||
if (!be_getmember(vm, idx, "_p")) {
|
||||
be_pop(vm, 1); // remove `nil`
|
||||
|
@ -286,6 +273,9 @@ intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, const ch
|
|||
// - 'b': bool
|
||||
// - 'i': int (int32_t)
|
||||
// - 's': string (const char *)
|
||||
// - '.': any argument (no check)
|
||||
// - '-': skip argument and ignore
|
||||
// - '~': send the length of the previous bytes() buffer (or raise an exception if no length known)
|
||||
//
|
||||
// - a class name surroungded by parenthesis
|
||||
// - '(lv_button)' -> lv_button class or derived
|
||||
|
@ -298,6 +288,7 @@ void be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type,
|
|||
char type_short_name[32];
|
||||
|
||||
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
|
||||
for (uint32_t i = 0; i < argc; i++) {
|
||||
type_short_name[0] = 0; // clear string
|
||||
// extract individual type
|
||||
|
@ -344,9 +335,18 @@ void be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type,
|
|||
}
|
||||
}
|
||||
// AddLog(LOG_LEVEL_INFO, ">> be_call_c_func arg %i, type %s", i, arg_type_check ? type_short_name : "<null>");
|
||||
p[p_idx] = be_convert_single_elt(vm, i + arg_start, arg_type_check ? type_short_name : NULL, "cb.make_cb");
|
||||
p[p_idx] = be_convert_single_elt(vm, i + arg_start, arg_type_check ? type_short_name : NULL, &buf_len);
|
||||
// berry_log_C("< ret[%i]=%i", p_idx, p[p_idx]);
|
||||
p_idx++;
|
||||
|
||||
if (arg_type[arg_idx] == '~') { // if next argument is virtual
|
||||
if (buf_len < 0) {
|
||||
be_raisef(vm, "value_error", "no bytes() length known");
|
||||
}
|
||||
p[p_idx] = buf_len; // add the previous buffer len
|
||||
p_idx++;
|
||||
arg_idx++; // skip this arg
|
||||
}
|
||||
}
|
||||
|
||||
// check if we are missing arguments
|
||||
|
|
|
@ -43,7 +43,6 @@ typedef struct be_ntv_class_def_t {
|
|||
} be_ntv_class_def_t;
|
||||
|
||||
void be_raisef(bvm *vm, const char *except, const char *msg, ...);
|
||||
void be_set_gen_cb_name(bvm *vm, const char * gen_cb);
|
||||
|
||||
extern void be_map_insert_int(bvm *vm, const char *key, bint value);
|
||||
extern void be_map_insert_bool(bvm *vm, const char *key, bbool value);
|
||||
|
@ -57,7 +56,7 @@ extern void be_create_class_wrapper(bvm *vm, const char * class_name, void * ptr
|
|||
extern int be_find_global_or_module_member(bvm *vm, const char * cl_name);
|
||||
|
||||
extern bbool be_const_member(bvm *vm, const be_const_member_t * definitions, size_t def_len);
|
||||
extern intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, const char * gen_cb);
|
||||
extern intptr_t be_convert_single_elt(bvm *vm, int idx, const char * arg_type, int *len);
|
||||
extern void be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type, intptr_t p[8]);;
|
||||
extern int be_call_c_func(bvm *vm, void * func, const char * return_type, const char * arg_type);
|
||||
|
||||
|
|
|
@ -375,7 +375,6 @@ extern "C" {
|
|||
if (argc == 1) {
|
||||
uconfig = be_tostring(vm, 1);
|
||||
}
|
||||
be_set_gen_cb_name(vm, "_lvgl.gen_cb"); // TODO maybe not the best place for it
|
||||
start_lvgl(uconfig);
|
||||
be_return_nil(vm);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue