/* * Subscribes a mqtt client to a topic. */ enum v7_err MQTT_subscribe(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; struct user_data *ud; struct mg_connection *nc; struct mg_mqtt_topic_expression expr; v7_val_t topicv = v7_arg(v7, 0); const char *topic; nc = v7_to_foreign(v7_get(v7, v7_get_this(v7), "_nc", ~0)); if (nc == NULL) { rcode = v7_throwf(v7, "Error", "unsupported protocol"); goto clean; } ud = (struct user_data *) nc->user_data; topic = v7_to_cstring(v7, &topicv); if (topic == NULL || strlen(topic) == 0) { rcode = v7_throwf(v7, "TypeError", "invalid topic"); goto clean; } expr.topic = topic; expr.qos = 0; mg_mqtt_subscribe(nc, &expr, 1, ud->msgid++); *res = v7_mk_boolean(1); clean: return rcode; }
static v7_val_t WebSocket_send(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t datav = v7_array_get(v7, args, 0); v7_val_t ncv = v7_get(v7, this_obj, "_nc", ~0); struct mg_connection *nc; /* * TODO(alashkin): check why v7_is_instanceof throws exception * in case of string */ int is_blob = !v7_is_string(datav) && v7_is_instanceof(v7, datav, "Blob"); if (!v7_is_string(datav) && !is_blob) { v7_throw(v7, "arg should be string or Blob"); return v7_create_undefined(); } if (!v7_is_foreign(ncv) || (nc = (struct mg_connection *) v7_to_foreign(ncv)) == NULL) { v7_throw(v7, "ws not connected"); return v7_create_undefined(); } if (is_blob) { _WebSocket_send_blob(v7, nc, datav); } else { _WebSocket_send_string(v7, nc, datav); } return v7_create_undefined(); }
/* * 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_to_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_data(v7, &messagev, &message_len); nc = v7_to_foreign(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; }
/* * Read the content of the UART. It does not block. * Optional `max_len` parameter, defaults to max size_t. */ static enum v7_err UART_read(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), maxv = v7_arg(v7, 0); size_t max = v7_is_number(maxv) ? (size_t) v7_to_number(maxv) : ~0; *res = sj_hal_read_uart(v7, v7_to_foreign(dev), max); return V7_OK; }
static struct clubby *get_clubby(struct v7 *v7, v7_val_t obj) { v7_val_t clubbyv = v7_get(v7, obj, s_clubby_prop, sizeof(s_clubby_prop)); if (!v7_is_foreign(clubbyv)) { return 0; } return v7_to_foreign(clubbyv); }
static v7_val_t WebSocket_close(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { struct ns_connection *nc; v7_val_t ncv = v7_get(v7, this_obj, "_nc", ~0); (void) args; if (v7_is_foreign(ncv) && (nc = (struct ns_connection *) v7_to_foreign(ncv)) != NULL) { nc->flags |= NSF_CLOSE_IMMEDIATELY; } return v7_create_undefined(); }
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_data(v7, &data, &len); (void) v7; (void) this_obj; sj_hal_write_uart(v7_to_foreign(dev), d, len); 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_to_number(wantv) : ~0; struct user_data *ud = (struct user_data *) v7_to_foreign(udv); ud->cb = cb; v7_own(v7, &ud->cb); ud->want = want; /* TODO(mkm): trigger cb if there is already something in the buffer */ return V7_OK; }
static v7_val_t WebSocket_send(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t datav = v7_array_get(v7, args, 0); v7_val_t ncv = v7_get(v7, this_obj, "_nc", ~0); struct ns_connection *nc; const char *data; size_t len; if (!v7_is_string(datav)) { v7_throw(v7, "non string data not implemented"); return v7_create_undefined(); } if (!v7_is_foreign(ncv) || (nc = (struct ns_connection *) v7_to_foreign(ncv)) == NULL) { v7_throw(v7, "ws not connected"); return v7_create_undefined(); } data = v7_to_string(v7, &datav, &len); ns_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, data, len); return v7_create_undefined(); }
/* * Returns mongoose connection saved in the user data object `obj`. * * For some details on `obj`, see `struct user_data::obj` */ static struct mg_connection *get_mgconn_obj(struct v7 *v7, v7_val_t obj) { v7_val_t _c = v7_get(v7, obj, "_c", ~0); return (struct mg_connection *) v7_to_foreign(_c); }