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 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; }
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 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; }
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; }
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 v7_val_t GPIO_setmode(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 modev = v7_array_get(v7, args, 1); v7_val_t pullv = v7_array_get(v7, args, 2); int pin, mode, pull; if (!v7_is_number(pinv) || !v7_is_number(modev) || !v7_is_number(pullv)) { printf("Invalid arguments"); return v7_create_undefined(); } pin = v7_to_number(pinv); mode = v7_to_number(modev); pull = v7_to_number(pullv); return v7_create_boolean(sj_gpio_set_mode(pin, mode, pull) == 0); }
/* * 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 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; }
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; }
/* * 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(); }
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\n"); *res = V7_UNDEFINED; } else { pin = v7_get_double(v7, pinv); mode = v7_get_double(v7, modev); pull = v7_get_double(v7, pullv); *res = v7_mk_boolean(v7, sj_gpio_set_mode(pin, (enum gpio_mode) mode, (enum gpio_pull_type) pull) == 0); } return V7_OK; }
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(); }
static enum v7_err UART_get(struct v7 *v7, v7_val_t *res) { enum v7_err ret = V7_OK; v7_val_t arg0 = v7_arg(v7, 0); int uart_no = v7_to_number(arg0); if (v7_is_number(arg0) && (uart_no == 0 || uart_no == 1)) { *res = sj_us[uart_no].obj; } else { ret = v7_throwf(v7, "Error", "Invalid UART number"); } return ret; }
/* 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 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)); }
// JS: i2c.setup(address, speed) static v7_val_t i2c_setup(struct v7 *v7) { vm_dcl_i2c_control_config_t conf_data; int result; v7_val_t addressv = v7_arg(v7, 0); v7_val_t speedv = v7_arg(v7, 1); int address, speed; if(!v7_is_number(addressv) || !v7_is_number(speedv)) { printf("Invalid arguments\n"); return v7_create_undefined(); } address = v7_to_number(addressv); speed = v7_to_number(speedv); if(speed >= 400) { conf_data.transaction_mode = VM_DCL_I2C_TRANSACTION_HIGH_SPEED_MODE; } else { conf_data.transaction_mode = VM_DCL_I2C_TRANSACTION_FAST_MODE; } if(g_i2c_handle == VM_DCL_HANDLE_INVALID) { g_i2c_handle = vm_dcl_open(VM_DCL_I2C, 0); } conf_data.reserved_0 = (VM_DCL_I2C_OWNER)0; conf_data.get_handle_wait = TRUE; conf_data.reserved_1 = 0; conf_data.delay_length = 0; conf_data.slave_address = (address << 1); conf_data.fast_mode_speed = speed; conf_data.high_mode_speed = 0; result = vm_dcl_control(g_i2c_handle, VM_DCL_I2C_CMD_CONFIG, &conf_data); return v7_create_number(result); }
SJ_PRIVATE enum v7_err global_usleep(struct v7 *v7, v7_val_t *res) { v7_val_t usecsv = v7_arg(v7, 0); int usecs; (void) res; if (!v7_is_number(usecsv)) { printf("usecs is not a double\n\r"); } else { usecs = v7_to_number(usecsv); sj_usleep(usecs); } return V7_OK; }
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); }
SJ_PRIVATE 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_mk_undefined(); } else { pin = v7_to_number(pinv); *res = v7_mk_number(sj_gpio_read(pin)); } return V7_OK; }
SJ_PRIVATE 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_UNDEFINED; } else { pin = v7_get_double(v7, pinv); *res = v7_mk_number(v7, sj_gpio_read(pin)); } return V7_OK; }
static enum v7_err Sys_wdtSetTimeout(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t timeoutv = v7_arg(v7, 0); if (!v7_is_number(timeoutv)) { rcode = v7_throwf(v7, "Error", "Timeout should be a number"); } else { sj_wdt_set_timeout(v7_get_double(v7, timeoutv)); } *res = v7_mk_boolean(v7, rcode == V7_OK); return V7_OK; }
static enum v7_err ADC_readVoltage(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_mk_undefined(); } else { pin = v7_to_number(pinv); *res = v7_mk_number(sj_adc_read_voltage(pin)); } return V7_OK; }
/* HAL functions */ spi_connection sj_spi_create(struct v7 *v7, v7_val_t args) { struct lnx_spi_connection *conn; v7_val_t spi_no_val = v7_array_get(v7, args, 0); double spi_no = v7_to_number(spi_no_val); ; if (!v7_is_number(spi_no_val) || spi_no < 0) { v7_throw(v7, "Missing arguments for SPI number or wrong type."); } conn = malloc(sizeof(*conn)); conn->spi_no = v7_to_number(spi_no); return conn; }
/* * 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 enum v7_err Sys_reboot(struct v7 *v7, v7_val_t *res) { int exit_code = 0; (void) v7; (void) res; v7_val_t code_v = v7_arg(v7, 0); if (v7_is_number(code_v)) { exit_code = v7_to_number(code_v); } sj_system_restart(exit_code); /* Unreachable */ return V7_OK; }
/* * Sets output for debug messages. * Available modes are: * 0 - no debug output * 1 - print debug output to UART0 (V7's console) * 2 - print debug output to UART1 */ static v7_val_t Debug_mode(struct v7 *v7) { int mode, res; v7_val_t output_val = v7_arg(v7, 0); if (!v7_is_number(output_val)) { printf("Output is not a number\n"); return v7_create_undefined(); } mode = v7_to_number(output_val); uart_debug_init(0, 0); res = uart_redirect_debug(mode); return v7_create_number(res < 0 ? res : mode); }
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; }
static enum v7_err jsClearInterval(struct v7* v7, v7_val_t* res) { v7_val_t ind = v7_arg(v7, 0); if (!v7_is_number(ind)) { //TODO: throw error _activeBot->say("Invalid timer key, (not a number)"); return V7_OK; } long n = (long)floor(v7_to_number(ind)); TIMER* p = (TIMER*)n; v7_disown(v7, (v7_val_t*)p->pToFunc); delete (v7_val_t*)p->pToFunc; _activeBot->_timers.Del(p); delete p; return V7_OK; }
SJ_PRIVATE enum v7_err Wifi_ip(struct v7 *v7, v7_val_t *res) { v7_val_t arg0 = v7_arg(v7, 0); char *ip = NULL; ip = v7_is_number(arg0) && v7_get_double(v7, arg0) == 1 ? sj_wifi_get_ap_ip() : sj_wifi_get_sta_ip(); if (ip == NULL) { *res = V7_UNDEFINED; goto clean; } *res = v7_mk_string(v7, ip, strlen(ip), 1); clean: if (ip != NULL) { free(ip); } return V7_OK; }