Merge pull request #14160 from s-hadinger/berry_udp

Berry add support for udp client/server
This commit is contained in:
s-hadinger 2021-12-23 19:07:37 +01:00 committed by GitHub
commit 0039f5a8c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1091 additions and 926 deletions

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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
);

View File

@ -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

View File

@ -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);

View File

@ -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);
}