static v7_val_t WebSocket_send(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t datav = v7_array_get(v7, args, 0); v7_val_t ncv = v7_get(v7, this_obj, "_nc", ~0); struct mg_connection *nc; /* * TODO(alashkin): check why v7_is_instanceof throws exception * in case of string */ int is_blob = !v7_is_string(datav) && v7_is_instanceof(v7, datav, "Blob"); if (!v7_is_string(datav) && !is_blob) { v7_throw(v7, "arg should be string or Blob"); return v7_create_undefined(); } if (!v7_is_foreign(ncv) || (nc = (struct mg_connection *) v7_to_foreign(ncv)) == NULL) { v7_throw(v7, "ws not connected"); return v7_create_undefined(); } if (is_blob) { _WebSocket_send_blob(v7, nc, datav); } else { _WebSocket_send_string(v7, nc, datav); } return v7_create_undefined(); }
/* 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(); }
void sj_init_uart(struct v7 *v7) { v7_val_t uart = v7_create_undefined(), uart_proto = v7_create_undefined(), uart_ctor = v7_create_undefined(); v7_own(v7, &uart); v7_own(v7, &uart_proto); v7_own(v7, &uart_ctor); uart = v7_create_object(v7); uart_proto = v7_create_object(v7); uart_ctor = v7_create_constructor(v7, uart_proto, UART_ctor); v7_set(v7, uart, "dev", ~0, V7_PROPERTY_HIDDEN, uart_ctor); v7_set_method(v7, uart_proto, "read", UART_read); v7_set_method(v7, uart_proto, "write", UART_write); v7_set_method(v7, uart_proto, "recv", UART_recv); v7_set(v7, v7_get_global(v7), "UART", ~0, 0, uart); { enum v7_err rcode = v7_exec( v7, "UART.open = function (d) { return new UART.dev(d); }", NULL); assert(rcode == V7_OK); #if defined(NDEBUG) (void) rcode; #endif } v7_disown(v7, &uart_ctor); v7_disown(v7, &uart_proto); v7_disown(v7, &uart); }
/* * Start dummy TCP generator server. * * port: tcp port to listen to */ static v7_val_t Tcp_gen(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t port = v7_array_get(v7, args, 0); if (!v7_is_number(port)) { printf("bad port number\n"); return v7_create_undefined(); } start_data_gen_server(v7_to_number(port)); return v7_create_undefined(); }
static v7_val_t global_usleep(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t usecsv = v7_array_get(v7, args, 0); int usecs; if (!v7_is_number(usecsv)) { printf("usecs is not a double\n\r"); return v7_create_undefined(); } usecs = v7_to_number(usecsv); sj_usleep(usecs); return v7_create_undefined(); }
ICACHE_FLASH_ATTR static v7_val_t usleep(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t usecsv = v7_array_get(v7, args, 0); int usecs; if (!v7_is_double(usecsv)) { printf("usecs is not a double\n\r"); return v7_create_undefined(); } usecs = v7_to_double(usecsv); os_delay_us(usecs); return v7_create_undefined(); }
/* * Usage: * * new UART("platform_specific_name") * */ static enum v7_err UART_ctor(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t this_obj = v7_get_this(v7); v7_val_t dev = v7_arg(v7, 0); struct user_data *ud; void *uart; const char *name; size_t len; if (!v7_is_string(dev)) { rcode = v7_throwf(v7, "Error", "device must be string"); goto clean; } ud = (struct user_data *) calloc(1, sizeof(struct user_data)); ud->v7 = v7; ud->want = 0; ud->cb = v7_create_undefined(); v7_own(v7, &ud->cb); name = v7_get_string_data(v7, &dev, &len); uart = sj_hal_open_uart(name, (void *) ud); if (uart == NULL) { rcode = v7_throwf(v7, "Error", "cannot open uart"); goto clean; } v7_set(v7, this_obj, "_ud", ~0, V7_PROPERTY_HIDDEN, v7_create_foreign(ud)); v7_set(v7, this_obj, "_dev", ~0, V7_PROPERTY_HIDDEN, v7_create_foreign(uart)); clean: return rcode; }
V7_PRIVATE val_t Regex_ctor(struct v7 *v7, val_t this_obj, val_t args) { long argnum = v7_array_length(v7, args); if (argnum > 0) { val_t ro = to_string(v7, v7_array_get(v7, args, 0)); size_t re_len, flags_len = 0; const char *re = v7_to_string(v7, &ro, &re_len), *flags = NULL; struct slre_prog *p = NULL; struct v7_regexp *rp; (void) this_obj; if (argnum > 1) { val_t fl = to_string(v7, v7_array_get(v7, args, 1)); flags = v7_to_string(v7, &fl, &flags_len); } if (slre_compile(re, re_len, flags, flags_len, &p, 1) != SLRE_OK || p == NULL) { throw_exception(v7, TYPE_ERROR, "Invalid regex"); return v7_create_undefined(); } else { rp = (struct v7_regexp *) malloc(sizeof(*rp)); rp->regexp_string = v7_create_string(v7, re, re_len, 1); rp->compiled_regexp = p; rp->lastIndex = 0; return v7_pointer_to_value(rp) | V7_TAG_REGEXP; } } return v7_create_regexp(v7, "(?:)", 4, NULL, 0); }
/* * Force a pass of the garbage collector. */ static v7_val_t GC_gc(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { (void) this_obj; (void) args; v7_gc(v7, 1); return v7_create_undefined(); }
ICACHE_FLASH_ATTR static v7_val_t Wifi_setup(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { struct station_config stationConf; v7_val_t ssidv = v7_array_get(v7, args, 0); v7_val_t passv = v7_array_get(v7, args, 1); const char *ssid, *pass; size_t ssid_len, pass_len; int res; if (!v7_is_string(ssidv) || !v7_is_string(passv)) { printf("ssid/pass are not strings\n"); return v7_create_undefined(); } wifi_station_disconnect(); ssid = v7_to_string(v7, &ssidv, &ssid_len); pass = v7_to_string(v7, &passv, &pass_len); stationConf.bssid_set = 0; strncpy((char *) &stationConf.ssid, ssid, 32); strncpy((char *) &stationConf.password, pass, 64); res = v7_create_boolean(wifi_station_set_config(&stationConf)); if (!res) { printf("Failed to set station config\n"); return v7_create_boolean(0); } return v7_create_boolean(wifi_station_connect()); }
/* * Crashes the process/CPU. Useful to attach a debugger until we have * breakpoints. */ static v7_val_t crash(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { (void) v7; (void) this_obj; (void) args; *(int *) 1 = 1; return v7_create_undefined(); }
static v7_val_t Wifi_ip(struct v7 *v7) { v7_val_t res; char *ip = sj_wifi_get_sta_ip(); if (ip == NULL) return v7_create_undefined(); res = v7_create_string(v7, ip, strlen(ip), 1); free(ip); return res; }
static v7_val_t Wifi_status(struct v7 *v7) { v7_val_t res; char *status = sj_wifi_get_status(); if (status == NULL) return v7_create_undefined(); res = v7_create_string(v7, status, strlen(status), 1); free(status); return res; }
/* * Force a pass of the garbage collector. */ ICACHE_FLASH_ATTR static v7_val_t GC_collect(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { (void) this_obj; (void) args; v7_gc(v7); return v7_create_undefined(); }
ICACHE_FLASH_ATTR static v7_val_t GPIO_out(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 valv = v7_array_get(v7, args, 1); int pin, val; if (!v7_is_double(pinv)) { printf("non-numeric pin\n"); return v7_create_undefined(); } pin = v7_to_double(pinv); val = v7_is_true(v7, valv) ? 1 : 0; set_gpio(pin, val); return v7_create_undefined(); }
static v7_val_t Wifi_show(struct v7 *v7) { v7_val_t res; char *ssid = sj_wifi_get_connected_ssid(); if (ssid == NULL) return v7_create_undefined(); res = v7_create_string(v7, ssid, strlen(ssid), 1); free(ssid); return res; }
/* * Prints message to current debug output */ v7_val_t Debug_print(struct v7 *v7) { int i, num_args = v7_argc(v7); for (i = 0; i < num_args; i++) { v7_fprint(stderr, v7, v7_arg(v7, i)); fprintf(stderr, " "); } fprintf(stderr, "\n"); return v7_create_undefined(); }
static v7_val_t WebSocket_close(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { struct ns_connection *nc; v7_val_t ncv = v7_get(v7, this_obj, "_nc", ~0); (void) args; if (v7_is_foreign(ncv) && (nc = (struct ns_connection *) v7_to_foreign(ncv)) != NULL) { nc->flags |= NSF_CLOSE_IMMEDIATELY; } return v7_create_undefined(); }
ICACHE_FLASH_ATTR static v7_val_t GPIO_in(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t pinv = v7_array_get(v7, args, 0); int pin; if (!v7_is_double(pinv)) { printf("non-numeric pin\n"); return v7_create_undefined(); } pin = v7_to_double(pinv); return v7_create_boolean(read_gpio_pin(pin)); }
/* * 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)); }
/* * Prints message to current debug output */ v7_val_t Debug_print(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { int i, num_args = v7_array_length(v7, args); (void) this_obj; for (i = 0; i < num_args; i++) { v7_fprint(stderr, v7, v7_array_get(v7, args, i)); fprintf(stderr, " "); } fprintf(stderr, "\n"); return v7_create_undefined(); }
static void invoke_cb(struct user_data *ud, const char *name, v7_val_t ev) { struct v7 *v7 = ud->v7; v7_val_t met = v7_get(v7, ud->ws, name, ~0); if (!v7_is_undefined(met)) { v7_val_t res, args = v7_create_array(v7); v7_array_set(v7, args, 0, ev); if (v7_apply(v7, &res, met, v7_create_undefined(), args) != V7_OK) { /* TODO(mkm): make it print stack trace */ fprintf(stderr, "cb threw an exception\n"); } } }
static enum v7_err GPIO_setisr(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t pinv = v7_arg(v7, 0); v7_val_t typev = v7_arg(v7, 1); v7_val_t cb = v7_arg(v7, 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"); *res = v7_create_boolean(0); goto clean; } 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(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"); *res = v7_create_boolean(0); goto clean; }; if (has_isr && new_isr_provided && current_cb != cb) { printf("Only one interruption handler is allowed for pin\n"); *res = v7_create_boolean(0); goto clean; } if (type == 0 && has_isr) { v7_set(v7, v7_get_global(v7), prop_name, len, 0, v7_create_undefined()); } else if (!has_isr && new_isr_provided) { v7_set(v7, v7_get_global(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; } *res = v7_create_boolean(sj_gpio_intr_set(pin, type) == 0); goto clean; clean: return rcode; }
static v7_val_t GPIO_read(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t pinv = v7_array_get(v7, args, 0); int pin; if (!v7_is_number(pinv)) { printf("non-numeric pin\n"); return v7_create_undefined(); } pin = v7_to_number(pinv); return v7_create_number(sj_gpio_read(pin)); }
static v7_val_t gsm_call(struct v7* v7) { v7_val_t numberv = v7_arg(v7, 0); const char* number; size_t len; if(!v7_is_string(numberv)) { return v7_create_undefined(); } number = v7_to_string(v7, &numberv, &len); return v7_create_number(_gsm_call(number)); }
/* Currently can only handle one timer */ static v7_val_t global_set_timeout(struct v7 *v7) { v7_val_t *cb; v7_val_t msecsv = v7_arg(v7, 1); int msecs; cb = (v7_val_t *) malloc(sizeof(*cb)); v7_own(v7, cb); *cb = v7_arg(v7, 0); if (!v7_is_function(*cb)) { printf("cb is not a function\n"); return v7_create_undefined(); } if (!v7_is_number(msecsv)) { printf("msecs is not a double\n"); return v7_create_undefined(); } msecs = v7_to_number(msecsv); sj_set_timeout(msecs, cb); return v7_create_undefined(); }
static v7_val_t GPIO_write(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 valv = v7_array_get(v7, args, 1); int pin, val; if (!v7_is_number(pinv)) { printf("non-numeric pin\n"); return v7_create_undefined(); } pin = v7_to_number(pinv); val = v7_to_number(valv); return v7_create_boolean(sj_gpio_write(pin, val) == 0); }
static enum v7_err GPIO_read(struct v7 *v7, v7_val_t *res) { v7_val_t pinv = v7_arg(v7, 0); int pin; if (!v7_is_number(pinv)) { printf("non-numeric pin\n"); *res = v7_create_undefined(); } else { pin = v7_to_number(pinv); *res = v7_create_number(sj_gpio_read(pin)); } return V7_OK; }
void sj_wifi_scan_done(const char **ssids) { struct v7 *v7 = s_v7; v7_val_t cb = v7_get(v7, s_wifi, "_scb", ~0); v7_val_t res = v7_create_undefined(); const char **p; if (!v7_is_function(cb)) return; v7_own(v7, &res); if (ssids != NULL) { res = v7_create_array(v7); for (p = ssids; *p != NULL; p++) { v7_array_push(v7, res, v7_create_string(v7, *p, strlen(*p), 1)); } } else { res = v7_create_undefined(); } sj_invoke_cb1(v7, cb, res); v7_disown(v7, &res); v7_set(v7, s_wifi, "_scb", ~0, V7_PROPERTY_DONT_ENUM | V7_PROPERTY_HIDDEN, v7_create_undefined()); }