Add lightswitch to this firmware
This commit is contained in:
23
fs/mqtt.pem
Normal file
23
fs/mqtt.pem
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDvzCCAqegAwIBAgIJAOfvQdPViBT2MA0GCSqGSIb3DQEBCwUAMHYxCzAJBgNV
|
||||||
|
BAYTAkNIMQswCQYDVQQIDAJaSDEVMBMGA1UEBwwMQnJ1dHRpc2VsbGVuMRAwDgYD
|
||||||
|
VQQKDAdJUG5nLm5sMRUwEwYDVQQDDAxtcXR0LmlwbmcubmwxGjAYBgkqhkiG9w0B
|
||||||
|
CQEWC3BpbUBpcG5nLm5sMB4XDTE3MTIxNzEwMDMwOVoXDTIyMTIxNzEwMDMwOVow
|
||||||
|
djELMAkGA1UEBhMCQ0gxCzAJBgNVBAgMAlpIMRUwEwYDVQQHDAxCcnV0dGlzZWxs
|
||||||
|
ZW4xEDAOBgNVBAoMB0lQbmcubmwxFTATBgNVBAMMDG1xdHQuaXBuZy5ubDEaMBgG
|
||||||
|
CSqGSIb3DQEJARYLcGltQGlwbmcubmwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||||
|
ggEKAoIBAQDH8aZRJPF/wHHLG7LDPp6zJsAv4MbgmhEMLsl4pv3Z7gp0ftsJEqVy
|
||||||
|
Wkb5ab5jNDbPgxn2djJG1j1947boCV1AnRQQY2klfwFSEi41o+ncKzu8vjYETvJA
|
||||||
|
8jz+iqh9Izw+31HNp+TxVabQ5AQnd+9sMq+enTTC/fQoY9TSSh4pMqMuT7kBE5zu
|
||||||
|
lecHGi78Mw4v2WXXUFm3otfVa4disFBw3EAZMQOeh+C9sTx+QGjDQJ2n+dvn5HUI
|
||||||
|
23xfRsaX9U8nGbf57/QyoG+r0gP83DK6Ed7Z1AtEY7VUcB7+qOloEh7lweb6h+Z3
|
||||||
|
RL3N6o5eCLPaEfIhBTbli4kCmZzTarULAgMBAAGjUDBOMB0GA1UdDgQWBBRJgIbw
|
||||||
|
FOVojHrq/OhjjTpqdWXwHjAfBgNVHSMEGDAWgBRJgIbwFOVojHrq/OhjjTpqdWXw
|
||||||
|
HjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBFI5a7ZRr5li/yYOmt
|
||||||
|
VOHcLysxVSF1uDkAwoA/L+NL4/xWp9MYo9XlJ5Ug730PztC5rhpV5fAo57X8v4P8
|
||||||
|
dWJgnoJ40ivExLrp87pzrO9p1IkDcfFXVfCyatd453iBiD1iRkwheqTld+I9mKNa
|
||||||
|
Spf8kJxODz5C6LSqr6AuBMNOJVs0rXSzHawiFxGFZKMJ0glMAuH5mnmXD6+KVhOG
|
||||||
|
MbCKQxstq4e6/0VexzPXIcqEEf1XmB9ga1AwFJm46N6u4XTM99YpvSh1/6DqRHHF
|
||||||
|
6sdWSTx++N+sQJJhBDTQ5E6Zb/AOkmT+bipU49heRk5uGgTyR0wPDWywP73ZHKas
|
||||||
|
kMT3
|
||||||
|
-----END CERTIFICATE-----
|
26
include/buttons.h
Normal file
26
include/buttons.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __BUTTONS_H
|
||||||
|
#define __BUTTONS_H
|
||||||
|
|
||||||
|
#include "mgos.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_BUTTONS 8
|
||||||
|
|
||||||
|
struct button_t {
|
||||||
|
uint8_t gpio;
|
||||||
|
float last_change;
|
||||||
|
};
|
||||||
|
|
||||||
|
int buttons_init(const char *flag);
|
||||||
|
uint8_t buttons_find_by_gpio(uint8_t gpio);
|
||||||
|
bool buttons_touch_by_gpio(uint8_t gpio);
|
||||||
|
float buttons_get_last_change_by_gpio(uint8_t gpio);
|
||||||
|
|
||||||
|
bool buttons_touch_by_idx(uint8_t idx);
|
||||||
|
float buttons_get_last_change_by_idx(uint8_t idx);
|
||||||
|
uint8_t buttons_get_gpio_by_idx(uint8_t idx);
|
||||||
|
|
||||||
|
void buttons_cb(int gpio, void *args);
|
||||||
|
|
||||||
|
#endif // __BUTTONS_H
|
||||||
|
|
19
include/helper.h
Normal file
19
include/helper.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef __HELPER_H
|
||||||
|
#define __HELPER_H
|
||||||
|
|
||||||
|
#include "mgos.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
|
||||||
|
#define MIN_GPIO 0
|
||||||
|
#define MAX_GPIO 16
|
||||||
|
#define MQTT_TOPIC_PREFIX ""
|
||||||
|
#define MQTT_TOPIC_BROADCAST_CMD "/mongoose/broadcast"
|
||||||
|
#define MQTT_TOPIC_BROADCAST_STAT "/mongoose/broadcast/stat"
|
||||||
|
|
||||||
|
#define ERR_GPIO_INVALID 255
|
||||||
|
|
||||||
|
bool is_button_flag_valid(const char *flag);
|
||||||
|
bool is_relay_flag_valid(const char *flag);
|
||||||
|
|
||||||
|
#endif // __HELPER_H
|
10
include/lightswitch.h
Normal file
10
include/lightswitch.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef __LIGHTSWITCH_H
|
||||||
|
#define __LIGHTSWITCH_h
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "mgos.h"
|
||||||
|
#include "helper.h"
|
||||||
|
#include "buttons.h"
|
||||||
|
#include "relays.h"
|
||||||
|
|
||||||
|
#endif // __LIGHTSWITCH_h
|
10
include/mqtt.h
Normal file
10
include/mqtt.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef __MQTT_H
|
||||||
|
#define __MQTT_H
|
||||||
|
|
||||||
|
#include "mgos.h"
|
||||||
|
#include "mgos_mqtt.h"
|
||||||
|
|
||||||
|
void mqtt_init();
|
||||||
|
void mqtt_publish_stat(const char *stat, const char *msg);
|
||||||
|
|
||||||
|
#endif // __MQTT_H
|
26
include/relays.h
Normal file
26
include/relays.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __RELAYS_H
|
||||||
|
#define __RELAYS_H
|
||||||
|
|
||||||
|
#include "mgos.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_RELAYS 8
|
||||||
|
|
||||||
|
struct relay_t {
|
||||||
|
uint8_t gpio;
|
||||||
|
float last_change;
|
||||||
|
bool state;
|
||||||
|
};
|
||||||
|
|
||||||
|
int relays_init(const char *flag);
|
||||||
|
uint8_t relays_find_by_gpio(uint8_t gpio);
|
||||||
|
bool relays_set_by_gpio(uint8_t gpio, bool state);
|
||||||
|
bool relays_get_by_gpio(uint8_t gpio);
|
||||||
|
float relays_get_last_change_by_gpio(uint8_t gpio);
|
||||||
|
|
||||||
|
bool relays_set_by_idx(uint8_t idx, bool state);
|
||||||
|
bool relays_get_by_idx(uint8_t idx);
|
||||||
|
float relays_get_last_change_by_idx(uint8_t idx);
|
||||||
|
uint8_t relays_get_gpio_by_idx(uint8_t idx);
|
||||||
|
#endif // __RELAYS_H
|
||||||
|
|
10
include/rpc.h
Normal file
10
include/rpc.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef __RPC_H
|
||||||
|
#define __RPC_H
|
||||||
|
|
||||||
|
#include "mgos.h"
|
||||||
|
#include "mgos_rpc.h"
|
||||||
|
#include "common/mg_str.h"
|
||||||
|
|
||||||
|
void rpc_init();
|
||||||
|
|
||||||
|
#endif // __RPC_H
|
15
mos.yml
15
mos.yml
@ -46,6 +46,10 @@ config_schema:
|
|||||||
- ["app.inactivity_timeout", 10]
|
- ["app.inactivity_timeout", 10]
|
||||||
- ["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]
|
||||||
|
- ["app.buttons", "s", {title: "comma-separated list of button pins"}]
|
||||||
|
- ["app.buttons", "0,2"]
|
||||||
|
- ["app.relays", "s", {title: "comma-separated list of relay pins"}]
|
||||||
|
- ["app.relays", "16,12,13,14"]
|
||||||
- ["spi.enable", true]
|
- ["spi.enable", true]
|
||||||
- ["spi.cs1_gpio", -1]
|
- ["spi.cs1_gpio", -1]
|
||||||
- ["spi.cs2_gpio", -1]
|
- ["spi.cs2_gpio", -1]
|
||||||
@ -53,7 +57,11 @@ config_schema:
|
|||||||
- ["stmpe610.cs_index", 1]
|
- ["stmpe610.cs_index", 1]
|
||||||
- ["stmpe610.orientation", 5] # Set to 4 for 2.4" Featherwing, set to 5 for 3.5" Featherwing
|
- ["stmpe610.orientation", 5] # Set to 4 for 2.4" Featherwing, set to 5 for 3.5" Featherwing
|
||||||
- ["mqtt.enable", true]
|
- ["mqtt.enable", true]
|
||||||
- ["mqtt.server", "chbtl01.paphosting.net:1883"]
|
- ["http.enable", true]
|
||||||
|
- ["mqtt.server", "mqtt.ipng.nl:8883"]
|
||||||
|
- ["mqtt.ssl_ca_cert", "mqtt.pem"]
|
||||||
|
- ["rpc.mqtt.enable", true]
|
||||||
|
|
||||||
|
|
||||||
conds:
|
conds:
|
||||||
- when: mos.platform == "esp32"
|
- when: mos.platform == "esp32"
|
||||||
@ -83,14 +91,15 @@ libs:
|
|||||||
- origin: https://github.com/mongoose-os-libs/rpc-service-config
|
- origin: https://github.com/mongoose-os-libs/rpc-service-config
|
||||||
- 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/prometheus-metrics
|
- origin: https://github.com/mongoose-os-libs/prometheus-metrics
|
||||||
|
- origin: https://github.com/mongoose-os-libs/rpc-common
|
||||||
|
- origin: https://github.com/mongoose-os-libs/rpc-service-config
|
||||||
|
- origin: https://github.com/mongoose-os-libs/rpc-mqtt
|
||||||
- origin: https://github.com/mongoose-os-libs/mqtt
|
- 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
|
||||||
- origin: https://github.com/mongoose-os-libs/ili9341-spi
|
- origin: https://github.com/mongoose-os-libs/ili9341-spi
|
||||||
- origin: https://github.com/mongoose-os-libs/stmpe610-spi
|
- origin: https://github.com/mongoose-os-libs/stmpe610-spi
|
||||||
- origin: libs/ota-http-client
|
|
||||||
- origin: libs/ota-http-server
|
|
||||||
- origin: libs/rpc-service-ota
|
- origin: libs/rpc-service-ota
|
||||||
|
|
||||||
|
|
||||||
|
119
src/buttons.c
Normal file
119
src/buttons.c
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include "mqtt.h"
|
||||||
|
#include "mgos_gpio.h"
|
||||||
|
#include "buttons.h"
|
||||||
|
#include "relays.h"
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
|
struct button_t s_buttons[MAX_BUTTONS];
|
||||||
|
|
||||||
|
void buttons_cb(int gpio, void *arg) {
|
||||||
|
int idx = buttons_find_by_gpio(gpio);
|
||||||
|
|
||||||
|
if (ERR_GPIO_INVALID == idx) {
|
||||||
|
LOG(LL_ERROR, ("No button on gpio=%d", gpio));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG(LL_INFO, ("Button on gpio=%d idx=%d", gpio, idx));
|
||||||
|
|
||||||
|
buttons_touch_by_idx(idx);
|
||||||
|
return;
|
||||||
|
(void) arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int buttons_init(const char *flag) {
|
||||||
|
int next_button=0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(s_buttons, -1, sizeof(s_buttons));
|
||||||
|
|
||||||
|
LOG(LL_DEBUG, ("Flag='%s'", flag));
|
||||||
|
if (!is_button_flag_valid(flag)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i=0;
|
||||||
|
while(i<(int) strlen(flag)) {
|
||||||
|
int gpio = -1;
|
||||||
|
|
||||||
|
if (!isdigit((int) flag[i])) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio = atoi((char *)flag+i);
|
||||||
|
// LOG(LL_DEBUG, ("Token: %d at pos %u", gpio, i));
|
||||||
|
if (gpio<MIN_GPIO || gpio>MAX_GPIO) {
|
||||||
|
LOG(LL_ERROR, ("GPIO values must be within [%d,%d], gpio=%d is invalid", MIN_GPIO, MAX_GPIO, gpio));
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
s_buttons[next_button].gpio=gpio;
|
||||||
|
s_buttons[next_button].last_change=-1;
|
||||||
|
mgos_gpio_set_mode(gpio, MGOS_GPIO_MODE_INPUT);
|
||||||
|
mgos_gpio_set_button_handler(gpio, MGOS_GPIO_PULL_UP, MGOS_GPIO_INT_EDGE_NEG, 100, buttons_cb, NULL);
|
||||||
|
|
||||||
|
next_button++;
|
||||||
|
if (next_button>MAX_BUTTONS) {
|
||||||
|
LOG(LL_ERROR, ("Too many buttons defined, max is %d", MAX_BUTTONS));
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i<(int)strlen(flag) && isdigit((int) flag[i])) i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t buttons_get_gpio_by_idx(uint8_t idx) {
|
||||||
|
if (idx>=MAX_BUTTONS)
|
||||||
|
return ERR_GPIO_INVALID;
|
||||||
|
return s_buttons[idx].gpio;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t buttons_find_by_gpio(uint8_t gpio) {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<MAX_BUTTONS; i++) {
|
||||||
|
if (gpio==s_buttons[i].gpio)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return ERR_GPIO_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool buttons_touch_by_idx(uint8_t idx) {
|
||||||
|
char msg[80];
|
||||||
|
int relay_gpio;
|
||||||
|
|
||||||
|
if (idx>=MAX_BUTTONS || s_buttons[idx].gpio == ERR_GPIO_INVALID) {
|
||||||
|
LOG(LL_ERROR, ("No button at idx=%d", idx));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
s_buttons[idx].last_change=mg_time();
|
||||||
|
|
||||||
|
snprintf(msg, sizeof(msg)-1, "{\"idx\": %d, \"gpio\": %d}", idx, s_buttons[idx].gpio);
|
||||||
|
mqtt_publish_stat("button", msg);
|
||||||
|
|
||||||
|
// Lookup corresponding relay at the same index. If it exists, trigger it.
|
||||||
|
relay_gpio = relays_get_gpio_by_idx(idx);
|
||||||
|
if (ERR_GPIO_INVALID == relay_gpio)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
relays_set_by_gpio(relay_gpio, !relays_get_by_gpio(relay_gpio));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool buttons_touch_by_gpio(uint8_t gpio) {
|
||||||
|
return buttons_touch_by_idx(buttons_find_by_gpio(gpio));
|
||||||
|
}
|
||||||
|
|
||||||
|
float buttons_get_last_change_by_gpio(uint8_t gpio) {
|
||||||
|
return buttons_get_last_change_by_idx(buttons_find_by_gpio(gpio));
|
||||||
|
}
|
||||||
|
|
||||||
|
float buttons_get_last_change_by_idx(uint8_t idx) {
|
||||||
|
if (idx>=MAX_BUTTONS || s_buttons[idx].gpio == ERR_GPIO_INVALID) {
|
||||||
|
LOG(LL_ERROR, ("No button at idx=%d", idx));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return s_buttons[idx].last_change;
|
||||||
|
}
|
22
src/helper.c
Normal file
22
src/helper.c
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "helper.h"
|
||||||
|
|
||||||
|
static bool is_csv_of_digits(const char *flag) {
|
||||||
|
unsigned char *p = (unsigned char*)flag;
|
||||||
|
|
||||||
|
while (*p) {
|
||||||
|
if (*p!=' ' && !isdigit(*p) && *p!=',') {
|
||||||
|
LOG(LL_ERROR, ("Flag value '%s' invalid CSV of digits at pos %d: use only digits, ' ' and ','", flag, (int) ((char*)p-(char*)flag)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_button_flag_valid(const char *flag) {
|
||||||
|
return is_csv_of_digits(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_relay_flag_valid(const char *flag) {
|
||||||
|
return is_csv_of_digits(flag);
|
||||||
|
}
|
18
src/main.c
18
src/main.c
@ -6,6 +6,11 @@
|
|||||||
#include "mongoose-touch.h"
|
#include "mongoose-touch.h"
|
||||||
#include "fonts/FreeSerifBold9pt7b.h"
|
#include "fonts/FreeSerifBold9pt7b.h"
|
||||||
#include "fonts/FreeMonoBold9pt7b.h"
|
#include "fonts/FreeMonoBold9pt7b.h"
|
||||||
|
#include "mgos_config.h"
|
||||||
|
#include "buttons.h"
|
||||||
|
#include "relays.h"
|
||||||
|
#include "mqtt.h"
|
||||||
|
#include "rpc.h"
|
||||||
|
|
||||||
struct screen_t *s_screen = NULL;
|
struct screen_t *s_screen = NULL;
|
||||||
|
|
||||||
@ -62,18 +67,13 @@ 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)
|
||||||
{
|
{
|
||||||
|
buttons_init(mgos_sys_config_get_app_buttons());
|
||||||
|
relays_init(mgos_sys_config_get_app_relays());
|
||||||
|
mqtt_init();
|
||||||
|
rpc_init();
|
||||||
backlight_init();
|
backlight_init();
|
||||||
mgos_mqtt_sub("/s/#", mqtt_recv_cb, NULL);
|
|
||||||
|
|
||||||
tft_demo();
|
tft_demo();
|
||||||
|
|
||||||
|
84
src/mqtt.c
Normal file
84
src/mqtt.c
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "mgos.h"
|
||||||
|
#include "mgos_mqtt.h"
|
||||||
|
#include "mgos_config.h"
|
||||||
|
#include "mqtt.h"
|
||||||
|
#include "buttons.h"
|
||||||
|
#include "relays.h"
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
|
static void mqtt_publish_broadcast_stat(const char *stat, const char *msg) {
|
||||||
|
char topic[80];
|
||||||
|
snprintf(topic, sizeof(topic)-1, "%s/%s", MQTT_TOPIC_BROADCAST_STAT, stat);
|
||||||
|
mgos_mqtt_pub((char*)topic, (char*)msg, strlen(msg), 0, false);
|
||||||
|
LOG(LL_INFO, ("Sent topic='%s' msg='%s'", topic, msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mqtt_broadcast_cmd_id() {
|
||||||
|
char resp[300];
|
||||||
|
struct mgos_net_ip_info ip_info;
|
||||||
|
char sta_ip[16], ap_ip[16];
|
||||||
|
|
||||||
|
memset(sta_ip, 0, sizeof(sta_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))
|
||||||
|
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))
|
||||||
|
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}",
|
||||||
|
mgos_sys_config_get_device_id(),
|
||||||
|
mgos_sys_ro_vars_get_mac_address(),
|
||||||
|
sta_ip,
|
||||||
|
ap_ip,
|
||||||
|
MGOS_APP,
|
||||||
|
mgos_sys_ro_vars_get_arch(), (unsigned long) mgos_uptime());
|
||||||
|
|
||||||
|
mqtt_publish_broadcast_stat("id", resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mqtt_cb(struct mg_connection *nc, const char *topic, int topic_len, const char *msg, int msg_len, void *ud) {
|
||||||
|
LOG(LL_INFO, ("Received topic='%.*s' msg='%.*s'", topic_len, topic, msg_len, msg));
|
||||||
|
|
||||||
|
if (topic_len >= strlen(MQTT_TOPIC_BROADCAST_CMD) && 0 == strncmp(MQTT_TOPIC_BROADCAST_CMD, topic, strlen(MQTT_TOPIC_BROADCAST_CMD)))
|
||||||
|
mqtt_broadcast_cmd_id();
|
||||||
|
(void) nc;
|
||||||
|
(void) ud;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mqtt_ev(struct mg_connection *nc, int ev, void *ev_data, void *user_data) {
|
||||||
|
switch (ev) {
|
||||||
|
case MG_EV_MQTT_CONNACK:
|
||||||
|
mqtt_broadcast_cmd_id();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(void) nc;
|
||||||
|
(void) ev_data;
|
||||||
|
(void) user_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mqtt_publish_stat(const char *stat, const char *msg) {
|
||||||
|
char topic[80];
|
||||||
|
snprintf(topic, sizeof(topic)-1, "%s%s/stat/%s", MQTT_TOPIC_PREFIX, mgos_sys_config_get_device_id(), stat);
|
||||||
|
mgos_mqtt_pub((char*)topic, (char*)msg, strlen(msg), 0, false);
|
||||||
|
LOG(LL_INFO, ("Sent topic='%s' msg='%s'", topic, msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mqtt_init() {
|
||||||
|
char topic[100];
|
||||||
|
|
||||||
|
mgos_mqtt_add_global_handler(mqtt_ev, NULL);
|
||||||
|
|
||||||
|
// Subscribe to broadcast for identification purposes
|
||||||
|
mgos_mqtt_sub(MQTT_TOPIC_BROADCAST_CMD, mqtt_cb, NULL);
|
||||||
|
|
||||||
|
// Subscribe to broadcast/appname
|
||||||
|
snprintf(topic, sizeof(topic)-1, "%s/%s", MQTT_TOPIC_BROADCAST_CMD, MGOS_APP);
|
||||||
|
mgos_mqtt_sub(topic, mqtt_cb, NULL);
|
||||||
|
|
||||||
|
// Subscribe to Sonoff updates
|
||||||
|
mgos_mqtt_sub("/s/#", mqtt_cb, NULL);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
112
src/relays.c
Normal file
112
src/relays.c
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#include "mgos_gpio.h"
|
||||||
|
#include "mqtt.h"
|
||||||
|
#include "relays.h"
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
|
struct relay_t s_relays[MAX_RELAYS];
|
||||||
|
|
||||||
|
int relays_init(const char *flag) {
|
||||||
|
int next_relay=0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(s_relays, -1, sizeof(s_relays));
|
||||||
|
|
||||||
|
LOG(LL_DEBUG, ("Flag='%s'", flag));
|
||||||
|
if (!is_relay_flag_valid(flag)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i=0;
|
||||||
|
while(i<(int) strlen(flag)) {
|
||||||
|
int gpio = -1;
|
||||||
|
|
||||||
|
if (!isdigit((int) flag[i])) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio = atoi((char *)flag+i);
|
||||||
|
// LOG(LL_DEBUG, ("Token: %d at pos %u", gpio, i));
|
||||||
|
if (gpio<MIN_GPIO || gpio>MAX_GPIO) {
|
||||||
|
LOG(LL_ERROR, ("GPIO values must be within [%d,%d], gpio=%d is invalid", MIN_GPIO, MAX_GPIO, gpio));
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
s_relays[next_relay].gpio=gpio;
|
||||||
|
s_relays[next_relay].last_change=-1;
|
||||||
|
s_relays[next_relay].state=0;
|
||||||
|
mgos_gpio_set_mode(gpio, MGOS_GPIO_MODE_OUTPUT);
|
||||||
|
mgos_gpio_write(gpio, !s_relays[next_relay].state);
|
||||||
|
next_relay++;
|
||||||
|
if (next_relay>MAX_RELAYS) {
|
||||||
|
LOG(LL_ERROR, ("Too many relays defined, max is %d", MAX_RELAYS));
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i<(int)strlen(flag) && isdigit((int) flag[i])) i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t relays_get_gpio_by_idx(uint8_t idx) {
|
||||||
|
if (idx>=MAX_RELAYS)
|
||||||
|
return ERR_GPIO_INVALID;
|
||||||
|
return s_relays[idx].gpio;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t relays_find_by_gpio(uint8_t gpio) {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<MAX_RELAYS; i++) {
|
||||||
|
if (gpio==s_relays[i].gpio)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return ERR_GPIO_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool relays_set_by_gpio(uint8_t gpio, bool state) {
|
||||||
|
return relays_set_by_idx(relays_find_by_gpio(gpio), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool relays_set_by_idx(uint8_t idx, bool state) {
|
||||||
|
char msg[60];
|
||||||
|
|
||||||
|
if (idx>=MAX_RELAYS || s_relays[idx].gpio == ERR_GPIO_INVALID) {
|
||||||
|
LOG(LL_ERROR, ("No relay at idx=%d", idx));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
s_relays[idx].last_change=mg_time();
|
||||||
|
if (state != s_relays[idx].state) {
|
||||||
|
|
||||||
|
LOG(LL_INFO, ("Setting relay idx=%d gpio=%d to %s", idx, s_relays[idx].gpio, state==true?"ON":"OFF"));
|
||||||
|
s_relays[idx].state=state;
|
||||||
|
mgos_gpio_write(s_relays[idx].gpio, !s_relays[idx].state);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(msg, sizeof(msg)-1, "{\"idx\": %d, \"gpio\": %d, \"state\": %d}", idx, s_relays[idx].gpio, state);
|
||||||
|
mqtt_publish_stat("relay", msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool relays_get_by_gpio(uint8_t gpio) {
|
||||||
|
return relays_get_by_idx(relays_find_by_gpio(gpio));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool relays_get_by_idx(uint8_t idx) {
|
||||||
|
if (idx>=MAX_RELAYS || s_relays[idx].gpio == ERR_GPIO_INVALID) {
|
||||||
|
LOG(LL_ERROR, ("No relay at idx=%d", idx));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return s_relays[idx].state;
|
||||||
|
}
|
||||||
|
|
||||||
|
float relays_get_last_change_by_gpio(uint8_t gpio) {
|
||||||
|
return relays_get_last_change_by_idx(relays_find_by_gpio(gpio));
|
||||||
|
}
|
||||||
|
|
||||||
|
float relays_get_last_change_by_idx(uint8_t idx) {
|
||||||
|
if (idx>=MAX_RELAYS || s_relays[idx].gpio == ERR_GPIO_INVALID) {
|
||||||
|
LOG(LL_ERROR, ("No relay at idx=%d", idx));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return s_relays[idx].last_change;
|
||||||
|
}
|
133
src/rpc.c
Normal file
133
src/rpc.c
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#include "rpc.h"
|
||||||
|
#include "relays.h"
|
||||||
|
#include "buttons.h"
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
|
static void rpc_log(struct mg_rpc_request_info *ri, struct mg_str args) {
|
||||||
|
LOG(LL_INFO, ("tag=%.*s src=%.*s method=%.*s args='%.*s'",
|
||||||
|
ri->tag.len, ri->tag.p, ri->src.len, ri->src.p,
|
||||||
|
ri->method.len, ri->method.p, args.len, args.p));
|
||||||
|
// TODO(pim): log to MQTT
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void rpc_button_touch_handler(struct mg_rpc_request_info *ri, void *cb_arg, struct mg_rpc_frame_info *fi, struct mg_str args) {
|
||||||
|
int idx;
|
||||||
|
uint8_t gpio;
|
||||||
|
|
||||||
|
rpc_log(ri, args);
|
||||||
|
|
||||||
|
if (json_scanf(args.p, args.len, ri->args_fmt, &idx) != 1) {
|
||||||
|
mg_rpc_send_errorf(ri, 400, "idx is required");
|
||||||
|
ri = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ERR_GPIO_INVALID==(gpio=buttons_get_gpio_by_idx(idx))) {
|
||||||
|
mg_rpc_send_errorf(ri, 400, "No button at idx=%d", idx);
|
||||||
|
ri = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buttons_touch_by_idx(idx);
|
||||||
|
mg_rpc_send_responsef(ri, "{idx: %d, gpio: %d}", idx, gpio);
|
||||||
|
ri = NULL;
|
||||||
|
|
||||||
|
(void) ri;
|
||||||
|
(void) cb_arg;
|
||||||
|
(void) fi;
|
||||||
|
(void) args;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpc_relay_get_handler(struct mg_rpc_request_info *ri, void *cb_arg, struct mg_rpc_frame_info *fi, struct mg_str args) {
|
||||||
|
int idx;
|
||||||
|
uint8_t gpio;
|
||||||
|
bool state;
|
||||||
|
|
||||||
|
rpc_log(ri, args);
|
||||||
|
|
||||||
|
if (json_scanf(args.p, args.len, ri->args_fmt, &idx) != 1) {
|
||||||
|
mg_rpc_send_errorf(ri, 400, "idx is required");
|
||||||
|
ri = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ERR_GPIO_INVALID==(gpio=relays_get_gpio_by_idx(idx))) {
|
||||||
|
mg_rpc_send_errorf(ri, 400, "No relay at idx=%d", idx);
|
||||||
|
ri = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state=relays_get_by_idx(idx);
|
||||||
|
mg_rpc_send_responsef(ri, "{idx: %d, gpio: %d, state: %d}", idx, gpio, state);
|
||||||
|
ri = NULL;
|
||||||
|
|
||||||
|
(void) cb_arg;
|
||||||
|
(void) fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpc_relay_set_handler(struct mg_rpc_request_info *ri, void *cb_arg, struct mg_rpc_frame_info *fi, struct mg_str args) {
|
||||||
|
int idx;
|
||||||
|
uint8_t gpio;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
rpc_log(ri, args);
|
||||||
|
|
||||||
|
if (json_scanf(args.p, args.len, ri->args_fmt, &idx, &state) != 2) {
|
||||||
|
mg_rpc_send_errorf(ri, 400, "idx and state are required");
|
||||||
|
ri = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (state!=0 && state!=1) {
|
||||||
|
mg_rpc_send_errorf(ri, 400, "state must be 0 or 1");
|
||||||
|
ri = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ERR_GPIO_INVALID==(gpio=relays_get_gpio_by_idx(idx))) {
|
||||||
|
mg_rpc_send_errorf(ri, 400, "No relay at idx=%d", idx);
|
||||||
|
ri = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
relays_set_by_idx(idx, state);
|
||||||
|
mg_rpc_send_responsef(ri, "{idx: %d, gpio: %d, state: %d}", idx, gpio, state);
|
||||||
|
|
||||||
|
(void) cb_arg;
|
||||||
|
(void) fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpc_relay_toggle_handler(struct mg_rpc_request_info *ri, void *cb_arg, struct mg_rpc_frame_info *fi, struct mg_str args) {
|
||||||
|
int idx;
|
||||||
|
uint8_t gpio;
|
||||||
|
bool state;
|
||||||
|
|
||||||
|
rpc_log(ri, args);
|
||||||
|
|
||||||
|
if (json_scanf(args.p, args.len, ri->args_fmt, &idx) != 1) {
|
||||||
|
mg_rpc_send_errorf(ri, 400, "idx is required");
|
||||||
|
ri = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ERR_GPIO_INVALID==(gpio=relays_get_gpio_by_idx(idx))) {
|
||||||
|
mg_rpc_send_errorf(ri, 400, "No relay at idx=%d", idx);
|
||||||
|
ri = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state=!relays_get_by_idx(idx);
|
||||||
|
relays_set_by_idx(idx, state);
|
||||||
|
mg_rpc_send_responsef(ri, "{idx: %d, gpio: %d, state: %d}", idx, gpio, state);
|
||||||
|
|
||||||
|
(void) cb_arg;
|
||||||
|
(void) fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpc_init() {
|
||||||
|
struct mg_rpc *c = mgos_rpc_get_global();
|
||||||
|
mg_rpc_add_handler(c, "Button.Touch", "{idx: %d}", rpc_button_touch_handler, NULL);
|
||||||
|
mg_rpc_add_handler(c, "Relay.Get", "{idx: %d}", rpc_relay_get_handler, NULL);
|
||||||
|
mg_rpc_add_handler(c, "Relay.Set", "{idx: %d, state:%d}", rpc_relay_set_handler, NULL);
|
||||||
|
mg_rpc_add_handler(c, "Relay.Toggle", "{idx: %d}", rpc_relay_toggle_handler, NULL);
|
||||||
|
}
|
@ -9,7 +9,7 @@ default: $(TARGET)
|
|||||||
all: default
|
all: default
|
||||||
|
|
||||||
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
|
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
|
||||||
SRCS = frozen/frozen.c ../src/widget.c ../src/screen.c
|
SRCS = frozen/frozen.c ../src/widget.c ../src/screen.c ../src/helper.c ../src/buttons.c ../src/relays.c ../src/mqtt.c
|
||||||
HEADERS = $(wildcard *.h)
|
HEADERS = $(wildcard *.h)
|
||||||
|
|
||||||
%.o: %.c $(HEADERS)
|
%.o: %.c $(HEADERS)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define __MGOS_H
|
#define __MGOS_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
5
unittest/mgos_config.c
Normal file
5
unittest/mgos_config.c
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "mgos_config.h"
|
||||||
|
|
||||||
|
const char *mgos_sys_config_get_device_id() {
|
||||||
|
return "esp8266_ABCDEF";
|
||||||
|
}
|
6
unittest/mgos_config.h
Normal file
6
unittest/mgos_config.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef __MGOS_CONFIG_H
|
||||||
|
#define __MGOS_CONFIG_H
|
||||||
|
|
||||||
|
const char *mgos_sys_config_get_device_id();
|
||||||
|
|
||||||
|
#endif // __MGOS_CONFIG_H
|
31
unittest/mgos_gpio.c
Normal file
31
unittest/mgos_gpio.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "mgos.h"
|
||||||
|
#include "mgos_gpio.h"
|
||||||
|
|
||||||
|
static mgos_gpio_int_handler_f s_handler_cb;
|
||||||
|
static void *s_handler_cb_arg;
|
||||||
|
|
||||||
|
bool mgos_gpio_set_mode(int pin, enum mgos_gpio_mode mode) {
|
||||||
|
LOG(LL_INFO, ("Setting pin=%d to mode=%d", pin, mode));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mgos_gpio_write(int pin, bool level) {
|
||||||
|
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) {
|
||||||
|
s_handler_cb = cb;
|
||||||
|
s_handler_cb_arg = arg;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
(void) debounce_ms;
|
||||||
|
(void) int_mode;
|
||||||
|
(void) pull_type;
|
||||||
|
(void) pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mgos_gpio_inject(int pin) {
|
||||||
|
if (s_handler_cb)
|
||||||
|
s_handler_cb(pin, s_handler_cb_arg);
|
||||||
|
}
|
||||||
|
|
39
unittest/mgos_gpio.h
Normal file
39
unittest/mgos_gpio.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef __MGOS_GPIO_H
|
||||||
|
#define __MGOS_GPIO_H
|
||||||
|
|
||||||
|
#include "mgos.h"
|
||||||
|
|
||||||
|
enum mgos_gpio_mode {
|
||||||
|
MGOS_GPIO_MODE_INPUT = 0, /* input mode */
|
||||||
|
MGOS_GPIO_MODE_OUTPUT = 1 /* output mode */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum mgos_gpio_pull_type {
|
||||||
|
MGOS_GPIO_PULL_NONE = 0,
|
||||||
|
MGOS_GPIO_PULL_UP = 1, /* pin is pilled to the high voltage */
|
||||||
|
MGOS_GPIO_PULL_DOWN = 2 /* pin is pulled to the low voltage */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum mgos_gpio_int_mode {
|
||||||
|
MGOS_GPIO_INT_NONE = 0,
|
||||||
|
MGOS_GPIO_INT_EDGE_POS = 1, /* positive edge */
|
||||||
|
MGOS_GPIO_INT_EDGE_NEG = 2, /* negative edge */
|
||||||
|
MGOS_GPIO_INT_EDGE_ANY = 3, /* any edge - positive or negative */
|
||||||
|
MGOS_GPIO_INT_LEVEL_HI = 4, /* high voltage level */
|
||||||
|
MGOS_GPIO_INT_LEVEL_LO = 5 /* low voltage level */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*mgos_gpio_int_handler_f)(int pin, void *arg);
|
||||||
|
|
||||||
|
bool mgos_gpio_set_mode(int pin, enum mgos_gpio_mode mode);
|
||||||
|
void mgos_gpio_write(int pin, bool level);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
void mgos_gpio_inject(int pin);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __MGOS_GPIO_H
|
@ -49,3 +49,7 @@ void mgos_clear_timer(mgos_timer_id id) {
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float mg_time() {
|
||||||
|
return (float) time(NULL);
|
||||||
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "mgos.h"
|
#include "mgos.h"
|
||||||
|
|
||||||
|
#define MGOS_APP "unittest"
|
||||||
|
|
||||||
// mgos_log
|
// mgos_log
|
||||||
enum cs_log_level {
|
enum cs_log_level {
|
||||||
LL_NONE = -1,
|
LL_NONE = -1,
|
||||||
@ -36,4 +38,6 @@ typedef void (*timer_callback)(void *param);
|
|||||||
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);
|
||||||
void mgos_clear_timer(mgos_timer_id id);
|
void mgos_clear_timer(mgos_timer_id id);
|
||||||
|
|
||||||
|
float mg_time();
|
||||||
|
|
||||||
#endif // __MGOS_MOCK_H
|
#endif // __MGOS_MOCK_H
|
||||||
|
26
unittest/mgos_mqtt.c
Normal file
26
unittest/mgos_mqtt.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include "mgos.h"
|
||||||
|
#include "mgos_mqtt.h"
|
||||||
|
|
||||||
|
uint32_t mqtt_pub_count=0;
|
||||||
|
uint32_t mqtt_sub_count=0;
|
||||||
|
|
||||||
|
static sub_handler_t s_handler;
|
||||||
|
static void *s_handler_ud;
|
||||||
|
|
||||||
|
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"));
|
||||||
|
mqtt_pub_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mgos_mqtt_sub(char *t, sub_handler_t cb, void *ud) {
|
||||||
|
LOG(LL_INFO, ("Subscribing to topic='%s'", t));
|
||||||
|
s_handler = cb;
|
||||||
|
s_handler_ud = ud;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mgos_mqtt_inject(char *topic, char *msg) {
|
||||||
|
LOG(LL_INFO, ("Injecting topic='%s' msg='%s'", topic, msg));
|
||||||
|
mqtt_sub_count++;
|
||||||
|
if (s_handler)
|
||||||
|
s_handler(NULL, topic, strlen(topic), msg, strlen(msg), s_handler_ud);
|
||||||
|
}
|
17
unittest/mgos_mqtt.h
Normal file
17
unittest/mgos_mqtt.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef __MGOS_MQTT_H
|
||||||
|
#define __MGOS_MQTT_H
|
||||||
|
|
||||||
|
#include "mgos.h"
|
||||||
|
|
||||||
|
struct mg_connection;
|
||||||
|
|
||||||
|
typedef void (*sub_handler_t)(struct mg_connection *nc, const char *topic,
|
||||||
|
int topic_len, const char *msg, int msg_len,
|
||||||
|
void *ud);
|
||||||
|
|
||||||
|
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_inject(char *topic, char *msg);
|
||||||
|
|
||||||
|
#endif // __MGOS_MQTT_H
|
Reference in New Issue
Block a user