static enum v7_err jsBotSay(struct v7 *v7, v7_val_t *res) { long argc = v7_argc(v7); if (argc == 0) { return V7_OK; } v7_val_t v = v7_arg(v7, 0); if (!v7_is_string(v)) { return V7_OK; } TString str = (const char*)v7_to_cstring(v7, &v); TString font; if (argc >= 2) { v7_val_t fontt = v7_arg(v7, 1); if (!v7_is_null(fontt) && !v7_is_undefined(fontt)) font = (const char*)v7_to_cstring(v7, &fontt); } int size = 0; if (argc >= 3) { v7_val_t sizee = v7_arg(v7, 2); if (v7_is_number(sizee)) size = floor(v7_to_number(sizee)); if (size < 10) size = 10; } TString col; if (argc >= 4) { v7_val_t coll = v7_arg(v7, 3); if (v7_is_string(coll)) col = (const char*)v7_to_cstring(v7, &coll); if (col.GetAt(0) != L'#' || col.GetLength() != 7) col = L""; } _activeBot->say(str, font, size, col); return V7_OK; }
/* * Publishes a message to a topic. * * Args: * - `topic`: topic, string. * - `message`: message, string. * * Only QOS 0 is implemented at the moment. */ enum v7_err MQTT_publish(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; struct user_data *ud; struct mg_connection *nc; const char *topic; const char *message; size_t message_len; v7_val_t topicv = v7_arg(v7, 0), messagev = v7_arg(v7, 1); (void) res; topic = v7_get_cstring(v7, &topicv); if (topic == NULL || strlen(topic) == 0) { rcode = v7_throwf(v7, "TypeError", "invalid topic"); goto clean; } if (!v7_is_string(messagev)) { rcode = v7_throwf(v7, "TypeError", "invalid message"); goto clean; } message = v7_get_string(v7, &messagev, &message_len); nc = v7_get_ptr(v7, v7_get(v7, v7_get_this(v7), "_nc", ~0)); if (nc == NULL) { rcode = v7_throwf(v7, "Error", "invalid connection"); goto clean; } ud = (struct user_data *) nc->user_data; mg_mqtt_publish(nc, topic, ud->msgid++, MG_MQTT_QOS(0), message, message_len); clean: return rcode; }
SJ_PRIVATE enum v7_err Http_response_writeHead(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; DECLARE_CONN(); unsigned long code = 200; v7_val_t arg0 = v7_arg(v7, 0), arg1 = v7_arg(v7, 1); if (v7_is_truthy(v7, v7_get(v7, v7_get_this(v7), "_whd", ~0))) { rcode = v7_throwf(v7, "Error", "Headers already sent"); goto clean; } if (v7_is_number(arg0)) { code = v7_to_number(arg0); } write_http_status(c, code); http_write_headers(v7, arg1, c); mg_send(c, "\r\n", 2); v7_set(v7, v7_get_this(v7), "_whd", ~0, v7_mk_boolean(1)); *res = v7_get_this(v7); clean: return rcode; }
/* * `on` method on a mqtt client object registers an event handler * for a given event type. Recognized event types: * * - `connect`: invoked on sucessfull connection (mqtt connack message) * - `error`: invoked on connection error * - `close`: invoked when the connection gets closed * - `message`: invoked when a new message is received. The callback * receives (topic, message) arguments, both strings */ enum v7_err MQTT_on(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t evv = v7_arg(v7, 0); v7_val_t cb = v7_arg(v7, 1); const char *ev, *key = NULL; ev = v7_get_cstring(v7, &evv); if (strcmp(ev, "connect") == 0) { key = SJ_MQTT_CONNECT_CB; } else if (strcmp(ev, "message") == 0) { key = SJ_MQTT_MESSAGE_CB; } else if (strcmp(ev, "error") == 0) { key = SJ_MQTT_ERROR_CB; } else if (strcmp(ev, "close") == 0) { key = SJ_MQTT_CLOSE_CB; } else { rcode = v7_throwf(v7, "Error", "unsupported protocol"); goto clean; } v7_def(v7, v7_get_this(v7), key, ~0, V7_DESC_ENUMERABLE(0), cb); (void) res; clean: return rcode; }
static v7_val_t sj_http_post(struct v7 *v7) { v7_val_t urlv = v7_arg(v7, 0); v7_val_t body = v7_arg(v7, 1); v7_val_t cb = v7_arg(v7, 2); return sj_http_call_helper(v7, urlv, body, cb, "POST"); }
static enum v7_err jsSetTimeout(struct v7* v7, v7_val_t* res) { v7_val_t* func = new v7_val_t; v7_own(v7, func); *func = v7_arg(v7, 0); v7_val_t inv = v7_arg(v7, 1); if (!v7_is_callable(v7, *func)) { //TODO: catch error if 1st argument not callable code return V7_OK; } if (!v7_is_number(inv)) { //TODO: catch error if 2nd argument not a number return V7_OK; } double ms = v7_to_number(inv); long lms = floor(ms); //v7_apply(v7, func, _activeBot->getV7Obj(), v7_mk_undefined(), NULL); TIMER* newTimer = new TIMER; newTimer->pToFunc = func; newTimer->delay = lms; newTimer->timeBegin = GetTickCount(); newTimer->id = (long)newTimer; _activeBot->_timers.Add(newTimer); double vOut = (double)newTimer->id; *res = v7_mk_number(vOut); return V7_OK; }
static enum v7_err dsleep(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t time_v = v7_arg(v7, 0); double time = v7_to_number(time_v); v7_val_t flags_v = v7_arg(v7, 1); uint8 flags = v7_to_number(flags_v); if (!v7_is_number(time_v) || time < 0) { *res = v7_mk_boolean(false); goto clean; } if (v7_is_number(flags_v)) { if (!system_deep_sleep_set_option(flags)) { *res = v7_mk_boolean(false); goto clean; } } system_deep_sleep((uint32_t) time); *res = v7_mk_boolean(true); goto clean; clean: return rcode; }
SJ_PRIVATE enum v7_err global_clearTimeoutOrInterval(struct v7 *v7, v7_val_t *res) { (void) res; if (v7_is_number(v7_arg(v7, 0))) { sj_clear_timer(v7_get_double(v7, v7_arg(v7, 0))); } return V7_OK; }
static enum v7_err js_sum(struct v7 *v7, v7_val_t *res) { double arg0 = v7_to_number(v7_arg(v7, 0)); double arg1 = v7_to_number(v7_arg(v7, 1)); double result = sum(arg0, arg1); *res = v7_mk_number(result); return V7_OK; }
SJ_PRIVATE 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_mk_boolean(v7, 0); goto clean; } pin = v7_get_double(v7, pinv); type = v7_get_double(v7, 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_callable(v7, current_cb); new_isr_provided = v7_is_callable(v7, cb); if (!has_isr && !new_isr_provided) { printf("Missing callback\n"); *res = v7_mk_boolean(v7, 0); goto clean; }; if (has_isr && new_isr_provided && current_cb != cb) { printf("Only one interruption handler is allowed for pin\n"); *res = v7_mk_boolean(v7, 0); goto clean; } if (type == 0 && has_isr) { v7_set(v7, v7_get_global(v7), prop_name, len, V7_UNDEFINED); } else if (!has_isr && new_isr_provided) { v7_set(v7, v7_get_global(v7), prop_name, len, cb); } if (type != 0 && !s_gpio_intr_installed) { sj_gpio_intr_init(gpio_intr_handler_proxy, v7); s_isr_cb_proxy_v = v7_mk_cfunction(isr_cb_proxy); v7_own(v7, &s_isr_cb_proxy_v); s_gpio_intr_installed = 1; } *res = v7_mk_boolean(v7, sj_gpio_intr_set(pin, (enum gpio_int_mode) type) == 0); goto clean; clean: return rcode; }
/* JS signature: listen(addr, [options]) */ SJ_PRIVATE enum v7_err Http_Server_listen(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; char buf[50], *p = buf; const char *ca_cert = NULL, *cert = NULL; v7_val_t this_obj = v7_get_this(v7); v7_val_t arg0 = v7_arg(v7, 0); v7_val_t opts = v7_arg(v7, 1); if (!v7_is_number(arg0) && !v7_is_string(arg0)) { rcode = v7_throwf(v7, "TypeError", "Function expected"); goto clean; } if (!v7_is_undefined(opts) && !v7_is_object(opts)) { rcode = v7_throwf(v7, "TypeError", "Options must be an object"); goto clean; } if (!v7_is_undefined(opts)) { v7_val_t ca_cert_v = v7_get(v7, opts, "ssl_ca_cert", ~0); v7_val_t cert_v = v7_get(v7, opts, "ssl_cert", ~0); if (!v7_is_undefined(ca_cert_v) && !v7_is_string(ca_cert_v)) { rcode = v7_throwf(v7, "TypeError", "ca_cert must be a string"); goto clean; } if (!v7_is_undefined(cert_v) && !v7_is_string(cert_v)) { rcode = v7_throwf(v7, "TypeError", "cert must be a string"); goto clean; } if (!v7_is_undefined(ca_cert_v)) { ca_cert = v7_to_cstring(v7, &ca_cert_v); } if (!v7_is_undefined(cert_v)) { cert = v7_to_cstring(v7, &cert_v); } } p = v7_stringify(v7, arg0, buf, sizeof(buf), 0); rcode = start_http_server(v7, p, this_obj, ca_cert, cert); if (rcode != V7_OK) { goto clean; } *res = this_obj; clean: if (p != buf) { free(p); } return rcode; }
static enum v7_err UART_onTXEmpty(struct v7 *v7, v7_val_t *res) { struct esp_sj_uart_state *us; enum v7_err ret = esp_sj_uart_get_state(v7, &us); if (ret != V7_OK) return ret; v7_set(v7, us->obj, "_txcb", 5, v7_arg(v7, 0)); if (v7_is_callable(v7, v7_arg(v7, 0))) { esp_sj_uart_schedule_dispatcher(us->uart_no); } *res = v7_mk_undefined(); return V7_OK; }
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; }
/* Args: callable, disable_rx */ static enum v7_err UART_onRecv(struct v7 *v7, v7_val_t *res) { struct esp_sj_uart_state *us; enum v7_err ret = esp_sj_uart_get_state(v7, &us); if (ret != V7_OK) return ret; v7_set(v7, us->obj, "_rxcb", 5, v7_arg(v7, 0)); esp_uart_set_rx_enabled(us->uart_no, !v7_is_truthy(v7, v7_arg(v7, 1))); if (v7_is_callable(v7, v7_arg(v7, 0))) { esp_sj_uart_schedule_dispatcher(us->uart_no); } *res = V7_UNDEFINED; return V7_OK; }
static enum v7_err jsBotFontStyle(struct v7* v7, v7_val_t* res) { v7_val_t fontName = v7_arg(v7, 0); v7_val_t fontSize = v7_arg(v7, 1); v7_val_t fontColor = v7_arg(v7, 2); if (!v7_is_string(fontName) || !v7_is_number(fontSize) || !v7_is_string(fontColor)) { return V7_OK; } TString fontColor2 = v7_to_cstring(v7, &fontColor); TString strFontName = (v7_is_null(fontName)) ? "" : (const char*)v7_to_cstring(v7, &fontName); int nFontSize = (!v7_is_number(fontSize)) ? NULL : (int)v7_to_number(fontSize); COLORREF nFontColor = (!v7_is_string(fontColor)) ? NULL : GetCol(fontColor2.GetAsWChar()); _activeBot->setFontStyle(strFontName, nFontSize, nFontColor); return V7_OK; }
SJ_PRIVATE enum v7_err Http_request_set_timeout(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; DECLARE_CONN(); struct user_data *ud = (struct user_data *) c->user_data; mg_set_timer(c, time(NULL) + v7_to_number(v7_arg(v7, 0)) / 1000.0); ud->timeout_callback = v7_arg(v7, 1); v7_own(v7, &ud->timeout_callback); *res = v7_get_this(v7); clean: return rcode; }
/* * Regiter a callback to be invoked when there is at least N bytes available. * N defaults to maxint if undefined */ static enum v7_err UART_recv(struct v7 *v7, v7_val_t *res) { v7_val_t this_obj = v7_get_this(v7); v7_val_t cb = v7_arg(v7, 0); v7_val_t wantv = v7_arg(v7, 1); v7_val_t udv = v7_get(v7, this_obj, "_ud", ~0); size_t want = v7_is_number(wantv) ? (size_t) v7_to_number(wantv) : ~0; struct user_data *ud = (struct user_data *) v7_to_foreign(udv); ud->cb = cb; v7_own(v7, &ud->cb); ud->want = want; /* TODO(mkm): trigger cb if there is already something in the buffer */ return V7_OK; }
static v7_val_t dsleep(struct v7 *v7) { v7_val_t time_v = v7_arg(v7, 0); uint32 time = v7_to_number(time_v); v7_val_t flags_v = v7_arg(v7, 1); uint8 flags = v7_to_number(flags_v); if (!v7_is_number(time_v) || time < 0) return v7_create_boolean(false); if (v7_is_number(flags_v)) { if (!system_deep_sleep_set_option(flags)) return v7_create_boolean(false); } system_deep_sleep(time); return v7_create_boolean(true); }
SJ_PRIVATE enum v7_err Wifi_ready(struct v7 *v7, v7_val_t *res) { int ret = 0; v7_val_t cbv = v7_arg(v7, 0); if (!v7_is_callable(v7, cbv)) { LOG(LL_ERROR, ("Invalid arguments")); goto exit; } if (sj_wifi_get_status() == SJ_WIFI_IP_ACQUIRED) { sj_invoke_cb0(v7, cbv); ret = 1; } else { struct wifi_cb_arg *arg = (struct wifi_cb_arg *) calloc(1, sizeof(*arg)); if (arg != NULL) { arg->v7 = v7; arg->v = cbv; v7_own(v7, &arg->v); sj_wifi_add_on_change_cb(sj_wifi_ready_js, arg); } else { ret = 0; } } exit: *res = v7_mk_boolean(v7, ret); return V7_OK; }
static enum v7_err isr_cb_proxy(struct v7 *v7, v7_val_t *res) { v7_val_t cb = v7_arg(v7, 0); v7_val_t args = v7_arg(v7, 1); v7_own(v7, &cb); v7_own(v7, &args); enum v7_err ret = v7_apply(v7, cb, v7_get_global(v7), args, res); sj_reenable_intr(v7_get_double(v7, v7_array_get(v7, args, 0))); v7_disown(v7, &args); v7_disown(v7, &cb); return ret; }
/* * 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; }
/* * Serve static files. * * Takes an object containing mongoose http server options. * Commonly used properties: * - `document_root`: Path to the web root directory * - `enable_directory_listing`: Set to "no" to disable directory listing. * Enabled by default. * - `extra_headers`: Extra HTTP headers to add to each server response. * * For the full option object definition see: * https://docs.cesanta.com/mongoose/dev/index.html#/c-api/http.h/struct_mg_serve_http_opts/ */ SJ_PRIVATE enum v7_err Http_response_serve(struct v7 *v7, v7_val_t *res) { struct mg_serve_http_opts opts; struct http_message hm; enum v7_err rcode = V7_OK; DECLARE_CONN(); size_t i, n; v7_val_t request = v7_get(v7, v7_get_this(v7), "_r", ~0); v7_val_t url_v = v7_get(v7, request, "url", ~0); const char *url = v7_get_string_data(v7, &url_v, &n); const char *quest = strchr(url, '?'); memset(&opts, 0, sizeof(opts)); memset(&hm, 0, sizeof(hm)); /* Set up "fake" parsed HTTP message */ hm.uri.p = url; hm.uri.len = quest == NULL ? n : n - (quest - url); if (v7_argc(v7) > 0) { populate_opts_from_js_argument(v7, v7_arg(v7, 0), &opts); } mg_serve_http(c, &hm, opts); for (i = 0; i < ARRAY_SIZE(s_map); i++) { free(*(char **) ((char *) &opts + s_map[i].offset)); } *res = v7_get_this(v7); clean: return rcode; }
/* * Subscribes a mqtt client to a topic. */ enum v7_err MQTT_subscribe(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; struct user_data *ud; struct mg_connection *nc; struct mg_mqtt_topic_expression expr; v7_val_t topicv = v7_arg(v7, 0); const char *topic; nc = v7_get_ptr(v7, v7_get(v7, v7_get_this(v7), "_nc", ~0)); if (nc == NULL) { rcode = v7_throwf(v7, "Error", "unsupported protocol"); goto clean; } ud = (struct user_data *) nc->user_data; topic = v7_get_cstring(v7, &topicv); if (topic == NULL || strlen(topic) == 0) { rcode = v7_throwf(v7, "TypeError", "invalid topic"); goto clean; } expr.topic = topic; expr.qos = 0; mg_mqtt_subscribe(nc, &expr, 1, ud->msgid++); *res = v7_mk_boolean(v7, 1); clean: return rcode; }
static v7_val_t Wifi_changed(struct v7 *v7) { v7_val_t cb = v7_arg(v7, 0); if (!v7_is_function(cb)) return v7_create_boolean(0); v7_set(v7, s_wifi, "_ccb", ~0, V7_PROPERTY_DONT_ENUM | V7_PROPERTY_HIDDEN, cb); return v7_create_boolean(1); }
static enum v7_err jsBotLoadFile(struct v7* v7, v7_val_t* res) { v7_val_t file = v7_arg(v7, 0); if (!v7_is_string(file)) { return V7_OK; } TString fullPath = _activeBot->getWorkDir(); TString fileName = v7_to_cstring(v7, &file); fullPath += fileName.GetAsWChar(); if (!fexists(fullPath)) { return V7_OK; } v7_val_t result; enum v7_err ress = V7_OK; ress = v7_exec_file(v7, fullPath.GetAsChar(), &result); //v7_val_t* v7Obj = _activeBot->getV7Obj(); //*v7Obj = v7_mk_object(v7); if (ress != V7_OK) { if (result == V7_SYNTAX_ERROR) MessageBox(NULL, "script fail syntax error", "Nooo", 0); else if (result == V7_EXEC_EXCEPTION) MessageBox(NULL, "script fail, exception", "Nooo", 0); else if (result == V7_EXEC_EXCEPTION) MessageBox(NULL, "script fail, exception", "Nooo", 0); else if (result == V7_AST_TOO_LARGE) MessageBox(NULL, "script fail, ast too large", "Nooo", 0); } return V7_OK; }
static v7_val_t sj_Wifi_setup(struct v7 *v7) { v7_val_t ssidv = v7_arg(v7, 0); v7_val_t passv = v7_arg(v7, 1); const char *ssid, *pass; size_t ssid_len, pass_len; if (!v7_is_string(ssidv) || !v7_is_string(passv)) { printf("ssid/pass are not strings\n"); return v7_create_undefined(); } ssid = v7_to_string(v7, &ssidv, &ssid_len); pass = v7_to_string(v7, &passv, &pass_len); return v7_create_boolean(sj_wifi_setup_sta(ssid, pass)); }
/* * Read the content of the UART. It does not block. * Optional `max_len` parameter, defaults to max size_t. */ static enum v7_err UART_read(struct v7 *v7, v7_val_t *res) { v7_val_t this_obj = v7_get_this(v7); v7_val_t dev = v7_get(v7, this_obj, "_dev", ~0), maxv = v7_arg(v7, 0); size_t max = v7_is_number(maxv) ? (size_t) v7_to_number(maxv) : ~0; *res = sj_hal_read_uart(v7, v7_to_foreign(dev), max); return V7_OK; }
SJ_PRIVATE enum v7_err sj_Wifi_setup(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t ssidv = v7_arg(v7, 0); v7_val_t passv = v7_arg(v7, 1); v7_val_t extrasv = v7_arg(v7, 2); const char *ssid, *pass; size_t ssid_len, pass_len; int permanent = 1, ret = 0; if (!v7_is_string(ssidv) || !v7_is_string(passv)) { printf("ssid/pass are not strings\n"); *res = V7_UNDEFINED; goto clean; } if (v7_is_object(extrasv)) { permanent = v7_is_truthy(v7, v7_get(v7, extrasv, "permanent", ~0)); } ssid = v7_get_string(v7, &ssidv, &ssid_len); pass = v7_get_string(v7, &passv, &pass_len); struct sys_config_wifi_sta cfg; memset(&cfg, 0, sizeof(cfg)); cfg.ssid = (char *) ssid; cfg.pass = (char *) pass; LOG(LL_INFO, ("WiFi: connecting to '%s'", ssid)); ret = sj_wifi_setup_sta(&cfg); if (ret && permanent) { struct sys_config *cfg = get_cfg(); cfg->wifi.sta.enable = 1; sj_conf_set_str(&cfg->wifi.sta.ssid, ssid); sj_conf_set_str(&cfg->wifi.sta.pass, pass); } *res = v7_mk_boolean(v7, ret); goto clean; clean: return rcode; }
SJ_PRIVATE enum v7_err GPIO_setmode(struct v7 *v7, v7_val_t *res) { v7_val_t pinv = v7_arg(v7, 0); v7_val_t modev = v7_arg(v7, 1); v7_val_t pullv = v7_arg(v7, 2); int pin, mode, pull; if (!v7_is_number(pinv) || !v7_is_number(modev) || !v7_is_number(pullv)) { printf("Invalid arguments"); *res = v7_mk_undefined(); } else { pin = v7_to_number(pinv); mode = v7_to_number(modev); pull = v7_to_number(pullv); *res = v7_mk_boolean(sj_gpio_set_mode(pin, mode, pull) == 0); } return V7_OK; }
SJ_PRIVATE enum v7_err sj_set_interval_or_timeout(struct v7 *v7, v7_val_t *res, int repeat) { v7_val_t msecsv = v7_arg(v7, 1); int msecs; (void) res; if (!v7_is_callable(v7, v7_arg(v7, 0))) { printf("cb is not a function\n"); } else if (!v7_is_number(msecsv)) { printf("msecs is not a number\n"); } else { v7_val_t cb = v7_arg(v7, 0); msecs = v7_get_double(v7, msecsv); *res = v7_mk_number(v7, sj_set_js_timer(msecs, repeat, v7, cb)); } return V7_OK; }