mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
added mqtt log
This commit is contained in:
235
src/MyESP.cpp
235
src/MyESP.cpp
@@ -22,7 +22,6 @@ union system_rtcmem_t {
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
|
||||
// nasty global variables that are called from internal ws functions
|
||||
static char * _general_password = nullptr;
|
||||
static bool _shouldRestart = false;
|
||||
@@ -103,6 +102,13 @@ MyESP::MyESP() {
|
||||
|
||||
// get the build time
|
||||
_buildTime = _getBuildTime();
|
||||
|
||||
// MQTT log
|
||||
for (uint8_t i = 0; i < MYESP_MQTTLOG_MAX; i++) {
|
||||
MQTT_log[i].timestamp = 0;
|
||||
MQTT_log[i].topic = nullptr;
|
||||
MQTT_log[i].payload = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
MyESP::~MyESP() {
|
||||
@@ -190,12 +196,6 @@ uint32_t MyESP::_getInitialFreeHeap() {
|
||||
return _heap;
|
||||
}
|
||||
|
||||
// used heap mem
|
||||
// note calls to getFreeHeap sometimes causes some ESPs to crash
|
||||
uint32_t MyESP::_getUsedHeap() {
|
||||
return _getInitialFreeHeap() - ESP.getFreeHeap();
|
||||
}
|
||||
|
||||
// called when WiFi is connected, and used to start OTA, MQTT
|
||||
void MyESP::_wifiCallback(justwifi_messages_t code, char * parameter) {
|
||||
if ((code == MESSAGE_CONNECTED)) {
|
||||
@@ -370,6 +370,8 @@ void MyESP::mqttUnsubscribe(const char * topic) {
|
||||
void MyESP::mqttPublish(const char * topic, const char * payload) {
|
||||
// myDebug_P(PSTR("[MQTT] Sending pubish to %s with payload %s"), _mqttTopic(topic), payload); // for debugging
|
||||
mqttClient.publish(_mqttTopic(topic), _mqtt_qos, _mqtt_retain, payload);
|
||||
|
||||
_addMQTTLog(topic, payload); // add to the log
|
||||
}
|
||||
|
||||
// MQTT onConnect - when a connect is established
|
||||
@@ -380,7 +382,7 @@ void MyESP::_mqttOnConnect() {
|
||||
_mqtt_last_connection = millis();
|
||||
|
||||
// say we're alive to the Last Will topic
|
||||
mqttClient.publish(_mqttTopic(_mqtt_will_topic), 1, true, _mqtt_will_online_payload);
|
||||
mqttClient.publish(_mqttTopic(_mqtt_will_topic), 1, true, _mqtt_will_online_payload); // qos=1, retain=true
|
||||
|
||||
// subscribe to general subs
|
||||
mqttSubscribe(MQTT_TOPIC_RESTART);
|
||||
@@ -389,6 +391,9 @@ void MyESP::_mqttOnConnect() {
|
||||
mqttSubscribe(MQTT_TOPIC_START);
|
||||
mqttPublish(MQTT_TOPIC_START, MQTT_TOPIC_START_PAYLOAD);
|
||||
|
||||
// send heartbeat if enabled
|
||||
_heartbeatCheck(true);
|
||||
|
||||
// call custom function to handle mqtt receives
|
||||
(_mqtt_callback_f)(MQTT_CONNECT_EVENT, nullptr, nullptr);
|
||||
}
|
||||
@@ -604,7 +609,7 @@ void MyESP::_consoleShowHelp() {
|
||||
myDebug_P(PSTR("*"));
|
||||
myDebug_P(PSTR("* Commands:"));
|
||||
myDebug_P(PSTR("* ?=help, CTRL-D/quit=exit telnet session"));
|
||||
myDebug_P(PSTR("* set, system, restart"));
|
||||
myDebug_P(PSTR("* set, system, restart, mqttlog"));
|
||||
#ifdef CRASH
|
||||
myDebug_P(PSTR("* crash <dump | clear | test [n]>"));
|
||||
#endif
|
||||
@@ -944,6 +949,13 @@ void MyESP::_telnetCommand(char * commandLine) {
|
||||
// restart command
|
||||
if ((strcmp(ptrToCommandName, "restart") == 0) && (wc == 1)) {
|
||||
resetESP();
|
||||
return;
|
||||
}
|
||||
|
||||
// print mqtt log command
|
||||
if ((strcmp(ptrToCommandName, "mqttlog") == 0) && (wc == 1)) {
|
||||
_printMQTTLog();
|
||||
return;
|
||||
}
|
||||
|
||||
// show system stats
|
||||
@@ -1108,7 +1120,7 @@ bool MyESP::_rtcmemStatus() {
|
||||
if (reason == REASON_EXT_SYS_RST) { // external system reset
|
||||
if (getSystemBootStatus() == MYESP_BOOTSTATUS_BOOTING) {
|
||||
_setSystemBootStatus(MYESP_BOOTSTATUS_RESETNEEDED);
|
||||
// _formatreq = true; // do a wipe next in the loop() TODO commented out for now
|
||||
// _formatreq = true; // do a wipe next in the loop() - commented out for now because we use the web
|
||||
} else {
|
||||
_setSystemBootStatus(MYESP_BOOTSTATUS_POWERON);
|
||||
}
|
||||
@@ -1199,7 +1211,6 @@ void MyESP::_systemCheckLoop() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// print out ESP system stats
|
||||
// for battery power is ESP.getVcc()
|
||||
void MyESP::showSystemStats() {
|
||||
@@ -1340,6 +1351,8 @@ void MyESP::_heartbeatCheck(bool force = false) {
|
||||
if ((millis() - last_heartbeat > MYESP_HEARTBEAT_INTERVAL) || force) {
|
||||
last_heartbeat = millis();
|
||||
|
||||
// _printHeap("Heartbeat"); // for heartbeat debugging
|
||||
|
||||
if (!isMQTTConnected() || !(_mqtt_heartbeat)) {
|
||||
return;
|
||||
}
|
||||
@@ -1819,7 +1832,7 @@ bool MyESP::_fs_createCustomConfig() {
|
||||
// if it doesn't exist try and create it
|
||||
void MyESP::_fs_setup() {
|
||||
if (!SPIFFS.begin()) {
|
||||
Serial.print(F("[WARN] Formatting filesystem..."));
|
||||
myDebug_P(PSTR("[FS] Formatting filesystem..."));
|
||||
if (SPIFFS.format()) {
|
||||
_writeEvent("WARN", "sys", "File system formatted", "");
|
||||
} else {
|
||||
@@ -2108,7 +2121,7 @@ void MyESP::_writeEvent(const char * type, const char * src, const char * desc,
|
||||
return;
|
||||
}
|
||||
|
||||
StaticJsonDocument<300> root;
|
||||
StaticJsonDocument<MYESP_JSON_LOG_MAXSIZE> root;
|
||||
root["type"] = type;
|
||||
root["src"] = src;
|
||||
root["desc"] = desc;
|
||||
@@ -2132,9 +2145,16 @@ void MyESP::_sendEventLog(uint8_t page) {
|
||||
if (!eventlog) {
|
||||
eventlog.close();
|
||||
myDebug_P(PSTR("[WEB] Event log is missing"));
|
||||
if (_ota_post_callback_f) {
|
||||
(_ota_post_callback_f)(); // call custom function
|
||||
}
|
||||
return; // file can't be opened
|
||||
}
|
||||
|
||||
if (_ota_pre_callback_f) {
|
||||
(_ota_pre_callback_f)(); // call custom function
|
||||
}
|
||||
|
||||
// the size of the json will be quite big so best not to use stack (StaticJsonDocument)
|
||||
DynamicJsonDocument doc(MYESP_JSON_MAXSIZE);
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
@@ -2143,31 +2163,67 @@ void MyESP::_sendEventLog(uint8_t page) {
|
||||
|
||||
JsonArray list = doc.createNestedArray("list");
|
||||
|
||||
uint8_t first = (page - 1) * 10;
|
||||
uint8_t last = page * 10;
|
||||
uint8_t i = 0;
|
||||
uint8_t first = ((page - 1) * 10) + 1;
|
||||
uint8_t last = page * 10;
|
||||
uint8_t char_count = 0;
|
||||
uint8_t line_count = 0;
|
||||
uint16_t read_count = 0;
|
||||
bool abort = false;
|
||||
char char_buffer[MYESP_JSON_LOG_MAXSIZE];
|
||||
|
||||
while (eventlog.available()) {
|
||||
String item = String();
|
||||
item = eventlog.readStringUntil('\n');
|
||||
if (i >= first && i < last) {
|
||||
list.add(item);
|
||||
// if at start, start immediately recording
|
||||
bool record = (first == 1) ? true : false;
|
||||
|
||||
// start at top and read until we find the page we want (sets of 10)
|
||||
while (eventlog.available() && !abort) {
|
||||
char c = eventlog.read();
|
||||
|
||||
// see if we've overrun, which means corrupt so ignore rest
|
||||
if (read_count++ > MYESP_JSON_LOG_MAXSIZE - 1) {
|
||||
abort = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
eventlog.close();
|
||||
|
||||
float pages = i / 10.0;
|
||||
// see if we have reached the end of the string
|
||||
if (c == '\0' || c == '\n') {
|
||||
line_count++;
|
||||
|
||||
// save line
|
||||
if (record) {
|
||||
char_buffer[char_count] = '\0';
|
||||
list.add(char_buffer);
|
||||
}
|
||||
|
||||
char_count = 0;
|
||||
read_count = 0;
|
||||
if (line_count == first - 1) { // have we come to the start position, start recording
|
||||
record = true;
|
||||
} else if (line_count == last) { // finish recording and exit loop
|
||||
record = false;
|
||||
}
|
||||
} else {
|
||||
// add the char to the buffer if recording
|
||||
if (record && (char_count < MYESP_JSON_LOG_MAXSIZE)) {
|
||||
char_buffer[char_count++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
eventlog.close(); // close SPIFFS
|
||||
|
||||
float pages = line_count / 10.0;
|
||||
root["haspages"] = ceil(pages);
|
||||
|
||||
char buffer[MYESP_JSON_MAXSIZE];
|
||||
size_t len = serializeJson(root, buffer);
|
||||
|
||||
//Serial.printf("\nEVENTLOG: page %d\n", page); // turn on for debugging
|
||||
//serializeJson(root, Serial); // turn on for debugging
|
||||
//Serial.printf("\nEVENTLOG: page %d\n", page); // turn on for debugging XXX
|
||||
//serializeJson(root, Serial); // turn on for debugging
|
||||
|
||||
_ws->textAll(buffer, len);
|
||||
_ws->textAll("{\"command\":\"result\",\"resultof\":\"eventlist\",\"result\": true}");
|
||||
|
||||
if (_ota_post_callback_f) {
|
||||
(_ota_post_callback_f)(); // call custom function
|
||||
}
|
||||
}
|
||||
|
||||
// Handles WebSocket Events
|
||||
@@ -2334,22 +2390,27 @@ void MyESP::_sendCustomStatus() {
|
||||
|
||||
// send system status via ws
|
||||
void MyESP::_sendStatus() {
|
||||
StaticJsonDocument<400> doc;
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
// capture memory before we stick in a huge json buffer on the heap!
|
||||
uint32_t total_memory = _getInitialFreeHeap();
|
||||
uint32_t free_memory = ESP.getFreeHeap();
|
||||
|
||||
DynamicJsonDocument doc(MQTT_MAX_PAYLOAD_SIZE_LARGE);
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
root["command"] = "status";
|
||||
|
||||
FSInfo fsinfo;
|
||||
if (!SPIFFS.info(fsinfo)) {
|
||||
myDebug("[SYSTEM] Error getting info on SPIFFS");
|
||||
} else {
|
||||
root["availspiffs"] = (fsinfo.totalBytes - fsinfo.usedBytes) / 1000;
|
||||
root["spiffssize"] = (fsinfo.totalBytes / 1000);
|
||||
}
|
||||
|
||||
root["command"] = "status";
|
||||
|
||||
// all sizes in bytes converted to KB
|
||||
root["heap"] = ESP.getFreeHeap() / 1000;
|
||||
root["sketchsize"] = ESP.getSketchSize() / 1000;
|
||||
root["availsize"] = ESP.getFreeSketchSpace() / 1000;
|
||||
root["availspiffs"] = (fsinfo.totalBytes - fsinfo.usedBytes) / 1000;
|
||||
root["spiffssize"] = (fsinfo.totalBytes / 1000);
|
||||
root["initheap"] = total_memory;
|
||||
root["heap"] = free_memory;
|
||||
root["sketchsize"] = ESP.getSketchSize() / 1000;
|
||||
root["availsize"] = ESP.getFreeSketchSpace() / 1000;
|
||||
|
||||
if (isAPmode()) {
|
||||
root["ip"] = WiFi.softAPIP().toString();
|
||||
@@ -2377,8 +2438,32 @@ void MyESP::_sendStatus() {
|
||||
sprintf(uptime, "%d day%s %d hour%s %d minute%s %d second%s", d, (d == 1) ? "" : "s", h, (h == 1) ? "" : "s", m, (m == 1) ? "" : "s", sec, (sec == 1) ? "" : "s");
|
||||
root["uptime"] = uptime;
|
||||
|
||||
char buffer[400];
|
||||
char topic_s[MQTT_MAX_TOPIC_SIZE] = {0};
|
||||
if (_hasValue(_mqtt_base)) {
|
||||
strlcpy(topic_s, _mqtt_base, sizeof(topic_s));
|
||||
strlcat(topic_s, "/", sizeof(topic_s));
|
||||
strlcat(topic_s, _general_hostname, sizeof(topic_s));
|
||||
} else {
|
||||
strlcpy(topic_s, _general_hostname, sizeof(topic_s));
|
||||
}
|
||||
strlcat(topic_s, "/", sizeof(topic_s));
|
||||
root["mqttloghdr"] = topic_s;
|
||||
|
||||
// create MQTT log
|
||||
JsonArray list = root.createNestedArray("mqttlog");
|
||||
|
||||
for (uint8_t i = 0; i < MYESP_MQTTLOG_MAX; i++) {
|
||||
if (MQTT_log[i].topic != nullptr) {
|
||||
JsonObject item = list.createNestedObject();
|
||||
item["topic"] = MQTT_log[i].topic;
|
||||
item["payload"] = MQTT_log[i].payload;
|
||||
item["time"] = MQTT_log[i].timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
char buffer[MQTT_MAX_PAYLOAD_SIZE_LARGE];
|
||||
size_t len = serializeJson(root, buffer);
|
||||
|
||||
_ws->textAll(buffer, len);
|
||||
}
|
||||
|
||||
@@ -2525,6 +2610,72 @@ void MyESP::_webserver_setup() {
|
||||
myDebug_P(PSTR("[WEB] Web server started"));
|
||||
}
|
||||
|
||||
// print memory
|
||||
void MyESP::_printHeap(const char * s) {
|
||||
uint32_t total_memory = _getInitialFreeHeap();
|
||||
uint32_t free_memory = ESP.getFreeHeap();
|
||||
|
||||
myDebug(" [%s] Free Heap: %d bytes initially | %d bytes used (%2u%%) | %d bytes free (%2u%%)",
|
||||
s,
|
||||
total_memory,
|
||||
total_memory - free_memory,
|
||||
100 * (total_memory - free_memory) / total_memory,
|
||||
free_memory,
|
||||
100 * free_memory / total_memory);
|
||||
}
|
||||
|
||||
// print MQTT log - everything that was published last per topic
|
||||
void MyESP::_printMQTTLog() {
|
||||
myDebug_P(PSTR("MQTT publish log:"));
|
||||
|
||||
for (uint8_t i = 0; i < MYESP_MQTTLOG_MAX; i++) {
|
||||
if (MQTT_log[i].topic != nullptr) {
|
||||
myDebug_P(PSTR("(%d) [%lu] Topic:%s Payload:%s"), i, MQTT_log[i].timestamp, MQTT_log[i].topic, MQTT_log[i].payload);
|
||||
}
|
||||
}
|
||||
|
||||
myDebug_P(PSTR("")); // newline
|
||||
}
|
||||
|
||||
// add an MQTT log entry
|
||||
void MyESP::_addMQTTLog(const char * topic, const char * payload) {
|
||||
static uint8_t logCount = 0;
|
||||
uint8_t logPointer = 0;
|
||||
bool found = false;
|
||||
|
||||
// myDebug("Publish [#%d] %s (%d) %s (%d)", logCount, topic, strlen(topic), payload, strlen(payload)); // for debugging
|
||||
|
||||
// find the topic
|
||||
while ((_hasValue(MQTT_log[logPointer].topic) && logPointer < MYESP_MQTTLOG_MAX)) {
|
||||
if (strcmp(MQTT_log[logPointer].topic, topic) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
logPointer++;
|
||||
}
|
||||
|
||||
// if not found add it and increment next free space pointer
|
||||
if (!found) {
|
||||
logPointer = logCount;
|
||||
if (++logCount == MYESP_MQTTLOG_MAX) {
|
||||
logCount = 0; // rotate
|
||||
}
|
||||
}
|
||||
|
||||
// delete old record
|
||||
if (MQTT_log[logPointer].topic) {
|
||||
free(MQTT_log[logPointer].topic);
|
||||
}
|
||||
|
||||
if (MQTT_log[logPointer].payload) {
|
||||
free(MQTT_log[logPointer].payload);
|
||||
}
|
||||
|
||||
// add new record
|
||||
MQTT_log[logPointer].topic = strdup(topic);
|
||||
MQTT_log[logPointer].payload = strdup(payload);
|
||||
MQTT_log[logPointer].timestamp = now();
|
||||
}
|
||||
|
||||
// send UTC time via ws
|
||||
void MyESP::_sendTime() {
|
||||
@@ -2594,6 +2745,10 @@ void MyESP::begin(const char * app_hostname, const char * app_name, const char *
|
||||
|
||||
_telnet_setup(); // Telnet setup, called first to set Serial
|
||||
|
||||
// _fs_printFile(MYESP_CONFIG_FILE); // for debugging
|
||||
//_fs_printFile(MYESP_CUSTOMCONFIG_FILE); // for debugging
|
||||
//_fs_printFile(MYESP_EVENTLOG_FILE); // for debugging
|
||||
|
||||
// print a welcome message
|
||||
myDebug_P(PSTR("\n\n* %s version %s"), _app_name, _app_version);
|
||||
|
||||
@@ -2613,10 +2768,6 @@ void MyESP::begin(const char * app_hostname, const char * app_name, const char *
|
||||
_heartbeatCheck(true); // force heartbeat
|
||||
|
||||
SerialAndTelnet.flush();
|
||||
|
||||
//_fs_printFile(MYESP_CONFIG_FILE); // for debugging
|
||||
//_fs_printFile(MYESP_CUSTOMCONFIG_FILE); // for debugging
|
||||
//_fs_printFile(MYESP_EVENTLOG_FILE); // for debugging
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2643,7 +2794,7 @@ void MyESP::loop() {
|
||||
}
|
||||
|
||||
if (_formatreq) {
|
||||
myDebug("[SYSTEM] Factory reset initiated");
|
||||
myDebug("[SYSTEM] Factory reset initiated. Please wait. System will automatically restart when complete...");
|
||||
SPIFFS.end();
|
||||
_ws->enable(false);
|
||||
SPIFFS.format();
|
||||
|
||||
50
src/MyESP.h
50
src/MyESP.h
@@ -72,7 +72,6 @@ extern struct rst_info resetInfo;
|
||||
#define MQTT_RECONNECT_DELAY_MIN 2000 // Try to reconnect in 3 seconds upon disconnection
|
||||
#define MQTT_RECONNECT_DELAY_STEP 3000 // Increase the reconnect delay in 3 seconds after each failed attempt
|
||||
#define MQTT_RECONNECT_DELAY_MAX 120000 // Set reconnect time to 2 minutes at most
|
||||
#define MQTT_MAX_TOPIC_SIZE 50 // max length of MQTT topic
|
||||
#define MQTT_TOPIC_START "start"
|
||||
#define MQTT_TOPIC_HEARTBEAT "heartbeat"
|
||||
#define MQTT_TOPIC_START_PAYLOAD "start"
|
||||
@@ -82,7 +81,13 @@ extern struct rst_info resetInfo;
|
||||
#define MQTT_RETAIN false
|
||||
#define MQTT_KEEPALIVE 60 // 1 minute
|
||||
#define MQTT_QOS 1
|
||||
#define MQTT_WILL_TOPIC "status" // for last will & testament topic name
|
||||
#define MQTT_WILL_TOPIC "status" // for last will & testament topic name
|
||||
#define MQTT_MAX_TOPIC_SIZE 50 // max length of MQTT topic
|
||||
#define MQTT_MAX_PAYLOAD_SIZE 500 // max size of a JSON object. See https://arduinojson.org/v6/assistant/
|
||||
#define MQTT_MAX_PAYLOAD_SIZE_LARGE 2000 // max size of a large JSON object, like for sending MQTT log
|
||||
#define MYESP_JSON_MAXSIZE 2000 // for large Dynamic json files
|
||||
#define MYESP_MQTTLOG_MAX 20 // max number of log entries for MQTT publishes
|
||||
#define MYESP_JSON_LOG_MAXSIZE 300 // max size of an JSON log entry
|
||||
|
||||
// Internal MQTT events
|
||||
#define MQTT_CONNECT_EVENT 0
|
||||
@@ -134,7 +139,6 @@ PROGMEM const char * const custom_reset_string[] = {custom_reset_hardware, cus
|
||||
|
||||
// SPIFFS
|
||||
#define MYESP_SPIFFS_MAXSIZE 800 // https://arduinojson.org/v6/assistant/
|
||||
#define MYESP_JSON_MAXSIZE 2000 // for large Dynamic json files
|
||||
|
||||
// CRASH
|
||||
/**
|
||||
@@ -186,8 +190,8 @@ struct RtcmemData {
|
||||
|
||||
static_assert(sizeof(RtcmemData) <= (RTCMEM_BLOCKS * 4u), "RTCMEM struct is too big");
|
||||
|
||||
#define MYESP_SYSTEM_CHECK_TIME 60000 // The system is considered stable after these many millis (1 minute)
|
||||
#define MYESP_SYSTEM_CHECK_MAX 10 // After this many crashes on boot
|
||||
#define MYESP_SYSTEM_CHECK_TIME 60000 // The system is considered stable after these many millis (1 minute)
|
||||
#define MYESP_SYSTEM_CHECK_MAX 10 // After this many crashes on boot
|
||||
#define MYESP_HEARTBEAT_INTERVAL 120000 // in milliseconds, how often the MQTT heartbeat is sent (2 mins)
|
||||
|
||||
typedef struct {
|
||||
@@ -205,6 +209,13 @@ typedef enum {
|
||||
MYESP_BOOTSTATUS_RESETNEEDED = 3
|
||||
} MYESP_BOOTSTATUS; // boot messages
|
||||
|
||||
// for storing all MQTT publish messages
|
||||
typedef struct {
|
||||
char * topic;
|
||||
char * payload;
|
||||
time_t timestamp;
|
||||
} _MQTT_Log;
|
||||
|
||||
typedef std::function<void(unsigned int, const char *, const char *)> mqtt_callback_f;
|
||||
typedef std::function<void()> wifi_callback_f;
|
||||
typedef std::function<void()> ota_callback_f;
|
||||
@@ -297,28 +308,34 @@ class MyESP {
|
||||
|
||||
private:
|
||||
// mqtt
|
||||
AsyncMqttClient mqttClient;
|
||||
unsigned long _mqtt_reconnect_delay;
|
||||
void _mqttOnMessage(char * topic, char * payload, size_t len);
|
||||
void _mqttConnect();
|
||||
void _mqtt_setup();
|
||||
void _mqttOnMessage(char * topic, char * payload, size_t len);
|
||||
void _mqttConnect();
|
||||
void _mqtt_setup();
|
||||
void _mqttOnConnect();
|
||||
void _sendStart();
|
||||
char * _mqttTopic(const char * topic);
|
||||
|
||||
// mqtt log
|
||||
_MQTT_Log MQTT_log[MYESP_MQTTLOG_MAX]; // log for publish messages
|
||||
void _printMQTTLog();
|
||||
void _addMQTTLog(const char * topic, const char * payload);
|
||||
|
||||
AsyncMqttClient mqttClient; // the MQTT class
|
||||
uint32_t _mqtt_reconnect_delay;
|
||||
mqtt_callback_f _mqtt_callback_f;
|
||||
void _mqttOnConnect();
|
||||
void _sendStart();
|
||||
char * _mqttTopic(const char * topic);
|
||||
char * _mqtt_ip;
|
||||
char * _mqtt_user;
|
||||
char * _mqtt_password;
|
||||
int _mqtt_port;
|
||||
char * _mqtt_base;
|
||||
bool _mqtt_enabled;
|
||||
unsigned long _mqtt_keepalive;
|
||||
unsigned char _mqtt_qos;
|
||||
uint32_t _mqtt_keepalive;
|
||||
uint8_t _mqtt_qos;
|
||||
bool _mqtt_retain;
|
||||
char * _mqtt_will_topic;
|
||||
char * _mqtt_will_online_payload;
|
||||
char * _mqtt_will_offline_payload;
|
||||
unsigned long _mqtt_last_connection;
|
||||
uint32_t _mqtt_last_connection;
|
||||
bool _mqtt_connecting;
|
||||
bool _mqtt_heartbeat;
|
||||
|
||||
@@ -383,6 +400,7 @@ class MyESP {
|
||||
bool _timerequest;
|
||||
bool _formatreq;
|
||||
bool _hasValue(char * s);
|
||||
void _printHeap(const char * s);
|
||||
|
||||
// reset reason and rtcmem
|
||||
bool _rtcmem_status;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<label class="col-xs-3">LED<i style="margin-left: 10px;"
|
||||
class="glyphicon glyphicon-exclamation-sign text-danger" aria-hidden="true" data-toggle="popover"
|
||||
data-trigger="hover" data-placement="right"
|
||||
data-content="Please choose if you want to enable the LED"></i></label>
|
||||
data-content="Please choose if you want to enable an LED to show status"></i></label>
|
||||
<div class="col-xs-9">
|
||||
<form>
|
||||
<label class="radio-inline">
|
||||
@@ -148,19 +148,15 @@
|
||||
|
||||
<div id="custom_statuscontent">
|
||||
<br>
|
||||
<div class="row text-center">
|
||||
<div class="row text-left">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<h1>Dashboard</h1>
|
||||
<p>Real-time values from the EMS-ESP device are shown here.
|
||||
<div class="row form-group">
|
||||
<button onclick="refreshEMS()" class="btn btn-primary">Refresh Data</button>
|
||||
</div>
|
||||
</p>
|
||||
<h2>EMS Dashboard</h2>
|
||||
<p>Real-time values from the EMS-ESP device are shown here.</p>
|
||||
</div>
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default table-responsive">
|
||||
<table class="table table-hover table-striped table-condensed">
|
||||
<caption>EMS Bus stats</caption>
|
||||
<caption>EMS Bus Status</caption>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<b>
|
||||
@@ -169,7 +165,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Detected Devices:</th>
|
||||
<th id="devicesshow">Discovered Devices:</th>
|
||||
<td>
|
||||
<ul class="list-group">
|
||||
<div id="devices"></div>
|
||||
@@ -228,4 +224,7 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group" style="text-align: center;">
|
||||
<button onclick="refreshEMS()" class="btn btn-primary">Refresh Data</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -82,6 +82,7 @@ function listCustomStats() {
|
||||
document.getElementById("msg").className = "alert alert-success";
|
||||
} else {
|
||||
document.getElementById("msg").className = "alert alert-danger";
|
||||
document.getElementById("devicesshow").style.display = "none";
|
||||
document.getElementById("thermostat_show").style.display = "none";
|
||||
document.getElementById("boiler_show").style.display = "none";
|
||||
return;
|
||||
@@ -89,6 +90,9 @@ function listCustomStats() {
|
||||
|
||||
var list = document.getElementById("devices");
|
||||
var obj = ajaxobj.emsbus.devices;
|
||||
|
||||
document.getElementById("devicesshow").style.display = "block";
|
||||
|
||||
for (var i = 0; i < obj.length; i++) {
|
||||
var l = document.createElement("li");
|
||||
var type = obj[i].type;
|
||||
|
||||
101
src/ems-esp.cpp
101
src/ems-esp.cpp
@@ -67,8 +67,6 @@ Ticker showerColdShotStopTimer;
|
||||
#define SHOWER_COLDSHOT_DURATION 10 // in seconds. 10 seconds for cold water before turning back hot water
|
||||
#define SHOWER_MAX_DURATION 420000 // in ms. 7 minutes, before trigger a shot of cold water
|
||||
|
||||
#define MQTT_MAX_SIZE 700 // max size of a JSON object. See https://arduinojson.org/v6/assistant/
|
||||
|
||||
typedef struct {
|
||||
uint32_t timestamp; // for internal timings, via millis()
|
||||
uint8_t dallas_sensors; // count of dallas sensors
|
||||
@@ -508,7 +506,7 @@ void showInfo() {
|
||||
_renderIntValue("Burner current power", "%", EMS_Boiler.curBurnPow);
|
||||
_renderShortValue("Flame current", "uA", EMS_Boiler.flameCurr);
|
||||
_renderIntValue("System pressure", "bar", EMS_Boiler.sysPress, 10);
|
||||
if (EMS_Boiler.serviceCode == EMS_VALUE_SHORT_NOTSET) {
|
||||
if (EMS_Boiler.serviceCode == EMS_VALUE_USHORT_NOTSET) {
|
||||
myDebug_P(PSTR(" System service code: %s"), EMS_Boiler.serviceCodeChar);
|
||||
} else {
|
||||
myDebug_P(PSTR(" System service code: %s (%d)"), EMS_Boiler.serviceCodeChar, EMS_Boiler.serviceCode);
|
||||
@@ -688,16 +686,17 @@ void publishSensorValues() {
|
||||
// CRC check is done to see if there are changes in the values since the last send to avoid too much wifi traffic
|
||||
// a check is done against the previous values and if there are changes only then they are published. Unless force=true
|
||||
void publishValues(bool force) {
|
||||
// don't send if MQTT is connected
|
||||
// don't send if MQTT is not connected
|
||||
if (!myESP.isMQTTConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
char s[20] = {0}; // for formatting strings
|
||||
StaticJsonDocument<MQTT_MAX_SIZE> doc;
|
||||
char data[MQTT_MAX_SIZE] = {0};
|
||||
CRC32 crc;
|
||||
uint32_t fchecksum;
|
||||
char s[20] = {0}; // for formatting strings
|
||||
StaticJsonDocument<MQTT_MAX_PAYLOAD_SIZE> doc;
|
||||
char data[MQTT_MAX_PAYLOAD_SIZE] = {0};
|
||||
CRC32 crc;
|
||||
uint32_t fchecksum;
|
||||
uint8_t jsonSize;
|
||||
|
||||
static uint8_t last_boilerActive = 0xFF; // for remembering last setting of the tap water or heating on/off
|
||||
static uint32_t previousBoilerPublishCRC = 0; // CRC check for boiler values
|
||||
@@ -769,22 +768,28 @@ void publishValues(bool force) {
|
||||
if (abs(EMS_Boiler.heatWorkMin) != EMS_VALUE_LONG_NOTSET)
|
||||
rootBoiler["heatWorkMin"] = (double)EMS_Boiler.heatWorkMin;
|
||||
|
||||
rootBoiler["ServiceCode"] = EMS_Boiler.serviceCodeChar;
|
||||
rootBoiler["ServiceCodeNumber"] = EMS_Boiler.serviceCode;
|
||||
if (EMS_Boiler.serviceCode != EMS_VALUE_USHORT_NOTSET) {
|
||||
rootBoiler["ServiceCode"] = EMS_Boiler.serviceCodeChar;
|
||||
rootBoiler["ServiceCodeNumber"] = EMS_Boiler.serviceCode;
|
||||
}
|
||||
|
||||
serializeJson(doc, data, sizeof(data));
|
||||
|
||||
// calculate hash and send values if something has changed, to save unnecessary wifi traffic
|
||||
for (size_t i = 0; i < measureJson(doc) - 1; i++) {
|
||||
crc.update(data[i]);
|
||||
}
|
||||
fchecksum = crc.finalize();
|
||||
if ((previousBoilerPublishCRC != fchecksum) || force) {
|
||||
previousBoilerPublishCRC = fchecksum;
|
||||
myDebugLog("Publishing boiler data via MQTT");
|
||||
// check for empty json
|
||||
jsonSize = measureJson(doc);
|
||||
if (jsonSize > 2) {
|
||||
// calculate hash and send values if something has changed, to save unnecessary wifi traffic
|
||||
for (uint8_t i = 0; i < (jsonSize - 1); i++) {
|
||||
crc.update(data[i]);
|
||||
}
|
||||
fchecksum = crc.finalize();
|
||||
if ((previousBoilerPublishCRC != fchecksum) || force) {
|
||||
previousBoilerPublishCRC = fchecksum;
|
||||
myDebugLog("Publishing boiler data via MQTT");
|
||||
|
||||
// send values via MQTT
|
||||
myESP.mqttPublish(TOPIC_BOILER_DATA, data);
|
||||
// send values via MQTT
|
||||
myESP.mqttPublish(TOPIC_BOILER_DATA, data);
|
||||
}
|
||||
}
|
||||
|
||||
// see if the heating or hot tap water has changed, if so send
|
||||
@@ -856,18 +861,22 @@ void publishValues(bool force) {
|
||||
data[0] = '\0'; // reset data for next package
|
||||
serializeJson(doc, data, sizeof(data));
|
||||
|
||||
// calculate new CRC
|
||||
crc.reset();
|
||||
for (size_t i = 0; i < measureJson(doc) - 1; i++) {
|
||||
crc.update(data[i]);
|
||||
}
|
||||
fchecksum = crc.finalize();
|
||||
if ((previousThermostatPublishCRC != fchecksum) || force) {
|
||||
previousThermostatPublishCRC = fchecksum;
|
||||
myDebugLog("Publishing thermostat data via MQTT");
|
||||
// check for empty json
|
||||
jsonSize = measureJson(doc);
|
||||
if (jsonSize > 2) {
|
||||
// calculate new CRC
|
||||
crc.reset();
|
||||
for (uint8_t i = 0; i < (jsonSize - 1); i++) {
|
||||
crc.update(data[i]);
|
||||
}
|
||||
fchecksum = crc.finalize();
|
||||
if ((previousThermostatPublishCRC != fchecksum) || force) {
|
||||
previousThermostatPublishCRC = fchecksum;
|
||||
myDebugLog("Publishing thermostat data via MQTT");
|
||||
|
||||
// send values via MQTT
|
||||
myESP.mqttPublish(TOPIC_THERMOSTAT_DATA, data);
|
||||
// send values via MQTT
|
||||
myESP.mqttPublish(TOPIC_THERMOSTAT_DATA, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -906,18 +915,22 @@ void publishValues(bool force) {
|
||||
data[0] = '\0'; // reset data for next package
|
||||
serializeJson(doc, data, sizeof(data));
|
||||
|
||||
// calculate new CRC
|
||||
crc.reset();
|
||||
for (size_t i = 0; i < measureJson(doc) - 1; i++) {
|
||||
crc.update(data[i]);
|
||||
}
|
||||
fchecksum = crc.finalize();
|
||||
if ((previousSMPublishCRC != fchecksum) || force) {
|
||||
previousSMPublishCRC = fchecksum;
|
||||
myDebugLog("Publishing SM data via MQTT");
|
||||
// check for empty json
|
||||
jsonSize = measureJson(doc);
|
||||
if (jsonSize > 2) {
|
||||
// calculate new CRC
|
||||
crc.reset();
|
||||
for (uint8_t i = 0; i < (jsonSize - 1); i++) {
|
||||
crc.update(data[i]);
|
||||
}
|
||||
fchecksum = crc.finalize();
|
||||
if ((previousSMPublishCRC != fchecksum) || force) {
|
||||
previousSMPublishCRC = fchecksum;
|
||||
myDebugLog("Publishing SM data via MQTT");
|
||||
|
||||
// send values via MQTT
|
||||
myESP.mqttPublish(TOPIC_SM_DATA, data);
|
||||
// send values via MQTT
|
||||
myESP.mqttPublish(TOPIC_SM_DATA, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1675,7 +1688,7 @@ void WebCallback(JsonObject root) {
|
||||
|
||||
if (myESP.getUseSerial()) {
|
||||
emsbus["ok"] = false;
|
||||
emsbus["msg"] = "EMS Bus is disabled when in Serial mode. Check Settings->General Settings";
|
||||
emsbus["msg"] = "EMS Bus is disabled when in Serial mode. Check Settings->General Settings->Serial Port";
|
||||
} else {
|
||||
if (ems_getBusConnected()) {
|
||||
if (ems_getTxDisabled()) {
|
||||
|
||||
18
src/ems.cpp
18
src/ems.cpp
@@ -273,10 +273,10 @@ void ems_init() {
|
||||
EMS_Boiler.wWCirc = EMS_VALUE_INT_NOTSET; // Circulation on/off
|
||||
EMS_Boiler.selBurnPow = EMS_VALUE_INT_NOTSET; // Burner max power
|
||||
EMS_Boiler.curBurnPow = EMS_VALUE_INT_NOTSET; // Burner current power
|
||||
EMS_Boiler.flameCurr = EMS_VALUE_SHORT_NOTSET; // Flame current in micro amps
|
||||
EMS_Boiler.flameCurr = EMS_VALUE_USHORT_NOTSET; // Flame current in micro amps
|
||||
EMS_Boiler.sysPress = EMS_VALUE_INT_NOTSET; // System pressure
|
||||
strlcpy(EMS_Boiler.serviceCodeChar, "??", sizeof(EMS_Boiler.serviceCodeChar));
|
||||
EMS_Boiler.serviceCode = EMS_VALUE_SHORT_NOTSET;
|
||||
EMS_Boiler.serviceCode = EMS_VALUE_USHORT_NOTSET;
|
||||
|
||||
// UBAMonitorSlow
|
||||
EMS_Boiler.extTemp = EMS_VALUE_SHORT_NOTSET; // Outside temperature
|
||||
@@ -335,7 +335,6 @@ void ems_init() {
|
||||
EMS_Thermostat.product_id = EMS_ID_NONE;
|
||||
strlcpy(EMS_Thermostat.version, "?", sizeof(EMS_Thermostat.version));
|
||||
|
||||
|
||||
// default logging is none
|
||||
ems_setLogging(EMS_SYS_LOGGING_DEFAULT);
|
||||
}
|
||||
@@ -605,7 +604,9 @@ void _ems_sendTelegram() {
|
||||
_EMS_TX_STATUS _txStatus = emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length); // send the telegram to the UART Tx
|
||||
if (EMS_TX_BRK_DETECT == _txStatus || EMS_TX_WTD_TIMEOUT == _txStatus) {
|
||||
// Tx Error!
|
||||
myDebug_P(PSTR("** error sending buffer: %s"), _txStatus == EMS_TX_BRK_DETECT ? "BRK" : "WDTO");
|
||||
if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) {
|
||||
myDebug_P(PSTR("** error sending buffer: %s"), _txStatus == EMS_TX_BRK_DETECT ? "BRK" : "WDTO");
|
||||
}
|
||||
// EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE;
|
||||
}
|
||||
EMS_TxQueue.shift(); // and remove from queue
|
||||
@@ -668,8 +669,9 @@ void _ems_sendTelegram() {
|
||||
EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_WAIT;
|
||||
else {
|
||||
// Tx Error!
|
||||
// Tx Error!
|
||||
myDebug_P(PSTR("** error sending buffer: %s"), _txStatus == EMS_TX_BRK_DETECT ? "BRK" : "WDTO");
|
||||
if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) {
|
||||
myDebug_P(PSTR("** error sending buffer: %s"), _txStatus == EMS_TX_BRK_DETECT ? "BRK" : "WDTO");
|
||||
}
|
||||
EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE;
|
||||
}
|
||||
}
|
||||
@@ -2509,10 +2511,6 @@ void ems_setThermostatTemp(float temperature, uint8_t temptype) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO XXX hack, please remove
|
||||
EMS_TxTelegram.type = EMS_TYPE_RCPLUSSet; // for 3000 and 1010, e.g. 0B 10 FF (0A | 08) 01 89 2B
|
||||
EMS_TxTelegram.offset = 0x08; // auto offset
|
||||
|
||||
EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH;
|
||||
EMS_TxTelegram.dataValue = (uint8_t)((float)temperature * (float)2); // value * 2
|
||||
EMS_TxTelegram.type_validate = EMS_TxTelegram.type;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#define APP_NAME "EMS-ESP"
|
||||
#define APP_VERSION "1.9.0b2_web"
|
||||
#define APP_VERSION "1.9.0b3_web"
|
||||
#define APP_HOSTNAME "ems-esp"
|
||||
#define APP_URL "https://github.com/proddy/EMS-ESP"
|
||||
#define APP_UPDATEURL "https://api.github.com/repos/proddy/EMS-ESP/releases/latest"
|
||||
|
||||
@@ -158,7 +158,8 @@
|
||||
<div class="alert alert-warning">
|
||||
<h5><b>Warning!</b> This action <strong>cannot</strong> be undone. This will permanently
|
||||
delete <strong>all
|
||||
the settings and logs.</strong> Please make sure you've made a backup before resetting!</h5>
|
||||
the settings and logs.</strong> Please make sure you've made a backup before
|
||||
resetting!</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5>Please type in the hostname of the device to confirm.</h5>
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
<div class="row form-group">
|
||||
<label class="col-xs-3">Serial Port<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
|
||||
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
|
||||
data-content="Please choose if you want to enable Serial port for debugging"></i></label>
|
||||
data-content="Serial port for console output directly via USB as well as Telnet"></i></label>
|
||||
<div class="col-xs-9">
|
||||
<form>
|
||||
<label class="radio-inline">
|
||||
@@ -224,7 +224,7 @@
|
||||
<div class="row form-group">
|
||||
<label class="col-xs-3">Heartbeat<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
|
||||
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
|
||||
data-content="Please choose if you want to enable the MQTT heartbeat"></i></label>
|
||||
data-content="enable/disable an automatic MQTT publish with system stats"></i></label>
|
||||
<div class="col-xs-9">
|
||||
<form>
|
||||
<label class="radio-inline">
|
||||
@@ -391,7 +391,7 @@
|
||||
<br><br>
|
||||
<legend>System Status</legend>
|
||||
<br>
|
||||
<div class="row text-center">
|
||||
<div class="row text-left">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default table-responsive">
|
||||
<table class="table table-hover table-striped table-condensed">
|
||||
@@ -476,9 +476,15 @@
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="panel-heading">
|
||||
<div class="panel-title" id="mqttloghdr"></div>
|
||||
</div>
|
||||
<div>
|
||||
<table id="mqttlogtable" class="table" data-paging="false" data-filtering="false"
|
||||
data-sorting="false" data-editing="false" data-state="true"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
@@ -346,8 +346,8 @@ function listStats() {
|
||||
|
||||
document.getElementById("uptime").innerHTML = ajaxobj.uptime;
|
||||
|
||||
document.getElementById("heap").innerHTML = ajaxobj.heap + " KB";
|
||||
document.getElementById("heap").style.width = (ajaxobj.heap * 100) / 41 + "%";
|
||||
document.getElementById("heap").innerHTML = ajaxobj.heap + " bytes";
|
||||
document.getElementById("heap").style.width = (ajaxobj.heap * 100) / ajaxobj.initheap + "%";
|
||||
colorStatusbar(document.getElementById("heap"));
|
||||
|
||||
document.getElementById("flash").innerHTML = ajaxobj.availsize + " KB";
|
||||
@@ -380,6 +380,8 @@ function listStats() {
|
||||
document.getElementById("mqttheartbeat").className = "label label-primary";
|
||||
}
|
||||
|
||||
document.getElementById("mqttloghdr").innerHTML = "MQTT Publish Log: (topics are prefixed with <b>" + ajaxobj.mqttloghdr + "</b>)";
|
||||
|
||||
}
|
||||
|
||||
function getContent(contentname) {
|
||||
@@ -605,6 +607,55 @@ function initEventTable() {
|
||||
});
|
||||
}
|
||||
|
||||
function initMQTTLogTable() {
|
||||
var newlist = [];
|
||||
for (var i = 0; i < ajaxobj.mqttlog.length; i++) {
|
||||
var data = JSON.stringify(ajaxobj.mqttlog[i]);
|
||||
newlist[i] = {};
|
||||
newlist[i].options = {};
|
||||
newlist[i].value = {};
|
||||
newlist[i].value = JSON.parse(data);
|
||||
newlist[i].options.classes = "warning";
|
||||
newlist[i].options.style = "color: blue";
|
||||
}
|
||||
jQuery(function ($) {
|
||||
window.FooTable.init("#mqttlogtable", {
|
||||
columns: [{
|
||||
"name": "time",
|
||||
"title": "Last Published",
|
||||
"style": { "min-width": "160px" },
|
||||
"parser": function (value) {
|
||||
if (value < 1563300000) {
|
||||
return "(" + value + ")";
|
||||
} else {
|
||||
var comp = new Date();
|
||||
value = Math.floor(value + ((comp.getTimezoneOffset() * 60) * -1));
|
||||
var vuepoch = new Date(value * 1000);
|
||||
var formatted = vuepoch.getUTCFullYear() +
|
||||
"-" + twoDigits(vuepoch.getUTCMonth() + 1) +
|
||||
"-" + twoDigits(vuepoch.getUTCDate()) +
|
||||
" " + twoDigits(vuepoch.getUTCHours()) +
|
||||
":" + twoDigits(vuepoch.getUTCMinutes()) +
|
||||
":" + twoDigits(vuepoch.getUTCSeconds());
|
||||
return formatted;
|
||||
}
|
||||
},
|
||||
"breakpoints": "xs sm"
|
||||
},
|
||||
{
|
||||
"name": "topic",
|
||||
"title": "Topic",
|
||||
},
|
||||
{
|
||||
"name": "payload",
|
||||
"title": "Payload",
|
||||
},
|
||||
],
|
||||
rows: newlist
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function restartESP() {
|
||||
inProgress("restart");
|
||||
}
|
||||
@@ -617,6 +668,7 @@ function socketMessageListener(evt) {
|
||||
switch (obj.command) {
|
||||
case "status":
|
||||
ajaxobj = obj;
|
||||
initMQTTLogTable();
|
||||
getContent("#statuscontent");
|
||||
break;
|
||||
case "custom_settings":
|
||||
|
||||
@@ -123,20 +123,32 @@ function sendEventLog() {
|
||||
function sendStatus() {
|
||||
var stats = {
|
||||
"command": "status",
|
||||
"heap": 30,
|
||||
"availsize": 555,
|
||||
"availspiffs": 445,
|
||||
"spiffssize": 888,
|
||||
"sketchsize": 222,
|
||||
"uptime": "1 Day 6 Hours",
|
||||
"ssid": "SSID",
|
||||
"mac": "EM:44:11:33:22",
|
||||
"ip": "192.168.2.2",
|
||||
"signalstr": 66,
|
||||
"systemload": 10,
|
||||
"availspiffs": 948,
|
||||
"spiffssize": 957,
|
||||
"initheap": 25392,
|
||||
"heap": 13944,
|
||||
"sketchsize": 673,
|
||||
"availsize": 2469,
|
||||
"ip": "10.10.10.198",
|
||||
"ssid": "derbyshire",
|
||||
"mac": "DC:4F:11:22:93:06",
|
||||
"signalstr": 62,
|
||||
"systemload": 0,
|
||||
"mqttconnected": true,
|
||||
"mqttheartbeat": false
|
||||
"mqttheartbeat": false,
|
||||
"uptime": "0 days 0 hours 1 minute 45 seconds",
|
||||
"mqttloghdr": "home/ems-esp/",
|
||||
"mqttlog": [
|
||||
{ "topic": "start", "payload": "start", "time": 1565956388 },
|
||||
{ "topic": "shower_timer", "payload": "1", "time": 1565956388 },
|
||||
{ "topic": "shower_alert", "payload": "0", "time": 1565956388 },
|
||||
{ "topic": "boiler_data", "payload": "{\"wWComfort\":\"Hot\",\"wWSelTemp\":60,\"selFlowTemp\":5,\"selBurnPow\":0,\"curBurnPow\":0,\"pumpMod\":0,\"wWCurTmp\":48.4,\"wWCurFlow\":0,\"curFlowTemp\":49.3,\"retTemp\":49.3,\"sysPress\":1.8,\"boilTemp\":50.5,\"wWActivated\":\"on\",\"burnGas\":\"off\",\"heatPmp\":\"off\",\"fanWork\":\"off\",\"ignWork\":\"off\",\"wWCirc\":\"off\",\"wWHeat\":\"on\",\"burnStarts\":223397,\"burnWorkMin\":366019,\"heatWorkMin\":294036,\"ServiceCode\":\"0H\",\"ServiceCodeNumber\":203}", "time": 1565956463 },
|
||||
{ "topic": "tapwater_active", "payload": "0", "time": 1565956408 },
|
||||
{ "topic": "heating_active", "payload": "0", "time": 1565956408 },
|
||||
{ "topic": "thermostat_data", "payload": "{\"thermostat_hc\":\"1\",\"thermostat_seltemp\":15,\"thermostat_currtemp\":23,\"thermostat_mode\":\"auto\"}", "time": 1565956444 }
|
||||
]
|
||||
};
|
||||
|
||||
wss.broadcast(stats);
|
||||
}
|
||||
|
||||
@@ -157,7 +169,6 @@ function sendCustomStatus() {
|
||||
{ "type": 3, "model": "model 3", "deviceid": "device id3", "version": "version id3", "productid": "product id3" },
|
||||
{ "type": 4, "model": "model 4", "deviceid": "device id3", "version": "version id3", "productid": "product id3" },
|
||||
{ "type": 5, "model": "model 5", "deviceid": "device id3", "version": "version id3", "productid": "product id3" }
|
||||
|
||||
]
|
||||
},
|
||||
|
||||
@@ -181,6 +192,7 @@ function sendCustomStatus() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
wss.broadcast(stats);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user