Пример #1
0
static void invoke_cb(struct user_data *ud, const char *name, v7_val_t ev) {
  struct v7 *v7 = ud->v7;
  v7_val_t met = v7_get(v7, ud->ws, name, ~0);
  if (!v7_is_undefined(met)) {
    sj_invoke_cb1(v7, met, ev);
  }
}
Пример #2
0
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;
}
Пример #3
0
void sj_print_exception(struct v7 *v7, v7_val_t exc, const char *msg) {
  /*
   * TOD(mkm) add some API to hal to fetch the current debug mode
   * and avoid logging to stdout if according no error messages should go
   * there (e.g. because it's used to implement a serial protocol).
   */
  FILE *fs[] = {stdout, stderr};
  size_t i;
  v7_val_t msg_v = V7_UNDEFINED;

  /*
   * own because the exception could be a string,
   * and if not owned here, print_stack_trace could get
   * an unrelocated argument an ASN violation.
   */
  v7_own(v7, &exc);
  v7_own(v7, &msg_v);

  msg_v = v7_get(v7, exc, "message", ~0);

  for (i = 0; i < sizeof(fs) / sizeof(fs[0]); i++) {
    fprintf(fs[i], "%s: ", msg);
    if (!v7_is_undefined(msg_v)) {
      v7_fprintln(fs[i], v7, msg_v);
    } else {
      v7_fprintln(fs[i], v7, exc);
    }
    v7_fprint_stack_trace(fs[i], v7, exc);
  }

  v7_disown(v7, &msg_v);
  v7_disown(v7, &exc);
}
Пример #4
0
static v7_val_t WebSocket_readyState(struct v7 *v7, v7_val_t this_obj,
                                     v7_val_t args) {
  v7_val_t ncv = v7_get(v7, this_obj, "_nc", ~0);
  if (v7_is_undefined(ncv)) {
    return WEBSOCKET_CLOSED;
  } else {
    return WEBSOCKET_OPEN;
  }
}
Пример #5
0
static void Http_write_data(struct v7 *v7, struct mg_connection *c) {
  v7_val_t arg0 = v7_arg(v7, 0);
  if (!v7_is_undefined(arg0)) {
    char buf[50], *p = buf;
    p = v7_stringify(v7, arg0, buf, sizeof(buf), 0);
    mg_send_http_chunk(c, p, strlen(p));
    if (p != buf) {
      free(p);
    }
  }
}
Пример #6
0
static void invoke_cb(struct user_data *ud, const char *name, v7_val_t ev) {
  struct v7 *v7 = ud->v7;
  v7_val_t met = v7_get(v7, ud->ws, name, ~0);
  if (!v7_is_undefined(met)) {
    v7_val_t res, args = v7_create_array(v7);
    v7_array_set(v7, args, 0, ev);
    if (v7_apply(v7, &res, met, v7_create_undefined(), args) != V7_OK) {
      /* TODO(mkm): make it print stack trace */
      fprintf(stderr, "cb threw an exception\n");
    }
  }
}
Пример #7
0
enum v7_err fill_ssl_connect_opts(struct v7 *v7, v7_val_t opts, int force_ssl,
                                  struct mg_connect_opts *copts) {
  enum v7_err rcode = V7_OK;

  v7_val_t v_use_ssl = v7_get(v7, opts, "use_ssl", ~0);
  v7_val_t v_ca_cert = v7_get(v7, opts, "ssl_ca_cert", ~0);
  v7_val_t v_cert = v7_get(v7, opts, "ssl_cert", ~0);
  v7_val_t v_server_name = v7_get(v7, opts, "ssl_server_name", ~0);

  if (!v7_is_undefined(v_ca_cert) && !v7_is_string(v_ca_cert)) {
    rcode = v7_throwf(v7, "TypeError", "ssl_ca_cert must be a string");
    goto clean;
  }
  if (!v7_is_undefined(v_cert) && !v7_is_string(v_cert)) {
    rcode = v7_throwf(v7, "TypeError", "ssl_cert must be a string");
    goto clean;
  }
  if (!v7_is_undefined(v_server_name) && !v7_is_string(v_server_name)) {
    rcode = v7_throwf(v7, "TypeError", "ssl_server_name must be a string");
    goto clean;
  }

  copts->ssl_ca_cert = v7_get_cstring(v7, &v_ca_cert);
  copts->ssl_cert = v7_get_cstring(v7, &v_cert);
  copts->ssl_server_name = v7_get_cstring(v7, &v_server_name);

  if ((force_ssl ||
       (v7_is_boolean(v_use_ssl) && v7_get_bool(v7, v_use_ssl) != 0)) &&
      copts->ssl_ca_cert == NULL) {
    /* Defaults to configuration */
    copts->ssl_ca_cert = get_cfg()->tls.ca_file;
  }

clean:
  return rcode;
}
Пример #8
0
size_t sj_uart_recv_cb(void *ctx, const char *d, size_t len) {
  struct user_data *ud = (struct user_data *) ctx;
  v7_val_t s, cb = ud->cb;
  size_t want = ud->want;

  if (len < want || v7_is_undefined(ud->cb)) return 0;

  ud->cb = v7_create_undefined();
  ud->want = 0;

  s = v7_create_string(ud->v7, d, want, 1);
  sj_invoke_cb1(ud->v7, cb, s);

  return want;
}
Пример #9
0
/* 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;
}
Пример #10
0
static int notify_js(enum js_update_status us, const char *info) {
#ifndef CS_DISABLE_JS
  if (!v7_is_undefined(s_updater_notify_cb)) {
    if (info == NULL) {
      sj_invoke_cb1(s_v7, s_updater_notify_cb, v7_mk_number(s_v7, us));
    } else {
      sj_invoke_cb2(s_v7, s_updater_notify_cb, v7_mk_number(s_v7, us),
                    v7_mk_string(s_v7, info, ~0, 1));
    };

    return 1;
  }
#else
  (void) us;
  (void) info;
#endif

  return 0;
}
Пример #11
0
int update_sysconf(struct v7 *v7, const char *path, v7_val_t val) {
  v7_val_t sys = v7_get(v7, v7_get_global(v7), "Sys", ~0);
  if (!v7_is_object(sys)) {
    return 1;
  }

  v7_val_t conf = v7_get(v7, sys, "conf", ~0);
  if (!v7_is_object(conf)) {
    return 1;
  }

  v7_val_t prev_obj, curr_obj;
  prev_obj = curr_obj = conf;

  const char *prev_tok, *curr_tok;
  prev_tok = curr_tok = path;

  for (;;) {
    while (*curr_tok != 0 && *curr_tok != '.') {
      curr_tok++;
    }
    curr_obj = v7_get(v7, prev_obj, prev_tok, (curr_tok - prev_tok));
    if (v7_is_undefined(curr_obj)) {
      return 1;
    } else if (!v7_is_object(curr_obj)) {
      v7_set(v7, prev_obj, prev_tok, (curr_tok - prev_tok), val);
      return 0;
    }
    if (*curr_tok == 0) {
      return 1;
    }
    curr_tok++;
    prev_tok = curr_tok;
    prev_obj = curr_obj;
  }

  return 1;
}
Пример #12
0
static void _WebSocket_send_blob(struct v7 *v7, struct mg_connection *nc,
                                 v7_val_t blob) {
  const char *data;
  size_t len;
  unsigned long alen, i;
  v7_val_t chunks, chunk;

  chunks = v7_get(v7, blob, "a", ~0);
  alen = v7_array_length(v7, chunks);

  for (i = 0; i < alen; i++) {
    int op = i == 0 ? WEBSOCKET_OP_BINARY : WEBSOCKET_OP_CONTINUE;
    int flag = i == alen - 1 ? 0 : WEBSOCKET_DONT_FIN;

    chunk = v7_array_get(v7, chunks, i);
    /*
     * This hack allows us to skip the first or the last frame
     * while sending blobs. The effect of it is that it's possible to
     * concatenate more blobs into a single WS message composed of
     * several fragments.
     *
     * WebSocket.send(new Blob(["123", undefined]));
     * WebSocket.send(new Blob([undefined, "456"]));
     *
     * If the last blob component is undefined, the current message is thus
     * left open. In order to continue sending fragments of the same message
     * the next send call should have it's first component undefined.
     *
     * TODO(mkm): find a better API.
     */
    if (!v7_is_undefined(chunk)) {
      data = v7_to_string(v7, &chunk, &len);
      mg_send_websocket_frame(nc, op | flag, data, len);
    }
  }
}
Пример #13
0
/*
 * Create request object, used by `Http.request()` and `Http.get()`
 */
WARN_UNUSED_RESULT
static enum v7_err sj_http_request_common(struct v7 *v7, v7_val_t opts,
                                          v7_val_t cb, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  char addr[200];
  struct mg_connection *c;
  struct user_data *ud;
  struct mg_connect_opts copts;
#ifdef MG_ENABLE_SSL
  int force_ssl;
#endif

  memset(&copts, 0, sizeof(copts));
  /*
   * Determine type of provided `opts`, and if it's a string, then parse
   * it to object
   */
  if (v7_is_string(opts)) {
    rcode = sj_url_parse(v7, opts, &opts);
    if (rcode != V7_OK) {
      goto clean;
    }
  } else if (!v7_is_object(opts)) {
    rcode = v7_throwf(v7, "Error", "opts must be an object or a string URL");
    goto clean;
  }

  /*
   * Now, `opts` is guaranteed to be an object.
   * Let's retrieve needed properties
   */
  v7_val_t v_h = v7_get(v7, opts, "hostname", ~0);
  if (v7_is_undefined(v_h)) {
    v_h = v7_get(v7, opts, "host", ~0);
  }
  v7_val_t v_p = v7_get(v7, opts, "port", ~0);
  v7_val_t v_uri = v7_get(v7, opts, "path", ~0);
  v7_val_t v_m = v7_get(v7, opts, "method", ~0);
  v7_val_t v_hdrs = v7_get(v7, opts, "headers", ~0);

  /* Perform options validation and set defaults if needed */
  int port = v7_is_number(v_p) ? v7_to_number(v_p) : 80;
  const char *host = v7_is_string(v_h) ? v7_to_cstring(v7, &v_h) : "";
  const char *uri = v7_is_string(v_uri) ? v7_to_cstring(v7, &v_uri) : "/";
  const char *method = v7_is_string(v_m) ? v7_to_cstring(v7, &v_m) : "GET";

#ifdef MG_ENABLE_SSL
  v7_val_t v_pr = v7_get(v7, opts, "protocol", ~0);
  const char *protocol = v7_is_string(v_pr) ? v7_to_cstring(v7, &v_pr) : "";
  force_ssl = (strcasecmp(protocol, "https") == 0);
  if ((rcode = fill_ssl_connect_opts(v7, opts, force_ssl, &copts)) != V7_OK) {
    goto clean;
  }
#endif

  /* Compose address like host:port */
  snprintf(addr, sizeof(addr), "%s:%d", host, port);

  /*
   * Try to connect, passing `http_ev_handler` as the callback, which will
   * call provided JavaScript function (we'll set it in user data below).
   * TODO(alashkin): change mg_connect_opt to mg_connect_http_opt
   */
  if ((c = mg_connect_opt(&sj_mgr, addr, http_ev_handler, copts)) == NULL) {
    rcode = v7_throwf(v7, "Error", "Cannot connect");
    goto clean;
  }

  /*
   * Attach mongoose's built-in HTTP event handler to the connection, and send
   * necessary headers
   */
  mg_set_protocol_http_websocket(c);
  mg_printf(c, "%s %s HTTP/1.1\r\n", method, uri);
  mg_printf(c, "Host: %s\r\n", host);
  http_write_headers(v7, v_hdrs, c);
  http_write_chunked_encoding_header(c);
  mg_printf(c, "%s", "\r\n");

  /*
   * Allocate and initialize user data structure that is used by the JS HTTP
   * interface. Create the request object (which will have the request
   * prototype `sj_http_request_proto`), and set provided callback function.
   */
  c->user_data = ud = (struct user_data *) calloc(1, sizeof(*ud));

  ud->v7 = v7;
  ud->obj = v7_mk_object(v7);
  ud->handler = cb;

  v7_own(v7, &ud->obj);
  v7_set_proto(v7, ud->obj, sj_http_request_proto);

  /* internal property: mongoose connection */
  v7_set(v7, ud->obj, "_c", ~0, v7_mk_foreign(c));

  /* internal property: callback function that was passed as an argument */
  v7_set(v7, ud->obj, "_cb", ~0, ud->handler);

  *res = ud->obj;

clean:
  return rcode;
}
Пример #14
0
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_UNDEFINED);
      v7_disown(v7, &ud->client);
      free(ud->client_id);
      free(ud);
      break;
  }
}
Пример #15
0
/*
 * Make a new MQTT client.
 *
 * Arguments:
 * url: url where to connect to
 * opts: option object
 *
 * Recognized option object properties:
 *
 * - clientId: string; mqtt client id. defaults to
 *             Math.random().toString(16).substr(2, 10)
 *
 * Example:
 *
 * var client = MQTT.connect('mqtt://test.mosquitto.org');
 *
 * client.on('connect', function () {
 *   client.subscribe('presence');
 *   client.publish('presence', 'Hello mqtt');
 * });
 *
 * client.on('message', function (topic, message) {
 *   console.log(message);
 * });
 *
 * TLS can be enabled by choosing the `mqtts://` protocol. In that
 * case the default port is 8883 as defined by IANA.
 *
 * The API is modeled after https://www.npmjs.com/package/mqtt.
 *
 */
enum v7_err sj_mqtt_connect(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  const char *url;
  size_t len;
  struct mg_str host, scheme;
  unsigned int port;
  struct mg_connection *nc;
  struct user_data *ud;
  char *url_with_port = NULL;
  int use_ssl = 0;
  v7_val_t urlv = v7_arg(v7, 0), opts = v7_arg(v7, 1);
  v7_val_t client_id;
  v7_val_t proto =
      v7_get(v7, v7_get(v7, v7_get_global(v7), "MQTT", ~0), "proto", ~0);

  if (!v7_is_string(urlv)) {
    rcode = v7_throwf(v7, "Error", "invalid url string");
    goto clean;
  }

  url = v7_get_string(v7, &urlv, &len);

  if (mg_parse_uri(mg_mk_str(url), &scheme, NULL, &host, &port, NULL, NULL,
                   NULL) < 0) {
    rcode = v7_throwf(v7, "Error", "invalid url string");
    goto clean;
  }

  if (mg_vcmp(&scheme, "mqtt") == 0) {
    url += sizeof("mqtt://") - 1;
  } else if (mg_vcmp(&scheme, "mqtts") == 0) {
    url += sizeof("mqtts://") - 1;
    use_ssl = 1;
  } else {
    rcode = v7_throwf(v7, "Error", "unsupported protocol");
    goto clean;
  }

  client_id = v7_get(v7, opts, "clientId", ~0);
  if (v7_is_undefined(client_id)) {
    rcode = v7_exec(v7, "Math.random().toString(16).substr(2,8)", &client_id);
    if (rcode != V7_OK) {
      goto clean;
    }
  }

  if (port == 0) {
    if (asprintf(&url_with_port, "%.*s%s", (int) host.len, host.p,
                 (use_ssl ? ":8883" : ":1883")) < 0) {
      rcode = v7_throwf(v7, "Error", "Out of memory");
      goto clean;
    }
  }

  nc =
      mg_connect(&sj_mgr, url_with_port ? url_with_port : url, mqtt_ev_handler);
  if (nc == NULL) {
    rcode = v7_throwf(v7, "Error", "cannot create connection");
    goto clean;
  }

  if (use_ssl) {
#ifdef MG_ENABLE_SSL
    mg_set_ssl(nc, NULL, NULL);
#else
    rcode = v7_throwf(v7, "Error", "SSL not enabled");
    goto clean;
#endif
  }
  mg_set_protocol_mqtt(nc);

  *res = v7_mk_object(v7);
  v7_set_proto(v7, *res, proto);

  ud = calloc(1, sizeof(*ud));
  if (ud == NULL) {
    rcode = v7_throwf(v7, "Error", "Out of memory");
    goto clean;
  }
  ud->v7 = v7;
  ud->client = *res;
  ud->client_id = strdup(v7_get_cstring(v7, &client_id));
  if (ud->client_id == NULL) {
    free(ud);
    rcode = v7_throwf(v7, "Error", "Out of memory");
    goto clean;
  }
  nc->user_data = ud;
  v7_own(v7, &ud->client);

  v7_def(v7, *res, "_nc", ~0, _V7_DESC_HIDDEN(1), v7_mk_foreign(v7, nc));

clean:
  free(url_with_port);

  return rcode;
}
Пример #16
0
/*
 * SmartJS initialization, called as an SDK timer callback (`os_timer_...()`).
 */
void sjs_init(void *dummy) {
  /*
   * In order to see debug output (at least errors) during boot we have to
   * initialize debug in this point. But default we put debug to UART0 with
   * level=LL_ERROR, then configuration is loaded this settings are overridden
   */
  {
    struct esp_uart_config *u0cfg = esp_sj_uart_default_config(0);
#if ESP_DEBUG_UART == 0
    u0cfg->baud_rate = ESP_DEBUG_UART_BAUD_RATE;
#endif
    esp_uart_init(u0cfg);
    struct esp_uart_config *u1cfg = esp_sj_uart_default_config(1);
    /* UART1 has no RX pin, no point in allocating a buffer. */
    u1cfg->rx_buf_size = 0;
#if ESP_DEBUG_UART == 1
    u1cfg->baud_rate = ESP_DEBUG_UART_BAUD_RATE;
#endif
    esp_uart_init(u1cfg);
    fs_set_stdout_uart(0);
    fs_set_stderr_uart(ESP_DEBUG_UART);
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stderr, NULL, _IONBF, 0);
    cs_log_set_level(LL_DEBUG);
    os_install_putc1(dbg_putc);
    system_set_os_print(1);
#ifdef ESP_ENABLE_HEAP_LOG
    uart_initialized = 1;
#endif
  }

  init_v7(&dummy);
  /* disable GC during further initialization */
  v7_set_gc_enabled(v7, 0);

  esp_sj_uart_init(v7);

#ifndef V7_NO_FS
#ifndef DISABLE_OTA
  fs_init(get_fs_addr(get_current_rom()), get_fs_size(get_current_rom()));
  finish_update();
#else
  fs_init(FS_ADDR, FS_SIZE);
#endif
#endif

  sj_common_api_setup(v7);
  sj_common_init(v7);

  sj_init_sys(v7);

  mongoose_init();

  /* NOTE(lsm): must be done after mongoose_init(). */
  if (!init_device(v7)) {
    LOG(LL_ERROR, ("init_device failed"));
    abort();
  }

  esp_print_reset_info();

#ifndef DISABLE_OTA
  init_updater(v7);
#endif
  LOG(LL_INFO, ("Sys init done, SDK %s", system_get_sdk_version()));

  if (!sj_app_init(v7)) {
    LOG(LL_ERROR, ("App init failed"));
    abort();
  }
  LOG(LL_INFO, ("App init done"));

  /* SJS initialized, enable GC back, and trigger it */
  v7_set_gc_enabled(v7, 1);
  v7_gc(v7, 1);

#ifndef V7_NO_FS
  run_init_script();
#endif

  /* Install prompt if enabled in the config and user's app has not installed
   * a custom RX handler. */
  if (get_cfg()->debug.enable_prompt &&
      v7_is_undefined(esp_sj_uart_get_recv_handler(0))) {
    sj_prompt_init(v7);
    esp_sj_uart_set_prompt(0);
  }

#ifdef ESP_UMM_ENABLE
  /*
   * We want to use our own heap functions instead of the ones provided by the
   * SDK.
   *
   * We have marked `pvPortMalloc` and friends weak, so that we can override
   * them with our own implementations, but to actually make it work, we have
   * to reference any function from the file with our implementation, so that
   * linker will not garbage-collect the whole compilation unit.
   *
   * So, we have a call to the no-op `esp_umm_init()` here.
   */
  esp_umm_init();
#endif
}
Пример #17
0
void wifi_changed_cb(System_Event_t *evt) {
  enum sj_wifi_status sj_ev = -1;

  /* TODO(rojer): Share this logic between platforms. */
  if (wifi_setting_up &&
#ifndef RTOS_SDK
      evt->event == EVENT_STAMODE_GOT_IP
#else
      evt->event_id == EVENT_STAMODE_GOT_IP
#endif
      ) {
    struct station_config config;
    v7_val_t res;
    v7_val_t conf = v7_get(v7, v7_get_global_object(v7), "conf", ~0);
    v7_val_t known, wifi;

    if (v7_is_undefined(conf)) {
      fprintf(stderr, "cannot save conf, no conf object\n");
      return;
    }
    wifi = v7_get(v7, conf, "wifi", ~0);

    if (v7_is_undefined(wifi)) {
      wifi = v7_create_object(v7);
      v7_set(v7, conf, "wifi", ~0, 0, wifi);
    }
    known = v7_get(v7, conf, "known", ~0);
    if (v7_is_undefined(known)) {
      known = v7_create_object(v7);
      v7_set(v7, wifi, "known", ~0, 0, known);
    }

    wifi_station_get_config(&config);

    v7_set(v7, known, (const char *) config.ssid, ~0, 0,
           v7_create_string(v7, (const char *) config.password,
                            strlen((const char *) config.password), 1));

    v7_exec(v7, "conf.save()", &res);
    wifi_setting_up = 0;
  }

#ifndef RTOS_SDK
  switch (evt->event) {
#else
  switch (evt->event_id) {
#endif
    case EVENT_STAMODE_DISCONNECTED:
      sj_ev = SJ_WIFI_DISCONNECTED;
      break;
    case EVENT_STAMODE_CONNECTED:
      sj_ev = SJ_WIFI_CONNECTED;
      break;
    case EVENT_STAMODE_GOT_IP:
      sj_ev = SJ_WIFI_IP_ACQUIRED;
      break;
  }

  if (sj_ev >= 0) sj_wifi_on_change_callback(sj_ev);
}

char *sj_wifi_get_connected_ssid() {
  struct station_config conf;
  if (!wifi_station_get_config(&conf)) return NULL;
  return strdup((const char *) conf.ssid);
}

char *sj_wifi_get_sta_ip() {
  struct ip_info info;
  char *ip;
  if (!wifi_get_ip_info(0, &info) || info.ip.addr == 0) return NULL;
  if (asprintf(&ip, IPSTR, IP2STR(&info.ip)) < 0) {
    return NULL;
  }
  return ip;
}

void wifi_scan_done(void *arg, STATUS status) {
  if (status == OK) {
    STAILQ_HEAD(, bss_info) *info = arg;
    struct bss_info *p;
    const char **ssids;
    int n = 0;
    STAILQ_FOREACH(p, info, next) n++;
    ssids = calloc(n + 1, sizeof(*ssids));
    n = 0;
    STAILQ_FOREACH(p, info, next) {
      ssids[n++] = (const char *) p->ssid;
    }
    wifi_scan_cb(ssids);
    free(ssids);
  } else {
Пример #18
0
/* 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);
}
Пример #19
0
void sj_wifi_on_change_callback(enum sj_wifi_status event) {
  struct v7 *v7 = s_v7;
  v7_val_t cb = v7_get(v7, s_wifi, "_ccb", ~0);
  if (v7_is_undefined(cb) || v7_is_null(cb)) return;
  sj_invoke_cb1(s_v7, cb, v7_create_number(event));
}