diff --git a/code/espurna/alexa.ino b/code/espurna/alexa.ino index e12b5fe1..17ac7a66 100644 --- a/code/espurna/alexa.ino +++ b/code/espurna/alexa.ino @@ -20,6 +20,13 @@ bool _alexa_change = false; unsigned int _alexa_device_id = 0; bool _alexa_state = false; +#if WEB_SUPPORT + void _alexaWSSend(JsonObject& root) { + root["alexaVisible"] = 1; + root["alexaEnabled"] = getSetting("alexaEnabled", ALEXA_ENABLED).toInt() == 1; + } +#endif + // ----------------------------------------------------------------------------- void alexaConfigure() { @@ -34,6 +41,11 @@ void alexaSetup() { // Load & cache settings alexaConfigure(); + #if WEB_SUPPORT + // Websockets + wsRegister(_alexaWSSend); + #endif + unsigned int relays = relayCount(); String hostname = getSetting("hostname"); if (relays == 1) { diff --git a/code/espurna/analog.ino b/code/espurna/analog.ino index d2bcef5d..ce21e7a4 100644 --- a/code/espurna/analog.ino +++ b/code/espurna/analog.ino @@ -12,6 +12,13 @@ Copyright (C) 2016-2017 by Xose Pérez // ANALOG // ----------------------------------------------------------------------------- +void _analogWSSend(JsonObject& root) { + root["analogVisible"] = 1; + root["analogValue"] = getAnalog(); +} + +// ----------------------------------------------------------------------------- + unsigned int getAnalog() { return analogRead(ANALOG_PIN); } @@ -21,9 +28,15 @@ void analogSetup() { pinMode(ANALOG_PIN, INPUT); #if WEB_SUPPORT + + // Websocket register + wsRegister(_analogWSSend); + + // API register apiRegister(ANALOG_TOPIC, ANALOG_TOPIC, [](char * buffer, size_t len) { snprintf_P(buffer, len, PSTR("%d"), getAnalog()); }); + #endif DEBUG_MSG_P(PSTR("[ANALOG] Monitoring analog values\n")); @@ -56,9 +69,7 @@ void analogLoop() { // Update websocket clients #if WEB_SUPPORT - char buffer[100]; - snprintf_P(buffer, sizeof(buffer), PSTR("{\"analogVisible\": 1, \"analogValue\": %d}"), analog); - wsSend(buffer); + wsSend(_analogWSSend); #endif } diff --git a/code/espurna/api.ino b/code/espurna/api.ino index 6270ea06..52474480 100644 --- a/code/espurna/api.ino +++ b/code/espurna/api.ino @@ -16,8 +16,8 @@ Copyright (C) 2016-2017 by Xose Pérez typedef struct { char * url; char * key; - apiGetCallbackFunction getFn = NULL; - apiPutCallbackFunction putFn = NULL; + api_get_callback_f getFn = NULL; + api_put_callback_f putFn = NULL; } web_api_t; std::vector _apis; @@ -154,7 +154,7 @@ void _onRPC(AsyncWebServerRequest *request) { // ----------------------------------------------------------------------------- -void apiRegister(const char * url, const char * key, apiGetCallbackFunction getFn, apiPutCallbackFunction putFn) { +void apiRegister(const char * url, const char * key, api_get_callback_f getFn, api_put_callback_f putFn) { // Store it web_api_t api; diff --git a/code/espurna/config/prototypes.h b/code/espurna/config/prototypes.h index bd819a17..185d1a9b 100644 --- a/code/espurna/config/prototypes.h +++ b/code/espurna/config/prototypes.h @@ -2,21 +2,28 @@ #include #include #include +#include #include AsyncWebServer * webServer(); -typedef std::function apiGetCallbackFunction; -typedef std::function apiPutCallbackFunction; -void apiRegister(const char * url, const char * key, apiGetCallbackFunction getFn, apiPutCallbackFunction putFn = NULL); +typedef std::function api_get_callback_f; +typedef std::function api_put_callback_f; +void apiRegister(const char * url, const char * key, api_get_callback_f getFn, api_put_callback_f putFn = NULL); -void mqttRegister(void (*callback)(unsigned int, const char *, const char *)); +typedef std::function mqtt_callback_f; +void mqttRegister(mqtt_callback_f callback); String mqttSubtopic(char * topic); +typedef std::function ws_callback_f; +void wsRegister(ws_callback_f sender, ws_callback_f receiver = NULL); +void wsSend(ws_callback_f sender); + template bool setSetting(const String& key, T value); template bool setSetting(const String& key, unsigned int index, T value); template String getSetting(const String& key, T defaultValue); template String getSetting(const String& key, unsigned int index, T defaultValue); + template void domoticzSend(const char * key, T value); template void domoticzSend(const char * key, T nvalue, const char * svalue); diff --git a/code/espurna/counter.ino b/code/espurna/counter.ino index 878b8b3b..5a4d1c08 100644 --- a/code/espurna/counter.ino +++ b/code/espurna/counter.ino @@ -26,6 +26,13 @@ void ICACHE_RAM_ATTR _counterISR() { } } +#if WEB_SUPPORT +void _counterWSSend(JsonObject& root) { + root["counterVisible"] = 1; + root["counterValue"] = getCounter(); +} +#endif + unsigned long getCounter() { return _counterValue; } @@ -36,9 +43,15 @@ void counterSetup() { attachInterrupt(COUNTER_PIN, _counterISR, COUNTER_INTERRUPT_MODE); #if WEB_SUPPORT + + // Websockets + wsRegister(_counterWSSend); + + // API apiRegister(COUNTER_TOPIC, COUNTER_TOPIC, [](char * buffer, size_t len) { snprintf_P(buffer, len, PSTR("%d"), getCounter()); }); + #endif DEBUG_MSG_P(PSTR("[COUNTER] Counter on GPIO %d\n"), COUNTER_PIN); @@ -62,9 +75,7 @@ void counterLoop() { // Update websocket clients #if WEB_SUPPORT - char buffer[100]; - snprintf_P(buffer, sizeof(buffer), PSTR("{\"counterVisible\": 1, \"counterValue\": %d}"), _counterValue); - wsSend(buffer); + wsSend(_counterWSSend); #endif // Do we have to report? diff --git a/code/espurna/influxdb.ino b/code/espurna/influxdb.ino index 5dc25835..a6669936 100644 --- a/code/espurna/influxdb.ino +++ b/code/espurna/influxdb.ino @@ -14,6 +14,21 @@ Copyright (C) 2017 by Xose Pérez bool _idb_enabled = false; SyncClient _idb_client; +// ----------------------------------------------------------------------------- + +#if WEB_SUPPORT +void _idbWSSend(JsonObject& root) { + root["idbVisible"] = 1; + root["idbHost"] = getSetting("idbHost"); + root["idbPort"] = getSetting("idbPort", INFLUXDB_PORT).toInt(); + root["idbDatabase"] = getSetting("idbDatabase"); + root["idbUsername"] = getSetting("idbUsername"); + root["idbPassword"] = getSetting("idbPassword"); +} +#endif + +// ----------------------------------------------------------------------------- + template bool idbSend(const char * topic, T payload) { if (!_idb_enabled) return true; @@ -61,6 +76,9 @@ void idbConfigure() { void idbSetup() { idbConfigure(); + #if WEB_SUPPORT + wsRegister(_idbWSSend); + #endif } #endif diff --git a/code/espurna/mqtt.ino b/code/espurna/mqtt.ino index 82c25fe3..a419570a 100644 --- a/code/espurna/mqtt.ino +++ b/code/espurna/mqtt.ino @@ -44,7 +44,7 @@ char *_mqtt_will; unsigned long _mqtt_connected_at = 0; #endif -std::vector _mqtt_callbacks; +std::vector _mqtt_callbacks; typedef struct { char * topic; @@ -192,7 +192,7 @@ void mqttUnsubscribeRaw(const char * topic) { } } -void mqttRegister(void (*callback)(unsigned int, const char *, const char *)) { +void mqttRegister(mqtt_callback_f callback) { _mqtt_callbacks.push_back(callback); } @@ -241,7 +241,7 @@ void _mqttOnConnect() { // Send connect event to subscribers for (unsigned char i = 0; i < _mqtt_callbacks.size(); i++) { - (*_mqtt_callbacks[i])(MQTT_CONNECT_EVENT, NULL, NULL); + (_mqtt_callbacks[i])(MQTT_CONNECT_EVENT, NULL, NULL); } } @@ -252,7 +252,7 @@ void _mqttOnDisconnect() { // Send disconnect event to subscribers for (unsigned char i = 0; i < _mqtt_callbacks.size(); i++) { - (*_mqtt_callbacks[i])(MQTT_DISCONNECT_EVENT, NULL, NULL); + (_mqtt_callbacks[i])(MQTT_DISCONNECT_EVENT, NULL, NULL); } } @@ -274,7 +274,7 @@ void _mqttOnMessage(char* topic, char* payload, unsigned int len) { // Send message event to subscribers for (unsigned char i = 0; i < _mqtt_callbacks.size(); i++) { - (*_mqtt_callbacks[i])(MQTT_MESSAGE_EVENT, topic, message); + (_mqtt_callbacks[i])(MQTT_MESSAGE_EVENT, topic, message); } } diff --git a/code/espurna/ws.ino b/code/espurna/ws.ino index f9cb3c62..c06ab70d 100644 --- a/code/espurna/ws.ino +++ b/code/espurna/ws.ino @@ -12,10 +12,15 @@ Copyright (C) 2016-2017 by Xose Pérez #include #include #include +#include #include "ws.h" AsyncWebSocket _ws("/ws"); Ticker _web_defer; + +std::vector _ws_sender_callbacks; +std::vector _ws_receiver_callbacks; + // ----------------------------------------------------------------------------- // Private methods // ----------------------------------------------------------------------------- @@ -558,20 +563,6 @@ void _wsStart(uint32_t client_id) { #endif - #if INFLUXDB_SUPPORT - root["idbVisible"] = 1; - root["idbHost"] = getSetting("idbHost"); - root["idbPort"] = getSetting("idbPort", INFLUXDB_PORT).toInt(); - root["idbDatabase"] = getSetting("idbDatabase"); - root["idbUsername"] = getSetting("idbUsername"); - root["idbPassword"] = getSetting("idbPassword"); - #endif - - #if ALEXA_SUPPORT - root["alexaVisible"] = 1; - root["alexaEnabled"] = getSetting("alexaEnabled", ALEXA_ENABLED).toInt() == 1; - #endif - #if DS18B20_SUPPORT root["dsVisible"] = 1; root["dsTmp"] = getDSTemperatureStr(); @@ -589,16 +580,6 @@ void _wsStart(uint32_t client_id) { root["rfDevice"] = getSetting("rfDevice", RF_DEVICE); #endif - #if ANALOG_SUPPORT - root["analogVisible"] = 1; - root["analogValue"] = getAnalog(); - #endif - - #if COUNTER_SUPPORT - root["counterVisible"] = 1; - root["counterValue"] = getCounter(); - #endif - #if POWER_PROVIDER != POWER_PROVIDER_NONE root["pwrVisible"] = 1; root["pwrCurrent"] = getCurrent(); @@ -664,6 +645,12 @@ void _wsStart(uint32_t client_id) { network["dns"] = getSetting("dns" + String(i)); } + // Module setters + for (unsigned char i = 0; i < _ws_sender_callbacks.size(); i++) { + (_ws_sender_callbacks[i])(root); + } + + } String output; @@ -713,6 +700,22 @@ bool wsConnected() { return (_ws.count() > 0); } +void wsRegister(ws_callback_f sender, ws_callback_f receiver) { + _ws_sender_callbacks.push_back(sender); + if (receiver) _ws_receiver_callbacks.push_back(receiver); +} + +void wsSend(ws_callback_f sender) { + if (_ws.count() > 0) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.createObject(); + sender(root); + String output; + root.printTo(output); + wsSend((char *) output.c_str()); + } +} + void wsSend(const char * payload) { if (_ws.count() > 0) { _ws.textAll(payload);