void init_v7(void *stack_base) { struct v7_create_opts opts; v7_val_t dht11, debug; opts.object_arena_size = 164; opts.function_arena_size = 26; opts.property_arena_size = 400; opts.c_stack_base = stack_base; v7 = v7_create_opt(opts); v7_set_method(v7, v7_get_global_object(v7), "dsleep", dsleep); v7_set_method(v7, v7_get_global_object(v7), "crash", crash); #if V7_ESP_ENABLE__DHT11 dht11 = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "DHT11", 5, 0, dht11); v7_set_method(v7, dht11, "read", DHT11_read); #else (void) dht11; #endif /* V7_ESP_ENABLE__DHT11 */ debug = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "Debug", 5, 0, debug); v7_set_method(v7, debug, "mode", Debug_mode); v7_set_method(v7, debug, "print", Debug_print); sj_init_timers(v7); sj_init_v7_ext(v7); init_gpiojs(v7); init_i2cjs(v7); init_spijs(v7); init_wifi(v7); #ifndef RTOS_TODO init_data_gen_server(v7); #endif esp_init_conf(v7); #ifdef RTOS_SDK mongoose_init(); #endif sj_init_simple_http_client(v7); #ifdef RTOS_SDK sj_init_ws_client(v7); #endif v7_gc(v7, 1); }
void sj_init_conf(struct v7 *v7, char *conf_str) { int i; const char *names[] = {"sys.json", "user.json"}; v7_val_t conf = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "conf", ~0, 0, conf); if (conf_str != NULL) { v7_val_t res; enum v7_err err; /* * Usage of strlen in weird here * but we use snprintf as well. * TODO(alashkin): think about providing len * as function argument AND changing of snprintf to * something else */ size_t len = strlen(conf_str); char *f = (char *) malloc(len + 3); snprintf(f, len + 3, "(%s)", conf_str); /* TODO(mkm): simplify when we'll have a C json parse API */ err = v7_exec(v7, &res, f); free(f); if (err != V7_OK) { printf("exc parsing dev conf: %s\n", f); v7_println(v7, res); } else { v7_set(v7, conf, "dev", ~0, 0, res); } } for (i = 0; i < (int) sizeof(names) / sizeof(names[0]); i++) { const char *name = names[i]; v7_set(v7, conf, name, strlen(name) - 5, 0, load_conf(v7, name)); } }
/* Currently can only handle one timer */ ICACHE_FLASH_ATTR static v7_val_t set_timeout(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t cb = v7_array_get(v7, args, 0); v7_val_t msecsv = v7_array_get(v7, args, 1); int msecs; if (!v7_is_function(cb)) { printf("cb is not a function\n"); return v7_create_undefined(); } if (!v7_is_double(msecsv)) { printf("msecs is not a double\n"); return v7_create_undefined(); } msecs = v7_to_double(msecsv); /* * used to convey the callback to the timer handler _and_ to root * the function so that the GC doesn't deallocate it. */ v7_set(v7, v7_get_global_object(v7), "_js_timeout_handler", 19, 0, cb); os_timer_disarm(&js_timeout_timer); os_timer_setfn(&js_timeout_timer, js_timeout, NULL); os_timer_arm(&js_timeout_timer, msecs, 0); return v7_create_undefined(); }
static v7_val_t GPIO_setisr(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t pinv = v7_array_get(v7, args, 0); v7_val_t typev = v7_array_get(v7, args, 1); v7_val_t cb = v7_array_get(v7, args, 2); v7_val_t current_cb; char prop_name[15]; int pin, type, len, has_isr, new_isr_provided; if (!v7_is_number(pinv) || !v7_is_number(typev)) { printf("Invalid arguments\n"); return v7_create_boolean(0); } pin = v7_to_number(pinv); type = v7_to_number(typev); len = snprintf(prop_name, sizeof(prop_name), "_ih_%d", (int) pin); current_cb = v7_get(v7, v7_get_global_object(v7), prop_name, len); has_isr = v7_is_function(current_cb); new_isr_provided = v7_is_function(cb); if (!has_isr && !new_isr_provided) { printf("Missing callback\n"); return v7_create_boolean(0); }; if (has_isr && new_isr_provided && current_cb != cb) { printf("Only one interruption handler is allowed for pin\n"); return v7_create_boolean(0); } if (type == 0 && has_isr) { v7_set(v7, v7_get_global_object(v7), prop_name, len, 0, v7_create_undefined()); } else if (!has_isr && new_isr_provided) { v7_set(v7, v7_get_global_object(v7), prop_name, len, 0, cb); } if (type != 0 && !s_gpio_intr_installed) { sj_gpio_intr_init(gpio_intr_handler_proxy); s_gpio_intr_installed = 1; } return v7_create_boolean(sj_gpio_intr_set(pin, type) == 0); }
int main(void) { struct v7 *v7 = v7_create(); v7_val_t result; v7_set_method(v7, v7_get_global_object(v7), "sum", &js_sum); v7_exec(v7, &result, "print(sum(1.2, 3.4))"); v7_destroy(v7); return 0; }
void sj_init_simple_http_client(struct v7 *v7) { v7_val_t http; http = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "Http", 4, 0, http); v7_set_method(v7, http, "get", sj_http_get); v7_set_method(v7, http, "post", sj_http_post); }
void init_gpiojs(struct v7 *v7) { s_v7 = v7; v7_val_t gpio = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "GPIO", 4, 0, gpio); v7_set_method(v7, gpio, "setmode", GPIO_setmode); v7_set_method(v7, gpio, "read", GPIO_read); v7_set_method(v7, gpio, "write", GPIO_write); v7_set_method(v7, gpio, "setisr", GPIO_setisr); }
void sj_init_v7_ext(struct v7 *v7) { v7_val_t os, gc; v7_set(v7, v7_get_global_object(v7), "version", 7, 0, v7_create_string(v7, sj_version, strlen(sj_version), 1)); v7_set_method(v7, v7_get_global_object(v7), "usleep", global_usleep); v7_set_method(v7, v7_get_global_object(v7), "setTimeout", global_set_timeout); gc = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "GC", 2, 0, gc); v7_set_method(v7, gc, "stat", GC_stat); v7_set_method(v7, gc, "gc", GC_gc); os = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "OS", 2, 0, os); v7_set_method(v7, os, "prof", OS_prof); v7_set_method(v7, os, "wdt_feed", OS_wdt_feed); v7_set_method(v7, os, "reset", OS_reset); }
/* * Construct a new WebSocket object: * * url: url where to connect to * protocol: websocket subprotocol * * Example: * ws = new WebSocket('wss://localhost:1234'); * ws.onopen = function(ev) { * print("ON OPEN", ev); * } * * ws.onclose = function(ev) { * print("ON CLOSE", ev); * } * * ws.onmessage = function(ev) { * print("ON MESSAGE", ev); * } * * ws.onerror = function(ev) { * print("ON ERROR", ev); * } * */ static v7_val_t sj_ws_ctor(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { struct mg_connection *nc; struct user_data *ud; v7_val_t urlv = v7_array_get(v7, args, 0); v7_val_t subprotov = v7_array_get(v7, args, 1); (void) this_obj; (void) args; if (!v7_is_string(urlv)) { v7_throw(v7, "invalid ws url string"); } if (v7_is_object(this_obj) && this_obj != v7_get_global_object(v7)) { int use_ssl = 0; size_t len; const char *url = v7_to_string(v7, &urlv, &len); if (strncmp(url, "ws://", 5) == 0) { url += 5; } else if (strncmp(url, "wss://", 6) == 0) { url += 6; use_ssl = 1; } nc = mg_connect(&sj_mgr, url, ws_ev_handler); if (nc == NULL) v7_throw(v7, "error creating the connection"); #ifdef NS_ENABLE_SSL if (use_ssl) { mg_set_ssl(nc, NULL, NULL); } #endif (void) use_ssl; mg_set_protocol_http_websocket(nc); ud = calloc(1, sizeof(*ud)); ud->v7 = v7; ud->ws = this_obj; nc->user_data = ud; v7_own(v7, &ud->ws); if (v7_is_string(subprotov)) { size_t len; const char *proto = v7_to_string(v7, &subprotov, &len); ud->proto = strdup(proto); } } else { v7_throw(v7, "WebSocket ctor called without new"); } return v7_create_undefined(); }
static void call_sum(struct v7 *v7) { v7_val_t func, result, args; func = v7_get(v7, v7_get_global_object(v7), "sum", 3); args = v7_create_array(v7); v7_array_push(v7, args, v7_create_number(123.0)); v7_array_push(v7, args, v7_create_number(456.789)); v7_apply(v7, &result, func, v7_create_undefined(), args); printf("Result: %g\n", v7_to_number(result)); }
void sj_invoke_cb2(struct v7 *v7, v7_val_t cb, v7_val_t arg1, v7_val_t arg2) { v7_val_t args; v7_own(v7, &cb); v7_own(v7, &arg1); v7_own(v7, &arg2); args = v7_create_array(v7); v7_own(v7, &args); v7_array_push(v7, args, arg1); v7_array_push(v7, args, arg2); sj_invoke_cb(v7, cb, v7_get_global_object(v7), args); v7_disown(v7, &args); v7_disown(v7, &arg2); v7_disown(v7, &arg1); v7_disown(v7, &cb); }
void sj_init_ws_client(struct v7 *v7) { v7_val_t ws_proto = v7_create_object(v7); v7_val_t ws = v7_create_constructor(v7, ws_proto, sj_ws_ctor, 1); v7_own(v7, &ws); v7_set_method(v7, ws_proto, "send", WebSocket_send); v7_set_method(v7, ws_proto, "close", WebSocket_close); v7_set(v7, ws_proto, "readyState", ~0, V7_PROPERTY_DONT_ENUM | V7_PROPERTY_GETTER, v7_create_function(v7, WebSocket_readyState, 0)); v7_set(v7, ws, "OPEN", ~0, 0, WEBSOCKET_OPEN); v7_set(v7, ws, "CLOSED", ~0, 0, WEBSOCKET_CLOSED); v7_set(v7, v7_get_global_object(v7), "WebSocket", ~0, 0, ws); v7_disown(v7, &ws); }
ICACHE_FLASH_ATTR void init_v7() { struct v7_create_opts opts; v7_val_t wifi, gpio, dht11, gc, debug; opts.object_arena_size = 94; opts.function_arena_size = 17; opts.property_arena_size = 340; v7 = v7_create_opt(opts); v7_set_method(v7, v7_get_global_object(v7), "usleep", usleep); v7_set_method(v7, v7_get_global_object(v7), "setTimeout", set_timeout); gpio = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "GPIO", 4, 0, gpio); v7_set_method(v7, gpio, "in", GPIO_in); v7_set_method(v7, gpio, "out", GPIO_out); wifi = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "Wifi", 4, 0, wifi); v7_set_method(v7, wifi, "setup", Wifi_setup); v7_set_method(v7, wifi, "disconnect", Wifi_disconnect); v7_set_method(v7, wifi, "connect", Wifi_connect); v7_set_method(v7, wifi, "status", Wifi_status); v7_set_method(v7, wifi, "ip", Wifi_ip); v7_set(v7, wifi, "STATION", 7, 0, v7_create_number(0)); v7_set(v7, wifi, "SOFTAP", 6, 0, v7_create_number(1)); #if V7_ESP_ENABLE__DHT11 dht11 = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "DHT11", 5, 0, dht11); v7_set_method(v7, dht11, "read", DHT11_read); #endif /* V7_ESP_ENABLE__DHT11 */ gc = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "GC", 2, 0, gc); v7_set_method(v7, gc, "stat", GC_stat); v7_set_method(v7, gc, "collect", GC_collect); debug = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "Debug", 5, 0, debug); v7_set_method(v7, debug, "setOutput", Debug_set_output); v7_set_method(v7, debug, "print", Debug_print); v7_init_http_client(v7); }
static void gpio_intr_handler_proxy(int pin, int level) { char prop_name[15]; int len; v7_val_t args; len = snprintf(prop_name, sizeof(prop_name), "_ih_%d", (int) pin); v7_val_t cb = v7_get(s_v7, v7_get_global_object(s_v7), prop_name, len); if (!v7_is_function(cb)) { return; } args = v7_create_array(s_v7); v7_array_push(s_v7, args, v7_create_number(pin)); v7_array_push(s_v7, args, v7_create_number(level)); v7_apply(s_v7, cb, v7_create_undefined(), args); }
int main(void) { struct v7 *v7 = v7_create(); v7_val_t ctor_func, proto, eval_result; proto = v7_create_object(v7); ctor_func = v7_create_constructor(v7, proto, MyThing_ctor, 1); v7_set(v7, ctor_func, "MY_CONST", ~0, V7_PROPERTY_READ_ONLY | V7_PROPERTY_DONT_DELETE, v7_create_number(123)); v7_set_method(v7, proto, "myMethod", &MyThing_myMethod); v7_set(v7, v7_get_global_object(v7), "MyThing", ~0, 0, ctor_func); v7_exec(v7, &eval_result, "\ print('MyThing.MY_CONST = ', MyThing.MY_CONST); \ var t = new MyThing(456); \ print('t.MY_CONST = ', t.MY_CONST); \ print('t.myMethod = ', t.myMethod); \ print('t.myMethod() = ', t.myMethod());"); v7_destroy(v7); return 0; }
void wifi_changed_cb(System_Event_t *evt) { enum sj_wifi_status sj_ev = -1; /* TODO(rojer): Share this logic between platforms. */ if (wifi_setting_up && #ifndef RTOS_SDK evt->event == EVENT_STAMODE_GOT_IP #else evt->event_id == EVENT_STAMODE_GOT_IP #endif ) { struct station_config config; v7_val_t res; v7_val_t conf = v7_get(v7, v7_get_global_object(v7), "conf", ~0); v7_val_t known, wifi; if (v7_is_undefined(conf)) { fprintf(stderr, "cannot save conf, no conf object\n"); return; } wifi = v7_get(v7, conf, "wifi", ~0); if (v7_is_undefined(wifi)) { wifi = v7_create_object(v7); v7_set(v7, conf, "wifi", ~0, 0, wifi); } known = v7_get(v7, conf, "known", ~0); if (v7_is_undefined(known)) { known = v7_create_object(v7); v7_set(v7, wifi, "known", ~0, 0, known); } wifi_station_get_config(&config); v7_set(v7, known, (const char *) config.ssid, ~0, 0, v7_create_string(v7, (const char *) config.password, strlen((const char *) config.password), 1)); v7_exec(v7, "conf.save()", &res); wifi_setting_up = 0; } #ifndef RTOS_SDK switch (evt->event) { #else switch (evt->event_id) { #endif case EVENT_STAMODE_DISCONNECTED: sj_ev = SJ_WIFI_DISCONNECTED; break; case EVENT_STAMODE_CONNECTED: sj_ev = SJ_WIFI_CONNECTED; break; case EVENT_STAMODE_GOT_IP: sj_ev = SJ_WIFI_IP_ACQUIRED; break; } if (sj_ev >= 0) sj_wifi_on_change_callback(sj_ev); } char *sj_wifi_get_connected_ssid() { struct station_config conf; if (!wifi_station_get_config(&conf)) return NULL; return strdup((const char *) conf.ssid); } char *sj_wifi_get_sta_ip() { struct ip_info info; char *ip; if (!wifi_get_ip_info(0, &info) || info.ip.addr == 0) return NULL; if (asprintf(&ip, IPSTR, IP2STR(&info.ip)) < 0) { return NULL; } return ip; } void wifi_scan_done(void *arg, STATUS status) { if (status == OK) { STAILQ_HEAD(, bss_info) *info = arg; struct bss_info *p; const char **ssids; int n = 0; STAILQ_FOREACH(p, info, next) n++; ssids = calloc(n + 1, sizeof(*ssids)); n = 0; STAILQ_FOREACH(p, info, next) { ssids[n++] = (const char *) p->ssid; } wifi_scan_cb(ssids); free(ssids); } else {
void sj_init_timers(struct v7 *v7) { v7_set_method(v7, v7_get_global_object(v7), "setTimeout", global_set_timeout); }
ICACHE_FLASH_ATTR static void js_timeout() { v7_val_t cb = v7_get(v7, v7_get_global_object(v7), "_js_timeout_handler", 19); v7_val_t undef = v7_create_undefined(); v7_apply(v7, cb, undef, undef); }
void init_data_gen_server(struct v7 *v7) { v7_val_t tcp = v7_create_object(v7); v7_set(v7, v7_get_global_object(v7), "Tcp", 3, 0, tcp); v7_set_method(v7, tcp, "gen", Tcp_gen); }