mirror of
https://github.com/xoseperez/espurna.git
synced 2026-03-04 07:24:20 +01:00
Compact WS data
* send all ws config at once on start * reduce ws json overhead by creating message buffer manually * use k:[values] instead of k1:value1, k2:value2 etc. for lists
This commit is contained in:
@@ -184,6 +184,8 @@ void webRequestRegister(web_request_callback_f callback);
|
||||
#if WEB_SUPPORT
|
||||
typedef std::function<void(JsonObject&)> ws_on_send_callback_f;
|
||||
void wsOnSendRegister(ws_on_send_callback_f callback);
|
||||
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;
|
||||
@@ -191,6 +193,8 @@ void webRequestRegister(web_request_callback_f callback);
|
||||
|
||||
typedef std::function<bool(const char *, JsonVariant&)> ws_on_receive_callback_f;
|
||||
void wsOnReceiveRegister(ws_on_receive_callback_f callback);
|
||||
|
||||
bool wsDebugSend(const char*);
|
||||
#else
|
||||
#define ws_on_send_callback_f void *
|
||||
#define ws_on_action_callback_f void *
|
||||
|
||||
@@ -8,6 +8,8 @@ Copyright (C) 2016-2018 by Xose Pérez <xose dot perez at gmail dot com>
|
||||
|
||||
#if DEBUG_SUPPORT
|
||||
|
||||
constexpr const uint8_t TIMESTAMP_LENGTH = 10;
|
||||
|
||||
#if DEBUG_UDP_SUPPORT
|
||||
#include <WiFiUdp.h>
|
||||
WiFiUDP _udp_debug;
|
||||
@@ -18,20 +20,30 @@ char _udp_syslog_header[40] = {0};
|
||||
|
||||
void _debugSend(char * message) {
|
||||
|
||||
size_t msg_len = strlen(message);
|
||||
bool pause = false;
|
||||
|
||||
#if DEBUG_ADD_TIMESTAMP
|
||||
static bool add_timestamp = true;
|
||||
char timestamp[10] = {0};
|
||||
if (add_timestamp) snprintf_P(timestamp, sizeof(timestamp), PSTR("[%06lu] "), millis() % 1000000);
|
||||
add_timestamp = (message[strlen(message)-1] == 10) || (message[strlen(message)-1] == 13);
|
||||
|
||||
size_t offset = 0;
|
||||
char buffer[TIMESTAMP_LENGTH + msg_len];
|
||||
|
||||
if (add_timestamp) {
|
||||
snprintf_P(buffer, TIMESTAMP_LENGTH, PSTR("[%06lu] "), millis() % 1000000);
|
||||
offset = TIMESTAMP_LENGTH - 1;
|
||||
}
|
||||
|
||||
memcpy(buffer + offset, message, msg_len);
|
||||
buffer[msg_len + offset] = '\0';
|
||||
|
||||
add_timestamp = (message[msg_len - 1] == 10) || (message[msg_len - 1] == 13);
|
||||
#else
|
||||
char* buffer = message;
|
||||
#endif
|
||||
|
||||
#if DEBUG_SERIAL_SUPPORT
|
||||
#if DEBUG_ADD_TIMESTAMP
|
||||
DEBUG_PORT.printf(timestamp);
|
||||
#endif
|
||||
DEBUG_PORT.printf(message);
|
||||
DEBUG_PORT.print(buffer);
|
||||
#endif
|
||||
|
||||
#if DEBUG_UDP_SUPPORT
|
||||
@@ -51,31 +63,12 @@ void _debugSend(char * message) {
|
||||
#endif
|
||||
|
||||
#if DEBUG_TELNET_SUPPORT
|
||||
#if DEBUG_ADD_TIMESTAMP
|
||||
_telnetWrite(timestamp, strlen(timestamp));
|
||||
#endif
|
||||
_telnetWrite(message, strlen(message));
|
||||
_telnetWrite(buffer, strlen(buffer));
|
||||
pause = true;
|
||||
#endif
|
||||
|
||||
#if DEBUG_WEB_SUPPORT
|
||||
if (wsConnected() && (getFreeHeap() > 10000)) {
|
||||
DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(1) + strlen(message) + 17);
|
||||
JsonObject &root = jsonBuffer.createObject();
|
||||
#if DEBUG_ADD_TIMESTAMP
|
||||
char buffer[strlen(timestamp) + strlen(message) + 1];
|
||||
snprintf_P(buffer, sizeof(buffer), "%s%s", timestamp, message);
|
||||
root.set("weblog", buffer);
|
||||
#else
|
||||
root.set("weblog", message);
|
||||
#endif
|
||||
String out;
|
||||
root.printTo(out);
|
||||
jsonBuffer.clear();
|
||||
|
||||
wsSend(out.c_str());
|
||||
pause = true;
|
||||
}
|
||||
wsDebugSend(buffer);
|
||||
#endif
|
||||
|
||||
if (pause) optimistic_yield(100);
|
||||
|
||||
@@ -171,7 +171,7 @@ bool _domoticzWebSocketOnReceive(const char * key, JsonVariant& value) {
|
||||
|
||||
void _domoticzWebSocketOnSend(JsonObject& root) {
|
||||
|
||||
root["dczVisible"] = 1;
|
||||
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);
|
||||
@@ -180,18 +180,15 @@ void _domoticzWebSocketOnSend(JsonObject& root) {
|
||||
for (unsigned char i=0; i<relayCount(); i++) {
|
||||
relays.add(domoticzIdx(i));
|
||||
}
|
||||
visible = (relayCount() > 0);
|
||||
|
||||
#if SENSOR_SUPPORT
|
||||
JsonArray& list = root.createNestedArray("dczMagnitudes");
|
||||
for (byte i=0; i<magnitudeCount(); i++) {
|
||||
JsonObject& element = list.createNestedObject();
|
||||
element["name"] = magnitudeName(i);
|
||||
element["type"] = magnitudeType(i);
|
||||
element["index"] = magnitudeIndex(i);
|
||||
element["idx"] = getSetting("dczMagnitude", i, 0).toInt();
|
||||
}
|
||||
_sensorWebSocketMagnitudes(root, "dcz");
|
||||
visible = visible || (magnitudeCount() > 0);
|
||||
#endif
|
||||
|
||||
root["dczVisible"] = visible;
|
||||
|
||||
}
|
||||
|
||||
#endif // WEB_SUPPORT
|
||||
|
||||
@@ -669,7 +669,7 @@ void _lightComms(unsigned char mask) {
|
||||
|
||||
// Report color to WS clients (using current brightness setting)
|
||||
#if WEB_SUPPORT
|
||||
wsSend(_lightWebSocketOnSend);
|
||||
wsSend(_lightWebSocketStatus);
|
||||
#endif
|
||||
|
||||
// Report channels to local broker
|
||||
@@ -824,23 +824,13 @@ bool _lightWebSocketOnReceive(const char * key, JsonVariant& value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void _lightWebSocketOnSend(JsonObject& root) {
|
||||
root["colorVisible"] = 1;
|
||||
root["mqttGroupColor"] = getSetting("mqttGroupColor");
|
||||
root["useColor"] = _light_has_color;
|
||||
root["useWhite"] = _light_use_white;
|
||||
root["useGamma"] = _light_use_gamma;
|
||||
root["useTransitions"] = _light_use_transitions;
|
||||
root["lightTime"] = _light_transition_time;
|
||||
root["useCSS"] = getSetting("useCSS", LIGHT_USE_CSS).toInt() == 1;
|
||||
bool useRGB = getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1;
|
||||
root["useRGB"] = useRGB;
|
||||
void _lightWebSocketStatus(JsonObject& root) {
|
||||
if (_light_has_color) {
|
||||
if (_light_use_cct) {
|
||||
root["useCCT"] = _light_use_cct;
|
||||
root["mireds"] = _light_mireds;
|
||||
}
|
||||
if (useRGB) {
|
||||
if (getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1) {
|
||||
root["rgb"] = lightColor(true);
|
||||
} else {
|
||||
root["hsv"] = lightColor(false);
|
||||
@@ -850,7 +840,20 @@ void _lightWebSocketOnSend(JsonObject& root) {
|
||||
for (unsigned char id=0; id < _light_channel.size(); id++) {
|
||||
channels.add(lightChannel(id));
|
||||
}
|
||||
root["brightness"] = lightBrightness();
|
||||
}
|
||||
|
||||
void _lightWebSocketOnSend(JsonObject& root) {
|
||||
root["colorVisible"] = 1;
|
||||
root["mqttGroupColor"] = getSetting("mqttGroupColor");
|
||||
root["useColor"] = _light_has_color;
|
||||
root["useWhite"] = _light_use_white;
|
||||
root["useGamma"] = _light_use_gamma;
|
||||
root["useTransitions"] = _light_use_transitions;
|
||||
root["useCSS"] = getSetting("useCSS", LIGHT_USE_CSS).toInt() == 1;
|
||||
root["useRGB"] = getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1;
|
||||
root["lightTime"] = _light_transition_time;
|
||||
|
||||
_lightWebSocketStatus(root);
|
||||
}
|
||||
|
||||
void _lightWebSocketOnAction(uint32_t client_id, const char * action, JsonObject& data) {
|
||||
|
||||
@@ -34,7 +34,6 @@ void _ntpWebSocketOnSend(JsonObject& root) {
|
||||
root["ntpOffset"] = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
|
||||
root["ntpDST"] = getSetting("ntpDST", NTP_DAY_LIGHT).toInt() == 1;
|
||||
root["ntpRegion"] = getSetting("ntpRegion", NTP_DST_REGION).toInt();
|
||||
if (ntpSynced()) root["now"] = now();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -581,65 +581,78 @@ bool _relayWebSocketOnReceive(const char * key, JsonVariant& value) {
|
||||
void _relayWebSocketUpdate(JsonObject& root) {
|
||||
JsonArray& relay = root.createNestedArray("relayStatus");
|
||||
for (unsigned char i=0; i<relayCount(); i++) {
|
||||
relay.add(_relays[i].target_status);
|
||||
relay.add<uint8_t>(_relays[i].target_status);
|
||||
}
|
||||
}
|
||||
|
||||
void _relayWebSocketSendRelay(unsigned char i) {
|
||||
String _relayFriendlyName(unsigned char i) {
|
||||
String res = String("GPIO") + String(_relays[i].pin);
|
||||
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
JsonArray& config = root.createNestedArray("relayConfig");
|
||||
JsonObject& line = config.createNestedObject();
|
||||
|
||||
line["id"] = i;
|
||||
if (GPIO_NONE == _relays[i].pin) {
|
||||
#if (RELAY_PROVIDER == RELAY_PROVIDER_LIGHT)
|
||||
uint8_t physical = _relays.size() - DUMMY_RELAY_COUNT;
|
||||
if (i >= physical) {
|
||||
if (DUMMY_RELAY_COUNT == lightChannels()) {
|
||||
line["gpio"] = String("CH") + String(i-physical);
|
||||
res = String("CH") + String(i-physical);
|
||||
} else if (DUMMY_RELAY_COUNT == (lightChannels() + 1u)) {
|
||||
if (physical == i) {
|
||||
line["gpio"] = String("Light");
|
||||
res = String("Light");
|
||||
} else {
|
||||
line["gpio"] = String("CH") + String(i-1-physical);
|
||||
res = String("CH") + String(i-1-physical);
|
||||
}
|
||||
} else {
|
||||
line["gpio"] = String("Light");
|
||||
res = String("Light");
|
||||
}
|
||||
} else {
|
||||
line["gpio"] = String("?");
|
||||
res = String("?");
|
||||
}
|
||||
#else
|
||||
line["gpio"] = String("SW") + String(i);
|
||||
res = String("SW") + String(i);
|
||||
#endif
|
||||
} else {
|
||||
line["gpio"] = String("GPIO") + String(_relays[i].pin);
|
||||
}
|
||||
|
||||
line["type"] = _relays[i].type;
|
||||
line["reset"] = _relays[i].reset_pin;
|
||||
line["boot"] = getSetting("relayBoot", i, RELAY_BOOT_MODE).toInt();
|
||||
line["pulse"] = _relays[i].pulse;
|
||||
line["pulse_ms"] = _relays[i].pulse_ms / 1000.0;
|
||||
#if MQTT_SUPPORT
|
||||
line["group"] = getSetting("mqttGroup", i, "");
|
||||
line["group_inv"] = getSetting("mqttGroupInv", i, 0).toInt();
|
||||
line["on_disc"] = getSetting("relayOnDisc", i, 0).toInt();
|
||||
#endif
|
||||
|
||||
String output;
|
||||
root.printTo(output);
|
||||
jsonBuffer.clear();
|
||||
wsSend((char *) output.c_str());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void _relayWebSocketSendRelays() {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
JsonObject& relays = root.createNestedObject("relayConfig");
|
||||
|
||||
relays["size"] = relayCount();
|
||||
relays["start"] = 0;
|
||||
|
||||
JsonArray& gpio = relays.createNestedArray("gpio");
|
||||
JsonArray& type = relays.createNestedArray("type");
|
||||
JsonArray& reset = relays.createNestedArray("reset");
|
||||
JsonArray& boot = relays.createNestedArray("boot");
|
||||
JsonArray& pulse = relays.createNestedArray("pulse");
|
||||
JsonArray& pulse_time = relays.createNestedArray("pulse_time");
|
||||
|
||||
#if MQTT_SUPPORT
|
||||
JsonArray& group = relays.createNestedArray("group");
|
||||
JsonArray& group_inverse = relays.createNestedArray("group_inv");
|
||||
JsonArray& on_disconnect = relays.createNestedArray("on_disc");
|
||||
#endif
|
||||
|
||||
for (unsigned char i=0; i<relayCount(); i++) {
|
||||
_relayWebSocketSendRelay(i);
|
||||
gpio.add(_relayFriendlyName(i));
|
||||
|
||||
type.add(_relays[i].type);
|
||||
reset.add(_relays[i].reset_pin);
|
||||
boot.add(getSetting("relayBoot", i, RELAY_BOOT_MODE).toInt());
|
||||
|
||||
pulse.add(_relays[i].pulse);
|
||||
pulse_time.add(_relays[i].pulse_ms / 1000.0);
|
||||
|
||||
#if MQTT_SUPPORT
|
||||
group.add(getSetting("mqttGroup", i, ""));
|
||||
group_inverse.add(getSetting("mqttGroupInv", i, 0).toInt() == 1);
|
||||
on_disconnect.add(getSetting("relayOnDisc", i, 0).toInt());
|
||||
#endif
|
||||
}
|
||||
|
||||
wsSend(root);
|
||||
}
|
||||
|
||||
void _relayWebSocketOnStart(JsonObject& root) {
|
||||
|
||||
@@ -88,17 +88,21 @@ static bool _rfbToChar(byte * in, char * out, int n = RF_MESSAGE_SIZE) {
|
||||
|
||||
#if WEB_SUPPORT
|
||||
|
||||
void _rfbWebSocketSendCode(unsigned char id, bool status, const char * code) {
|
||||
char wsb[192]; // (32 * 5): 46 bytes for json , 116 bytes raw code, reserve
|
||||
snprintf_P(wsb, sizeof(wsb), PSTR("{\"rfb\":[{\"id\": %d, \"status\": %d, \"data\": \"%s\"}]}"), id, status ? 1 : 0, code);
|
||||
wsSend(wsb);
|
||||
}
|
||||
|
||||
void _rfbWebSocketSendCodes() {
|
||||
for (unsigned char id=0; id<relayCount(); id++) {
|
||||
_rfbWebSocketSendCode(id, true, rfbRetrieve(id, true).c_str());
|
||||
_rfbWebSocketSendCode(id, false, rfbRetrieve(id, false).c_str());
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
root["size"] = relayCount();
|
||||
|
||||
JsonArray& on = root.createNestedArray("on");
|
||||
JsonArray& off = root.createNestedArray("off");
|
||||
|
||||
for (byte id=0; id<relayCount(); id++) {
|
||||
on.add(rfbRetrieve(id, true));
|
||||
off.add(rfbRetrieve(id, false));
|
||||
}
|
||||
|
||||
wsSend(rfb);
|
||||
}
|
||||
|
||||
void _rfbWebSocketOnSend(JsonObject& root) {
|
||||
|
||||
@@ -21,26 +21,41 @@ bool _schWebSocketOnReceive(const char * key, JsonVariant& value) {
|
||||
|
||||
void _schWebSocketOnSend(JsonObject &root){
|
||||
|
||||
if (relayCount() > 0) {
|
||||
if (!relayCount()) return;
|
||||
|
||||
root["schVisible"] = 1;
|
||||
root["maxSchedules"] = SCHEDULER_MAX_SCHEDULES;
|
||||
JsonArray &sch = root.createNestedArray("schedule");
|
||||
for (byte i = 0; i < SCHEDULER_MAX_SCHEDULES; i++) {
|
||||
if (!hasSetting("schSwitch", i)) break;
|
||||
JsonObject &scheduler = sch.createNestedObject();
|
||||
scheduler["schEnabled"] = getSetting("schEnabled", i, 1).toInt() == 1;
|
||||
scheduler["schSwitch"] = getSetting("schSwitch", i, 0).toInt();
|
||||
scheduler["schAction"] = getSetting("schAction", i, 0).toInt();
|
||||
scheduler["schType"] = getSetting("schType", i, 0).toInt();
|
||||
scheduler["schHour"] = getSetting("schHour", i, 0).toInt();
|
||||
scheduler["schMinute"] = getSetting("schMinute", i, 0).toInt();
|
||||
scheduler["schUTC"] = getSetting("schUTC", i, 0).toInt() == 1;
|
||||
scheduler["schWDs"] = getSetting("schWDs", i, "");
|
||||
}
|
||||
root["schVisible"] = 1;
|
||||
root["maxSchedules"] = SCHEDULER_MAX_SCHEDULES;
|
||||
|
||||
JsonObject &schedules = root.createNestedObject("schedules");
|
||||
uint8_t size = 0;
|
||||
|
||||
JsonArray& enabled = schedules.createNestedArray("schEnabled");
|
||||
JsonArray& switch_ = schedules.createNestedArray("schSwitch");
|
||||
JsonArray& action = schedules.createNestedArray("schAction");
|
||||
JsonArray& type = schedules.createNestedArray("schType");
|
||||
JsonArray& hour = schedules.createNestedArray("schHour");
|
||||
JsonArray& minute = schedules.createNestedArray("schMinute");
|
||||
JsonArray& utc = schedules.createNestedArray("schUTC");
|
||||
JsonArray& weekdays = schedules.createNestedArray("schWDs");
|
||||
|
||||
for (byte i = 0; i < SCHEDULER_MAX_SCHEDULES; i++) {
|
||||
if (!hasSetting("schSwitch", i)) break;
|
||||
++size;
|
||||
|
||||
enabled.add<uint8_t>(getSetting("schEnabled", i, 1).toInt() == 1);
|
||||
utc.add<uint8_t>(getSetting("schUTC", i, 0).toInt() == 1);
|
||||
|
||||
switch_.add(getSetting("schSwitch", i, 0).toInt());
|
||||
action.add(getSetting("schAction", i, 0).toInt());
|
||||
type.add(getSetting("schType", i, 0).toInt());
|
||||
hour.add(getSetting("schHour", i, 0).toInt());
|
||||
minute.add(getSetting("schMinute", i, 0).toInt());
|
||||
weekdays.add(getSetting("schWDs", i, ""));
|
||||
}
|
||||
|
||||
schedules["size"] = size;
|
||||
schedules["start"] = 0;
|
||||
|
||||
}
|
||||
|
||||
#endif // WEB_SUPPORT
|
||||
|
||||
@@ -102,6 +102,32 @@ double _magnitudeProcess(unsigned char type, double value) {
|
||||
|
||||
#if WEB_SUPPORT
|
||||
|
||||
template<typename T>
|
||||
void _sensorWebSocketMagnitudes(JsonObject& root, T prefix) {
|
||||
|
||||
// ws produces flat list <prefix>Magnitudes
|
||||
String ws_name = String(prefix);
|
||||
ws_name.concat("Magnitudes");
|
||||
|
||||
// config uses <prefix>Magnitude<index> (cut 's')
|
||||
String conf_name = ws_name.substring(0, ws_name.length() - 1);
|
||||
|
||||
JsonObject& list = root.createNestedObject(ws_name);
|
||||
list["size"] = magnitudeCount();
|
||||
|
||||
JsonArray& name = list.createNestedArray("name");
|
||||
JsonArray& type = list.createNestedArray("type");
|
||||
JsonArray& index = list.createNestedArray("index");
|
||||
JsonArray& idx = list.createNestedArray("idx");
|
||||
|
||||
for (unsigned char i=0; i<magnitudeCount(); ++i) {
|
||||
name.add(magnitudeName(i));
|
||||
type.add(magnitudeType(i));
|
||||
index.add(magnitudeIndex(i));
|
||||
idx.add(getSetting(conf_name, i, 0).toInt());
|
||||
}
|
||||
}
|
||||
|
||||
bool _sensorWebSocketOnReceive(const char * key, JsonVariant& value) {
|
||||
if (strncmp(key, "pwr", 3) == 0) return true;
|
||||
if (strncmp(key, "sns", 3) == 0) return true;
|
||||
@@ -118,27 +144,36 @@ void _sensorWebSocketSendData(JsonObject& root) {
|
||||
bool hasHumidity = false;
|
||||
bool hasMICS = false;
|
||||
|
||||
JsonArray& list = root.createNestedArray("magnitudes");
|
||||
for (unsigned char i=0; i<_magnitudes.size(); i++) {
|
||||
JsonObject& magnitudes = root.createNestedObject("magnitudes");
|
||||
uint8_t size = 0;
|
||||
|
||||
JsonArray& index = magnitudes.createNestedArray("index");
|
||||
JsonArray& type = magnitudes.createNestedArray("type");
|
||||
JsonArray& value = magnitudes.createNestedArray("value");
|
||||
JsonArray& units = magnitudes.createNestedArray("units");
|
||||
JsonArray& error = magnitudes.createNestedArray("error");
|
||||
JsonArray& description = magnitudes.createNestedArray("description");
|
||||
|
||||
for (unsigned char i=0; i<magnitudeCount(); i++) {
|
||||
|
||||
sensor_magnitude_t magnitude = _magnitudes[i];
|
||||
if (magnitude.type == MAGNITUDE_EVENT) continue;
|
||||
++size;
|
||||
|
||||
unsigned char decimals = _magnitudeDecimals(magnitude.type);
|
||||
dtostrf(magnitude.current, 1-sizeof(buffer), decimals, buffer);
|
||||
|
||||
JsonObject& element = list.createNestedObject();
|
||||
element["index"] = int(magnitude.global);
|
||||
element["type"] = int(magnitude.type);
|
||||
element["value"] = String(buffer);
|
||||
element["units"] = magnitudeUnits(magnitude.type);
|
||||
element["error"] = magnitude.sensor->error();
|
||||
index.add<uint8_t>(magnitude.global);
|
||||
type.add<uint8_t>(magnitude.type);
|
||||
value.add(buffer);
|
||||
units.add(magnitudeUnits(magnitude.type));
|
||||
error.add(magnitude.sensor->error());
|
||||
|
||||
if (magnitude.type == MAGNITUDE_ENERGY) {
|
||||
if (_sensor_energy_reset_ts.length() == 0) _sensorResetTS();
|
||||
element["description"] = magnitude.sensor->slot(magnitude.local) + String(" (since ") + _sensor_energy_reset_ts + String(")");
|
||||
description.add(magnitude.sensor->slot(magnitude.local) + String(" (since ") + _sensor_energy_reset_ts + String(")"));
|
||||
} else {
|
||||
element["description"] = magnitude.sensor->slot(magnitude.local);
|
||||
description.add(magnitude.sensor->slot(magnitude.local));
|
||||
}
|
||||
|
||||
if (magnitude.type == MAGNITUDE_TEMPERATURE) hasTemperature = true;
|
||||
@@ -148,6 +183,8 @@ void _sensorWebSocketSendData(JsonObject& root) {
|
||||
#endif
|
||||
}
|
||||
|
||||
magnitudes["size"] = size;
|
||||
|
||||
if (hasTemperature) root["temperatureVisible"] = 1;
|
||||
if (hasHumidity) root["humidityVisible"] = 1;
|
||||
if (hasMICS) root["micsVisible"] = 1;
|
||||
@@ -210,7 +247,7 @@ void _sensorWebSocketStart(JsonObject& root) {
|
||||
|
||||
}
|
||||
|
||||
if (_magnitudes.size() > 0) {
|
||||
if (magnitudeCount()) {
|
||||
root["snsVisible"] = 1;
|
||||
//root["apiRealTime"] = _sensor_realtime;
|
||||
root["pwrUnits"] = _sensor_power_units;
|
||||
|
||||
@@ -75,15 +75,8 @@ void _tspkWebSocketOnSend(JsonObject& root) {
|
||||
if (relayCount() > 0) visible = 1;
|
||||
|
||||
#if SENSOR_SUPPORT
|
||||
JsonArray& list = root.createNestedArray("tspkMagnitudes");
|
||||
for (byte i=0; i<magnitudeCount(); i++) {
|
||||
JsonObject& element = list.createNestedObject();
|
||||
element["name"] = magnitudeName(i);
|
||||
element["type"] = magnitudeType(i);
|
||||
element["index"] = magnitudeIndex(i);
|
||||
element["idx"] = getSetting("tspkMagnitude", i, 0).toInt();
|
||||
}
|
||||
if (magnitudeCount() > 0) visible = 1;
|
||||
_sensorWebSocketMagnitudes(root, "tspk");
|
||||
visible = visible || (magnitudeCount() > 0);
|
||||
#endif
|
||||
|
||||
root["tspkVisible"] = visible;
|
||||
|
||||
@@ -73,6 +73,22 @@ bool _wsAuth(AsyncWebSocketClient * client) {
|
||||
|
||||
}
|
||||
|
||||
#if DEBUG_WEB_SUPPORT
|
||||
|
||||
bool wsDebugSend(const char* message) {
|
||||
if (!wsConnected()) return false;
|
||||
if (getFreeHeap() < (strlen(message) * 3)) return false;
|
||||
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject &root = jsonBuffer.createObject();
|
||||
root.set("weblog", message);
|
||||
|
||||
wsSend(root);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if MQTT_SUPPORT
|
||||
@@ -289,6 +305,20 @@ void _wsUpdate(JsonObject& root) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void _wsDoUpdate(bool reset = false) {
|
||||
static unsigned long last = 0;
|
||||
if (reset) {
|
||||
last = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (millis() - last > WS_UPDATE_INTERVAL) {
|
||||
last = millis();
|
||||
wsSend(_wsUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool _wsOnReceive(const char * key, JsonVariant& value) {
|
||||
if (strncmp(key, "ws", 2) == 0) return true;
|
||||
if (strncmp(key, "admin", 5) == 0) return true;
|
||||
@@ -298,69 +328,94 @@ bool _wsOnReceive(const char * key, JsonVariant& value) {
|
||||
}
|
||||
|
||||
void _wsOnStart(JsonObject& root) {
|
||||
char chipid[7];
|
||||
snprintf_P(chipid, sizeof(chipid), PSTR("%06X"), ESP.getChipId());
|
||||
uint8_t * bssid = WiFi.BSSID();
|
||||
char bssid_str[20];
|
||||
snprintf_P(bssid_str, sizeof(bssid_str),
|
||||
PSTR("%02X:%02X:%02X:%02X:%02X:%02X"),
|
||||
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]
|
||||
);
|
||||
|
||||
root["webMode"] = WEB_MODE_NORMAL;
|
||||
|
||||
root["app_name"] = APP_NAME;
|
||||
root["app_version"] = APP_VERSION;
|
||||
root["app_build"] = buildTime();
|
||||
#if defined(APP_REVISION)
|
||||
root["app_revision"] = APP_REVISION;
|
||||
#endif
|
||||
root["manufacturer"] = MANUFACTURER;
|
||||
root["chipid"] = String(chipid);
|
||||
root["mac"] = WiFi.macAddress();
|
||||
root["bssid"] = String(bssid_str);
|
||||
root["channel"] = WiFi.channel();
|
||||
root["device"] = DEVICE;
|
||||
root["hostname"] = getSetting("hostname");
|
||||
root["network"] = getNetwork();
|
||||
root["deviceip"] = getIP();
|
||||
root["sketch_size"] = ESP.getSketchSize();
|
||||
root["free_size"] = ESP.getFreeSketchSpace();
|
||||
root["sdk"] = ESP.getSdkVersion();
|
||||
root["core"] = getCoreVersion();
|
||||
|
||||
root["btnDelay"] = getSetting("btnDelay", BUTTON_DBLCLICK_DELAY).toInt();
|
||||
root["webPort"] = getSetting("webPort", WEB_PORT).toInt();
|
||||
root["wsAuth"] = getSetting("wsAuth", WS_AUTHENTICATION).toInt() == 1;
|
||||
#if TERMINAL_SUPPORT
|
||||
root["cmdVisible"] = 1;
|
||||
#endif
|
||||
root["hbMode"] = getSetting("hbMode", HEARTBEAT_MODE).toInt();
|
||||
root["hbInterval"] = getSetting("hbInterval", HEARTBEAT_INTERVAL).toInt();
|
||||
|
||||
_wsDoUpdate(true);
|
||||
|
||||
}
|
||||
|
||||
void wsSend(JsonObject& root) {
|
||||
size_t len = root.measureLength();
|
||||
AsyncWebSocketMessageBuffer* buffer = _ws.makeBuffer(len);
|
||||
|
||||
if (buffer) {
|
||||
root.printTo(reinterpret_cast<char*>(buffer->get()), len + 1);
|
||||
_ws.textAll(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void wsSend(uint32_t client_id, JsonObject& root) {
|
||||
AsyncWebSocketClient* client = _ws.client(client_id);
|
||||
if (client == nullptr) return;
|
||||
|
||||
size_t len = root.measureLength();
|
||||
AsyncWebSocketMessageBuffer* buffer = _ws.makeBuffer(len);
|
||||
|
||||
if (buffer) {
|
||||
root.printTo(reinterpret_cast<char*>(buffer->get()), len + 1);
|
||||
client->text(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void _wsStart(uint32_t client_id) {
|
||||
#if USE_PASSWORD && WEB_FORCE_PASS_CHANGE
|
||||
bool changePassword = getAdminPass().equals(ADMIN_PASS);
|
||||
#else
|
||||
bool changePassword = false;
|
||||
#endif
|
||||
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
if (changePassword) {
|
||||
|
||||
root["webMode"] = WEB_MODE_PASSWORD;
|
||||
|
||||
} else {
|
||||
|
||||
char chipid[7];
|
||||
snprintf_P(chipid, sizeof(chipid), PSTR("%06X"), ESP.getChipId());
|
||||
uint8_t * bssid = WiFi.BSSID();
|
||||
char bssid_str[20];
|
||||
snprintf_P(bssid_str, sizeof(bssid_str),
|
||||
PSTR("%02X:%02X:%02X:%02X:%02X:%02X"),
|
||||
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]
|
||||
);
|
||||
|
||||
root["webMode"] = WEB_MODE_NORMAL;
|
||||
|
||||
root["app_name"] = APP_NAME;
|
||||
root["app_version"] = APP_VERSION;
|
||||
root["app_build"] = buildTime();
|
||||
#if defined(APP_REVISION)
|
||||
root["app_revision"] = APP_REVISION;
|
||||
#endif
|
||||
root["manufacturer"] = MANUFACTURER;
|
||||
root["chipid"] = String(chipid);
|
||||
root["mac"] = WiFi.macAddress();
|
||||
root["bssid"] = String(bssid_str);
|
||||
root["channel"] = WiFi.channel();
|
||||
root["device"] = DEVICE;
|
||||
root["hostname"] = getSetting("hostname");
|
||||
root["network"] = getNetwork();
|
||||
root["deviceip"] = getIP();
|
||||
root["sketch_size"] = ESP.getSketchSize();
|
||||
root["free_size"] = ESP.getFreeSketchSpace();
|
||||
root["sdk"] = ESP.getSdkVersion();
|
||||
root["core"] = getCoreVersion();
|
||||
|
||||
_wsUpdate(root);
|
||||
|
||||
root["btnDelay"] = getSetting("btnDelay", BUTTON_DBLCLICK_DELAY).toInt();
|
||||
root["webPort"] = getSetting("webPort", WEB_PORT).toInt();
|
||||
root["wsAuth"] = getSetting("wsAuth", WS_AUTHENTICATION).toInt() == 1;
|
||||
#if TERMINAL_SUPPORT
|
||||
root["cmdVisible"] = 1;
|
||||
#endif
|
||||
root["hbMode"] = getSetting("hbMode", HEARTBEAT_MODE).toInt();
|
||||
root["hbInterval"] = getSetting("hbInterval", HEARTBEAT_INTERVAL).toInt();
|
||||
|
||||
wsSend(root);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void _wsStart(uint32_t client_id) {
|
||||
for (unsigned char i = 0; i < _ws_on_send_callbacks.size(); i++) {
|
||||
wsSend(client_id, _ws_on_send_callbacks[i]);
|
||||
for (auto callback : _ws_on_send_callbacks) {
|
||||
callback(root);
|
||||
}
|
||||
|
||||
wsSend(client_id, root);
|
||||
}
|
||||
|
||||
void _wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
|
||||
@@ -408,12 +463,8 @@ void _wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTy
|
||||
}
|
||||
|
||||
void _wsLoop() {
|
||||
static unsigned long last = 0;
|
||||
if (!wsConnected()) return;
|
||||
if (millis() - last > WS_UPDATE_INTERVAL) {
|
||||
last = millis();
|
||||
wsSend(_wsUpdate);
|
||||
}
|
||||
_wsDoUpdate();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -441,10 +492,8 @@ void wsSend(ws_on_send_callback_f callback) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
callback(root);
|
||||
String output;
|
||||
root.printTo(output);
|
||||
jsonBuffer.clear();
|
||||
_ws.textAll((char *) output.c_str());
|
||||
|
||||
wsSend(root);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,13 +512,20 @@ void wsSend_P(PGM_P payload) {
|
||||
}
|
||||
|
||||
void wsSend(uint32_t client_id, ws_on_send_callback_f callback) {
|
||||
AsyncWebSocketClient* client = _ws.client(client_id);
|
||||
if (client == nullptr) return;
|
||||
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
callback(root);
|
||||
String output;
|
||||
root.printTo(output);
|
||||
jsonBuffer.clear();
|
||||
_ws.text(client_id, (char *) output.c_str());
|
||||
|
||||
size_t len = root.measureLength();
|
||||
AsyncWebSocketMessageBuffer* buffer = _ws.makeBuffer(len);
|
||||
|
||||
if (buffer) {
|
||||
root.printTo(reinterpret_cast<char*>(buffer->get()), len + 1);
|
||||
client->text(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void wsSend(uint32_t client_id, const char * payload) {
|
||||
|
||||
@@ -767,12 +767,13 @@ function createMagnitudeList(data, container, template_name) {
|
||||
if (current > 0) { return; }
|
||||
|
||||
var template = $("#" + template_name + " .pure-g")[0];
|
||||
for (var i in data) {
|
||||
var magnitude = data[i];
|
||||
var size = data.size;
|
||||
|
||||
for (var i=0; i<size; ++i) {
|
||||
var line = $(template).clone();
|
||||
$("label", line).html(magnitudeType(magnitude.type) + " #" + parseInt(magnitude.index, 10));
|
||||
$("div.hint", line).html(magnitude.name);
|
||||
$("input", line).attr("tabindex", 40 + i).val(magnitude.idx);
|
||||
$("label", line).html(magnitudeType(data.type[i]) + " #" + parseInt(data.index[i], 10));
|
||||
$("div.hint", line).html(data.name[i]);
|
||||
$("input", line).attr("tabindex", 40 + i).val(data.idx[i]);
|
||||
line.appendTo("#" + container);
|
||||
}
|
||||
|
||||
@@ -934,24 +935,34 @@ function createCheckboxes() {
|
||||
|
||||
function initRelayConfig(data) {
|
||||
|
||||
var current = $("#relayConfig > div").length / 6; // there are 6 divs per each relay
|
||||
var current = $("#relayConfig > legend").length; // there is a legend per relay
|
||||
if (current > 0) { return; }
|
||||
|
||||
var size = data.size;
|
||||
var start = data.start;
|
||||
|
||||
var template = $("#relayConfigTemplate").children();
|
||||
for (var i in data) {
|
||||
|
||||
var relay = data[i];
|
||||
if (current > relay.id) continue;
|
||||
|
||||
for (var i=start; i<size; ++i) {
|
||||
var line = $(template).clone();
|
||||
$("span.gpio", line).html(relay.gpio);
|
||||
$("span.id", line).html(relay.id);
|
||||
$("select[name='relayBoot']", line).val(relay.boot);
|
||||
$("select[name='relayPulse']", line).val(relay.pulse);
|
||||
$("input[name='relayTime']", line).val(relay.pulse_ms);
|
||||
$("input[name='mqttGroup']", line).val(relay.group);
|
||||
$("select[name='mqttGroupInv']", line).val(relay.group_inv);
|
||||
$("select[name='relayOnDisc']", line).val(relay.on_disc);
|
||||
line.appendTo("#relayConfig");
|
||||
|
||||
$("span.id", line).html(i);
|
||||
$("span.gpio", line).html(data.gpio[i]);
|
||||
$("select[name='relayBoot']", line).val(data.boot[i]);
|
||||
$("select[name='relayPulse']", line).val(data.pulse[i]);
|
||||
$("input[name='relayTime']", line).val(data.pulse_time[i]);
|
||||
|
||||
if ("group" in data) {
|
||||
$("input[name='mqttGroup']", line).val(data.group[i]);
|
||||
}
|
||||
if ("group_inv" in data) {
|
||||
$("input[name='mqttGroupInv']", line).val(data.group_inv[i]);
|
||||
}
|
||||
if ("on_disc" in data) {
|
||||
$("input[name='relayOnDisc']", line).val(data.on_disc[i]);
|
||||
}
|
||||
|
||||
line.appendTo("#relayConfig");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -963,17 +974,19 @@ function initRelayConfig(data) {
|
||||
<!-- removeIf(!sensor)-->
|
||||
function initMagnitudes(data) {
|
||||
|
||||
// check if already initialized
|
||||
// check if already initialized (each magnitude is inside div.pure-g)
|
||||
var done = $("#magnitudes > div").length;
|
||||
if (done > 0) { return; }
|
||||
|
||||
var size = data.size;
|
||||
|
||||
// add templates
|
||||
var template = $("#magnitudeTemplate").children();
|
||||
for (var i in data) {
|
||||
var magnitude = data[i];
|
||||
|
||||
for (var i=0; i<size; ++i) {
|
||||
var line = $(template).clone();
|
||||
$("label", line).html(magnitudeType(magnitude.type) + " #" + parseInt(magnitude.index, 10));
|
||||
$("div.hint", line).html(magnitude.description);
|
||||
$("label", line).html(magnitudeType(data.type[i]) + " #" + parseInt(data.index[i], 10));
|
||||
$("div.hint", line).html(data.description[i]);
|
||||
$("input", line).attr("data", i);
|
||||
line.appendTo("#magnitudes");
|
||||
}
|
||||
@@ -1202,11 +1215,17 @@ function processData(data) {
|
||||
}
|
||||
|
||||
if ("rfb" === key) {
|
||||
var nodes = data.rfb;
|
||||
for (i in nodes) {
|
||||
var node = nodes[i];
|
||||
$("input[name='rfbcode'][data-id='" + node.id + "'][data-status='" + node.status + "']").val(node.data);
|
||||
var rfb = data.rfb;
|
||||
var size = data.size;
|
||||
|
||||
var on = rfb[0];
|
||||
var off = rfb[1];
|
||||
|
||||
for (var i=0; i<size; ++i) {
|
||||
$("input[name='rfbcode'][data-id='" + i + "'][data-status='1']").val(on[i]);
|
||||
$("input[name='rfbcode'][data-id='" + i + "'][data-status='0']").val(off[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
<!-- endRemoveIf(!rfbridge)-->
|
||||
@@ -1321,15 +1340,13 @@ function processData(data) {
|
||||
|
||||
if ("magnitudes" === key) {
|
||||
initMagnitudes(value);
|
||||
for (i in value) {
|
||||
var magnitude = value[i];
|
||||
var error = magnitude.error || 0;
|
||||
for (var i=0; i<value.size; ++i) {
|
||||
var error = value.error[i] || 0;
|
||||
var text = (0 === error) ?
|
||||
magnitude.value + magnitude.units :
|
||||
value.value[i] + value.units[i] :
|
||||
magnitudeError(error);
|
||||
var element = $("input[name='magnitude'][data='" + i + "']");
|
||||
element.val(text);
|
||||
$("div.hint", element.parent().parent()).html(magnitude.description);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1378,13 +1395,13 @@ function processData(data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ("schedule" === key) {
|
||||
for (i in value) {
|
||||
var schedule = value[i];
|
||||
var sch_line = addSchedule({ data: {schType: schedule["schType"] }});
|
||||
if ("schedules" === key) {
|
||||
for (var i=0; i<value.size; ++i) {
|
||||
var sch_line = addSchedule({ data: {schType: value.schType[i] }});
|
||||
|
||||
Object.keys(schedule).forEach(function(key) {
|
||||
var sch_value = schedule[key];
|
||||
Object.keys(value).forEach(function(key) {
|
||||
if ("size" == key) return;
|
||||
var sch_value = value[key][i];
|
||||
$("input[name='" + key + "']", sch_line).val(sch_value);
|
||||
$("select[name='" + key + "']", sch_line).prop("value", sch_value);
|
||||
$("input[type='checkbox'][name='" + key + "']", sch_line).prop("checked", sch_value);
|
||||
@@ -1459,6 +1476,7 @@ function processData(data) {
|
||||
|
||||
// Web log
|
||||
if ("weblog" === key) {
|
||||
websock.send("{}");
|
||||
$("#weblog").append(new Text(value));
|
||||
$("#weblog").scrollTop($("#weblog")[0].scrollHeight - $("#weblog").height());
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user