static enum v7_err UART_configure(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; struct esp_uart_config *cfg = esp_sj_uart_default_config(us->uart_no); v7_val_t cobj = v7_arg(v7, 0); if (v7_is_object(cobj)) { v7_val_t v; #define NUM_PROP(p) \ v = v7_get(v7, cobj, #p, ~0); \ if (v7_is_number(v)) cfg->p = v7_to_number(v); #define BOOL_PROP(p) \ v = v7_get(v7, cobj, #p, ~0); \ if (!v7_is_undefined(v)) cfg->p = v7_to_boolean(v); NUM_PROP(baud_rate); NUM_PROP(rx_buf_size); BOOL_PROP(rx_fc_ena); NUM_PROP(rx_fifo_full_thresh); NUM_PROP(rx_fifo_fc_thresh); NUM_PROP(rx_fifo_alarm); NUM_PROP(rx_linger_micros); NUM_PROP(tx_buf_size); BOOL_PROP(tx_fc_ena); NUM_PROP(tx_fifo_empty_thresh); NUM_PROP(tx_fifo_full_thresh); BOOL_PROP(swap_rxtx_ctsrts); NUM_PROP(status_interval_ms); } if (esp_uart_init(cfg)) { esp_sj_uart_schedule_dispatcher(cfg->uart_no); *res = v7_mk_boolean(1); } else { free(cfg); *res = v7_mk_boolean(0); } return V7_OK; }
static enum v7_err Sys_setLogLevel(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t llv = v7_arg(v7, 0); int ll; if (!v7_is_number(llv)) { *res = v7_mk_boolean(0); goto clean; } ll = v7_to_number(llv); if (ll <= _LL_MIN || ll >= _LL_MAX) { *res = v7_mk_boolean(0); goto clean; } cs_log_set_level((enum cs_log_level) ll); *res = v7_mk_boolean(1); goto clean; clean: return rcode; }
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 UART_write(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), data = v7_arg(v7, 0); size_t len; const char *d = v7_get_string(v7, &data, &len); (void) v7; (void) this_obj; sj_hal_write_uart(v7_get_ptr(v7, dev), d, len); *res = v7_mk_boolean(v7, 1); return V7_OK; }
SJ_PRIVATE enum v7_err Http_response_write(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; DECLARE_CONN(); if (!v7_is_truthy(v7, v7_get(v7, v7_get_this(v7), "_whd", ~0))) { write_http_status(c, 200); mg_send(c, "\r\n", 2); v7_set(v7, v7_get_this(v7), "_whd", ~0, v7_mk_boolean(1)); } Http_write_data(v7, c); *res = v7_get_this(v7); clean: return rcode; }
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; }
/* * 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_get_double(v7, wantv) : (size_t) ~0; struct user_data *ud = (struct user_data *) v7_get_ptr(v7, udv); ud->cb = cb; v7_own(v7, &ud->cb); ud->want = want; /* TODO(mkm): trigger cb if there is already something in the buffer */ *res = v7_mk_boolean(v7, 1); return V7_OK; }
static enum v7_err Updater_startupdate(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t manifest_url_v = v7_arg(v7, 0); if (!v7_is_string(manifest_url_v)) { rcode = v7_throwf(v7, "Error", "URL is not a string"); } else { struct update_context *ctx = updater_context_create(); if (ctx == NULL) { rcode = v7_throwf(v7, "Error", "Failed to init updater"); } else if (start_update_download(ctx, v7_get_cstring(v7, &manifest_url_v)) < 0) { rcode = v7_throwf(v7, "Error", ctx->status_msg); } } *res = v7_mk_boolean(v7, rcode == V7_OK); 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\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; }
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; }
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_UNDEFINED; } else { pin = v7_get_double(v7, 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( v7, sj_gpio_write(pin, val ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW) == 0); } return V7_OK; }
SJ_PRIVATE enum v7_err Wifi_disconnect(struct v7 *v7, v7_val_t *res) { (void) v7; *res = v7_mk_boolean(v7, sj_wifi_disconnect()); return V7_OK; }
/* Callback for json_walk() */ static void frozen_cb(void *data, const char *name, size_t name_len, const char *path, const struct json_token *token) { struct json_parse_ctx *ctx = (struct json_parse_ctx *) data; v7_val_t v = V7_UNDEFINED; (void) path; v7_own(ctx->v7, &v); switch (token->type) { case JSON_TYPE_STRING: v = v7_mk_string(ctx->v7, token->ptr, token->len, 1 /* copy */); break; case JSON_TYPE_NUMBER: v = v7_mk_number(ctx->v7, cs_strtod(token->ptr, NULL)); break; case JSON_TYPE_TRUE: v = v7_mk_boolean(ctx->v7, 1); break; case JSON_TYPE_FALSE: v = v7_mk_boolean(ctx->v7, 0); break; case JSON_TYPE_NULL: v = V7_NULL; break; case JSON_TYPE_OBJECT_START: v = v7_mk_object(ctx->v7); break; case JSON_TYPE_ARRAY_START: v = v7_mk_array(ctx->v7); break; case JSON_TYPE_OBJECT_END: case JSON_TYPE_ARRAY_END: { /* Object or array has finished: deallocate its frame */ ctx->frame = free_json_frame(ctx, ctx->frame); } break; default: LOG(LL_ERROR, ("Wrong token type %d\n", token->type)); break; } if (!v7_is_undefined(v)) { if (name != NULL && name_len != 0) { /* Need to define a property on the current object/array */ if (v7_is_object(ctx->frame->val)) { v7_set(ctx->v7, ctx->frame->val, name, name_len, v); } else if (v7_is_array(ctx->v7, ctx->frame->val)) { /* * TODO(dfrank): consult name_len. Currently it's not a problem due to * the implementation details of frozen, but it might change */ int idx = (int) cs_strtod(name, NULL); v7_array_set(ctx->v7, ctx->frame->val, idx, v); } else { LOG(LL_ERROR, ("Current value is neither object nor array\n")); } } else { /* This is a root value */ assert(ctx->frame == NULL); /* * This value will also be the overall result of JSON parsing * (it's already owned by the `v7_alt_json_parse()`) */ ctx->result = v; } if (token->type == JSON_TYPE_OBJECT_START || token->type == JSON_TYPE_ARRAY_START) { /* New object or array has just started, so we need to allocate a frame * for it */ struct json_parse_frame *new_frame = alloc_json_frame(ctx, v); new_frame->up = ctx->frame; ctx->frame = new_frame; } } v7_disown(ctx->v7, &v); }