From b8e5637c8bb8edf96836903eaab2d258717f9682 Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sat, 2 Dec 2017 16:51:09 +0100 Subject: [PATCH] First start of MQTT buttons --- fs/screen_one.json | 35 ++++++++++++++++++++++++------ src/widget.c | 18 +++++++++++++++ src/widget_default.c | 10 ++++++--- src/widget_network.c | 21 ++++++++++++++++-- unittest/data/TestWidget-MQTT.json | 10 +++++++++ unittest/data/TestWidget.json | 2 +- unittest/main.c | 1 + unittest/test.h | 1 + unittest/test_widget.c | 12 ++++++++++ 9 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 unittest/data/TestWidget-MQTT.json diff --git a/fs/screen_one.json b/fs/screen_one.json index b179db8..def1cbe 100644 --- a/fs/screen_one.json +++ b/fs/screen_one.json @@ -1,5 +1,5 @@ { - "name": "One", + "name": "Heli", "widgets": [ { "name": "back", @@ -12,13 +12,34 @@ "screen": "/screen_main.json" }, { - "name": "one", - "x": 256, + "name": "heli_led_on", + "x": 240, "y": 36, - "w": 48, - "h": 48, - "label": "One", - "type": 0 + "w": 64, + "h": 56, + "label": "On", + "type": 1, + "mqtt": [ "/s/cmnd/60:01:94:80:85:01/power3 On" ] + }, + { + "name": "heli_led_off", + "x": 240, + "y": 108, + "w": 64, + "h": 56, + "label": "Off", + "type": 1, + "mqtt": [ "/s/cmnd/60:01:94:80:85:01/power3 Off" ] + }, + { + "name": "heli_led_toggle", + "x": 240, + "y": 180, + "w": 64, + "h": 56, + "label": "Toggle", + "type": 1, + "mqtt": [ "/s/cmnd/60:01:94:80:85:01/power3 Toggle", "test", "foo", "bar" ] } ] } diff --git a/src/widget.c b/src/widget.c index e49bbb5..66da807 100644 --- a/src/widget.c +++ b/src/widget.c @@ -81,6 +81,8 @@ struct widget_t *widget_create_from_json(const char *json) { widget->type=type; widget->label=label; widget->img=img; + + // Load widget-specific attributes if (type == WIDGET_TYPE_LOADSCREEN) { if (json_scanf(json, strlen(json), "{screen:%Q}", &screen) != 1) { LOG(LL_WARN, ("Widget '%s' is of type LOADSCREEN but does not have attribute 'screen'", widget->name)); @@ -88,6 +90,22 @@ struct widget_t *widget_create_from_json(const char *json) { if (widget->user_data) free(widget->user_data); 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 { + while ((h = json_next_elem(json, strlen(json), h, ".mqtt", &idx, &val)) != NULL) { + LOG(LL_INFO, ("[%d]: [%.*s]", idx, val.len, val.ptr)); + if (val.len>0 && val.ptr) { + } + } + if(mqtt) free(mqtt); + } } return widget; diff --git a/src/widget_default.c b/src/widget_default.c index c2da05a..edf775d 100644 --- a/src/widget_default.c +++ b/src/widget_default.c @@ -78,6 +78,7 @@ void screen_add_default_widgets(struct screen_t *screen) { static void widget_default_loadscreen(struct widget_t *w, void *ev_data) { struct screen_t *new_screen; + char *new_screen_fn; if (!w) return; @@ -86,8 +87,12 @@ static void widget_default_loadscreen(struct widget_t *w, void *ev_data) { return; } + new_screen_fn=strdup(w->user_data); + + screen_destroy(&s_screen); + new_screen = screen_create_from_file(new_screen_fn, widget_default_ev, NULL); + free(new_screen_fn); - new_screen = screen_create_from_file(w->user_data, widget_default_ev, NULL); if (!new_screen) { LOG(LL_ERROR, ("Could not load screen")); return; @@ -95,7 +100,6 @@ static void widget_default_loadscreen(struct widget_t *w, void *ev_data) { screen_add_default_widgets(new_screen); LOG(LL_INFO, ("Navigating to new screen '%s' which has %d widgets", new_screen->name, screen_get_num_widgets(new_screen))); - screen_destroy(&s_screen); s_screen = new_screen; screen_widget_broadcast(s_screen, EV_WIDGET_DRAW, NULL); @@ -109,7 +113,7 @@ void widget_default_ev(int ev, struct widget_t *w, void *ev_data) { return; widget_ev_to_str(ev, evname, sizeof(evname)-1); - LOG(LL_INFO, ("Event %s received for widget '%s'", evname, w->name)); + LOG(LL_DEBUG, ("Event %s received for widget '%s'", evname, w->name)); switch(ev) { case EV_WIDGET_CREATE: diff --git a/src/widget_network.c b/src/widget_network.c index e383e1f..65ba015 100644 --- a/src/widget_network.c +++ b/src/widget_network.c @@ -7,6 +7,9 @@ static mgos_timer_id recv_timer = 0; static struct widget_t *widget_network = NULL; static void widget_network_render(struct widget_t *w, void *ev_data) { + if (!w) + return; + mgos_ili9341_set_window(w->x, w->y, w->x+w->w-1, w->y+w->h-1); // Send mgos_ili9341_set_fgcolor565(send_timer?ILI9341_YELLOW:ILI9341_DARKGREY); @@ -34,8 +37,10 @@ static void widget_network_recv_clear(void *arg) { } void widget_network_send() { - if (!widget_network) + if (!widget_network) { + LOG(LL_ERROR, ("called without widget_network set")); return; + } if (!send_timer) send_timer=mgos_set_timer(100, 0, widget_network_send_clear, NULL); @@ -43,8 +48,10 @@ void widget_network_send() { } void widget_network_recv() { - if (!widget_network) + if (!widget_network) { + LOG(LL_ERROR, ("called without widget_network set")); return; + } if (!recv_timer) recv_timer=mgos_set_timer(100, 0, widget_network_recv_clear, NULL); @@ -52,12 +59,18 @@ void widget_network_recv() { } void widget_network_ev(int ev, struct widget_t *w, void *ev_data) { + char evname[15]; if (!w) return; + widget_ev_to_str(ev, evname, sizeof(evname)-1); + LOG(LL_DEBUG, ("Event %s received for widget '%s'", evname, w->name)); + switch(ev) { case EV_WIDGET_CREATE: widget_network=w; + send_timer=0; + recv_timer=0; break; case EV_WIDGET_DRAW: case EV_WIDGET_REDRAW: @@ -65,7 +78,11 @@ void widget_network_ev(int ev, struct widget_t *w, void *ev_data) { break; case EV_WIDGET_DESTROY: widget_network=NULL; + if (send_timer) + mgos_clear_timer(send_timer); send_timer=0; + if (recv_timer) + mgos_clear_timer(recv_timer); recv_timer=0; break; case EV_WIDGET_TIMER: diff --git a/unittest/data/TestWidget-MQTT.json b/unittest/data/TestWidget-MQTT.json new file mode 100644 index 0000000..990311f --- /dev/null +++ b/unittest/data/TestWidget-MQTT.json @@ -0,0 +1,10 @@ +{ + "name": "heli_led_on", + "x": 240, + "y": 36, + "w": 64, + "h": 56, + "label": "On", + "type": 1, + "mqtt": [ "/topic1 Hello", "/topic2 World" ] +} diff --git a/unittest/data/TestWidget.json b/unittest/data/TestWidget.json index 76cadac..d4bdcb3 100644 --- a/unittest/data/TestWidget.json +++ b/unittest/data/TestWidget.json @@ -5,6 +5,6 @@ "w": 48, "h": 48, "label": "One", - "type": 0 + "type": 0, "img": "/some/file.ext" } diff --git a/unittest/main.c b/unittest/main.c index 2b5dbce..516fb9c 100644 --- a/unittest/main.c +++ b/unittest/main.c @@ -5,6 +5,7 @@ int assert_count=0; int main() { test_widget(); + test_widget_mqtt(); test_screen(); if (test_failures) { diff --git a/unittest/test.h b/unittest/test.h index 3f211b2..bf4df84 100644 --- a/unittest/test.h +++ b/unittest/test.h @@ -21,6 +21,7 @@ extern int assert_count; int test_widget(void); +int test_widget_mqtt(void); int test_screen(void); #endif // __TEST_H diff --git a/unittest/test_widget.c b/unittest/test_widget.c index c0105c0..38e2bbb 100644 --- a/unittest/test_widget.c +++ b/unittest/test_widget.c @@ -71,3 +71,15 @@ int test_widget() { return 0; } + +int test_widget_mqtt() { + struct widget_t *w; + + char *fn = "data/TestWidget-MQTT.json"; + LOG(LL_INFO, ("widget_create_from_file(%s)", fn)); + w = widget_create_from_file(fn); + 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"); + return 0; +}