static enum v7_err UART_setRXEnabled(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; esp_uart_set_rx_enabled(us->uart_no, v7_is_truthy(v7, v7_arg(v7, 0))); esp_sj_uart_schedule_dispatcher(us->uart_no); *res = v7_mk_undefined(); return V7_OK; }
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; }
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(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_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(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(0); goto clean; } if (type == 0 && has_isr) { v7_set(v7, v7_get_global(v7), prop_name, len, v7_mk_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); s_gpio_intr_installed = 1; } *res = v7_mk_boolean(sj_gpio_intr_set(pin, type) == 0); goto clean; clean: return rcode; }
/* * Mongoose event handler. If JavaScript callback was provided, call it */ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) { struct user_data *ud = (struct user_data *) c->user_data; if (ev == MG_EV_HTTP_REQUEST) { /* HTTP request has arrived */ if (v7_is_callable(ud->v7, ud->handler)) { /* call provided JavaScript callback with `request` and `response` */ v7_val_t request = v7_mk_object(ud->v7); v7_own(ud->v7, &request); v7_val_t response = v7_mk_object(ud->v7); v7_own(ud->v7, &response); setup_request_object(ud->v7, request, ev_data); setup_response_object(ud->v7, response, c, request); sj_invoke_cb2_this(ud->v7, ud->handler, ud->obj, request, response); v7_disown(ud->v7, &request); v7_disown(ud->v7, &response); } else { /* * no JavaScript callback provided; serve the request with the default * options by `mg_serve_http()` */ struct mg_serve_http_opts opts; memset(&opts, 0, sizeof(opts)); mg_serve_http(c, ev_data, opts); } } else if (ev == MG_EV_HTTP_REPLY) { /* HTTP response has arrived */ /* if JavaScript callback was provided, call it with `response` */ if (v7_is_callable(ud->v7, ud->handler)) { v7_val_t response = v7_mk_object(ud->v7); v7_own(ud->v7, &response); setup_request_object(ud->v7, response, ev_data); sj_invoke_cb1_this(ud->v7, ud->handler, ud->obj, response); v7_disown(ud->v7, &response); } if (c->flags & MG_F_CLOSE_CONNECTION_AFTER_RESPONSE) { c->flags |= MG_F_CLOSE_IMMEDIATELY; } } else if (ev == MG_EV_TIMER) { sj_invoke_cb0_this(ud->v7, ud->timeout_callback, ud->obj); } else if (ev == MG_EV_CLOSE) { if (c->listener == NULL && ud != NULL) { v7_set(ud->v7, ud->obj, "_c", ~0, v7_mk_undefined()); v7_disown(ud->v7, &ud->obj); v7_disown(ud->v7, &ud->timeout_callback); free(ud); c->user_data = NULL; } } }
static void call_sum(struct v7 *v7) { v7_val_t func, result, args; func = v7_get(v7, v7_get_global(v7), "sum", 3); args = v7_mk_array(v7); v7_array_push(v7, args, v7_mk_number(123.0)); v7_array_push(v7, args, v7_mk_number(456.789)); v7_apply(v7, func, v7_mk_undefined(), args, &result); printf("Result: %g\n", v7_to_number(result)); }
void Bot::onText(bot_exchange_format& f) { long i, l; l = _onTexts.GetLength(); std::string nick = std::string(f[1]); std::string text = std::string(f[2]); v7_val_t attr; if ((u_char)f[3] == 0) { attr = v7_mk_undefined(); } else { attr = v7_mk_object(v7); v7_val_t size = v7_mk_number((u_char)f[4]); v7_set(v7, attr, "size", ~0, size); COLORREF col = (u_long)f[5]; int r = GetRValue(col); int g = GetGValue(col); int b = GetBValue(col); char strCol[8]; sprintf(strCol, "#%02X%02X%02X", r, g, b); v7_val_t color = v7_mk_string(v7, strCol, ~0, 1); v7_set(v7, attr, "color", ~0, color); v7_val_t effects = v7_mk_number((u_long)f[6]); v7_set(v7, attr, "effects", ~0, effects); v7_val_t charset = v7_mk_number((u_char)f[7]); v7_set(v7, attr, "charset", ~0, charset); v7_val_t pitch = v7_mk_number((u_char)f[8]); v7_set(v7, attr, "pitch", ~0, pitch); std::string font = std::string(f[9]); v7_val_t fontName = v7_mk_string(v7, font.c_str(), ~0, 1); v7_set(v7, attr, "font", ~0, fontName); } v7_val_t nickName = v7_mk_string(v7, nick.c_str(), ~0, 0); v7_val_t fullText = v7_mk_string(v7, text.c_str(), ~0, 0); for (i = 0; i < l; i++) { v7_val_t* func = (v7_val_t*)_onTexts.GetAt(i); v7_val_t args; args = v7_mk_array(v7); v7_array_push(v7, args, nickName); v7_array_push(v7, args, fullText); v7_array_push(v7, args, attr); v7_apply(v7, *func, *v7Obj, args, NULL); } }
void esp_sj_uart_dispatcher(void *arg) { int uart_no = (int) arg; struct esp_sj_uart_state *us = &sj_us[uart_no]; cs_rbuf_t *rxb = esp_uart_rx_buf(uart_no); cs_rbuf_t *txb = esp_uart_tx_buf(uart_no); us->dispatch_pending = 0; esp_uart_dispatch_rx_top(uart_no); uint16_t tx_used_before = txb->used; esp_uart_dispatch_tx_top(uart_no); if (us->v7 != NULL) { /* Detect the edge of TX buffer becoming empty. */ if (tx_used_before > 0 && txb->used == 0) { v7_val_t txcb = v7_get(us->v7, us->obj, "_txcb", 5); if (v7_is_callable(us->v7, txcb)) { sj_invoke_cb(us->v7, txcb, us->obj, v7_mk_undefined()); } } if (rxb->used > 0) { /* Check for JS recv handler. */ v7_val_t rxcb = esp_sj_uart_get_recv_handler(uart_no); if (v7_is_callable(us->v7, rxcb)) { if (!us->recv_pending) { us->recv_pending = 1; sj_invoke_cb(us->v7, rxcb, us->obj, v7_mk_undefined()); /* Note: Callback has not run yet, it has been scheduled. */ } } else if (us->prompt) { uint8_t *cp; while (rxb != NULL && cs_rbuf_get(rxb, 1, &cp) == 1) { char c = (char) *cp; cs_rbuf_consume(rxb, 1); sj_prompt_process_char(c); /* UART could've been re-initialized by the command from prompt. */ rxb = esp_uart_rx_buf(uart_no); } } } } esp_uart_dispatch_bottom(uart_no); }
void sj_http_init(struct v7 *v7) { v7_val_t Http = v7_mk_undefined(); sj_http_server_proto = v7_mk_undefined(); sj_http_response_proto = v7_mk_undefined(); sj_http_request_proto = v7_mk_undefined(); /* own temporary Http var */ v7_own(v7, &Http); /* other values are owned forever */ v7_own(v7, &sj_http_server_proto); v7_own(v7, &sj_http_response_proto); v7_own(v7, &sj_http_request_proto); Http = v7_get(v7, v7_get_global(v7), "Http", ~0); sj_http_server_proto = v7_get(v7, Http, "_serv", ~0); sj_http_response_proto = v7_get(v7, Http, "_resp", ~0); sj_http_request_proto = v7_get(v7, Http, "_req", ~0); v7_disown(v7, &Http); }
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; }
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_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; }
void sj_wifi_scan_done(const char **ssids, void *arg) { struct wifi_cb_arg *cba = (struct wifi_cb_arg *) arg; struct v7 *v7 = cba->v7; v7_val_t res = v7_mk_undefined(); const char **p; v7_own(v7, &res); if (ssids != NULL) { res = v7_mk_array(v7); for (p = ssids; *p != NULL; p++) { v7_array_push(v7, res, v7_mk_string(v7, *p, strlen(*p), 1)); } } /* Free the struct in case callback launches a new scan. */ cba->v7 = NULL; v7_disown(v7, &cba->v); sj_invoke_cb1(v7, cba->v, res); v7_disown(v7, &res); }
void Bot::onTimer() { long i, p, chk, chk2, timeNow; TIMER* tmr; for (i = 0; i < _timers.GetLength(); i++) { tmr = (TIMER*)_timers.GetAt(i); timeNow = GetTickCount(); chk = timeNow - tmr->timeBegin; if (chk >= tmr->delay) { v7_apply(v7, *((v7_val_t*)tmr->pToFunc), *v7Obj, v7_mk_undefined(), NULL); if (tmr->repeat != 0) { _timers.DelAt(i--); v7_disown(v7, (v7_val_t*)tmr->pToFunc); delete (v7_val_t*)tmr->pToFunc; delete tmr; } else { tmr->timeBegin = timeNow - (chk - tmr->delay); } } } }
SJ_PRIVATE enum v7_err GPIO_write(struct v7 *v7, v7_val_t *res) { v7_val_t pinv = v7_arg(v7, 0); v7_val_t valv = v7_arg(v7, 1); int pin, val; if (!v7_is_number(pinv)) { printf("non-numeric pin\n"); *res = v7_mk_undefined(); } else { pin = v7_to_number(pinv); /* * We assume 0 if the value is "falsy", * and 1 if the value is "truthy" */ val = !!v7_is_truthy(v7, valv); *res = v7_mk_boolean(sj_gpio_write(pin, val) == 0); } return V7_OK; }
static void gpio_intr_handler_proxy(int pin, int level) { char prop_name[15]; int len; v7_val_t res, args; len = snprintf(prop_name, sizeof(prop_name), "_ih_%d", (int) pin); v7_val_t cb = v7_get(s_v7, v7_get_global(s_v7), prop_name, len); if (!v7_is_callable(s_v7, cb)) { return; } args = v7_mk_array(s_v7); v7_array_push(s_v7, args, v7_mk_number(pin)); v7_array_push(s_v7, args, v7_mk_number(level)); if (v7_apply(s_v7, cb, v7_mk_undefined(), args, &res) != V7_OK) { /* TODO(mkm): make it print stack trace */ fprintf(stderr, "cb threw an exception\n"); } }
static void mqtt_ev_handler(struct mg_connection *nc, int ev, void *ev_data) { struct mg_mqtt_message *msg = (struct mg_mqtt_message *) ev_data; struct user_data *ud = (struct user_data *) nc->user_data; struct v7 *v7 = ud->v7; v7_val_t cb; (void) nc; (void) ev_data; switch (ev) { case MG_EV_CONNECT: if (*(int *) ev_data == 0) { mg_send_mqtt_handshake(nc, ud->client_id); } else { cb = v7_get(v7, ud->client, SJ_MQTT_ERROR_CB, ~0); if (!v7_is_undefined(cb)) { sj_invoke_cb0(v7, cb); } } break; case MG_EV_MQTT_CONNACK: { /* * Call connect or error cb if they were registered. */ const char *key; if (msg->connack_ret_code == MG_EV_MQTT_CONNACK_ACCEPTED) { key = SJ_MQTT_CONNECT_CB; } else { key = SJ_MQTT_ERROR_CB; } cb = v7_get(v7, ud->client, key, ~0); if (!v7_is_undefined(cb)) { sj_invoke_cb0(v7, cb); } break; } case MG_EV_MQTT_PUBLISH: cb = v7_get(v7, ud->client, SJ_MQTT_MESSAGE_CB, ~0); if (!v7_is_undefined(cb)) { v7_val_t topic = v7_mk_string(v7, msg->topic, strlen(msg->topic), 1); v7_val_t payload = v7_mk_string(v7, msg->payload.p, msg->payload.len, 1); sj_invoke_cb2(v7, cb, topic, payload); } break; case MG_EV_CLOSE: /* * Invoke close cb and then destroys all mg state. */ cb = v7_get(v7, ud->client, SJ_MQTT_CLOSE_CB, ~0); if (!v7_is_undefined(cb)) { sj_invoke_cb0(v7, cb); } v7_def(v7, ud->client, "_nc", ~0, _V7_DESC_HIDDEN(1), v7_mk_undefined()); v7_disown(v7, &ud->client); free(ud->client_id); free(ud); break; } }
v7_val_t esp_sj_uart_get_recv_handler(int uart_no) { if (uart_no < 0 || uart_no > 1) return v7_mk_undefined(); return v7_get(sj_us[uart_no].v7, sj_us[uart_no].obj, "_rxcb", 5); }
void sj_wifi_js_init(struct v7 *v7) { s_wifi_changed_cb.v7 = v7; s_wifi_changed_cb.v = v7_mk_undefined(); v7_own(v7, &s_wifi_changed_cb.v); sj_wifi_add_on_change_cb(sj_wifi_on_change_js, &s_wifi_changed_cb); }
void sj_http_api_setup(struct v7 *v7) { v7_val_t Http = v7_mk_undefined(); v7_val_t URL = v7_mk_undefined(); sj_http_server_proto = v7_mk_undefined(); sj_http_response_proto = v7_mk_undefined(); sj_http_request_proto = v7_mk_undefined(); /* * All values are owned temporarily: static values like * `sj_http_server_proto` will be owned later forever, in `sj_http_init()`. * * This is needed to support freezing */ v7_own(v7, &Http); v7_own(v7, &URL); v7_own(v7, &sj_http_server_proto); v7_own(v7, &sj_http_response_proto); v7_own(v7, &sj_http_request_proto); sj_http_server_proto = v7_mk_object(v7); sj_http_response_proto = v7_mk_object(v7); sj_http_request_proto = v7_mk_object(v7); /* NOTE(lsm): setting Http to globals immediately to avoid gc-ing it */ Http = v7_mk_object(v7); v7_set(v7, v7_get_global(v7), "Http", ~0, Http); v7_set(v7, Http, "_serv", ~0, sj_http_server_proto); v7_set(v7, Http, "_resp", ~0, sj_http_response_proto); v7_set(v7, Http, "_req", ~0, sj_http_request_proto); v7_set_method(v7, Http, "createServer", Http_createServer); v7_set_method(v7, Http, "get", Http_get); v7_set_method(v7, Http, "request", Http_createClient); v7_set_method(v7, sj_http_server_proto, "listen", Http_Server_listen); /* Initialize response prototype */ v7_set_method(v7, sj_http_response_proto, "writeHead", Http_response_writeHead); v7_set_method(v7, sj_http_response_proto, "write", Http_response_write); v7_set_method(v7, sj_http_response_proto, "end", Http_response_end); v7_set_method(v7, sj_http_response_proto, "serve", Http_response_serve); /* Initialize request prototype */ v7_set_method(v7, sj_http_request_proto, "write", Http_request_write); v7_set_method(v7, sj_http_request_proto, "end", Http_request_end); v7_set_method(v7, sj_http_request_proto, "abort", Http_request_abort); v7_set_method(v7, sj_http_request_proto, "setTimeout", Http_request_set_timeout); URL = v7_mk_object(v7); v7_set(v7, v7_get_global(v7), "URL", ~0, URL); v7_set_method(v7, URL, "parse", URL_parse); v7_disown(v7, &sj_http_request_proto); v7_disown(v7, &sj_http_response_proto); v7_disown(v7, &sj_http_server_proto); v7_disown(v7, &URL); v7_disown(v7, &Http); }