Skip to content

Commit

Permalink
Fixed size json payload & other WS bugfixes (#1843)
Browse files Browse the repository at this point in the history
- update every dynamicjsonbuffer with fixed size constructor argument
- change to ws callback registration to use a class builder (just cosmetic)
- test multiple ws data callbacks for each module
- remove some of the static strings in favour of ws data callback
- improve sensor ws callback data size, remove duplicated strings
- use static buffer in wsDebugSend
- postpone wsSend until loop, implement wsPost to allow other modules to queue message callbacks. remove Ticker based ws callbacks for data
- update WebUI files
  • Loading branch information
mcspr authored Aug 12, 2019
1 parent 9156eb1 commit 2142343
Show file tree
Hide file tree
Showing 38 changed files with 2,936 additions and 2,574 deletions.
11 changes: 6 additions & 5 deletions code/espurna/alexa.ino
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ static std::queue<alexa_queue_element_t> _alexa_queue;
// ALEXA
// -----------------------------------------------------------------------------

bool _alexaWebSocketOnReceive(const char * key, JsonVariant& value) {
bool _alexaWebSocketOnKeyCheck(const char * key, JsonVariant& value) {
return (strncmp(key, "alexa", 5) == 0);
}

void _alexaWebSocketOnSend(JsonObject& root) {
root["alexaVisible"] = 1;
void _alexaWebSocketOnConnected(JsonObject& root) {
root["alexaEnabled"] = alexaEnabled();
root["alexaName"] = getSetting("alexaName");
}
Expand Down Expand Up @@ -123,8 +122,10 @@ void alexaSetup() {
#if WEB_SUPPORT
webBodyRegister(_alexaBodyCallback);
webRequestRegister(_alexaRequestCallback);
wsOnSendRegister(_alexaWebSocketOnSend);
wsOnReceiveRegister(_alexaWebSocketOnReceive);
wsRegister()
.onVisible([](JsonObject& root) { root["alexaVisible"] = 1; })
.onConnected(_alexaWebSocketOnConnected)
.onKeyCheck(_alexaWebSocketOnKeyCheck);
#endif

// Register wifi callback
Expand Down
71 changes: 49 additions & 22 deletions code/espurna/api.ino
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ std::vector<web_api_t> _apis;

// -----------------------------------------------------------------------------

bool _apiWebSocketOnReceive(const char * key, JsonVariant& value) {
bool _apiWebSocketOnKeyCheck(const char * key, JsonVariant& value) {
return (strncmp(key, "api", 3) == 0);
}

void _apiWebSocketOnSend(JsonObject& root) {
root["apiVisible"] = 1;
void _apiWebSocketOnConnected(JsonObject& root) {
root["apiEnabled"] = getSetting("apiEnabled", API_ENABLED).toInt() == 1;
root["apiKey"] = getSetting("apiKey");
root["apiRealTime"] = getSetting("apiRealTime", API_REAL_TIME_VALUES).toInt() == 1;
Expand Down Expand Up @@ -76,33 +75,59 @@ bool _asJson(AsyncWebServerRequest *request) {
return asJson;
}

void _onAPIsText(AsyncWebServerRequest *request) {
AsyncResponseStream *response = request->beginResponseStream("text/plain");
String output;
output.reserve(48);
for (unsigned int i=0; i < _apis.size(); i++) {
output = "";
output += _apis[i].key;
output += " -> ";
output += "/api/";
output += _apis[i].key;
output += '\n';
response->write(output.c_str());
}
request->send(response);
}

constexpr const size_t API_JSON_BUFFER_SIZE = 1024;

void _onAPIsJson(AsyncWebServerRequest *request) {


DynamicJsonBuffer jsonBuffer(API_JSON_BUFFER_SIZE);
JsonObject& root = jsonBuffer.createObject();

constexpr const int BUFFER_SIZE = 48;

for (unsigned int i=0; i < _apis.size(); i++) {
char buffer[BUFFER_SIZE] = {0};
int res = snprintf(buffer, sizeof(buffer), "/api/%s", _apis[i].key);
if ((res < 0) || (res > (BUFFER_SIZE - 1))) {
request->send(500);
return;
}
root[_apis[i].key] = buffer;
}
AsyncResponseStream *response = request->beginResponseStream("application/json");
root.printTo(*response);
request->send(response);

}

void _onAPIs(AsyncWebServerRequest *request) {

webLog(request);
if (!_authAPI(request)) return;

bool asJson = _asJson(request);

char buffer[40];

String output;
if (asJson) {
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
for (unsigned int i=0; i < _apis.size(); i++) {
snprintf_P(buffer, sizeof(buffer), PSTR("/api/%s"), _apis[i].key);
root[_apis[i].key] = String(buffer);
}
root.printTo(output);
jsonBuffer.clear();
request->send(200, "application/json", output);

_onAPIsJson(request);
} else {
for (unsigned int i=0; i < _apis.size(); i++) {
snprintf_P(buffer, sizeof(buffer), PSTR("/api/%s"), _apis[i].key);
output += _apis[i].key + String(" -> ") + String(buffer) + String("\n");
}
request->send(200, "text/plain", output);
_onAPIsText(request);
}

}
Expand Down Expand Up @@ -220,8 +245,10 @@ void apiRegister(const char * key, api_get_callback_f getFn, api_put_callback_f

void apiSetup() {
_apiConfigure();
wsOnSendRegister(_apiWebSocketOnSend);
wsOnReceiveRegister(_apiWebSocketOnReceive);
wsRegister()
.onVisible([](JsonObject& root) { root["apiVisible"] = 1; })
.onConnected(_apiWebSocketOnConnected)
.onKeyCheck(_apiWebSocketOnKeyCheck);
webRequestRegister(_apiRequestCallback);
espurnaRegisterReload(_apiConfigure);
}
Expand Down
4 changes: 2 additions & 2 deletions code/espurna/button.ino
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void buttonMQTT(unsigned char id, uint8_t event) {

#if WEB_SUPPORT

bool _buttonWebSocketOnReceive(const char * key, JsonVariant& value) {
bool _buttonWebSocketOnKeyCheck(const char * key, JsonVariant& value) {
return (strncmp(key, "btn", 3) == 0);
}

Expand Down Expand Up @@ -243,7 +243,7 @@ void buttonSetup() {

// Websocket Callbacks
#if WEB_SUPPORT
wsOnReceiveRegister(_buttonWebSocketOnReceive);
wsRegister().onKeyCheck(_buttonWebSocketOnKeyCheck);
#endif

// Register loop
Expand Down
65 changes: 58 additions & 7 deletions code/espurna/config/prototypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ bool gpioValid(unsigned char gpio);
bool gpioGetLock(unsigned char gpio);
bool gpioReleaseLock(unsigned char gpio);

// -----------------------------------------------------------------------------
// Homeassistant
// -----------------------------------------------------------------------------
struct ha_config_t;

// -----------------------------------------------------------------------------
// I2C
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -159,7 +164,7 @@ void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len);
// MQTT
// -----------------------------------------------------------------------------
#if MQTT_SUPPORT
typedef std::function<void(unsigned int, const char *, const char *)> mqtt_callback_f;
typedef std::function<void(unsigned int, const char *, char *)> mqtt_callback_f;
void mqttRegister(mqtt_callback_f callback);
String mqttMagnitude(char * topic);
#else
Expand Down Expand Up @@ -266,17 +271,63 @@ void webRequestRegister(web_request_callback_f callback);
// WebSockets
// -----------------------------------------------------------------------------
#if WEB_SUPPORT
typedef std::function<void(JsonObject&)> ws_on_send_callback_f;
void wsOnSendRegister(ws_on_send_callback_f callback);
using ws_on_send_callback_f = std::function<void(JsonObject&)>;
using ws_on_action_callback_f = std::function<void(uint32_t, const char *, JsonObject&)>;
using ws_on_keycheck_callback_f = std::function<bool(const char *, JsonVariant&)>;

using ws_on_send_callback_list_t = std::vector<ws_on_send_callback_f>;
using ws_on_action_callback_list_t = std::vector<ws_on_action_callback_f>;
using ws_on_keycheck_callback_list_t = std::vector<ws_on_keycheck_callback_f>;

struct ws_callbacks_t {
ws_on_send_callback_list_t on_visible;
ws_on_send_callback_list_t on_connected;
ws_on_send_callback_list_t on_data;

ws_on_action_callback_list_t on_action;
ws_on_keycheck_callback_list_t on_keycheck;

ws_callbacks_t& onVisible(ws_on_send_callback_f cb) {
on_visible.push_back(cb);
return *this;
}

ws_callbacks_t& onConnected(ws_on_send_callback_f cb) {
on_connected.push_back(cb);
return *this;
}

ws_callbacks_t& onData(ws_on_send_callback_f cb) {
on_data.push_back(cb);
return *this;
}

ws_callbacks_t& onAction(ws_on_action_callback_f cb) {
on_action.push_back(cb);
return *this;
}

ws_callbacks_t& onKeyCheck(ws_on_keycheck_callback_f cb) {
on_keycheck.push_back(cb);
return *this;
}

};

ws_callbacks_t& wsRegister();

void wsSend(uint32_t, JsonObject& root);
void wsSend(JsonObject& root);
void wsSend(ws_on_send_callback_f sender);

typedef std::function<void(uint32_t, const char *, JsonObject&)> ws_on_action_callback_f;
void wsOnActionRegister(ws_on_action_callback_f callback);
void wsPost(const ws_on_send_callback_list_t&);
void wsPost(uint32_t, const ws_on_send_callback_list_t&);

void wsPostAll(uint32_t, const ws_on_send_callback_list_t&);
void wsPostAll(const ws_on_send_callback_list_t&);

typedef std::function<bool(const char *, JsonVariant&)> ws_on_receive_callback_f;
void wsOnReceiveRegister(ws_on_receive_callback_f callback);
void wsPostSequence(uint32_t, const ws_on_send_callback_list_t&);
void wsPostSequence(const ws_on_send_callback_list_t&);

bool wsConnected();
bool wsConnected(uint32_t);
Expand Down
2 changes: 1 addition & 1 deletion code/espurna/crash.ino
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ extern "C" {
#define SAVE_CRASH_STACK_TRACE_MAX 0x80 // limit at 128 bytes (increment/decrement by 16)

uint16_t _save_crash_stack_trace_max = SAVE_CRASH_STACK_TRACE_MAX;
uint16_t _save_crash_enabled = true;
bool _save_crash_enabled = true;

/**
* Save crash information in EEPROM
Expand Down
Binary file modified code/espurna/data/index.all.html.gz
Binary file not shown.
Binary file modified code/espurna/data/index.sensor.html.gz
Binary file not shown.
28 changes: 15 additions & 13 deletions code/espurna/debug.ino
Original file line number Diff line number Diff line change
Expand Up @@ -90,24 +90,26 @@ void debugSendImpl(const char * message) {

#if DEBUG_WEB_SUPPORT

void debugWebSetup() {

wsOnSendRegister([](JsonObject& root) {
root["dbgVisible"] = 1;
});

wsOnActionRegister([](uint32_t client_id, const char * action, JsonObject& data) {
void _debugWebSocketOnAction(uint32_t client_id, const char * action, JsonObject& data) {

#if TERMINAL_SUPPORT
if (strcmp(action, "dbgcmd") == 0) {
const char* command = data.get<const char*>("command");
char buffer[strlen(command) + 2];
snprintf(buffer, sizeof(buffer), "%s\n", command);
terminalInject((void*) buffer, strlen(buffer));
if (!data.containsKey("command") || !data["command"].is<const char*>()) return;
const char* command = data["command"];
if (command && strlen(command)) {
auto command = data.get<const char*>("command");
terminalInject((void*) command, strlen(command));
terminalInject('\n');
}
}
#endif

});
}

void debugWebSetup() {

wsRegister()
.onVisible([](JsonObject& root) { root["dbgVisible"] = 1; })
.onAction(_debugWebSocketOnAction);

#if DEBUG_UDP_SUPPORT
#if DEBUG_UDP_PORT == 514
Expand Down
25 changes: 13 additions & 12 deletions code/espurna/domoticz.ino
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ void _domoticzLight(unsigned int idx, const JsonObject& root) {

#endif

void _domoticzMqtt(unsigned int type, const char * topic, const char * payload) {
void _domoticzMqtt(unsigned int type, const char * topic, char * payload) {

if (!_dcz_enabled) return;

Expand All @@ -118,8 +118,8 @@ void _domoticzMqtt(unsigned int type, const char * topic, const char * payload)
if (dczTopicOut.equals(topic)) {

// Parse response
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject((char *) payload);
DynamicJsonBuffer jsonBuffer(1024);
JsonObject& root = jsonBuffer.parseObject(payload);
if (!root.success()) {
DEBUG_MSG_P(PSTR("[DOMOTICZ] Error parsing data\n"));
return;
Expand Down Expand Up @@ -166,13 +166,16 @@ void _domoticzBrokerCallback(const unsigned char type, const char * topic, unsig

#if WEB_SUPPORT

bool _domoticzWebSocketOnReceive(const char * key, JsonVariant& value) {
bool _domoticzWebSocketOnKeyCheck(const char * key, JsonVariant& value) {
return (strncmp(key, "dcz", 3) == 0);
}

void _domoticzWebSocketOnSend(JsonObject& root) {
void _domoticzWebSocketOnVisible(JsonObject& root) {
root["dczVisible"] = static_cast<unsigned char>(haveRelaysOrSensors());
}

void _domoticzWebSocketOnConnected(JsonObject& root) {

unsigned char visible = 0;
root["dczEnabled"] = getSetting("dczEnabled", DOMOTICZ_ENABLED).toInt() == 1;
root["dczTopicIn"] = getSetting("dczTopicIn", DOMOTICZ_IN_TOPIC);
root["dczTopicOut"] = getSetting("dczTopicOut", DOMOTICZ_OUT_TOPIC);
Expand All @@ -181,15 +184,11 @@ void _domoticzWebSocketOnSend(JsonObject& root) {
for (unsigned char i=0; i<relayCount(); i++) {
relays.add(domoticzIdx(i));
}
visible = (relayCount() > 0);

#if SENSOR_SUPPORT
_sensorWebSocketMagnitudes(root, "dcz");
visible = visible || (magnitudeCount() > 0);
#endif

root["dczVisible"] = visible;

}

#endif // WEB_SUPPORT
Expand Down Expand Up @@ -248,8 +247,10 @@ void domoticzSetup() {
_domoticzConfigure();

#if WEB_SUPPORT
wsOnSendRegister(_domoticzWebSocketOnSend);
wsOnReceiveRegister(_domoticzWebSocketOnReceive);
wsRegister()
.onVisible(_domoticzWebSocketOnVisible)
.onConnected(_domoticzWebSocketOnConnected)
.onKeyCheck(_domoticzWebSocketOnKeyCheck);
#endif

#if BROKER_SUPPORT
Expand Down
6 changes: 3 additions & 3 deletions code/espurna/espurna.ino
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ void setup() {
#if NOFUSS_SUPPORT
nofussSetup();
#endif
#if SENSOR_SUPPORT
sensorSetup();
#endif
#if INFLUXDB_SUPPORT
idbSetup();
#endif
Expand All @@ -210,9 +213,6 @@ void setup() {
#if HOMEASSISTANT_SUPPORT
haSetup();
#endif
#if SENSOR_SUPPORT
sensorSetup();
#endif
#if SCHEDULER_SUPPORT
schSetup();
#endif
Expand Down
Loading

0 comments on commit 2142343

Please sign in to comment.