Add *_get_info in json format

This commit is contained in:
fvanroie 2021-05-01 08:13:35 +02:00
parent 06ee1a3c78
commit 6a34490d4e
13 changed files with 295 additions and 47 deletions

View File

@ -573,6 +573,83 @@ void haspSetPage(uint8_t pageid)
}
}
void hasp_get_info(JsonDocument& doc)
{
std::string buffer;
buffer.reserve(64);
char size_buf[32];
JsonObject info = doc.createNestedObject(F(D_MANUFACTURER));
haspGetVersion(size_buf, sizeof(size_buf));
info[F("Version")] = size_buf;
buffer = __DATE__;
buffer += (" ");
buffer += __TIME__;
buffer += (" UTC"); // Github buildservers are in UTC
info[F("Build DateTime")] = buffer;
unsigned long time = millis() / 1000;
uint16_t day = time / 86400;
time = time % 86400;
uint8_t hour = time / 3600;
time = time % 3600;
uint8_t min = time / 60;
time = time % 60;
uint8_t sec = time;
buffer.clear();
if(day > 0) {
itoa(day, size_buf, DEC);
buffer += size_buf;
buffer += "d ";
}
if(day > 0 || hour > 0) {
itoa(hour, size_buf, DEC);
buffer += size_buf;
buffer += "h ";
}
if(day > 0 || hour > 0 || min > 0) {
itoa(min, size_buf, DEC);
buffer += size_buf;
buffer += "m ";
}
itoa(sec, size_buf, DEC);
buffer += size_buf;
buffer += "s";
info[F("Uptime")] = buffer;
info = doc.createNestedObject(F("Device Memory"));
Parser::format_bytes(haspDevice.get_free_heap(), size_buf, sizeof(size_buf));
info[F("Free Heap")] = size_buf;
Parser::format_bytes(haspDevice.get_free_max_block(), size_buf, sizeof(size_buf));
info[F("Free Block")] = size_buf;
info[F("Fragmentation")] = haspDevice.get_heap_fragmentation();
#if ARDUINO_ARCH_ESP32
if(psramFound()) {
Parser::format_bytes(ESP.getFreePsram(), size_buf, sizeof(size_buf));
info[F("Free PSRam")] = size_buf;
Parser::format_bytes(ESP.getPsramSize(), size_buf, sizeof(size_buf));
info[F("PSRam Size")] = size_buf;
}
#endif
info = doc.createNestedObject(F("LVGL Memory"));
lv_mem_monitor_t mem_mon;
lv_mem_monitor(&mem_mon);
Parser::format_bytes(mem_mon.total_size, size_buf, sizeof(size_buf));
info[F("Total")] = size_buf;
Parser::format_bytes(mem_mon.free_size, size_buf, sizeof(size_buf));
info[F("Free")] = size_buf;
info[F("Fragmentation")] = mem_mon.frag_pct;
info = doc.createNestedObject(F("HASP State"));
hasp_get_sleep_state(size_buf);
info[F("Idle")] = size_buf;
info[F("Active Page")] = haspPages.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if HASP_USE_CONFIG > 0
bool haspGetConfig(const JsonObject& settings)

View File

@ -77,6 +77,8 @@ void hasp_disable_wakeup_touch();
void hasp_init(void);
void hasp_load_json(void);
void hasp_get_info(JsonDocument& info);
/**********************
* MACROS
**********************/

View File

@ -34,6 +34,7 @@ int mqtt_send_discovery(const char* payload, size_t len);
int mqttPublish(const char* topic, const char* payload, size_t len, bool retain);
bool mqttIsConnected();
void mqtt_get_info(JsonDocument& doc);
#if HASP_USE_CONFIG > 0
bool mqttGetConfig(const JsonObject& settings);

View File

@ -59,6 +59,9 @@ std::string mqttGroupTopic;
std::string mqttLwtTopic;
bool mqttEnabled = false;
bool mqttHAautodiscover = true;
uint32_t mqttPublishCount;
uint32_t mqttReceiveCount;
uint32_t mqttFailedCount;
////////////////////////////////////////////////////////////////////////////////////////////////////
// These defaults may be overwritten with values saved by the web interface
@ -117,9 +120,11 @@ void connlost(void* context, char* cause)
static void mqtt_message_cb(char* topic, char* payload, size_t length)
{ // Handle incoming commands from MQTT
if(length + 1 >= MQTT_MAX_PACKET_SIZE) {
mqttFailedCount++;
LOG_ERROR(TAG_MQTT_RCV, F(D_MQTT_PAYLOAD_TOO_LONG), (uint32_t)length);
return;
} else {
mqttReceiveCount++;
payload[length] = '\0';
}
@ -198,7 +203,10 @@ void mqtt_subscribe(void* context, const char* topic)
int mqttPublish(const char* topic, const char* payload, size_t len, bool retain)
{
if(!mqttIsConnected()) return MQTT_ERR_NO_CONN;
if(!mqttIsConnected()) {
mqttFailedCount++;
return MQTT_ERR_NO_CONN;
}
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
@ -212,10 +220,12 @@ int mqttPublish(const char* topic, const char* payload, size_t len, bool retain)
int rc = MQTTClient_waitForCompletion(mqtt_client, token, TIMEOUT); // time to wait in milliseconds
if(rc != MQTTCLIENT_SUCCESS) {
mqttFailedCount++;
LOG_ERROR(TAG_MQTT_PUB, F(D_MQTT_FAILED " '%s' => %s"), topic, payload);
return MQTT_ERR_PUB_FAIL;
} else {
// LOG_TRACE(TAG_MQTT_PUB, F("'%s' => %s OK"), topic, payload);
mqttPublishCount++;
return MQTT_ERR_OK;
}
}
@ -383,5 +393,26 @@ void mqttLoop()
void mqttEvery5Seconds(bool wifiIsConnected){};
void mqtt_get_info(JsonDocument& doc)
{
char mqttClientId[64];
JsonObject info = doc.createNestedObject(F("MQTT"));
info[F("Server")] = mqttServer;
info[F("User")] = mqttUser;
info[F("ClientID")] = haspDevice.get_hostname();
if(mqttIsConnected()) { // Check MQTT connection
info[F("Status")] = F("Connected");
} else {
info[F("Status")] = F("<font color='red'><b>Disconnected</b></font>, return code: ");
// +String(mqttClient.returnCode());
}
info[F("Received")] = mqttReceiveCount;
info[F("Published")] = mqttPublishCount;
info[F("Failed")] = mqttFailedCount;
}
#endif // USE_PAHO
#endif // USE_MQTT

View File

@ -50,6 +50,9 @@ char mqttNodeTopic[24];
char mqttGroupTopic[24];
bool mqttEnabled = false;
bool mqttHAautodiscover = true;
uint32_t mqttPublishCount;
uint32_t mqttReceiveCount;
uint32_t mqttFailedCount;
////////////////////////////////////////////////////////////////////////////////////////////////////
// These defaults may be overwritten with values saved by the web interface
@ -95,11 +98,13 @@ int mqttPublish(const char* topic, const char* payload, size_t len, bool retain)
if(!mqttClient.connected()) return MQTT_ERR_NO_CONN;
if(mqttClient.beginPublish(topic, len, retain)) {
mqttPublishCount++;
mqttClient.write((uint8_t*)payload, len);
mqttClient.endPublish();
return MQTT_ERR_OK;
}
mqttFailedCount++;
return MQTT_ERR_PUB_FAIL;
}
@ -156,9 +161,11 @@ int mqtt_send_discovery(const char* payload, size_t len)
static void mqtt_message_cb(char* topic, byte* payload, unsigned int length)
{ // Handle incoming commands from MQTT
if(length + 1 >= mqttClient.getBufferSize()) {
mqttFailedCount++;
LOG_ERROR(TAG_MQTT_RCV, F(D_MQTT_PAYLOAD_TOO_LONG), (uint32_t)length);
return;
} else {
mqttReceiveCount++;
payload[length] = '\0';
}
@ -372,6 +379,33 @@ void mqttStop()
}
}
void mqtt_get_info(JsonDocument& doc)
{
char mqttClientId[64];
String mac((char*)0);
mac.reserve(64);
JsonObject info = doc.createNestedObject(F("MQTT"));
info[F("Server")] = mqttServer;
info[F("User")] = mqttUser;
mac = halGetMacAddress(3, "");
mac.toLowerCase();
snprintf_P(mqttClientId, sizeof(mqttClientId), PSTR("%s-%s"), haspDevice.get_hostname(), mac.c_str());
info[F("ClientID")] = mqttClientId;
if(mqttIsConnected()) { // Check MQTT connection
info[F("Status")] = F("Connected");
} else {
info[F("Status")] = F("<font color='red'><b>Disconnected</b></font>, return code: ");
// +String(mqttClient.returnCode());
}
info[F("Received")] = mqttReceiveCount;
info[F("Published")] = mqttPublishCount;
info[F("Failed")] = mqttFailedCount;
}
#if HASP_USE_CONFIG > 0
bool mqttGetConfig(const JsonObject& settings)
{

View File

@ -70,4 +70,25 @@ void ethernet_get_statusupdate(char* buffer, size_t len)
eth_connected ? F("on") : F("off"), ETH.linkSpeed(), ETH.localIP().toString().c_str());
}
void ethernet_get_info(JsonDocument& doc)
{
char size_buf[32];
String buffer((char*)0);
buffer.reserve(64);
JsonObject info = doc.createNestedObject(F("Ethernet"));
buffer = ETH.linkSpeed();
buffer += F(" Mbps");
if(ETH.fullDuplex()) {
buffer += F(" FULL_DUPLEX");
}
info[F("Link Speed")] = buffer;
info[F("IP Address")] = ETH.localIP().toString();
info[F("Gateway")] = ETH.gatewayIP().toString();
info[F("DNS Server")] = ETH.dnsIP().toString();
info[F("MAC Address")] = ETH.macAddress();
}
#endif

View File

@ -4,6 +4,8 @@
#ifndef HASP_ETHERNET_ESP32_H
#define HASP_ETHERNET_ESP32_H
#include "ArduinoJson.h"
static bool eth_connected = false;
void ethernetSetup();
@ -13,4 +15,6 @@ bool ethernetEverySecond();
bool ethernetEvery5Seconds();
void ethernet_get_statusupdate(char* buffer, size_t len);
void ethernet_get_info(JsonDocument& doc);
#endif

View File

@ -4,6 +4,8 @@
#ifndef HASP_ETHERNET_STM32_H
#define HASP_ETHERNET_STM32_H
#include "ArduinoJson.h"
static bool eth_connected = false;
void ethernetSetup();
@ -13,4 +15,6 @@ bool ethernetEverySecond();
bool ethernetEvery5Seconds();
void ethernet_get_statusupdate(char* buffer, size_t len);
void ethernet_get_info(JsonDocument& doc);
#endif

View File

@ -132,4 +132,15 @@ void network_get_statusupdate(char* buffer, size_t len)
#endif
}
void network_get_info(JsonDocument& doc)
{
#if HASP_USE_ETHERNET > 0
ethernet_get_info(doc);
#endif
#if HASP_USE_WIFI > 0
wifi_get_info(doc);
#endif
}
#endif

View File

@ -16,6 +16,7 @@ void networkStop(void);
/* ===== Getter and Setter Functions ===== */
void network_get_statusupdate(char* buffer, size_t len);
void network_get_info(JsonDocument& doc);
/* ===== Read/Write Configuration ===== */

View File

@ -519,6 +519,51 @@ void wifi_get_statusupdate(char* buffer, size_t len)
#endif
}
void wifi_get_info(JsonDocument& doc)
{
String buffer((char*)0);
buffer.reserve(64);
JsonObject info = doc.createNestedObject(F("Wifi"));
int8_t rssi = WiFi.RSSI();
buffer += String(rssi);
buffer += F("dBm (");
if(rssi >= -50) {
buffer += F("Excellent)");
} else if(rssi >= -60) {
buffer += F("Good)");
} else if(rssi >= -70) {
buffer += F("Fair)");
} else if(rssi >= -80) {
buffer += F("Weak)");
} else {
buffer += F("Very Bad)");
}
info[F("SSID")] = String(WiFi.SSID());
info[F("Signal Strength")] = buffer;
#if defined(STM32F4xx)
byte mac[6];
WiFi.macAddress(mac);
char macAddress[16];
snprintf_P(macAddress, sizeof(macAddress), PSTR("%02x%02x%02x"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
httpMessage += F("</br><b>IP Address: </b>");
httpMessage += String(WiFi.localIP());
httpMessage += F("</br><b>Gateway: </b>");
httpMessage += String(WiFi.gatewayIP());
httpMessage += F("</br><b>MAC Address: </b>");
httpMessage += String(macAddress);
#else
info[F("IP Address")] = WiFi.localIP().toString();
info[F("Gateway")] = WiFi.gatewayIP().toString();
info[F("DNS Server")] = WiFi.dnsIP().toString();
info[F("MAC Address")] = WiFi.macAddress();
#endif
}
/* ============ Confiuration =============================================================== */
#if HASP_USE_CONFIG > 0
bool wifiGetConfig(const JsonObject& settings)

View File

@ -15,6 +15,8 @@ void wifiStop(void);
bool wifiValidateSsid(const char* ssid, const char* pass);
void wifi_get_statusupdate(char* buffer, size_t len);
void wifi_get_info(JsonDocument& doc);
#if HASP_USE_CONFIG > 0
bool wifiGetConfig(const JsonObject& settings);
bool wifiSetConfig(const JsonObject& settings);

View File

@ -18,6 +18,7 @@
#include "hasp_config.h"
#if HASP_USE_HTTP > 0
#include "sys/net/hasp_network.h"
// #ifdef USE_CONFIG_OVERRIDE
// #include "user_config_override.h"
@ -200,6 +201,22 @@ static void add_form_button(String& str, const __FlashStringHelper* label, const
close_form(str);
}
static String getContentType(const String& path)
{
char buff[sizeof(mime::mimeTable[0].mimeType)];
// Check all entries but last one for match, return if found
for(size_t i = 0; i < sizeof(mime::mimeTable) / sizeof(mime::mimeTable[0]) - 1; i++) {
strcpy_P(buff, mime::mimeTable[i].endsWith);
if(path.endsWith(buff)) {
strcpy_P(buff, mime::mimeTable[i].mimeType);
return String(buff);
}
}
// Fall-through and just return default type
strcpy_P(buff, mime::mimeTable[sizeof(mime::mimeTable) / sizeof(mime::mimeTable[0]) - 1].mimeType);
return String(buff);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void webHandleHaspConfig();
@ -522,6 +539,49 @@ void webHandleAbout()
webSendFooter();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void add_json(String& data, JsonDocument& doc)
{
char buffer[512];
size_t len = serializeJson(doc, buffer, sizeof(buffer));
if(len <= 2) return; // empty document
buffer[len - 1] = ',';
char* start = buffer + 1;
data += String(start);
doc.clear();
}
void webHandleInfoJson()
{ // http://plate01/
if(!httpIsAuthenticated(F("infojson"))) return;
String htmldata((char*)0);
htmldata.reserve(HTTP_PAGE_SIZE);
DynamicJsonDocument doc(512);
htmldata = "{";
hasp_get_info(doc);
add_json(htmldata, doc);
#if HASP_USE_MQTT > 0
mqtt_get_info(doc);
add_json(htmldata, doc);
#endif
network_get_info(doc);
add_json(htmldata, doc);
// haspDevice.get_info(doc);
// add_json(htmldata, doc);
htmldata[htmldata.length() - 1] = '}'; // Replace last comma with a bracket
String path = F(".json");
webServer.send(200, getContentType(path), htmldata);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void webHandleInfo()
{ // http://plate01/
@ -730,52 +790,6 @@ void webHandleInfo()
webSendFooter();
}
// String getContentType(String filename)
// {
// if(webServer.hasArg(F("download"))) {
// return F("application/octet-stream");
// } else if(filename.endsWith(F(".htm")) || filename.endsWith(F(".html"))) {
// return F("text/html");
// } else if(filename.endsWith(F(".css"))) {
// return F("text/css");
// } else if(filename.endsWith(F(".js"))) {
// return F("application/javascript");
// } else if(filename.endsWith(F(".png"))) {
// return F("image/png");
// } else if(filename.endsWith(F(".gif"))) {
// return F("image/gif");
// } else if(filename.endsWith(F(".jpg"))) {
// return F("image/jpeg");
// } else if(filename.endsWith(F(".ico"))) {
// return F("image/x-icon");
// } else if(filename.endsWith(F(".xml"))) {
// return F("text/xml");
// } else if(filename.endsWith(F(".pdf"))) {
// return F("application/x-pdf");
// } else if(filename.endsWith(F(".zip"))) {
// return F("application/x-zip");
// } else if(filename.endsWith(F(".gz"))) {
// return F("application/x-gzip");
// }
// return F("text/plain");
// }
static String getContentType(const String& path)
{
char buff[sizeof(mime::mimeTable[0].mimeType)];
// Check all entries but last one for match, return if found
for(size_t i = 0; i < sizeof(mime::mimeTable) / sizeof(mime::mimeTable[0]) - 1; i++) {
strcpy_P(buff, mime::mimeTable[i].endsWith);
if(path.endsWith(buff)) {
strcpy_P(buff, mime::mimeTable[i].mimeType);
return String(buff);
}
}
// Fall-through and just return default type
strcpy_P(buff, mime::mimeTable[sizeof(mime::mimeTable) / sizeof(mime::mimeTable[0]) - 1].mimeType);
return String(buff);
}
/* String urldecode(String str)
{
String encodedString = "";
@ -2108,6 +2122,7 @@ void httpSetup()
webServer.on(F("/"), webHandleRoot);
webServer.on(F("/info"), webHandleInfo);
webServer.on(F("/infojson"), webHandleInfoJson);
webServer.on(F("/screenshot"), webHandleScreenshot);
webServer.on(F("/firmware"), webHandleFirmware);
webServer.on(F("/reboot"), httpHandleReboot);