Add MQTT buttons!
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "Heli",
|
"name": "Sticky",
|
||||||
"widgets": [
|
"widgets": [
|
||||||
{
|
{
|
||||||
"name": "back",
|
"name": "back",
|
||||||
@ -19,7 +19,7 @@
|
|||||||
"h": 56,
|
"h": 56,
|
||||||
"label": "On",
|
"label": "On",
|
||||||
"type": 1,
|
"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",
|
"name": "heli_led_off",
|
||||||
@ -29,7 +29,7 @@
|
|||||||
"h": 56,
|
"h": 56,
|
||||||
"label": "Off",
|
"label": "Off",
|
||||||
"type": 1,
|
"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",
|
"name": "heli_led_toggle",
|
||||||
@ -39,7 +39,7 @@
|
|||||||
"h": 56,
|
"h": 56,
|
||||||
"label": "Toggle",
|
"label": "Toggle",
|
||||||
"type": 1,
|
"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" ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
5
mos.yml
5
mos.yml
@ -39,13 +39,15 @@ config_schema:
|
|||||||
- ["app.backlight_pin", "i", {title: "Backlight pin"}]
|
- ["app.backlight_pin", "i", {title: "Backlight pin"}]
|
||||||
- ["app.backlight_pin", 22]
|
- ["app.backlight_pin", 22]
|
||||||
- ["app.inactivity_timeout", "i", {title: "Inactivity timeout in seconds"}]
|
- ["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", i, {title: "Battery ADC value at 4000mV"}]
|
||||||
- ["app.battery_calibration", 2360]
|
- ["app.battery_calibration", 2360]
|
||||||
- ["spi.enable", true]
|
- ["spi.enable", true]
|
||||||
- ["spi.cs1_gpio", -1]
|
- ["spi.cs1_gpio", -1]
|
||||||
- ["spi.cs2_gpio", -1]
|
- ["spi.cs2_gpio", -1]
|
||||||
- ["stmpe610.cs_index", 0]
|
- ["stmpe610.cs_index", 0]
|
||||||
|
- ["mqtt.enable", true]
|
||||||
|
- ["mqtt.server", "chbtl01.paphosting.net:1883"]
|
||||||
|
|
||||||
conds:
|
conds:
|
||||||
- when: mos.platform == "esp32"
|
- 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-service-fs
|
||||||
- origin: https://github.com/mongoose-os-libs/rpc-uart
|
- 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/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/pwm
|
||||||
- origin: https://github.com/mongoose-os-libs/adc
|
- origin: https://github.com/mongoose-os-libs/adc
|
||||||
- origin: https://github.com/mongoose-os-libs/spi
|
- origin: https://github.com/mongoose-os-libs/spi
|
||||||
|
13
src/main.c
13
src/main.c
@ -2,7 +2,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "mgos.h"
|
#include "mgos.h"
|
||||||
#include "mgos_pwm.h"
|
#include "mgos_mqtt.h"
|
||||||
#include "mongoose-touch.h"
|
#include "mongoose-touch.h"
|
||||||
#include "fonts/FreeSerifBold9pt7b.h"
|
#include "fonts/FreeSerifBold9pt7b.h"
|
||||||
#include "fonts/FreeMonoBold9pt7b.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);
|
widget = screen_widget_find_by_xy(s_screen, ed->x, ed->y);
|
||||||
|
|
||||||
if (ed->direction==TOUCH_DOWN) {
|
if (ed->direction==TOUCH_DOWN) {
|
||||||
widget_network_recv();
|
|
||||||
if (widget && widget->handler)
|
if (widget && widget->handler)
|
||||||
widget->handler(EV_WIDGET_TOUCH_DOWN, widget, ed);
|
widget->handler(EV_WIDGET_TOUCH_DOWN, widget, ed);
|
||||||
} else {
|
} else {
|
||||||
widget_network_send();
|
|
||||||
if (widget && widget->handler)
|
if (widget && widget->handler)
|
||||||
widget->handler(EV_WIDGET_TOUCH_UP, widget, ed);
|
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)));
|
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)
|
enum mgos_app_init_result mgos_app_init(void)
|
||||||
{
|
{
|
||||||
backlight_init();
|
backlight_init();
|
||||||
|
mgos_mqtt_sub("/s/#", mqtt_recv_cb, NULL);
|
||||||
|
|
||||||
tft_demo();
|
tft_demo();
|
||||||
|
|
||||||
|
23
src/widget.c
23
src/widget.c
@ -91,31 +91,12 @@ struct widget_t *widget_create_from_json(const char *json) {
|
|||||||
widget->user_data = screen;
|
widget->user_data = screen;
|
||||||
}
|
}
|
||||||
} else if (type == WIDGET_TYPE_MQTT_BUTTON) {
|
} else if (type == WIDGET_TYPE_MQTT_BUTTON) {
|
||||||
void *h = NULL;
|
|
||||||
char *mqtt = NULL;
|
char *mqtt = NULL;
|
||||||
struct json_token val;
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
if (json_scanf(json, strlen(json), "{mqtt:%Q}", &mqtt) != 1) {
|
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));
|
LOG(LL_WARN, ("Widget '%s' is of type MQTT_BUTTON but does not have attribute 'mqtt'", widget->name));
|
||||||
} else {
|
} else {
|
||||||
// Find length of all messages
|
if (widget->user_data) free(widget->user_data);
|
||||||
uint16_t len=0;
|
widget->user_data=mqtt;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "mgos.h"
|
#include "mgos.h"
|
||||||
|
#include "mgos_mqtt.h"
|
||||||
#include "mongoose-touch.h"
|
#include "mongoose-touch.h"
|
||||||
|
|
||||||
extern GFXfont FreeSerifBold9pt7b;
|
extern GFXfont FreeSerifBold9pt7b;
|
||||||
@ -106,6 +107,46 @@ static void widget_default_loadscreen(struct widget_t *w, void *ev_data) {
|
|||||||
(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) {
|
void widget_default_ev(int ev, struct widget_t *w, void *ev_data) {
|
||||||
char evname[15];
|
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);
|
widget_default_draw(w, ILI9341_GREEN);
|
||||||
break;
|
break;
|
||||||
case EV_WIDGET_TOUCH_UP:
|
case EV_WIDGET_TOUCH_UP:
|
||||||
if (w->type == WIDGET_TYPE_LOADSCREEN)
|
if (w->type == WIDGET_TYPE_LOADSCREEN) {
|
||||||
widget_default_loadscreen(w, ev_data);
|
widget_default_loadscreen(w, ev_data);
|
||||||
else
|
break;
|
||||||
widget_default_draw(w, ILI9341_GREEN);
|
}
|
||||||
|
if (w->type == WIDGET_TYPE_MQTT_BUTTON) {
|
||||||
|
widget_default_mqtt_send(w, ev_data);
|
||||||
|
}
|
||||||
|
widget_default_draw(w, ILI9341_GREEN);
|
||||||
break;
|
break;
|
||||||
case EV_WIDGET_TOUCH_DOWN:
|
case EV_WIDGET_TOUCH_DOWN:
|
||||||
widget_default_draw(w, ILI9341_RED);
|
widget_default_draw(w, ILI9341_RED);
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
"h": 56,
|
"h": 56,
|
||||||
"label": "On",
|
"label": "On",
|
||||||
"type": 1,
|
"type": 1,
|
||||||
"mqtt": [ "/topic1 Hello", "/topic2 World" ]
|
"mqtt": [ "/topic1 Hello", "/t2 Wereld", "/topic3", "", "/top4" ]
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,45 @@ int test_widget() {
|
|||||||
return 0;
|
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() {
|
int test_widget_mqtt() {
|
||||||
struct widget_t *w;
|
struct widget_t *w;
|
||||||
|
|
||||||
@ -81,5 +120,6 @@ int test_widget_mqtt() {
|
|||||||
ASSERT(w, "widget_create_from_file()");
|
ASSERT(w, "widget_create_from_file()");
|
||||||
ASSERT(w->x == 240, "'x' field is invalid");
|
ASSERT(w->x == 240, "'x' field is invalid");
|
||||||
ASSERT(w->type == WIDGET_TYPE_MQTT_BUTTON, "'type' field is not WIDGET_TYPE_MQTT_BUTTON");
|
ASSERT(w->type == WIDGET_TYPE_MQTT_BUTTON, "'type' field is not WIDGET_TYPE_MQTT_BUTTON");
|
||||||
|
widget_default_mqtt_send(w, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user