Formatting

This commit is contained in:
Pim van Pelt
2018-04-17 15:00:29 +02:00
parent 8bf7b919cc
commit 491ba88d1a
25 changed files with 2290 additions and 1956 deletions

View File

@ -4,18 +4,18 @@
#include "mgos.h" #include "mgos.h"
#include "mgos_gpio.h" #include "mgos_gpio.h"
#define CHANNEL_CHANGE_COOLDOWN_SECONDS 0.250 #define CHANNEL_CHANGE_COOLDOWN_SECONDS 0.250
#define CHANNEL_MAX 16 #define CHANNEL_MAX 16
#define GPIO_INVALID 255 #define GPIO_INVALID 255
#define GPIO_MIN 0 #define GPIO_MIN 0
#define GPIO_MAX 16 #define GPIO_MAX 16
struct channel_t { struct channel_t {
uint8_t button_gpio; uint8_t button_gpio;
uint8_t led_gpio; uint8_t led_gpio;
uint8_t relay_gpio; uint8_t relay_gpio;
bool relay_state; bool relay_state;
double button_last_change; double button_last_change;
}; };
void statusled_blink(); void statusled_blink();

View File

@ -4,9 +4,9 @@
#include "mgos.h" #include "mgos.h"
#include "mgos_mqtt.h" #include "mgos_mqtt.h"
#define MQTT_TOPIC_PREFIX "" #define MQTT_TOPIC_PREFIX ""
#define MQTT_TOPIC_BROADCAST_CMD "/mongoose/broadcast" #define MQTT_TOPIC_BROADCAST_CMD "/mongoose/broadcast"
#define MQTT_TOPIC_BROADCAST_STAT "/mongoose/broadcast/stat" #define MQTT_TOPIC_BROADCAST_STAT "/mongoose/broadcast/stat"
void mqtt_init(); void mqtt_init();
void mqtt_publish_stat(const char *stat, const char *fmt, ...); void mqtt_publish_stat(const char *stat, const char *fmt, ...);

View File

@ -20,6 +20,7 @@ extern "C" {
bool mgos_ota_http_client_init(void); bool mgos_ota_http_client_init(void);
void mgos_ota_http_start(struct update_context *ctx, const char *url); void mgos_ota_http_start(struct update_context *ctx, const char *url);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -17,104 +17,118 @@
static void fw_download_handler(struct mg_connection *c, int ev, void *p, static void fw_download_handler(struct mg_connection *c, int ev, void *p,
void *user_data) { void *user_data) {
struct mbuf *io = &c->recv_mbuf; struct mbuf * io = &c->recv_mbuf;
struct update_context *ctx = (struct update_context *) user_data; struct update_context *ctx = (struct update_context *)user_data;
int res = 0; int res = 0;
struct mg_str *loc; struct mg_str *loc;
(void) p;
(void)p;
switch (ev) { switch (ev) {
case MG_EV_CONNECT: { case MG_EV_CONNECT: {
int result = *((int *) p); int result = *((int *)p);
if (result != 0) LOG(LL_ERROR, ("connect error: %d", result)); if (result != 0) {
break; LOG(LL_ERROR, ("connect error: %d", result));
} }
case MG_EV_RECV: { break;
if (ctx->file_size == 0) { }
LOG(LL_DEBUG, ("Looking for HTTP header"));
struct http_message hm;
int parsed = mg_parse_http(io->buf, io->len, &hm, 0);
if (parsed <= 0) {
return;
}
if (hm.resp_code != 200) {
if (hm.resp_code == 304) {
ctx->result = 1;
ctx->need_reboot = false;
ctx->status_msg = "Not Modified";
updater_finish(ctx);
} else if ((hm.resp_code == 301 || hm.resp_code == 302) &&
(loc = mg_get_http_header(&hm, "Location")) != NULL) {
/* NUL-terminate the URL. Every header must be followed by \r\n,
* so there is deifnitely space there. */
((char *) loc->p)[loc->len] = '\0';
/* We were told to look elsewhere. Detach update context from this
* connection so that it doesn't get finalized when it's closed. */
mgos_ota_http_start(ctx, loc->p);
c->user_data = NULL;
} else {
ctx->result = -hm.resp_code;
ctx->need_reboot = false;
ctx->status_msg = "Invalid HTTP response code";
updater_finish(ctx);
}
c->flags |= MG_F_CLOSE_IMMEDIATELY;
return;
}
if (hm.body.len != 0) {
LOG(LL_DEBUG, ("HTTP header: file size: %d", (int) hm.body.len));
if (hm.body.len == (size_t) ~0) {
LOG(LL_ERROR, ("Invalid content-length, perhaps chunked-encoding"));
ctx->status_msg =
"Invalid content-length, perhaps chunked-encoding";
c->flags |= MG_F_CLOSE_IMMEDIATELY;
break;
} else {
ctx->file_size = hm.body.len;
}
mbuf_remove(io, parsed); case MG_EV_RECV: {
} if (ctx->file_size == 0) {
LOG(LL_DEBUG, ("Looking for HTTP header"));
struct http_message hm;
int parsed = mg_parse_http(io->buf, io->len, &hm, 0);
if (parsed <= 0) {
return;
} }
if (hm.resp_code != 200) {
if (hm.resp_code == 304) {
ctx->result = 1;
ctx->need_reboot = false;
ctx->status_msg = "Not Modified";
updater_finish(ctx);
} else if ((hm.resp_code == 301 || hm.resp_code == 302) &&
(loc = mg_get_http_header(&hm, "Location")) != NULL) {
/* NUL-terminate the URL. Every header must be followed by \r\n,
* so there is deifnitely space there. */
((char *)loc->p)[loc->len] = '\0';
if (io->len != 0) { /* We were told to look elsewhere. Detach update context from this
res = updater_process(ctx, io->buf, io->len); * connection so that it doesn't get finalized when it's closed. */
mbuf_remove(io, io->len); mgos_ota_http_start(ctx, loc->p);
c->user_data = NULL;
if (res == 0) { } else {
if (is_write_finished(ctx)) res = updater_finalize(ctx); ctx->result = -hm.resp_code;
if (res == 0) { ctx->need_reboot = false;
/* Need more data, everything is OK */ ctx->status_msg = "Invalid HTTP response code";
break; updater_finish(ctx);
}
}
if (res < 0) {
/* Error */
LOG(LL_ERROR, ("Update error: %d %s", ctx->result, ctx->status_msg));
} }
c->flags |= MG_F_CLOSE_IMMEDIATELY; c->flags |= MG_F_CLOSE_IMMEDIATELY;
return;
} }
if (hm.body.len != 0) {
LOG(LL_DEBUG, ("HTTP header: file size: %d", (int)hm.body.len));
if (hm.body.len == (size_t) ~0) {
LOG(LL_ERROR, ("Invalid content-length, perhaps chunked-encoding"));
ctx->status_msg =
"Invalid content-length, perhaps chunked-encoding";
c->flags |= MG_F_CLOSE_IMMEDIATELY;
break;
} else {
ctx->file_size = hm.body.len;
}
mbuf_remove(io, parsed);
}
}
if (io->len != 0) {
res = updater_process(ctx, io->buf, io->len);
mbuf_remove(io, io->len);
if (res == 0) {
if (is_write_finished(ctx)) {
res = updater_finalize(ctx);
}
if (res == 0) {
/* Need more data, everything is OK */
break;
}
}
if (res < 0) {
/* Error */
LOG(LL_ERROR, ("Update error: %d %s", ctx->result, ctx->status_msg));
}
c->flags |= MG_F_CLOSE_IMMEDIATELY;
}
break;
}
case MG_EV_CLOSE: {
if (ctx == NULL) {
break; break;
} }
case MG_EV_CLOSE: {
if (ctx == NULL) break;
if (is_write_finished(ctx)) updater_finalize(ctx); if (is_write_finished(ctx)) {
updater_finalize(ctx);
if (!is_update_finished(ctx)) {
/* Update failed or connection was terminated by server */
if (ctx->status_msg == NULL) ctx->status_msg = "Update failed";
ctx->result = -1;
} else if (is_reboot_required(ctx)) {
LOG(LL_INFO, ("Rebooting device"));
mgos_system_restart_after(100);
}
updater_finish(ctx);
updater_context_free(ctx);
c->user_data = NULL;
break;
} }
if (!is_update_finished(ctx)) {
/* Update failed or connection was terminated by server */
if (ctx->status_msg == NULL) {
ctx->status_msg = "Update failed";
}
ctx->result = -1;
} else if (is_reboot_required(ctx)) {
LOG(LL_INFO, ("Rebooting device"));
mgos_system_restart_after(100);
}
updater_finish(ctx);
updater_context_free(ctx);
c->user_data = NULL;
break;
}
} }
} }
@ -128,12 +142,12 @@ void mgos_ota_http_start(struct update_context *ctx, const char *url) {
#if MG_ENABLE_SSL #if MG_ENABLE_SSL
if (strlen(url) > 8 && strncmp(url, "https://", 8) == 0) { if (strlen(url) > 8 && strncmp(url, "https://", 8) == 0) {
opts.ssl_server_name = mgos_sys_config_get_update_ssl_server_name(); opts.ssl_server_name = mgos_sys_config_get_update_ssl_server_name();
opts.ssl_ca_cert = mgos_sys_config_get_update_ssl_ca_file(); opts.ssl_ca_cert = mgos_sys_config_get_update_ssl_ca_file();
opts.ssl_cert = mgos_sys_config_get_update_ssl_client_cert_file(); opts.ssl_cert = mgos_sys_config_get_update_ssl_client_cert_file();
} }
#endif #endif
char ehb[150]; char ehb[150];
char *extra_headers = ehb; char *extra_headers = ehb;
mg_asprintf(&extra_headers, sizeof(ehb), mg_asprintf(&extra_headers, sizeof(ehb),
"X-MGOS-Device-ID: %s %s\r\n" "X-MGOS-Device-ID: %s %s\r\n"
@ -145,15 +159,17 @@ void mgos_ota_http_start(struct update_context *ctx, const char *url) {
mgos_sys_ro_vars_get_fw_id()); mgos_sys_ro_vars_get_fw_id());
struct mg_connection *c = mg_connect_http_opt( struct mg_connection *c = mg_connect_http_opt(
mgos_get_mgr(), fw_download_handler, ctx, opts, url, extra_headers, NULL); mgos_get_mgr(), fw_download_handler, ctx, opts, url, extra_headers, NULL);
if (extra_headers != ehb) free(extra_headers); if (extra_headers != ehb) {
free(extra_headers);
}
if (c == NULL) { if (c == NULL) {
LOG(LL_ERROR, ("Failed to connect to %s", url)); LOG(LL_ERROR, ("Failed to connect to %s", url));
ctx->result = -10; ctx->result = -10;
ctx->need_reboot = false; ctx->need_reboot = false;
ctx->status_msg = "Failed to connect"; ctx->status_msg = "Failed to connect";
updater_finish(ctx); updater_finish(ctx);
return; return;
} }
@ -163,18 +179,24 @@ void mgos_ota_http_start(struct update_context *ctx, const char *url) {
static void mgos_ota_timer_cb(void *arg) { static void mgos_ota_timer_cb(void *arg) {
const struct mgos_config_update *mcu = mgos_sys_config_get_update(); const struct mgos_config_update *mcu = mgos_sys_config_get_update();
if (mcu->url == NULL) return;
if (mcu->url == NULL) {
return;
}
struct update_context *ctx = updater_context_create(); struct update_context *ctx = updater_context_create();
if (ctx == NULL) return; if (ctx == NULL) {
return;
}
ctx->ignore_same_version = true; ctx->ignore_same_version = true;
ctx->fctx.commit_timeout = mcu->commit_timeout; ctx->fctx.commit_timeout = mcu->commit_timeout;
mgos_ota_http_start(ctx, mcu->url); mgos_ota_http_start(ctx, mcu->url);
(void) arg; (void)arg;
} }
bool mgos_ota_http_client_init(void) { bool mgos_ota_http_client_init(void) {
const struct mgos_config_update *mcu = mgos_sys_config_get_update(); const struct mgos_config_update *mcu = mgos_sys_config_get_update();
if (mcu->url != NULL && mcu->interval > 0) { if (mcu->url != NULL && mcu->interval > 0) {
LOG(LL_INFO, LOG(LL_INFO,
("Updates from %s, every %d seconds", mcu->url, mcu->interval)); ("Updates from %s, every %d seconds", mcu->url, mcu->interval));

View File

@ -14,6 +14,7 @@ extern "C" {
#if MGOS_ENABLE_UPDATER #if MGOS_ENABLE_UPDATER
bool mgos_ota_http_server_init(void); bool mgos_ota_http_server_init(void);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -16,104 +16,119 @@
#include "mgos_utils.h" #include "mgos_utils.h"
static void handle_update_post(struct mg_connection *c, int ev, void *p) { static void handle_update_post(struct mg_connection *c, int ev, void *p) {
struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *) p; struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *)p;
struct update_context *ctx = (struct update_context *) c->user_data; struct update_context * ctx = (struct update_context *)c->user_data;
if (ctx == NULL && ev != MG_EV_HTTP_MULTIPART_REQUEST) return;
if (ctx == NULL && ev != MG_EV_HTTP_MULTIPART_REQUEST) {
return;
}
switch (ev) { switch (ev) {
case MG_EV_HTTP_MULTIPART_REQUEST: { case MG_EV_HTTP_MULTIPART_REQUEST: {
ctx = updater_context_create(); ctx = updater_context_create();
if (ctx != NULL) { if (ctx != NULL) {
ctx->nc = c; ctx->nc = c;
c->user_data = ctx; c->user_data = ctx;
} else { } else {
c->flags |= MG_F_CLOSE_IMMEDIATELY; c->flags |= MG_F_CLOSE_IMMEDIATELY;
}
break;
} }
case MG_EV_HTTP_PART_BEGIN: { break;
LOG(LL_DEBUG, ("MG_EV_HTTP_PART_BEGIN: %p %s %s", ctx, mp->var_name, }
mp->file_name));
/* We use ctx->file_name as a temp buffer for non-file variable values. */
if (mp->file_name[0] == '\0') {
ctx->file_name[0] = '\0';
}
break;
}
case MG_EV_HTTP_PART_DATA: {
LOG(LL_DEBUG, ("MG_EV_HTTP_PART_DATA: %p %s %s %d", ctx, mp->var_name,
mp->file_name, (int) mp->data.len));
if (mp->file_name[0] == '\0') { case MG_EV_HTTP_PART_BEGIN: {
/* It's a non-file form variable. */ LOG(LL_DEBUG, ("MG_EV_HTTP_PART_BEGIN: %p %s %s", ctx, mp->var_name,
size_t l = strlen(ctx->file_name); mp->file_name));
size_t avail = sizeof(ctx->file_name) - l - 1; /* We use ctx->file_name as a temp buffer for non-file variable values. */
strncat(ctx->file_name, mp->data.p, MIN(mp->data.len, avail)); if (mp->file_name[0] == '\0') {
break; ctx->file_name[0] = '\0';
} else if (!is_update_finished(ctx)) { }
updater_process(ctx, mp->data.p, mp->data.len); break;
LOG(LL_DEBUG, ("updater_process res: %d", ctx->result)); }
} else {
/* Don't close connection just yet, not all browsers like that. */ case MG_EV_HTTP_PART_DATA: {
} LOG(LL_DEBUG, ("MG_EV_HTTP_PART_DATA: %p %s %s %d", ctx, mp->var_name,
mp->file_name, (int)mp->data.len));
if (mp->file_name[0] == '\0') {
/* It's a non-file form variable. */
size_t l = strlen(ctx->file_name);
size_t avail = sizeof(ctx->file_name) - l - 1;
strncat(ctx->file_name, mp->data.p, MIN(mp->data.len, avail));
break;
} else if (!is_update_finished(ctx)) {
updater_process(ctx, mp->data.p, mp->data.len);
LOG(LL_DEBUG, ("updater_process res: %d", ctx->result));
} else {
/* Don't close connection just yet, not all browsers like that. */
}
break;
}
case MG_EV_HTTP_PART_END: {
LOG(LL_DEBUG, ("MG_EV_HTTP_PART_END: %p %s %s %d", ctx, mp->var_name,
mp->file_name, mp->status));
/* Part finished with an error. REQUEST_END will follow. */
if (mp->status < 0) {
break; break;
} }
case MG_EV_HTTP_PART_END: { if (mp->file_name[0] == '\0') {
LOG(LL_DEBUG, ("MG_EV_HTTP_PART_END: %p %s %s %d", ctx, mp->var_name, /* It's a non-file form variable. Value is in ctx->file_name. */
mp->file_name, mp->status)); LOG(LL_DEBUG, ("Got var: %s=%s", mp->var_name, ctx->file_name));
/* Part finished with an error. REQUEST_END will follow. */ /* Commit timeout can be set after flashing. */
if (mp->status < 0) break; if (strcmp(mp->var_name, "commit_timeout") == 0) {
if (mp->file_name[0] == '\0') { ctx->fctx.commit_timeout = atoi(ctx->file_name);
/* It's a non-file form variable. Value is in ctx->file_name. */
LOG(LL_DEBUG, ("Got var: %s=%s", mp->var_name, ctx->file_name));
/* Commit timeout can be set after flashing. */
if (strcmp(mp->var_name, "commit_timeout") == 0) {
ctx->fctx.commit_timeout = atoi(ctx->file_name);
}
} else {
/* End of the fw part, but there may still be parts with vars to follow,
* which can modify settings (that can be applied post-flashing). */
} }
} else {
/* End of the fw part, but there may still be parts with vars to follow,
* which can modify settings (that can be applied post-flashing). */
}
break;
}
case MG_EV_HTTP_MULTIPART_REQUEST_END: {
LOG(LL_DEBUG,
("MG_EV_HTTP_MULTIPART_REQUEST_END: %p %d", ctx, mp->status));
/* Whatever happens, this is the last thing we do. */
c->flags |= MG_F_SEND_AND_CLOSE;
if (ctx == NULL) {
break; break;
} }
case MG_EV_HTTP_MULTIPART_REQUEST_END: { if (is_write_finished(ctx)) {
LOG(LL_DEBUG, updater_finalize(ctx);
("MG_EV_HTTP_MULTIPART_REQUEST_END: %p %d", ctx, mp->status)); }
/* Whatever happens, this is the last thing we do. */ if (!is_update_finished(ctx)) {
ctx->result = -1;
ctx->status_msg = "Update aborted";
updater_finish(ctx);
}
if (mp->status < 0) {
/* mp->status < 0 means connection is dead, do not send reply */
} else {
int code = (ctx->result > 0 ? 200 : 400);
mg_send_response_line(c, code,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "%s\r\n",
ctx->status_msg ? ctx->status_msg : "Unknown error");
if (is_reboot_required(ctx)) {
LOG(LL_INFO, ("Rebooting device"));
mgos_system_restart_after(101);
}
c->flags |= MG_F_SEND_AND_CLOSE; c->flags |= MG_F_SEND_AND_CLOSE;
if (ctx == NULL) break;
if (is_write_finished(ctx)) updater_finalize(ctx);
if (!is_update_finished(ctx)) {
ctx->result = -1;
ctx->status_msg = "Update aborted";
updater_finish(ctx);
}
if (mp->status < 0) {
/* mp->status < 0 means connection is dead, do not send reply */
} else {
int code = (ctx->result > 0 ? 200 : 400);
mg_send_response_line(c, code,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "%s\r\n",
ctx->status_msg ? ctx->status_msg : "Unknown error");
if (is_reboot_required(ctx)) {
LOG(LL_INFO, ("Rebooting device"));
mgos_system_restart_after(101);
}
c->flags |= MG_F_SEND_AND_CLOSE;
}
updater_context_free(ctx);
c->user_data = NULL;
break;
} }
updater_context_free(ctx);
c->user_data = NULL;
break;
}
} }
} }
struct mg_connection *s_update_request_conn; struct mg_connection *s_update_request_conn;
static void mgos_ota_result_cb(struct update_context *ctx) { static void mgos_ota_result_cb(struct update_context *ctx) {
if (ctx != updater_context_get_current()) return; if (ctx != updater_context_get_current()) {
return;
}
if (s_update_request_conn != NULL) { if (s_update_request_conn != NULL) {
int code = (ctx->result > 0 ? 200 : 500); int code = (ctx->result > 0 ? 200 : 500);
mg_send_response_line(s_update_request_conn, code, mg_send_response_line(s_update_request_conn, code,
@ -122,112 +137,117 @@ static void mgos_ota_result_cb(struct update_context *ctx) {
mg_printf(s_update_request_conn, "(%d) %s\r\n", ctx->result, mg_printf(s_update_request_conn, "(%d) %s\r\n", ctx->result,
ctx->status_msg); ctx->status_msg);
s_update_request_conn->flags |= MG_F_SEND_AND_CLOSE; s_update_request_conn->flags |= MG_F_SEND_AND_CLOSE;
s_update_request_conn = NULL; s_update_request_conn = NULL;
} }
} }
static void update_handler(struct mg_connection *c, int ev, void *ev_data, static void update_handler(struct mg_connection *c, int ev, void *ev_data,
void *user_data) { void *user_data) {
switch (ev) { switch (ev) {
case MG_EV_HTTP_MULTIPART_REQUEST: case MG_EV_HTTP_MULTIPART_REQUEST:
case MG_EV_HTTP_PART_BEGIN: case MG_EV_HTTP_PART_BEGIN:
case MG_EV_HTTP_PART_DATA: case MG_EV_HTTP_PART_DATA:
case MG_EV_HTTP_PART_END: case MG_EV_HTTP_PART_END:
case MG_EV_HTTP_MULTIPART_REQUEST_END: { case MG_EV_HTTP_MULTIPART_REQUEST_END: {
if (mgos_sys_config_get_update_enable_post()) { if (mgos_sys_config_get_update_enable_post()) {
handle_update_post(c, ev, ev_data); handle_update_post(c, ev, ev_data);
} else { } else {
mg_send_response_line(c, 400, mg_send_response_line(c, 400,
"Content-Type: text/plain\r\n" "Content-Type: text/plain\r\n"
"Connection: close\r\n"); "Connection: close\r\n");
mg_printf(c, "POST updates are disabled."); mg_printf(c, "POST updates are disabled.");
c->flags |= MG_F_SEND_AND_CLOSE; c->flags |= MG_F_SEND_AND_CLOSE;
} }
return;
}
case MG_EV_HTTP_REQUEST: {
struct http_message *hm = (struct http_message *)ev_data;
if (updater_context_get_current() != NULL) {
mg_send_response_line(c, 409,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "Another update is in progress.\r\n");
c->flags |= MG_F_SEND_AND_CLOSE;
return; return;
} }
case MG_EV_HTTP_REQUEST: { const struct mgos_config_update *mcu = mgos_sys_config_get_update();
struct http_message *hm = (struct http_message *) ev_data; char * url = mcu->url;
if (updater_context_get_current() != NULL) { int commit_timeout = mcu->commit_timeout;
bool ignore_same_version = true;
struct mg_str params =
(mg_vcmp(&hm->method, "POST") == 0 ? hm->body : hm->query_string);
size_t buf_len = params.len;
char * buf = calloc(params.len, 1), *p = buf;
int len = mg_get_http_var(&params, "url", p, buf_len);
if (len > 0) {
url = p;
p += len + 1;
buf_len -= len + 1;
}
len = mg_get_http_var(&params, "commit_timeout", p, buf_len);
if (len > 0) {
commit_timeout = atoi(p);
}
len = mg_get_http_var(&params, "ignore_same_version", p, buf_len);
if (len > 0) {
ignore_same_version = (atoi(p) > 0);
}
if (url != NULL) {
s_update_request_conn = c;
struct update_context *ctx = updater_context_create();
if (ctx == NULL) {
mg_send_response_line(c, 409, mg_send_response_line(c, 409,
"Content-Type: text/plain\r\n" "Content-Type: text/plain\r\n"
"Connection: close\r\n"); "Connection: close\r\n");
mg_printf(c, "Another update is in progress.\r\n"); mg_printf(c, "Failed to create updater context.\r\n");
c->flags |= MG_F_SEND_AND_CLOSE; c->flags |= MG_F_SEND_AND_CLOSE;
return; return;
} }
const struct mgos_config_update *mcu = mgos_sys_config_get_update(); ctx->ignore_same_version = ignore_same_version;
char *url = mcu->url; ctx->fctx.commit_timeout = commit_timeout;
int commit_timeout = mcu->commit_timeout; ctx->result_cb = mgos_ota_result_cb;
bool ignore_same_version = true; mgos_ota_http_start(ctx, url);
struct mg_str params = } else {
(mg_vcmp(&hm->method, "POST") == 0 ? hm->body : hm->query_string); mg_send_response_line(c, 400,
size_t buf_len = params.len; "Content-Type: text/plain\r\n"
char *buf = calloc(params.len, 1), *p = buf; "Connection: close\r\n");
int len = mg_get_http_var(&params, "url", p, buf_len); mg_printf(c, "Update URL not specified and none is configured.\r\n");
if (len > 0) { c->flags |= MG_F_SEND_AND_CLOSE;
url = p;
p += len + 1;
buf_len -= len + 1;
}
len = mg_get_http_var(&params, "commit_timeout", p, buf_len);
if (len > 0) {
commit_timeout = atoi(p);
}
len = mg_get_http_var(&params, "ignore_same_version", p, buf_len);
if (len > 0) {
ignore_same_version = (atoi(p) > 0);
}
if (url != NULL) {
s_update_request_conn = c;
struct update_context *ctx = updater_context_create();
if (ctx == NULL) {
mg_send_response_line(c, 409,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "Failed to create updater context.\r\n");
c->flags |= MG_F_SEND_AND_CLOSE;
return;
}
ctx->ignore_same_version = ignore_same_version;
ctx->fctx.commit_timeout = commit_timeout;
ctx->result_cb = mgos_ota_result_cb;
mgos_ota_http_start(ctx, url);
} else {
mg_send_response_line(c, 400,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "Update URL not specified and none is configured.\r\n");
c->flags |= MG_F_SEND_AND_CLOSE;
}
free(buf);
break;
}
case MG_EV_CLOSE: {
if (s_update_request_conn == c) {
/* Client went away while waiting for response. */
s_update_request_conn = NULL;
}
break;
} }
free(buf);
break;
} }
(void) user_data;
case MG_EV_CLOSE: {
if (s_update_request_conn == c) {
/* Client went away while waiting for response. */
s_update_request_conn = NULL;
}
break;
}
}
(void)user_data;
} }
static void update_action_handler(struct mg_connection *c, int ev, void *p, static void update_action_handler(struct mg_connection *c, int ev, void *p,
void *user_data) { void *user_data) {
if (ev != MG_EV_HTTP_REQUEST) return; if (ev != MG_EV_HTTP_REQUEST) {
struct http_message *hm = (struct http_message *) p; return;
bool is_commit = (mg_vcmp(&hm->uri, "/update/commit") == 0); }
struct http_message *hm = (struct http_message *)p;
bool is_commit = (mg_vcmp(&hm->uri, "/update/commit") == 0);
bool ok = bool ok =
(is_commit ? mgos_upd_commit() : mgos_upd_revert(false /* reboot */)); (is_commit ? mgos_upd_commit() : mgos_upd_revert(false /* reboot */));
mg_send_response_line(c, (ok ? 200 : 400), mg_send_response_line(c, (ok ? 200 : 400),
"Content-Type: text/html\r\n" "Content-Type: text/html\r\n"
"Connection: close"); "Connection: close");
mg_printf(c, "\r\n%s\r\n", (ok ? "Ok" : "Error")); mg_printf(c, "\r\n%s\r\n", (ok ? "Ok" : "Error"));
c->flags |= MG_F_SEND_AND_CLOSE; c->flags |= MG_F_SEND_AND_CLOSE;
if (ok && !is_commit) mgos_system_restart_after(100); if (ok && !is_commit) {
(void) user_data; mgos_system_restart_after(100);
}
(void)user_data;
} }
bool mgos_ota_http_server_init(void) { bool mgos_ota_http_server_init(void) {

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2016 Cesanta Software Limited * Copyright (c) 2016 Cesanta Software Limited
* All rights reserved * All rights reserved
*/ */
#ifndef CS_FW_SRC_MGOS_UPDATER_MG_RPC_H_ #ifndef CS_FW_SRC_MGOS_UPDATER_MG_RPC_H_
#define CS_FW_SRC_MGOS_UPDATER_MG_RPC_H_ #define CS_FW_SRC_MGOS_UPDATER_MG_RPC_H_

View File

@ -18,7 +18,9 @@
static struct mg_rpc_request_info *s_update_req; static struct mg_rpc_request_info *s_update_req;
static void mg_rpc_updater_result(struct update_context *ctx) { static void mg_rpc_updater_result(struct update_context *ctx) {
if (s_update_req == NULL) return; if (s_update_req == NULL) {
return;
}
mg_rpc_send_errorf(s_update_req, (ctx->result > 0 ? 0 : -1), ctx->status_msg); mg_rpc_send_errorf(s_update_req, (ctx->result > 0 ? 0 : -1), ctx->status_msg);
s_update_req = NULL; s_update_req = NULL;
} }
@ -26,12 +28,12 @@ static void mg_rpc_updater_result(struct update_context *ctx) {
static void handle_update_req(struct mg_rpc_request_info *ri, void *cb_arg, static void handle_update_req(struct mg_rpc_request_info *ri, void *cb_arg,
struct mg_rpc_frame_info *fi, struct mg_rpc_frame_info *fi,
struct mg_str args) { struct mg_str args) {
char *blob_url = NULL; char * blob_url = NULL;
struct json_token url_tok = JSON_INVALID_TOKEN; struct json_token url_tok = JSON_INVALID_TOKEN;
int commit_timeout = 0; int commit_timeout = 0;
struct update_context *ctx = NULL; struct update_context *ctx = NULL;
LOG(LL_DEBUG, ("Update request received: %.*s", (int) args.len, args.p)); LOG(LL_DEBUG, ("Update request received: %.*s", (int)args.len, args.p));
const char *reply = "Malformed request"; const char *reply = "Malformed request";
@ -41,7 +43,9 @@ static void handle_update_req(struct mg_rpc_request_info *ri, void *cb_arg,
json_scanf(args.p, args.len, ri->args_fmt, &url_tok, &commit_timeout); json_scanf(args.p, args.len, ri->args_fmt, &url_tok, &commit_timeout);
if (url_tok.len == 0 || url_tok.type != JSON_TYPE_STRING) goto clean; if (url_tok.len == 0 || url_tok.type != JSON_TYPE_STRING) {
goto clean;
}
LOG(LL_DEBUG, ("URL: %.*s commit_timeout: %d", url_tok.len, url_tok.ptr, LOG(LL_DEBUG, ("URL: %.*s commit_timeout: %d", url_tok.len, url_tok.ptr,
commit_timeout)); commit_timeout));
@ -65,20 +69,22 @@ static void handle_update_req(struct mg_rpc_request_info *ri, void *cb_arg,
goto clean; goto clean;
} }
ctx->fctx.commit_timeout = commit_timeout; ctx->fctx.commit_timeout = commit_timeout;
ctx->result_cb = mg_rpc_updater_result; ctx->result_cb = mg_rpc_updater_result;
s_update_req = ri; s_update_req = ri;
mgos_ota_http_start(ctx, blob_url); mgos_ota_http_start(ctx, blob_url);
free(blob_url); free(blob_url);
return; return;
clean: clean:
if (blob_url != NULL) free(blob_url); if (blob_url != NULL) {
free(blob_url);
}
LOG(LL_ERROR, ("Failed to start update: %s", reply)); LOG(LL_ERROR, ("Failed to start update: %s", reply));
mg_rpc_send_errorf(ri, -1, reply); mg_rpc_send_errorf(ri, -1, reply);
ri = NULL; ri = NULL;
(void) cb_arg; (void)cb_arg;
(void) fi; (void)fi;
} }
static void handle_commit_req(struct mg_rpc_request_info *ri, void *cb_arg, static void handle_commit_req(struct mg_rpc_request_info *ri, void *cb_arg,
@ -90,9 +96,9 @@ static void handle_commit_req(struct mg_rpc_request_info *ri, void *cb_arg,
mg_rpc_send_errorf(ri, -1, NULL); mg_rpc_send_errorf(ri, -1, NULL);
} }
ri = NULL; ri = NULL;
(void) cb_arg; (void)cb_arg;
(void) fi; (void)fi;
(void) args; (void)args;
} }
static void handle_revert_req(struct mg_rpc_request_info *ri, void *cb_arg, static void handle_revert_req(struct mg_rpc_request_info *ri, void *cb_arg,
@ -105,9 +111,9 @@ static void handle_revert_req(struct mg_rpc_request_info *ri, void *cb_arg,
mg_rpc_send_errorf(ri, -1, NULL); mg_rpc_send_errorf(ri, -1, NULL);
} }
ri = NULL; ri = NULL;
(void) cb_arg; (void)cb_arg;
(void) fi; (void)fi;
(void) args; (void)args;
} }
static void handle_create_snapshot_req(struct mg_rpc_request_info *ri, static void handle_create_snapshot_req(struct mg_rpc_request_info *ri,
@ -115,31 +121,32 @@ static void handle_create_snapshot_req(struct mg_rpc_request_info *ri,
struct mg_rpc_frame_info *fi, struct mg_rpc_frame_info *fi,
struct mg_str args) { struct mg_str args) {
const char *err_msg = NULL; const char *err_msg = NULL;
int ret = -1; int ret = -1;
if (mgos_upd_is_committed()) { if (mgos_upd_is_committed()) {
ret = mgos_upd_create_snapshot(); ret = mgos_upd_create_snapshot();
if (ret >= 0) { if (ret >= 0) {
bool set_as_revert = false; bool set_as_revert = false;
int commit_timeout = -1; int commit_timeout = -1;
json_scanf(args.p, args.len, ri->args_fmt, &set_as_revert, json_scanf(args.p, args.len, ri->args_fmt, &set_as_revert,
&commit_timeout); &commit_timeout);
if (set_as_revert) { if (set_as_revert) {
struct mgos_upd_boot_state bs; struct mgos_upd_boot_state bs;
if (mgos_upd_boot_get_state(&bs)) { if (mgos_upd_boot_get_state(&bs)) {
bs.is_committed = false; bs.is_committed = false;
bs.revert_slot = ret; bs.revert_slot = ret;
if (mgos_upd_boot_set_state(&bs)) { if (mgos_upd_boot_set_state(&bs)) {
if (commit_timeout >= 0 && if (commit_timeout >= 0 &&
!mgos_upd_set_commit_timeout(commit_timeout)) { !mgos_upd_set_commit_timeout(commit_timeout)) {
ret = -4; ret = -4;
err_msg = "Failed to set commit timeout"; err_msg = "Failed to set commit timeout";
} }
} else { } else {
ret = -3; ret = -3;
err_msg = "Failed to set boot state"; err_msg = "Failed to set boot state";
} }
} else { } else {
ret = -2; ret = -2;
err_msg = "Failed to get boot state"; err_msg = "Failed to get boot state";
} }
} }
@ -147,7 +154,7 @@ static void handle_create_snapshot_req(struct mg_rpc_request_info *ri,
err_msg = "Failed to create snapshot"; err_msg = "Failed to create snapshot";
} }
} else { } else {
ret = -1; ret = -1;
err_msg = "Cannot create snapshots in uncommitted state"; err_msg = "Cannot create snapshots in uncommitted state";
} }
if (ret >= 0) { if (ret >= 0) {
@ -155,8 +162,8 @@ static void handle_create_snapshot_req(struct mg_rpc_request_info *ri,
} else { } else {
mg_rpc_send_errorf(ri, ret, err_msg); mg_rpc_send_errorf(ri, ret, err_msg);
} }
(void) cb_arg; (void)cb_arg;
(void) fi; (void)fi;
} }
static void handle_get_boot_state_req(struct mg_rpc_request_info *ri, static void handle_get_boot_state_req(struct mg_rpc_request_info *ri,
@ -164,6 +171,7 @@ static void handle_get_boot_state_req(struct mg_rpc_request_info *ri,
struct mg_rpc_frame_info *fi, struct mg_rpc_frame_info *fi,
struct mg_str args) { struct mg_str args) {
struct mgos_upd_boot_state bs; struct mgos_upd_boot_state bs;
if (!mgos_upd_boot_get_state(&bs)) { if (!mgos_upd_boot_get_state(&bs)) {
mg_rpc_send_errorf(ri, -1, NULL); mg_rpc_send_errorf(ri, -1, NULL);
} else { } else {
@ -173,9 +181,9 @@ static void handle_get_boot_state_req(struct mg_rpc_request_info *ri,
bs.active_slot, bs.is_committed, bs.revert_slot, bs.active_slot, bs.is_committed, bs.revert_slot,
mgos_upd_get_commit_timeout()); mgos_upd_get_commit_timeout());
} }
(void) cb_arg; (void)cb_arg;
(void) fi; (void)fi;
(void) args; (void)args;
} }
static void handle_set_boot_state_req(struct mg_rpc_request_info *ri, static void handle_set_boot_state_req(struct mg_rpc_request_info *ri,
@ -184,6 +192,7 @@ static void handle_set_boot_state_req(struct mg_rpc_request_info *ri,
struct mg_str args) { struct mg_str args) {
int ret = 0; int ret = 0;
struct mgos_upd_boot_state bs; struct mgos_upd_boot_state bs;
if (mgos_upd_boot_get_state(&bs)) { if (mgos_upd_boot_get_state(&bs)) {
int commit_timeout = -1; int commit_timeout = -1;
if (json_scanf(args.p, args.len, ri->args_fmt, &bs.active_slot, if (json_scanf(args.p, args.len, ri->args_fmt, &bs.active_slot,
@ -203,13 +212,16 @@ static void handle_set_boot_state_req(struct mg_rpc_request_info *ri,
} else { } else {
mg_rpc_send_errorf(ri, ret, NULL); mg_rpc_send_errorf(ri, ret, NULL);
} }
(void) cb_arg; (void)cb_arg;
(void) fi; (void)fi;
} }
bool mgos_rpc_service_ota_init(void) { bool mgos_rpc_service_ota_init(void) {
struct mg_rpc *mg_rpc = mgos_rpc_get_global(); struct mg_rpc *mg_rpc = mgos_rpc_get_global();
if (mg_rpc == NULL) return true;
if (mg_rpc == NULL) {
return true;
}
mg_rpc_add_handler(mg_rpc, "OTA.Update", "{url: %T, commit_timeout: %d}", mg_rpc_add_handler(mg_rpc, "OTA.Update", "{url: %T, commit_timeout: %d}",
handle_update_req, NULL); handle_update_req, NULL);
mg_rpc_add_handler(mg_rpc, "OTA.Commit", "", handle_commit_req, NULL); mg_rpc_add_handler(mg_rpc, "OTA.Commit", "", handle_commit_req, NULL);

View File

@ -3,13 +3,15 @@
#include "frozen/frozen.h" #include "frozen/frozen.h"
static struct channel_t s_channels[CHANNEL_MAX]; static struct channel_t s_channels[CHANNEL_MAX];
static int s_num_channels=0; static int s_num_channels = 0;
static bool valid_gpio(const int gpio) { static bool valid_gpio(const int gpio) {
if (gpio == -1) if (gpio == -1) {
return true; return true;
if (gpio < GPIO_MIN || gpio > GPIO_MAX) }
if (gpio < GPIO_MIN || gpio > GPIO_MAX) {
return false; return false;
}
return true; return true;
} }
@ -18,19 +20,19 @@ int channel_get_total() {
} }
bool channel_init(const char *fn) { bool channel_init(const char *fn) {
char *json; char * json;
void *h = NULL; void * h = NULL;
struct json_token val; struct json_token val;
bool ret = false; bool ret = false;
char *name = NULL; char *name = NULL;
int statusled = -1; int statusled = -1;
bool statusled_invert = false; bool statusled_invert = false;
int idx; int idx;
memset(s_channels, -1, sizeof(s_channels)); memset(s_channels, -1, sizeof(s_channels));
s_num_channels=0; s_num_channels = 0;
json = json_fread(fn); json = json_fread(fn);
if (!json) { if (!json) {
@ -54,11 +56,12 @@ bool channel_init(const char *fn) {
// Traverse Array // Traverse Array
while ((h = json_next_elem(json, strlen(json), h, ".channels", &idx, &val)) != NULL) { while ((h = json_next_elem(json, strlen(json), h, ".channels", &idx, &val)) != NULL) {
int led=-1, relay=-1, button=-1; int led = -1, relay = -1, button = -1;
LOG(LL_DEBUG, ("[%d]: [%.*s]", idx, val.len, val.ptr)); LOG(LL_DEBUG, ("[%d]: [%.*s]", idx, val.len, val.ptr));
if (val.len==0 || !val.ptr) if (val.len == 0 || !val.ptr) {
continue; continue;
}
if (json_scanf(val.ptr, val.len, "{led:%d, relay:%d, button:%d}", &led, &relay, &button) != 3) { if (json_scanf(val.ptr, val.len, "{led:%d, relay:%d, button:%d}", &led, &relay, &button) != 3) {
LOG(LL_ERROR, ("Incomplete Channel JSON: require 'led' and 'relay' and 'button' fields")); LOG(LL_ERROR, ("Incomplete Channel JSON: require 'led' and 'relay' and 'button' fields"));
goto exit; goto exit;
@ -76,60 +79,67 @@ bool channel_init(const char *fn) {
LOG(LL_ERROR, ("Button GPIO (%d) out of bounds [%d,%d]", button, GPIO_MIN, GPIO_MAX)); LOG(LL_ERROR, ("Button GPIO (%d) out of bounds [%d,%d]", button, GPIO_MIN, GPIO_MAX));
goto exit; goto exit;
} }
if (idx==CHANNEL_MAX) { if (idx == CHANNEL_MAX) {
LOG(LL_ERROR, ("Too many channels (max is %d)", CHANNEL_MAX)); LOG(LL_ERROR, ("Too many channels (max is %d)", CHANNEL_MAX));
goto exit; goto exit;
} }
s_channels[idx].button_gpio=button; s_channels[idx].button_gpio = button;
s_channels[idx].relay_gpio=relay; s_channels[idx].relay_gpio = relay;
s_channels[idx].led_gpio=led; s_channels[idx].led_gpio = led;
} }
ret=true; ret = true;
exit: exit:
if (ret) { if (ret) {
if (statusled!=-1) if (statusled != -1) {
statusled_init(statusled,statusled_invert); statusled_init(statusled, statusled_invert);
}
s_num_channels=idx+1; s_num_channels = idx + 1;
LOG(LL_INFO, ("Configuring %d channels", s_num_channels)); LOG(LL_INFO, ("Configuring %d channels", s_num_channels));
for (; idx>=0; idx--) { for (; idx >= 0; idx--) {
s_channels[idx].relay_state = 0; s_channels[idx].relay_state = 0;
if (s_channels[idx].relay_gpio!=GPIO_INVALID) { if (s_channels[idx].relay_gpio != GPIO_INVALID) {
mgos_gpio_set_mode(s_channels[idx].relay_gpio, MGOS_GPIO_MODE_OUTPUT); mgos_gpio_set_mode(s_channels[idx].relay_gpio, MGOS_GPIO_MODE_OUTPUT);
mgos_gpio_write(s_channels[idx].relay_gpio, s_channels[idx].relay_state); mgos_gpio_write(s_channels[idx].relay_gpio, s_channels[idx].relay_state);
} }
if (s_channels[idx].led_gpio!=GPIO_INVALID) { if (s_channels[idx].led_gpio != GPIO_INVALID) {
mgos_gpio_set_mode(s_channels[idx].led_gpio, MGOS_GPIO_MODE_OUTPUT); mgos_gpio_set_mode(s_channels[idx].led_gpio, MGOS_GPIO_MODE_OUTPUT);
mgos_gpio_write(s_channels[idx].led_gpio, s_channels[idx].relay_state); mgos_gpio_write(s_channels[idx].led_gpio, s_channels[idx].relay_state);
} }
if (s_channels[idx].button_gpio!=GPIO_INVALID) { if (s_channels[idx].button_gpio != GPIO_INVALID) {
mgos_gpio_set_mode(s_channels[idx].button_gpio, MGOS_GPIO_MODE_INPUT); mgos_gpio_set_mode(s_channels[idx].button_gpio, MGOS_GPIO_MODE_INPUT);
mgos_gpio_set_button_handler(s_channels[idx].button_gpio, MGOS_GPIO_PULL_UP, MGOS_GPIO_INT_EDGE_POS, 200, channel_handler, NULL); mgos_gpio_set_button_handler(s_channels[idx].button_gpio, MGOS_GPIO_PULL_UP, MGOS_GPIO_INT_EDGE_POS, 200, channel_handler, NULL);
} }
} }
} }
if (name) free(name); if (name) {
if (json) free(json); free(name);
}
if (json) {
free(json);
}
return ret; return ret;
} }
uint8_t channel_gpio_by_idx(int idx) { uint8_t channel_gpio_by_idx(int idx) {
if (idx<0 || idx>=s_num_channels) if (idx < 0 || idx >= s_num_channels) {
return GPIO_INVALID; return GPIO_INVALID;
}
return s_channels[idx].button_gpio; return s_channels[idx].button_gpio;
} }
uint8_t channel_idx_by_gpio(int gpio) { uint8_t channel_idx_by_gpio(int gpio) {
uint8_t i; uint8_t i;
for(i=0; i<channel_get_total(); i++) { for (i = 0; i < channel_get_total(); i++) {
if (gpio == s_channels[i].button_gpio) if (gpio == s_channels[i].button_gpio) {
return i; return i;
}
} }
return GPIO_INVALID; return GPIO_INVALID;
} }
@ -137,30 +147,34 @@ uint8_t channel_idx_by_gpio(int gpio) {
void channel_set(int idx, bool state) { void channel_set(int idx, bool state) {
double now = mg_time(); double now = mg_time();
if (idx<0 || idx>=channel_get_total()) if (idx < 0 || idx >= channel_get_total()) {
return; return;
}
s_channels[idx].button_last_change = now; s_channels[idx].button_last_change = now;
s_channels[idx].relay_state = state; s_channels[idx].relay_state = state;
if (s_channels[idx].relay_gpio!=GPIO_INVALID) if (s_channels[idx].relay_gpio != GPIO_INVALID) {
mgos_gpio_write(s_channels[idx].relay_gpio, state); mgos_gpio_write(s_channels[idx].relay_gpio, state);
if (s_channels[idx].led_gpio!=GPIO_INVALID) }
if (s_channels[idx].led_gpio != GPIO_INVALID) {
mgos_gpio_write(s_channels[idx].led_gpio, state); mgos_gpio_write(s_channels[idx].led_gpio, state);
}
mqtt_publish_stat("channel", "{idx: %d, relay_state: %d}", idx, channel_get(idx)); mqtt_publish_stat("channel", "{idx: %d, relay_state: %d}", idx, channel_get(idx));
} }
bool channel_get(int idx) { bool channel_get(int idx) {
if (idx<0 || idx>=channel_get_total()) if (idx < 0 || idx >= channel_get_total()) {
return false; return false;
}
return s_channels[idx].relay_state == 1; return s_channels[idx].relay_state == 1;
} }
void channel_handler(int gpio, void *arg) { void channel_handler(int gpio, void *arg) {
uint8_t idx; uint8_t idx;
double now = mg_time(); double now = mg_time();
bool state; bool state;
idx = channel_idx_by_gpio(gpio); idx = channel_idx_by_gpio(gpio);
if (idx == GPIO_INVALID) { if (idx == GPIO_INVALID) {
@ -168,7 +182,7 @@ void channel_handler(int gpio, void *arg) {
return; return;
} }
if (now<s_channels[idx].button_last_change+CHANNEL_CHANGE_COOLDOWN_SECONDS) { if (now < s_channels[idx].button_last_change + CHANNEL_CHANGE_COOLDOWN_SECONDS) {
LOG(LL_INFO, ("GPIO %d is cooling down -- skipping", gpio)); LOG(LL_INFO, ("GPIO %d is cooling down -- skipping", gpio));
return; return;
} }
@ -177,5 +191,5 @@ void channel_handler(int gpio, void *arg) {
state = channel_get(idx); state = channel_get(idx);
channel_set(idx, !state); channel_set(idx, !state);
(void) arg; (void)arg;
} }

View File

@ -10,9 +10,9 @@ static void mqtt_publish_broadcast_stat(const char *stat, const char *msg) {
char topic[80]; char topic[80];
statusled_blink(); statusled_blink();
snprintf(topic, sizeof(topic)-1, "%s/%s", MQTT_TOPIC_BROADCAST_STAT, stat); snprintf(topic, sizeof(topic) - 1, "%s/%s", MQTT_TOPIC_BROADCAST_STAT, stat);
mgos_mqtt_pub((char*)topic, (char*)msg, strlen(msg), 0, false); mgos_mqtt_pub((char *)topic, (char *)msg, strlen(msg), 0, false);
LOG(LL_INFO, ("Sent topic='%s' msg='%s'", topic, msg)); LOG(LL_INFO, ("Sent topic='%s' msg='%s'", topic, msg));
statusled_blink(); statusled_blink();
} }
@ -25,18 +25,20 @@ static void mqtt_broadcast_cmd_id() {
memset(sta_ip, 0, sizeof(sta_ip)); memset(sta_ip, 0, sizeof(sta_ip));
memset(ap_ip, 0, sizeof(ap_ip)); memset(ap_ip, 0, sizeof(ap_ip));
if (mgos_net_get_ip_info(MGOS_NET_IF_TYPE_WIFI, MGOS_NET_IF_WIFI_STA, &ip_info)) if (mgos_net_get_ip_info(MGOS_NET_IF_TYPE_WIFI, MGOS_NET_IF_WIFI_STA, &ip_info)) {
mgos_net_ip_to_str(&ip_info.ip, sta_ip); mgos_net_ip_to_str(&ip_info.ip, sta_ip);
if (mgos_net_get_ip_info(MGOS_NET_IF_TYPE_WIFI, MGOS_NET_IF_WIFI_AP, &ip_info)) }
if (mgos_net_get_ip_info(MGOS_NET_IF_TYPE_WIFI, MGOS_NET_IF_WIFI_AP, &ip_info)) {
mgos_net_ip_to_str(&ip_info.ip, ap_ip); mgos_net_ip_to_str(&ip_info.ip, ap_ip);
}
snprintf(resp, sizeof(resp)-1, "{\"deviceid\": \"%s\", \"macaddress\": \"%s\", \"sta_ip\": \"%s\", \"ap_ip\": \"%s\", \"app\": \"%s\", \"arch\": \"%s\", \"uptime\": %lu}", snprintf(resp, sizeof(resp) - 1, "{\"deviceid\": \"%s\", \"macaddress\": \"%s\", \"sta_ip\": \"%s\", \"ap_ip\": \"%s\", \"app\": \"%s\", \"arch\": \"%s\", \"uptime\": %lu}",
mgos_sys_config_get_device_id(), mgos_sys_config_get_device_id(),
mgos_sys_ro_vars_get_mac_address(), mgos_sys_ro_vars_get_mac_address(),
sta_ip, sta_ip,
ap_ip, ap_ip,
MGOS_APP, MGOS_APP,
mgos_sys_ro_vars_get_arch(), (unsigned long) mgos_uptime()); mgos_sys_ro_vars_get_arch(), (unsigned long)mgos_uptime());
mqtt_publish_broadcast_stat("id", resp); mqtt_publish_broadcast_stat("id", resp);
} }
@ -45,38 +47,38 @@ static void mqtt_cb(struct mg_connection *nc, const char *topic, int topic_len,
LOG(LL_INFO, ("Received topic='%.*s' msg='%.*s'", topic_len, topic, msg_len, msg)); LOG(LL_INFO, ("Received topic='%.*s' msg='%.*s'", topic_len, topic, msg_len, msg));
statusled_blink(); statusled_blink();
if (topic_len >= (int) strlen(MQTT_TOPIC_BROADCAST_CMD) && 0 == strncmp(MQTT_TOPIC_BROADCAST_CMD, topic, strlen(MQTT_TOPIC_BROADCAST_CMD))) if (topic_len >= (int)strlen(MQTT_TOPIC_BROADCAST_CMD) && 0 == strncmp(MQTT_TOPIC_BROADCAST_CMD, topic, strlen(MQTT_TOPIC_BROADCAST_CMD))) {
mqtt_broadcast_cmd_id(); mqtt_broadcast_cmd_id();
(void) nc; }
(void) ud; (void)nc;
(void)ud;
} }
static void mqtt_ev(struct mg_connection *nc, int ev, void *ev_data, void *user_data) { static void mqtt_ev(struct mg_connection *nc, int ev, void *ev_data, void *user_data) {
switch (ev) { switch (ev) {
case MG_EV_MQTT_CONNACK: case MG_EV_MQTT_CONNACK:
mqtt_broadcast_cmd_id(); mqtt_broadcast_cmd_id();
break; break;
} }
(void) nc; (void)nc;
(void) ev_data; (void)ev_data;
(void) user_data; (void)user_data;
} }
void mqtt_publish_stat(const char *stat, const char *fmt, ...) { void mqtt_publish_stat(const char *stat, const char *fmt, ...) {
char topic[80]; char topic[80];
char msg[200]; char msg[200];
struct json_out out = JSON_OUT_BUF(msg, 200); struct json_out out = JSON_OUT_BUF(msg, 200);
va_list ap; va_list ap;
snprintf(topic, sizeof(topic)-1, "%s%s/stat/%s", MQTT_TOPIC_PREFIX, mgos_sys_config_get_device_id(), stat); snprintf(topic, sizeof(topic) - 1, "%s%s/stat/%s", MQTT_TOPIC_PREFIX, mgos_sys_config_get_device_id(), stat);
va_start(ap, fmt); va_start(ap, fmt);
json_vprintf(&out, fmt, ap); json_vprintf(&out, fmt, ap);
va_end(ap); va_end(ap);
mgos_mqtt_pub((char*)topic, (char*)msg, strlen(msg), 0, false); mgos_mqtt_pub((char *)topic, (char *)msg, strlen(msg), 0, false);
LOG(LL_INFO, ("Sent topic='%s' msg='%s'", topic, msg)); LOG(LL_INFO, ("Sent topic='%s' msg='%s'", topic, msg));
statusled_blink(); statusled_blink();
} }
@ -90,7 +92,7 @@ void mqtt_init() {
mgos_mqtt_sub(MQTT_TOPIC_BROADCAST_CMD, mqtt_cb, NULL); mgos_mqtt_sub(MQTT_TOPIC_BROADCAST_CMD, mqtt_cb, NULL);
// Subscribe to broadcast/appname // Subscribe to broadcast/appname
snprintf(topic, sizeof(topic)-1, "%s/%s", MQTT_TOPIC_BROADCAST_CMD, MGOS_APP); snprintf(topic, sizeof(topic) - 1, "%s/%s", MQTT_TOPIC_BROADCAST_CMD, MGOS_APP);
mgos_mqtt_sub(topic, mqtt_cb, NULL); mgos_mqtt_sub(topic, mqtt_cb, NULL);
return; return;

View File

@ -21,8 +21,8 @@ static bool rpc_args_to_idx_and_gpio(struct mg_rpc_request_info *ri, struct mg_s
return false; return false;
} }
if (idx<0 || idx>=channel_get_total()) { if (idx < 0 || idx >= channel_get_total()) {
mg_rpc_send_errorf(ri, 400, "idx must be between 0 and %d", channel_get_total()-1); mg_rpc_send_errorf(ri, 400, "idx must be between 0 and %d", channel_get_total() - 1);
ri = NULL; ri = NULL;
return false; return false;
} }
@ -35,51 +35,53 @@ static bool rpc_args_to_idx_and_gpio(struct mg_rpc_request_info *ri, struct mg_s
} }
*return_gpio = gpio; *return_gpio = gpio;
*return_idx = idx; *return_idx = idx;
return true; return true;
} }
static void rpc_channel_toggle_handler(struct mg_rpc_request_info *ri, void *cb_arg, struct mg_rpc_frame_info *fi, struct mg_str args) { static void rpc_channel_toggle_handler(struct mg_rpc_request_info *ri, void *cb_arg, struct mg_rpc_frame_info *fi, struct mg_str args) {
uint8_t gpio; uint8_t gpio;
int idx; int idx;
rpc_log(ri, args); rpc_log(ri, args);
if (!rpc_args_to_idx_and_gpio(ri, args, &idx, &gpio)) if (!rpc_args_to_idx_and_gpio(ri, args, &idx, &gpio)) {
return; return;
}
channel_handler(gpio, NULL); channel_handler(gpio, NULL);
mg_rpc_send_responsef(ri, "{idx: %d, relay_state: %d}", idx, channel_get(idx)); mg_rpc_send_responsef(ri, "{idx: %d, relay_state: %d}", idx, channel_get(idx));
ri = NULL; ri = NULL;
(void) ri; (void)ri;
(void) cb_arg; (void)cb_arg;
(void) fi; (void)fi;
(void) args; (void)args;
} }
static void rpc_channel_get_handler(struct mg_rpc_request_info *ri, void *cb_arg, struct mg_rpc_frame_info *fi, struct mg_str args) { static void rpc_channel_get_handler(struct mg_rpc_request_info *ri, void *cb_arg, struct mg_rpc_frame_info *fi, struct mg_str args) {
uint8_t gpio; uint8_t gpio;
int idx; int idx;
rpc_log(ri, args); rpc_log(ri, args);
if (!rpc_args_to_idx_and_gpio(ri, args, &idx, &gpio)) if (!rpc_args_to_idx_and_gpio(ri, args, &idx, &gpio)) {
return; return;
}
mg_rpc_send_responsef(ri, "{idx: %d, relay_state: %d}", idx, channel_get(idx)); mg_rpc_send_responsef(ri, "{idx: %d, relay_state: %d}", idx, channel_get(idx));
ri = NULL; ri = NULL;
(void) ri; (void)ri;
(void) cb_arg; (void)cb_arg;
(void) fi; (void)fi;
(void) args; (void)args;
} }
static void rpc_channel_set_handler(struct mg_rpc_request_info *ri, void *cb_arg, struct mg_rpc_frame_info *fi, struct mg_str args) { static void rpc_channel_set_handler(struct mg_rpc_request_info *ri, void *cb_arg, struct mg_rpc_frame_info *fi, struct mg_str args) {
uint8_t gpio; uint8_t gpio;
int idx; int idx;
int value; int value;
rpc_log(ri, args); rpc_log(ri, args);
@ -89,8 +91,8 @@ static void rpc_channel_set_handler(struct mg_rpc_request_info *ri, void *cb_arg
return; return;
} }
if (idx<0 || idx>=channel_get_total()) { if (idx < 0 || idx >= channel_get_total()) {
mg_rpc_send_errorf(ri, 400, "idx must be between 0 and %d", channel_get_total()-1); mg_rpc_send_errorf(ri, 400, "idx must be between 0 and %d", channel_get_total() - 1);
ri = NULL; ri = NULL;
return; return;
} }
@ -102,18 +104,19 @@ static void rpc_channel_set_handler(struct mg_rpc_request_info *ri, void *cb_arg
return; return;
} }
channel_set(idx, (bool) value); channel_set(idx, (bool)value);
mg_rpc_send_responsef(ri, "{idx: %d, relay_state: %d}", idx, channel_get(idx)); mg_rpc_send_responsef(ri, "{idx: %d, relay_state: %d}", idx, channel_get(idx));
ri = NULL; ri = NULL;
(void) ri; (void)ri;
(void) cb_arg; (void)cb_arg;
(void) fi; (void)fi;
(void) args; (void)args;
} }
void rpc_init() { void rpc_init() {
struct mg_rpc *c = mgos_rpc_get_global(); struct mg_rpc *c = mgos_rpc_get_global();
mg_rpc_add_handler(c, "Channel.Toggle", "{idx: %d}", rpc_channel_toggle_handler, NULL); mg_rpc_add_handler(c, "Channel.Toggle", "{idx: %d}", rpc_channel_toggle_handler, NULL);
mg_rpc_add_handler(c, "Channel.Get", "{idx: %d}", rpc_channel_get_handler, NULL); mg_rpc_add_handler(c, "Channel.Get", "{idx: %d}", rpc_channel_get_handler, NULL);
mg_rpc_add_handler(c, "Channel.Set", "{idx: %d, value: %d}", rpc_channel_set_handler, NULL); mg_rpc_add_handler(c, "Channel.Set", "{idx: %d, value: %d}", rpc_channel_set_handler, NULL);

View File

@ -1,29 +1,30 @@
#include "main.h" #include "main.h"
static mgos_timer_id statusled_timer_id = 0; static mgos_timer_id statusled_timer_id = 0;
static uint8_t statusled_gpio = 0; static uint8_t statusled_gpio = 0;
static bool statusled_off_state = 0; static bool statusled_off_state = 0;
static void statusled_off_cb(void *arg) { static void statusled_off_cb(void *arg) {
mgos_gpio_write(statusled_gpio, statusled_off_state); mgos_gpio_write(statusled_gpio, statusled_off_state);
statusled_timer_id=0; statusled_timer_id = 0;
(void) arg; (void)arg;
} }
void statusled_blink() { void statusled_blink() {
if (statusled_gpio == GPIO_INVALID) if (statusled_gpio == GPIO_INVALID) {
return; return;
}
mgos_gpio_write(statusled_gpio, !statusled_off_state); mgos_gpio_write(statusled_gpio, !statusled_off_state);
if (statusled_timer_id) { if (statusled_timer_id) {
mgos_clear_timer(statusled_timer_id); mgos_clear_timer(statusled_timer_id);
statusled_timer_id=0; statusled_timer_id = 0;
} }
statusled_timer_id = mgos_set_timer(100, false, statusled_off_cb, NULL); statusled_timer_id = mgos_set_timer(100, false, statusled_off_cb, NULL);
} }
void statusled_init(uint8_t gpio, bool off_state) { void statusled_init(uint8_t gpio, bool off_state) {
statusled_gpio = gpio; statusled_gpio = gpio;
statusled_off_state = off_state; statusled_off_state = off_state;
mgos_gpio_set_mode(statusled_gpio, MGOS_GPIO_MODE_OUTPUT); mgos_gpio_set_mode(statusled_gpio, MGOS_GPIO_MODE_OUTPUT);
mgos_gpio_write(statusled_gpio, statusled_off_state); mgos_gpio_write(statusled_gpio, statusled_off_state);

File diff suppressed because it is too large Load Diff

View File

@ -56,8 +56,8 @@ enum json_token_type {
* `json_scanf()` with the format specifier `%T`. * `json_scanf()` with the format specifier `%T`.
*/ */
struct json_token { struct json_token {
const char *ptr; /* Points to the beginning of the value */ const char * ptr; /* Points to the beginning of the value */
int len; /* Value length */ int len; /* Value length */
enum json_token_type type; /* Type of the token, possible values are above */ enum json_token_type type; /* Type of the token, possible values are above */
}; };
@ -65,8 +65,8 @@ struct json_token {
{ 0, 0, JSON_TYPE_INVALID } { 0, 0, JSON_TYPE_INVALID }
/* Error codes */ /* Error codes */
#define JSON_STRING_INVALID -1 #define JSON_STRING_INVALID -1
#define JSON_STRING_INCOMPLETE -2 #define JSON_STRING_INCOMPLETE -2
/* /*
* Callback-based SAX-like API. * Callback-based SAX-like API.
@ -88,7 +88,7 @@ struct json_token {
* - type: JSON_TYPE_OBJECT_START, name: "2", path: ".bar[2]", value: NULL * - type: JSON_TYPE_OBJECT_START, name: "2", path: ".bar[2]", value: NULL
* - type: JSON_TYPE_TRUE, name: "baz", path: ".bar[2].baz", value: "true" * - type: JSON_TYPE_TRUE, name: "baz", path: ".bar[2].baz", value: "true"
* - type: JSON_TYPE_OBJECT_END, name: NULL, path: ".bar[2]", value: "{ \"baz\": * - type: JSON_TYPE_OBJECT_END, name: NULL, path: ".bar[2]", value: "{ \"baz\":
*true }" * true }"
* - type: JSON_TYPE_ARRAY_END, name: NULL, path: ".bar", value: "[ 1, 2, { * - type: JSON_TYPE_ARRAY_END, name: NULL, path: ".bar", value: "[ 1, 2, {
*\"baz\": true } ]" *\"baz\": true } ]"
* - type: JSON_TYPE_OBJECT_END, name: NULL, path: "", value: "{ \"foo\": 123, * - type: JSON_TYPE_OBJECT_END, name: NULL, path: "", value: "{ \"foo\": 123,
@ -114,13 +114,13 @@ struct json_out {
int (*printer)(struct json_out *, const char *str, size_t len); int (*printer)(struct json_out *, const char *str, size_t len);
union { union {
struct { struct {
char *buf; char * buf;
size_t size; size_t size;
size_t len; size_t len;
} buf; } buf;
void *data; void *data;
FILE *fp; FILE *fp;
} u; } u;
}; };
extern int json_printer_buf(struct json_out *, const char *, size_t); extern int json_printer_buf(struct json_out *, const char *, size_t);
@ -132,11 +132,11 @@ extern int json_printer_file(struct json_out *, const char *, size_t);
{ buf, len, 0 } \ { buf, len, 0 } \
} \ } \
} }
#define JSON_OUT_FILE(fp) \ #define JSON_OUT_FILE(fp) \
{ \ { \
json_printer_file, { \ json_printer_file, { \
{ (char *) fp, 0, 0 } \ { (char *)fp, 0, 0 } \
} \ } \
} }
typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap); typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);

View File

@ -1,7 +1,7 @@
#include "test.h" #include "test.h"
int test_failures=0; int test_failures = 0;
int assert_count=0; int assert_count = 0;
uint32_t mqtt_pub_count; uint32_t mqtt_pub_count;
uint32_t mqtt_sub_count; uint32_t mqtt_sub_count;

View File

@ -10,22 +10,23 @@ bool mgos_gpio_set_mode(int pin, enum mgos_gpio_mode mode) {
} }
void mgos_gpio_write(int pin, bool level) { void mgos_gpio_write(int pin, bool level) {
LOG(LL_INFO, ("Setting pin=%d to %s", pin, level?"HIGH":"LOW")); LOG(LL_INFO, ("Setting pin=%d to %s", pin, level ? "HIGH" : "LOW"));
} }
bool mgos_gpio_set_button_handler(int pin, enum mgos_gpio_pull_type pull_type, enum mgos_gpio_int_mode int_mode, int debounce_ms, mgos_gpio_int_handler_f cb, void *arg) { bool mgos_gpio_set_button_handler(int pin, enum mgos_gpio_pull_type pull_type, enum mgos_gpio_int_mode int_mode, int debounce_ms, mgos_gpio_int_handler_f cb, void *arg) {
s_handler_cb = cb; s_handler_cb = cb;
s_handler_cb_arg = arg; s_handler_cb_arg = arg;
return true; return true;
(void) debounce_ms;
(void) int_mode; (void)debounce_ms;
(void) pull_type; (void)int_mode;
(void) pin; (void)pull_type;
(void)pin;
} }
void mgos_gpio_inject(int pin) { void mgos_gpio_inject(int pin) {
if (s_handler_cb) if (s_handler_cb) {
s_handler_cb(pin, s_handler_cb_arg); s_handler_cb(pin, s_handler_cb_arg);
}
} }

View File

@ -4,18 +4,18 @@
#include "mgos.h" #include "mgos.h"
enum mgos_gpio_mode { enum mgos_gpio_mode {
MGOS_GPIO_MODE_INPUT = 0, /* input mode */ MGOS_GPIO_MODE_INPUT = 0, /* input mode */
MGOS_GPIO_MODE_OUTPUT = 1 /* output mode */ MGOS_GPIO_MODE_OUTPUT = 1 /* output mode */
}; };
enum mgos_gpio_pull_type { enum mgos_gpio_pull_type {
MGOS_GPIO_PULL_NONE = 0, MGOS_GPIO_PULL_NONE = 0,
MGOS_GPIO_PULL_UP = 1, /* pin is pilled to the high voltage */ MGOS_GPIO_PULL_UP = 1, /* pin is pilled to the high voltage */
MGOS_GPIO_PULL_DOWN = 2 /* pin is pulled to the low voltage */ MGOS_GPIO_PULL_DOWN = 2 /* pin is pulled to the low voltage */
}; };
enum mgos_gpio_int_mode { enum mgos_gpio_int_mode {
MGOS_GPIO_INT_NONE = 0, MGOS_GPIO_INT_NONE = 0,
MGOS_GPIO_INT_EDGE_POS = 1, /* positive edge */ MGOS_GPIO_INT_EDGE_POS = 1, /* positive edge */
MGOS_GPIO_INT_EDGE_NEG = 2, /* negative edge */ MGOS_GPIO_INT_EDGE_NEG = 2, /* negative edge */
MGOS_GPIO_INT_EDGE_ANY = 3, /* any edge - positive or negative */ MGOS_GPIO_INT_EDGE_ANY = 3, /* any edge - positive or negative */

View File

@ -8,36 +8,41 @@ int _mgos_timers = 0;
int log_print_prefix(enum cs_log_level l, const char *func, const char *file) { int log_print_prefix(enum cs_log_level l, const char *func, const char *file) {
char ll_str[6]; char ll_str[6];
switch(l) { switch (l) {
case LL_ERROR: case LL_ERROR:
strncpy(ll_str, "ERROR", sizeof(ll_str)); strncpy(ll_str, "ERROR", sizeof(ll_str));
break; break;
case LL_WARN:
strncpy(ll_str, "WARN", sizeof(ll_str)); case LL_WARN:
break; strncpy(ll_str, "WARN", sizeof(ll_str));
case LL_INFO: break;
strncpy(ll_str, "INFO", sizeof(ll_str));
break; case LL_INFO:
case LL_DEBUG: strncpy(ll_str, "INFO", sizeof(ll_str));
strncpy(ll_str, "DEBUG", sizeof(ll_str)); break;
break;
case LL_VERBOSE_DEBUG: case LL_DEBUG:
strncpy(ll_str, "VERB", sizeof(ll_str)); strncpy(ll_str, "DEBUG", sizeof(ll_str));
break; break;
default: // LL_NONE
return 0; case LL_VERBOSE_DEBUG:
strncpy(ll_str, "VERB", sizeof(ll_str));
break;
default: // LL_NONE
return 0;
} }
printf ("%-5s %-15s %-40s| ", ll_str, file, func); printf("%-5s %-15s %-40s| ", ll_str, file, func);
return 1; return 1;
} }
mgos_timer_id mgos_set_timer(int msecs, int flags, timer_callback cb, void *cb_arg) { mgos_timer_id mgos_set_timer(int msecs, int flags, timer_callback cb, void *cb_arg) {
_mgos_timers++; _mgos_timers++;
LOG(LL_INFO, ("Installing timer -- %d timers currently installed", _mgos_timers)); LOG(LL_INFO, ("Installing timer -- %d timers currently installed", _mgos_timers));
(void) msecs; (void)msecs;
(void) flags; (void)flags;
(void) cb; (void)cb;
(void) cb_arg; (void)cb_arg;
return _mgos_timers; return _mgos_timers;
} }
@ -45,17 +50,17 @@ mgos_timer_id mgos_set_timer(int msecs, int flags, timer_callback cb, void *cb_a
void mgos_clear_timer(mgos_timer_id id) { void mgos_clear_timer(mgos_timer_id id) {
_mgos_timers--; _mgos_timers--;
LOG(LL_INFO, ("Clearing timer -- %d timers currently installed", _mgos_timers)); LOG(LL_INFO, ("Clearing timer -- %d timers currently installed", _mgos_timers));
(void) id; (void)id;
return; return;
} }
double mg_time() { double mg_time() {
return (float) time(NULL); return (float)time(NULL);
} }
double mgos_uptime() { double mgos_uptime() {
return (double) time(NULL); return (double)time(NULL);
} }
char *mgos_sys_ro_vars_get_mac_address() { char *mgos_sys_ro_vars_get_mac_address() {

View File

@ -8,32 +8,32 @@
#include <time.h> #include <time.h>
#include "mongoose/mongoose.h" #include "mongoose/mongoose.h"
#define MGOS_APP "unittest" #define MGOS_APP "unittest"
// mgos_log // mgos_log
enum cs_log_level { enum cs_log_level {
LL_NONE = -1, LL_NONE = -1,
LL_ERROR = 0, LL_ERROR = 0,
LL_WARN = 1, LL_WARN = 1,
LL_INFO = 2, LL_INFO = 2,
LL_DEBUG = 3, LL_DEBUG = 3,
LL_VERBOSE_DEBUG = 4, LL_VERBOSE_DEBUG = 4,
_LL_MIN = -2, _LL_MIN = -2,
_LL_MAX = 5, _LL_MAX = 5,
}; };
int log_print_prefix(enum cs_log_level l, const char *func, const char *file); int log_print_prefix(enum cs_log_level l, const char *func, const char *file);
#define LOG(l, x) \ #define LOG(l, x) \
do { \ do { \
if (log_print_prefix(l, __func__, __FILE__)) printf x; \ if (log_print_prefix(l, __func__, __FILE__)) { printf x; } \
printf("\r\n"); \ printf("\r\n"); \
} while (0) } while (0)
// mgos_timer // mgos_timer
#define MGOS_TIMER_REPEAT 1 #define MGOS_TIMER_REPEAT 1
typedef uintptr_t mgos_timer_id; typedef uintptr_t mgos_timer_id;
typedef void (*timer_callback)(void *param); typedef void (*timer_callback)(void *param);

View File

@ -1,35 +1,35 @@
#include "mgos.h" #include "mgos.h"
#include "mgos_mqtt.h" #include "mgos_mqtt.h"
uint32_t mqtt_pub_count=0; uint32_t mqtt_pub_count = 0;
uint32_t mqtt_sub_count=0; uint32_t mqtt_sub_count = 0;
static sub_handler_t s_handler; static sub_handler_t s_handler;
static void *s_handler_ud; static void * s_handler_ud;
static mg_event_handler_t s_global_handler; static mg_event_handler_t s_global_handler;
static void *s_global_handler_ud; static void *s_global_handler_ud;
void mgos_mqtt_pub(char *t, char *m, int m_len, int flags, bool persist) { void mgos_mqtt_pub(char *t, char *m, int m_len, int flags, bool persist) {
LOG(LL_INFO, ("Sending topic='%s' msg='%s' persist=%s", t, m, persist?"ON":"OFF")); LOG(LL_INFO, ("Sending topic='%s' msg='%s' persist=%s", t, m, persist ? "ON" : "OFF"));
mqtt_pub_count++; mqtt_pub_count++;
} }
void mgos_mqtt_sub(char *t, sub_handler_t cb, void *ud) { void mgos_mqtt_sub(char *t, sub_handler_t cb, void *ud) {
LOG(LL_INFO, ("Subscribing to topic='%s'", t)); LOG(LL_INFO, ("Subscribing to topic='%s'", t));
s_handler = cb; s_handler = cb;
s_handler_ud = ud; s_handler_ud = ud;
} }
void mgos_mqtt_inject(char *topic, char *msg) { void mgos_mqtt_inject(char *topic, char *msg) {
LOG(LL_INFO, ("Injecting topic='%s' msg='%s'", topic, msg)); LOG(LL_INFO, ("Injecting topic='%s' msg='%s'", topic, msg));
mqtt_sub_count++; mqtt_sub_count++;
if (s_handler) if (s_handler) {
s_handler(NULL, topic, strlen(topic), msg, strlen(msg), s_handler_ud); s_handler(NULL, topic, strlen(topic), msg, strlen(msg), s_handler_ud);
}
} }
void mgos_mqtt_add_global_handler(mqtt_event_handler_t handler, void *ud) { void mgos_mqtt_add_global_handler(mqtt_event_handler_t handler, void *ud) {
s_global_handler = handler; s_global_handler = handler;
s_global_handler_ud = ud; s_global_handler_ud = ud;
} }

View File

@ -11,7 +11,7 @@ typedef void (*sub_handler_t)(struct mg_connection *nc, const char *topic,
void *ud); void *ud);
typedef void (*mqtt_event_handler_t)(struct mg_connection *nc, int ev, typedef void (*mqtt_event_handler_t)(struct mg_connection *nc, int ev,
void *ev_data, void *user_data); void *ev_data, void *user_data);
void mgos_mqtt_pub(char *t, char *m, int m_len, int flags, bool persist); void mgos_mqtt_pub(char *t, char *m, int m_len, int flags, bool persist);
void mgos_mqtt_sub(char *t, sub_handler_t cb, void *ud); void mgos_mqtt_sub(char *t, sub_handler_t cb, void *ud);

View File

@ -5,8 +5,8 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h> #include <netdb.h>
#define MGOS_NET_IF_WIFI_STA 0 #define MGOS_NET_IF_WIFI_STA 0
#define MGOS_NET_IF_WIFI_AP 1 #define MGOS_NET_IF_WIFI_AP 1
enum mgos_net_if_type { enum mgos_net_if_type {
MGOS_NET_IF_TYPE_WIFI, MGOS_NET_IF_TYPE_WIFI,

File diff suppressed because it is too large Load Diff

View File

@ -10,13 +10,13 @@
extern int test_failures; extern int test_failures;
extern int assert_count; extern int assert_count;
#define ASSERT(expr, errstr) \ #define ASSERT(expr, errstr) \
do { \ do { \
if (!(expr)) { \ if (!(expr)) { \
LOG(LL_ERROR, ("ASSERT FAIL: "errstr)); \ LOG(LL_ERROR, ("ASSERT FAIL: "errstr)); \
test_failures++; \ test_failures++; \
} \ } \
assert_count++; \ assert_count++; \
} while (0) } while (0)

View File

@ -5,5 +5,3 @@ int test_buttons() {
channel_init("testdata/testconfig1.json"); channel_init("testdata/testconfig1.json");
return 0; return 0;
} }