Exemple #1
0
/*
 * Publishes a message to a topic.
 *
 * Args:
 * - `topic`: topic, string.
 * - `message`: message, string.
 *
 * Only QOS 0 is implemented at the moment.
 */
enum v7_err MQTT_publish(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  struct user_data *ud;
  struct mg_connection *nc;
  const char *topic;
  const char *message;
  size_t message_len;
  v7_val_t topicv = v7_arg(v7, 0), messagev = v7_arg(v7, 1);
  (void) res;

  topic = v7_get_cstring(v7, &topicv);
  if (topic == NULL || strlen(topic) == 0) {
    rcode = v7_throwf(v7, "TypeError", "invalid topic");
    goto clean;
  }

  if (!v7_is_string(messagev)) {
    rcode = v7_throwf(v7, "TypeError", "invalid message");
    goto clean;
  }
  message = v7_get_string(v7, &messagev, &message_len);

  nc = v7_get_ptr(v7, v7_get(v7, v7_get_this(v7), "_nc", ~0));
  if (nc == NULL) {
    rcode = v7_throwf(v7, "Error", "invalid connection");
    goto clean;
  }
  ud = (struct user_data *) nc->user_data;

  mg_mqtt_publish(nc, topic, ud->msgid++, MG_MQTT_QOS(0), message, message_len);

clean:
  return rcode;
}
Exemple #2
0
/*
 * Usage:
 *
 * new UART("platform_specific_name")
 *
 */
static enum v7_err UART_ctor(struct v7 *v7, v7_val_t *res) {
  (void) res;
  enum v7_err rcode = V7_OK;
  v7_val_t this_obj = v7_get_this(v7);
  v7_val_t dev = v7_arg(v7, 0);
  struct user_data *ud;
  void *uart;
  const char *name;
  size_t len;

  if (!v7_is_string(dev)) {
    rcode = v7_throwf(v7, "Error", "device must be string");
    goto clean;
  }

  ud = (struct user_data *) calloc(1, sizeof(struct user_data));
  ud->v7 = v7;
  ud->want = 0;
  ud->cb = V7_UNDEFINED;
  v7_own(v7, &ud->cb);

  name = v7_get_string(v7, &dev, &len);
  uart = sj_hal_open_uart(name, (void *) ud);
  if (uart == NULL) {
    rcode = v7_throwf(v7, "Error", "cannot open uart");
    goto clean;
  }

  v7_def(v7, this_obj, "_ud", ~0, _V7_DESC_HIDDEN(1), v7_mk_foreign(v7, ud));
  v7_def(v7, this_obj, "_dev", ~0, _V7_DESC_HIDDEN(1), v7_mk_foreign(v7, uart));

clean:
  return rcode;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
static enum v7_err UART_send(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_val_t arg0 = v7_arg(v7, 0);
  if (!v7_is_string(arg0)) {
    return v7_throwf(v7, "Error", "String arg required");
  }
  size_t len = 0;
  const char *data = v7_get_string(v7, &arg0, &len);
  if (data != NULL && len > 0) {
    cs_rbuf_t *txb = esp_uart_tx_buf(us->uart_no);
    len = MIN(len, txb->avail);
    cs_rbuf_append(txb, (uint8_t *) data, len);
    esp_sj_uart_schedule_dispatcher(us->uart_no);
  }
  *res = v7_mk_number(v7, len);
  return V7_OK;
}
Exemple #6
0
/*
 * Alternative implementation of JSON.parse(), needed when v7 parser is
 * disabled
 */
enum v7_err v7_alt_json_parse(struct v7 *v7, v7_val_t json_string,
                              v7_val_t *res) {
  struct json_parse_ctx *ctx =
      (struct json_parse_ctx *) calloc(sizeof(struct json_parse_ctx), 1);
  size_t len;
  const char *str = v7_get_string(v7, &json_string, &len);
  int json_res;
  enum v7_err rcode = V7_OK;

  ctx->v7 = v7;
  ctx->result = V7_UNDEFINED;
  ctx->frame = NULL;

  v7_own(v7, &ctx->result);

  json_res = json_walk(str, len, frozen_cb, ctx);

  if (json_res >= 0) {
    /* Expression is parsed successfully */
    *res = ctx->result;

    /* There should be no allocated frames */
    assert(ctx->frame == NULL);
  } else {
    /* There was an error during parsing */
    rcode = v7_throwf(v7, "SyntaxError", "Invalid JSON string");

    /* There might be some allocated frames in case of malformed JSON */
    while (ctx->frame != NULL) {
      ctx->frame = free_json_frame(ctx, ctx->frame);
    }
  }

  v7_disown(v7, &ctx->result);
  free(ctx);

  return rcode;
}
Exemple #7
0
int v7_example(void) {
  size_t n;
  const char *domain_str;
  struct v7 *v7 = v7_create();
  v7_val_t domain, port0, config;

  /* Load JSON configuration */
  if (v7_parse_json_file(v7, "config.json", &config) != V7_OK) {
    printf("%s\n", "Cannot load JSON config");
    return 1;
  }

  /* Lookup values in JSON configuration object */
  domain = v7_get(v7, config, "domain", 6);
  port0 = v7_array_get(v7, v7_get(v7, config, "ports", 5), 0);
  domain_str = v7_get_string(v7, &domain, &n);

  printf("Domain: [%.*s], port 0: [%d]\n",
         (int) n, domain_str, (int) v7_get_double(port0));

  v7_destroy(v7);
  return 0;
}
MG_PRIVATE enum v7_err Console_log(struct v7 *v7, v7_val_t *res) {
  int argc = v7_argc(v7);
  /* Put everything into one message */
  for (int i = 0; i < argc; i++) {
    v7_val_t arg = v7_arg(v7, i);
    if (v7_is_string(arg)) {
      size_t len;
      const char *str = v7_get_string(v7, &arg, &len);
      miot_console_puts_n(str, len);
    } else {
      char buf[100], *p;
      p = v7_stringify(v7, arg, buf, sizeof(buf), V7_STRINGIFY_DEBUG);
      miot_console_puts_n(p, strlen(p));
      if (p != buf) free(p);
    }
    if (i != argc - 1) {
      miot_console_putc(' ');
    }
  }
  miot_console_putc('\n');

  *res = V7_UNDEFINED; /* like JS print */
  return V7_OK;
}
Exemple #9
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;
}