diff --git a/fs/screen_one.json b/fs/screen_one.json index def1cbe..dff8059 100644 --- a/fs/screen_one.json +++ b/fs/screen_one.json @@ -1,5 +1,5 @@ { - "name": "Heli", + "name": "Sticky", "widgets": [ { "name": "back", @@ -19,7 +19,7 @@ "h": 56, "label": "On", "type": 1, - "mqtt": [ "/s/cmnd/60:01:94:80:85:01/power3 On" ] + "mqtt": [ "/s/cmnd/5C:CF:7F:20:29:6E/Power On" ] }, { "name": "heli_led_off", @@ -29,7 +29,7 @@ "h": 56, "label": "Off", "type": 1, - "mqtt": [ "/s/cmnd/60:01:94:80:85:01/power3 Off" ] + "mqtt": [ "/s/cmnd/5C:CF:7F:20:29:6E/Power Off" ] }, { "name": "heli_led_toggle", @@ -39,7 +39,7 @@ "h": 56, "label": "Toggle", "type": 1, - "mqtt": [ "/s/cmnd/60:01:94:80:85:01/power3 Toggle", "test", "foo", "bar" ] + "mqtt": [ "/s/cmnd/5C:CF:7F:20:29:6E/Power Toggle" ] } ] } diff --git a/mos.yml b/mos.yml index 132bf12..0faf163 100644 --- a/mos.yml +++ b/mos.yml @@ -39,13 +39,15 @@ config_schema: - ["app.backlight_pin", "i", {title: "Backlight pin"}] - ["app.backlight_pin", 22] - ["app.inactivity_timeout", "i", {title: "Inactivity timeout in seconds"}] - - ["app.inactivity_timeout", 10] + - ["app.inactivity_timeout", 300] - ["app.battery_calibration", i, {title: "Battery ADC value at 4000mV"}] - ["app.battery_calibration", 2360] - ["spi.enable", true] - ["spi.cs1_gpio", -1] - ["spi.cs2_gpio", -1] - ["stmpe610.cs_index", 0] + - ["mqtt.enable", true] + - ["mqtt.server", "chbtl01.paphosting.net:1883"] conds: - when: mos.platform == "esp32" @@ -76,6 +78,7 @@ libs: - origin: https://github.com/mongoose-os-libs/rpc-service-fs - origin: https://github.com/mongoose-os-libs/rpc-uart - origin: https://github.com/mongoose-os-libs/prometheus-metrics + - origin: https://github.com/mongoose-os-libs/mqtt - origin: https://github.com/mongoose-os-libs/pwm - origin: https://github.com/mongoose-os-libs/adc - origin: https://github.com/mongoose-os-libs/spi diff --git a/src/main.c b/src/main.c index ec8920e..168dda2 100644 --- a/src/main.c +++ b/src/main.c @@ -2,7 +2,7 @@ #include #include "mgos.h" -#include "mgos_pwm.h" +#include "mgos_mqtt.h" #include "mongoose-touch.h" #include "fonts/FreeSerifBold9pt7b.h" #include "fonts/FreeMonoBold9pt7b.h" @@ -34,11 +34,9 @@ static void touch_handler(struct mgos_stmpe610_event_data *ed) { widget = screen_widget_find_by_xy(s_screen, ed->x, ed->y); if (ed->direction==TOUCH_DOWN) { - widget_network_recv(); if (widget && widget->handler) widget->handler(EV_WIDGET_TOUCH_DOWN, widget, ed); } else { - widget_network_send(); if (widget && widget->handler) widget->handler(EV_WIDGET_TOUCH_UP, widget, ed); } @@ -64,9 +62,18 @@ void tft_demo(void) LOG(LL_INFO, ("Screen '%s' has %d widgets", s_screen->name, screen_get_num_widgets(s_screen))); } +static void mqtt_recv_cb(struct mg_connection *nc, const char *topic, int topic_len, const char *msg, int msg_len, void *user_data) { + widget_network_recv(); + LOG(LL_INFO, ("topic='%.*s' msg='%.*s'", topic_len, topic, msg_len, msg)); + (void) nc; + (void) user_data; +} + + enum mgos_app_init_result mgos_app_init(void) { backlight_init(); + mgos_mqtt_sub("/s/#", mqtt_recv_cb, NULL); tft_demo(); diff --git a/src/widget.c b/src/widget.c index 63e64c1..7a779a1 100644 --- a/src/widget.c +++ b/src/widget.c @@ -91,31 +91,12 @@ struct widget_t *widget_create_from_json(const char *json) { widget->user_data = screen; } } else if (type == WIDGET_TYPE_MQTT_BUTTON) { - void *h = NULL; char *mqtt = NULL; - struct json_token val; - int idx; - if (json_scanf(json, strlen(json), "{mqtt:%Q}", &mqtt) != 1) { LOG(LL_WARN, ("Widget '%s' is of type MQTT_BUTTON but does not have attribute 'mqtt'", widget->name)); } else { - // Find length of all messages - uint16_t len=0; - char *p=NULL; - while ((h = json_next_elem(json, strlen(json), h, ".mqtt", &idx, &val)) != NULL) { - LOG(LL_INFO, ("[%d]: [%.*s]", idx, val.len, val.ptr)); - len+=val.len; - } - LOG(LL_INFO, ("%d elements in the list, %d total length", idx, len)); - p=malloc(len+1+idx); - memset(p, 0, len+1+idx); - while ((h = json_next_elem(json, strlen(json), h, ".mqtt", &idx, &val)) != NULL) { - strncat(p, val.ptr, val.len); - strncat(p, "\001", len+1+idx); - } - LOG(LL_INFO, ("String is '%.*s'", len+idx, p)); - widget->user_data=p; - if(mqtt) free(mqtt); + if (widget->user_data) free(widget->user_data); + widget->user_data=mqtt; } } diff --git a/src/widget_default.c b/src/widget_default.c index edf775d..aee8bdf 100644 --- a/src/widget_default.c +++ b/src/widget_default.c @@ -1,4 +1,5 @@ #include "mgos.h" +#include "mgos_mqtt.h" #include "mongoose-touch.h" extern GFXfont FreeSerifBold9pt7b; @@ -106,6 +107,46 @@ static void widget_default_loadscreen(struct widget_t *w, void *ev_data) { (void) ev_data; } + +static void widget_default_mqtt_send(struct widget_t *w, void *ev_data) { + struct json_token val; + int idx=0; + + if (!w) + return; + if (!w->user_data) + return; +// LOG(LL_DEBUG, ("MQTT string: '%s'", (char *)w->user_data)); + // Traverse Array + for (idx = 0; json_scanf_array_elem(w->user_data, strlen(w->user_data), "", idx, &val) > 0; idx++) { + char *t=NULL, *m=NULL; + uint16_t t_len=0, m_len=0; + char *topic; + + LOG(LL_DEBUG, ("Index %d, token [%.*s]", idx, val.len, val.ptr)); + t=(char*)val.ptr; + m=strstr(val.ptr, " "); + if (m-val.ptr <= val.len) { + t_len=m-t; + m++; + m_len=val.len-t_len-1; + } else { + t_len=val.len; + m_len=0; + m=NULL; + } + if ((topic=malloc(t_len+1))) { + memcpy(topic, t, t_len); + topic[t_len]=0; + LOG(LL_INFO, ("Sending topic='%s', message='%.*s'", topic, m_len, m)); + mgos_mqtt_pub(topic, m, m_len, 0, false); + free(topic); + widget_network_send(); + } + } + (void) ev_data; +} + void widget_default_ev(int ev, struct widget_t *w, void *ev_data) { char evname[15]; @@ -124,10 +165,14 @@ void widget_default_ev(int ev, struct widget_t *w, void *ev_data) { widget_default_draw(w, ILI9341_GREEN); break; case EV_WIDGET_TOUCH_UP: - if (w->type == WIDGET_TYPE_LOADSCREEN) + if (w->type == WIDGET_TYPE_LOADSCREEN) { widget_default_loadscreen(w, ev_data); - else - widget_default_draw(w, ILI9341_GREEN); + break; + } + if (w->type == WIDGET_TYPE_MQTT_BUTTON) { + widget_default_mqtt_send(w, ev_data); + } + widget_default_draw(w, ILI9341_GREEN); break; case EV_WIDGET_TOUCH_DOWN: widget_default_draw(w, ILI9341_RED); diff --git a/unittest/data/TestWidget-MQTT.json b/unittest/data/TestWidget-MQTT.json index 990311f..57e9435 100644 --- a/unittest/data/TestWidget-MQTT.json +++ b/unittest/data/TestWidget-MQTT.json @@ -6,5 +6,5 @@ "h": 56, "label": "On", "type": 1, - "mqtt": [ "/topic1 Hello", "/topic2 World" ] + "mqtt": [ "/topic1 Hello", "/t2 Wereld", "/topic3", "", "/top4" ] } diff --git a/unittest/test_widget.c b/unittest/test_widget.c index 38e2bbb..9a9f254 100644 --- a/unittest/test_widget.c +++ b/unittest/test_widget.c @@ -72,6 +72,45 @@ int test_widget() { return 0; } +static void widget_default_mqtt_send(struct widget_t *w, void *ev_data) { + struct json_token val; + int idx=0; + + if (!w) + return; + if (!w->user_data) + return; + LOG(LL_INFO, ("MQTT string: '%s'", (char *)w->user_data)); + // Traverse Array + for (idx = 0; json_scanf_array_elem(w->user_data, strlen(w->user_data), "", idx, &val) > 0; idx++) { + char *t=NULL, *m=NULL; + uint16_t t_len=0, m_len=0; + char *topic; + + LOG(LL_DEBUG, ("Index %d, token [%.*s]", idx, val.len, val.ptr)); + t=(char*)val.ptr; + m=strstr(val.ptr, " "); + if (m-val.ptr <= val.len) { + LOG(LL_INFO, ("Space found")); + t_len=m-t; + m++; + m_len=val.len-t_len-1; + } else { + t_len=val.len; + m_len=0; + m=NULL; + } + if ((topic=malloc(t_len+1))) { + memcpy(topic, t, t_len); + topic[t_len]=0; + LOG(LL_INFO, ("Sending topic='%s', message='%.*s'", topic, m_len, m)); + free(topic); + } + } + (void) ev_data; +} + + int test_widget_mqtt() { struct widget_t *w; @@ -81,5 +120,6 @@ int test_widget_mqtt() { ASSERT(w, "widget_create_from_file()"); ASSERT(w->x == 240, "'x' field is invalid"); ASSERT(w->type == WIDGET_TYPE_MQTT_BUTTON, "'type' field is not WIDGET_TYPE_MQTT_BUTTON"); + widget_default_mqtt_send(w, NULL); return 0; }