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; }
/* * 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; } } }
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 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; }
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 *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; /* ignore unused because of CS_DISABLE_JS below */ (void) tx_used_before; esp_uart_dispatch_tx_top(uart_no); #ifndef CS_DISABLE_JS cs_rbuf_t *rxb = esp_uart_rx_buf(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_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_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); } } } } #endif esp_uart_dispatch_bottom(uart_no); }
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; }
/* 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 Updater_notify(struct v7 *v7, v7_val_t *res) { v7_val_t cb = v7_arg(v7, 0); if (!v7_is_callable(v7, cb)) { printf("Invalid arguments\n"); *res = v7_mk_boolean(v7, 0); return V7_OK; } s_updater_notify_cb = cb; *res = v7_mk_boolean(v7, 1); return V7_OK; }
SJ_PRIVATE enum v7_err Http_createServer(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t cb = v7_arg(v7, 0); if (!v7_is_callable(v7, cb)) { rcode = v7_throwf(v7, "Error", "Invalid argument"); goto clean; } *res = v7_mk_object(v7); v7_set_proto(v7, *res, sj_http_server_proto); v7_set(v7, *res, "_cb", ~0, cb); clean: return rcode; }
SJ_PRIVATE enum v7_err Wifi_changed(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t cb = v7_arg(v7, 0); if (!v7_is_callable(v7, cb) && !v7_is_null(cb)) { *res = v7_mk_boolean(v7, 0); goto clean; } v7_disown(s_wifi_changed_cb.v7, &s_wifi_changed_cb.v); s_wifi_changed_cb.v7 = v7; s_wifi_changed_cb.v = cb; v7_own(s_wifi_changed_cb.v7, &s_wifi_changed_cb.v); *res = v7_mk_boolean(v7, 1); goto clean; clean: return rcode; }
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 void gpio_intr_handler_proxy(int pin, enum gpio_level level, void *arg) { struct v7 *v7 = (struct v7 *) arg; char prop_name[15]; int len; len = snprintf(prop_name, sizeof(prop_name), "_ih_%d", (int) pin); v7_val_t cb = v7_get(v7, v7_get_global(v7), prop_name, len); if (!v7_is_callable(v7, cb)) { return; } /* Forwarding call to common cbs queue */ v7_val_t args = v7_mk_array(v7); v7_array_push(v7, args, v7_mk_number(v7, pin)); v7_array_push(v7, args, v7_mk_number(v7, level)); sj_invoke_cb2(v7, s_isr_cb_proxy_v, cb, args); }
/* Call the callback with a list of ssids found in the air. */ SJ_PRIVATE enum v7_err Wifi_scan(struct v7 *v7, v7_val_t *res) { v7_val_t cb; if (s_wifi_scan_cb.v7 != NULL) { return v7_throwf(v7, "Error", "scan in progress"); } cb = v7_arg(v7, 0); if (!v7_is_callable(v7, cb)) { return v7_throwf(v7, "Error", "Invalid argument"); } s_wifi_scan_cb.v7 = v7; s_wifi_scan_cb.v = cb; v7_own(v7, &s_wifi_scan_cb.v); sj_wifi_scan(sj_wifi_scan_done, &s_wifi_scan_cb); (void) res; return V7_OK; }
/* Currently can only handle one timer */ static enum v7_err global_set_timeout(struct v7 *v7, v7_val_t *res) { v7_val_t *cb; v7_val_t msecsv = v7_arg(v7, 1); int msecs; (void) res; cb = (v7_val_t *) malloc(sizeof(*cb)); v7_own(v7, cb); *cb = v7_arg(v7, 0); if (!v7_is_callable(v7, *cb)) { printf("cb is not a function\n"); } else if (!v7_is_number(msecsv)) { printf("msecs is not a double\n"); } else { msecs = v7_to_number(msecsv); sj_set_timeout(msecs, cb); } 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 enum v7_err jsBotEvent(struct v7* v7, v7_val_t* res) { v7_val_t val = v7_arg(v7, 0); TString strEvent = (const char*)v7_to_cstring(v7, &val); v7_val_t* func = new v7_val_t; v7_own(v7, func); *func = v7_arg(v7, 1); //if not a function type in 2nd argument if (!v7_is_callable(v7, *func)) { //TODO: throw error return V7_OK; } else { } if (strEvent.IsEQNC(L"text")) { _activeBot->_onTexts.Add(func); } else if (strEvent.IsEQNC(L"join")) { _activeBot->_onJoin.Add(func); } else if (strEvent.IsEQNC(L"left")) { _activeBot->_onLeft.Add(func); } else if (strEvent.IsEQNC(L"talk")) { _activeBot->_onTalk.Add(func); } else if (strEvent.IsEQNC(L"motd")) { _activeBot->_onMotd.Add(func); } else if (strEvent.IsEQNC(L"im")) { _activeBot->_onIm.Add(func); } return V7_OK; }
void sj_wifi_on_change_js(enum sj_wifi_status event, void *arg) { struct wifi_cb_arg *cba = (struct wifi_cb_arg *) arg; if (v7_is_callable(cba->v7, cba->v)) { sj_invoke_cb1(cba->v7, cba->v, v7_mk_number(cba->v7, event)); } }