From ae53441a609b760217433f7a59d3c0ba7efbe9ce Mon Sep 17 00:00:00 2001 From: Gijs Noorlander Date: Tue, 12 May 2020 23:05:03 +0200 Subject: [PATCH] [ESPEasy-Now] Improve p2p NodeStruct + extend for ESPEasy-Now Also added the webserver port in PR #3053 --- src/Networking.ino | 68 ++++++-------------- src/WebServer_CustomPage.ino | 4 +- src/WebServer_DevicesPage.ino | 2 +- src/WebServer_JSON.ino | 14 ++-- src/WebServer_RootPage.ino | 6 +- src/src/DataStructs/ESPEasy_Now_peerInfo.cpp | 19 ++++++ src/src/DataStructs/ESPEasy_Now_peerInfo.h | 16 +++-- src/src/DataStructs/NodeStruct.cpp | 50 ++++++++++++++ src/src/DataStructs/NodeStruct.h | 44 ++++++++++--- src/src/Helpers/ESPEasy_checks.cpp | 2 +- src/src/Helpers/ESPEasy_now_handler.cpp | 14 ++-- src/src/Helpers/ESPEasy_now_handler.h | 13 ++-- 12 files changed, 161 insertions(+), 91 deletions(-) diff --git a/src/Networking.ino b/src/Networking.ino index e60cdfa649..86b18520fa 100644 --- a/src/Networking.ino +++ b/src/Networking.ino @@ -219,51 +219,25 @@ void checkUDP() if (len < 13) { break; } - byte unit = packetBuffer[12]; -#ifndef BUILD_NO_DEBUG - byte mac[6]; - byte ip[4]; - - for (byte x = 0; x < 6; x++) { - mac[x] = packetBuffer[x + 2]; - } - - for (byte x = 0; x < 4; x++) { - ip[x] = packetBuffer[x + 8]; - } -#endif // ifndef BUILD_NO_DEBUG - Nodes[unit].age = 0; // Create a new element when not present - NodesMap::iterator it = Nodes.find(unit); - - if (it != Nodes.end()) { - for (byte x = 0; x < 4; x++) { - it->second.ip[x] = packetBuffer[x + 8]; - } - it->second.age = 0; // reset 'age counter' - - if (len >= 41) // extended packet size - { - it->second.build = makeWord(packetBuffer[14], packetBuffer[13]); - char tmpNodeName[26] = { 0 }; - memcpy(&tmpNodeName[0], reinterpret_cast(&packetBuffer[15]), 25); - tmpNodeName[25] = 0; - it->second.nodeName = tmpNodeName; - it->second.nodeName.trim(); - it->second.nodeType = packetBuffer[40]; - it->second.webgui_portnumber = 80; - if (len >= 43 && it->second.build >= 20107) { - it->second.webgui_portnumber = makeWord(packetBuffer[42],packetBuffer[41]); - } - } + int copy_length = sizeof(NodeStruct); + if (copy_length > len) { + copy_length = len; } + NodeStruct received; + memcpy(&received, &packetBuffer[2], copy_length); + received.age = 0; // Data just got in, so age = 0 + Nodes[received.unit] = received; // Create a new element when not present #ifndef BUILD_NO_DEBUG - if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) { - char macaddress[20]; - formatMAC(mac, macaddress); - char log[80] = { 0 }; - sprintf_P(log, PSTR("UDP : %s,%s,%u"), macaddress, formatIP(ip).c_str(), unit); + String log; + log.reserve(64); + log = F("UDP : "); + log += formatMAC(received.mac); + log += ','; + log += formatIP(received.ip); + log += ','; + log += received.unit; addLog(LOG_LEVEL_DEBUG_MORE, log); } #endif // ifndef BUILD_NO_DEBUG @@ -402,21 +376,18 @@ void sendSysInfoUDP(byte repeats) return; } - // TODO: make a nice struct of it and clean up // 1 byte 'binary token 255' // 1 byte id '1' - // 6 byte mac - // 4 byte ip - // 1 byte unit - // 2 byte build - // 25 char name - // 1 byte node type id + // NodeStruct object (packed data struct) // send my info to the world... #ifndef BUILD_NO_DEBUG addLog(LOG_LEVEL_DEBUG_MORE, F("UDP : Send Sysinfo message")); #endif // ifndef BUILD_NO_DEBUG + NodeStruct thisNode; + thisNode.setLocalData(); + for (byte counter = 0; counter < repeats; counter++) { uint8_t mac[] = { 0, 0, 0, 0, 0, 0 }; @@ -425,6 +396,7 @@ void sendSysInfoUDP(byte repeats) byte data[80] = {0}; data[0] = 255; data[1] = 1; + memcpy(&data[2], &thisNode, sizeof(NodeStruct)); for (byte x = 0; x < 6; x++) { data[x + 2] = macread[x]; diff --git a/src/WebServer_CustomPage.ino b/src/WebServer_CustomPage.ino index 7ebe369767..d0e9284cb1 100644 --- a/src/WebServer_CustomPage.ino +++ b/src/WebServer_CustomPage.ino @@ -41,7 +41,7 @@ boolean handle_custom(String path) { TXBuffer.startStream(); sendHeadandTail(F("TmplDsh"), _HEAD); addHtml(F("second.ip.toString()); + addHtml(it->second.IP().toString()); addHtml(F("/dashboard.esp\">")); sendHeadandTail(F("TmplDsh"), _TAIL); TXBuffer.endStream(); @@ -65,7 +65,7 @@ boolean handle_custom(String path) { String name = String(it->first) + F(" - "); if (it->first != Settings.Unit) { - name += it->second.nodeName; + name += it->second.getNodeName(); } else { name += Settings.Name; diff --git a/src/WebServer_DevicesPage.ino b/src/WebServer_DevicesPage.ino index 2dbe563731..069d75c4cf 100644 --- a/src/WebServer_DevicesPage.ino +++ b/src/WebServer_DevicesPage.ino @@ -888,7 +888,7 @@ void handle_devices_TaskSettingsPage(taskIndex_t taskIndex, byte page) NodesMap::iterator it = Nodes.find(remoteUnit); if (it != Nodes.end()) { - addUnit(it->second.nodeName); + addUnit(it->second.getNodeName()); } else { addUnit(F("Unknown Unit Name")); } diff --git a/src/WebServer_JSON.ino b/src/WebServer_JSON.ino index 63ffbe6b18..5c485811f2 100644 --- a/src/WebServer_JSON.ino +++ b/src/WebServer_JSON.ino @@ -214,20 +214,16 @@ void handle_json() addHtml("{"); stream_next_json_object_value(F("nr"), String(it->first)); stream_next_json_object_value(F("name"), - (it->first != Settings.Unit) ? it->second.nodeName : Settings.Name); + (it->first != Settings.Unit) ? it->second.getNodeName() : Settings.Name); if (it->second.build) { stream_next_json_object_value(F("build"), String(it->second.build)); } if (it->second.nodeType) { - String platform = getNodeTypeDisplayString(it->second.nodeType); - - if (platform.length() > 0) { - stream_next_json_object_value(F("platform"), platform); - } + stream_next_json_object_value(F("platform"), it->second.getNodeTypeDisplayString()); } - stream_next_json_object_value(F("ip"), it->second.ip.toString()); + stream_next_json_object_value(F("ip"), it->second.IP().toString()); stream_last_json_object_value(F("age"), String(it->second.age)); } // if node info exists } // for loop @@ -410,10 +406,10 @@ void handle_nodes_list_json() { } json_number(F("first"), String(it->first)); - json_prop(F("name"), isThisUnit ? Settings.Name : it->second.nodeName); + json_prop(F("name"), isThisUnit ? Settings.Name : it->second.getNodeName()); if (it->second.build) { json_prop(F("build"), String(it->second.build)); } - json_prop(F("type"), getNodeTypeDisplayString(it->second.nodeType)); + json_prop(F("type"), it->second.getNodeTypeDisplayString()); json_prop(F("ip"), it->second.ip.toString()); json_number(F("age"), String(it->second.age)); json_close(); diff --git a/src/WebServer_RootPage.ino b/src/WebServer_RootPage.ino index 77f14cc36d..aea4c57b20 100644 --- a/src/WebServer_RootPage.ino +++ b/src/WebServer_RootPage.ino @@ -180,7 +180,7 @@ void handle_root() { addHtml(Settings.Name); } else { - addHtml(it->second.nodeName); + addHtml(it->second.getNodeName()); } html_TD(); @@ -188,7 +188,7 @@ void handle_root() { addHtml(String(it->second.build)); } html_TD(); - addHtml(getNodeTypeDisplayString(it->second.nodeType)); + addHtml(it->second.getNodeTypeDisplayString()); html_TD(); html_add_wide_button_prefix(); { @@ -203,7 +203,7 @@ void handle_root() { html += String(port); } html += "'>"; - html += it->second.ip.toString(); + html += it->second.IP().toString(); html += ""; addHtml(html); } diff --git a/src/src/DataStructs/ESPEasy_Now_peerInfo.cpp b/src/src/DataStructs/ESPEasy_Now_peerInfo.cpp index 22a8fb6b0d..618e9642ec 100644 --- a/src/src/DataStructs/ESPEasy_Now_peerInfo.cpp +++ b/src/src/DataStructs/ESPEasy_Now_peerInfo.cpp @@ -1,5 +1,7 @@ #include "ESPEasy_Now_peerInfo.h" +#include "../../ESPEasy_fdwdecl.h" + static uint64_t mac_to_key(const uint8_t *mac) { @@ -37,3 +39,20 @@ bool ESPEasy_Now_peerInfo::getPeer(const uint8_t *mac, return true; } + +String ESPEasy_Now_peerInfo::formatPeerInfo(const uint8_t *mac) const +{ + uint64_t key = mac_to_key(mac); + auto it = peer_map.find(key); + String res; + + res = formatMAC(mac); + + if (it == peer_map.end()) { return res; } + + res.reserve(128); + res += F(" \""); + res += it->second.nodeName; + res += '"'; + return res; +} diff --git a/src/src/DataStructs/ESPEasy_Now_peerInfo.h b/src/src/DataStructs/ESPEasy_Now_peerInfo.h index 7d9750d6e1..05eca7fa7e 100644 --- a/src/src/DataStructs/ESPEasy_Now_peerInfo.h +++ b/src/src/DataStructs/ESPEasy_Now_peerInfo.h @@ -4,10 +4,12 @@ #include #include - +#include struct ESPEasy_Now_peerInfo_meta { String nodeName; + IPAddress ip; + byte unit; uint8_t channel = 0; uint8_t distance = 0; bool encrypt = false; @@ -17,13 +19,15 @@ typedef std::map peerInfoMap_t; struct ESPEasy_Now_peerInfo { - void addPeer(const uint8_t *mac, - const ESPEasy_Now_peerInfo_meta& meta); + void addPeer(const uint8_t *mac, + const ESPEasy_Now_peerInfo_meta& meta); + + bool hasPeer(const uint8_t *mac) const; - bool hasPeer(const uint8_t *mac) const; + bool getPeer(const uint8_t *mac, + ESPEasy_Now_peerInfo_meta& meta) const; - bool getPeer(const uint8_t *mac, - ESPEasy_Now_peerInfo_meta& meta) const; + String formatPeerInfo(const uint8_t *mac) const; private: diff --git a/src/src/DataStructs/NodeStruct.cpp b/src/src/DataStructs/NodeStruct.cpp index d68601332c..36d6144147 100644 --- a/src/src/DataStructs/NodeStruct.cpp +++ b/src/src/DataStructs/NodeStruct.cpp @@ -1,5 +1,8 @@ #include "NodeStruct.h" +#include "../Globals/Settings.h" +#include "../../ESPEasy-Globals.h" + String getNodeTypeDisplayString(byte nodeType) { switch (nodeType) { @@ -18,3 +21,50 @@ String getNodeTypeDisplayString(byte nodeType) { { for (byte i = 0; i < 4; ++i) { ip[i] = 0; } } + + +void NodeStruct::setLocalData() { + WiFi.macAddress(mac); + WiFi.softAPmacAddress(ap_mac); + { + IPAddress localIP = WiFi.localIP(); + for (byte i = 0; i < 4; ++i) { + ip[i] = localIP[i]; + } + } + + unit = Settings.Unit; + build = Settings.Build; + memcpy(nodeName, Settings.Name, 25); + nodeType = NODE_TYPE_ID; + +// webserverPort = Settings.WebserverPort; // PR #3053 +} + + +String NodeStruct::getNodeTypeDisplayString() const { + switch (nodeType) + { + case NODE_TYPE_ID_ESP_EASY_STD: return F("ESP Easy"); + case NODE_TYPE_ID_ESP_EASYM_STD: return F("ESP Easy Mega"); + case NODE_TYPE_ID_ESP_EASY32_STD: return F("ESP Easy 32"); + case NODE_TYPE_ID_RPI_EASY_STD: return F("RPI Easy"); + case NODE_TYPE_ID_ARDUINO_EASY_STD: return F("Arduino Easy"); + case NODE_TYPE_ID_NANO_EASY_STD: return F("Nano Easy"); + } + return ""; +} + +String NodeStruct::getNodeName() const { + String res; + size_t length = strnlen(reinterpret_cast(nodeName), sizeof(nodeName)); + res.reserve(length); + for (size_t i = 0; i < length; ++i) { + res += static_cast(nodeName[i]); + } + return res; +} + +IPAddress NodeStruct::IP() const { + return IPAddress(ip[0], ip[1], ip[2], ip[3]); +} diff --git a/src/src/DataStructs/NodeStruct.h b/src/src/DataStructs/NodeStruct.h index c44f984a75..2c8e377d23 100644 --- a/src/src/DataStructs/NodeStruct.h +++ b/src/src/DataStructs/NodeStruct.h @@ -7,7 +7,7 @@ #define NODE_TYPE_ID_ESP_EASY_STD 1 -#define NODE_TYPE_ID_RPI_EASY_STD 5 // https://github.com/enesbcs/rpieasy +#define NODE_TYPE_ID_RPI_EASY_STD 5 // https://github.com/enesbcs/rpieasy #define NODE_TYPE_ID_ESP_EASYM_STD 17 #define NODE_TYPE_ID_ESP_EASY32_STD 33 #define NODE_TYPE_ID_ARDUINO_EASY_STD 65 @@ -18,16 +18,44 @@ String getNodeTypeDisplayString(byte nodeType); /*********************************************************************************************\ * NodeStruct \*********************************************************************************************/ -struct NodeStruct +struct __attribute__((__packed__)) NodeStruct { NodeStruct(); - String nodeName; - IPAddress ip; - uint16_t build; - byte age; - byte nodeType; - uint16_t webgui_portnumber; + void setLocalData(); + String getNodeTypeDisplayString() const; + + String getNodeName() const; + + IPAddress IP() const; + + // Do not change the order of this data, as it is being sent via P2P UDP. + // 1 byte 'binary token 255' + // 1 byte id '1' + // 6 byte mac (STA interface) + // 4 byte ip + // 1 byte unit + // 2 byte build + // 25 char name + // 1 byte node type id + + // Added starting build '20107': + // 2 bytes webserver port + // 6 bytes AP MAC + + + + uint8_t mac[6] = { 0 }; // STA mode MAC + uint8_t ip[4] = { 0 }; + byte unit = 0; + uint16_t build = 0; + byte nodeName[25] = { 0 }; + byte nodeType = 0; + byte age = 0; + uint16_t webserverPort = 80; + uint8_t ap_mac[6] = { 0 }; // AP mode MAC + + }; typedef std::map NodesMap; diff --git a/src/src/Helpers/ESPEasy_checks.cpp b/src/src/Helpers/ESPEasy_checks.cpp index ae52a9cb25..f7a98970c8 100644 --- a/src/src/Helpers/ESPEasy_checks.cpp +++ b/src/src/Helpers/ESPEasy_checks.cpp @@ -85,7 +85,7 @@ void run_compiletime_checks() { #ifdef USES_NOTIFIER check_size(); #endif - check_size(); + check_size(); check_size(); check_size(); check_size(); diff --git a/src/src/Helpers/ESPEasy_now_handler.cpp b/src/src/Helpers/ESPEasy_now_handler.cpp index 4a626fdde0..4db3e1bd9f 100644 --- a/src/src/Helpers/ESPEasy_now_handler.cpp +++ b/src/src/Helpers/ESPEasy_now_handler.cpp @@ -28,7 +28,7 @@ bool ESPEasy_now_handler_t::begin() String log; log.reserve(48); log = F("ESPEasy_Now: Failed to add peer "); - log += formatMAC(SecuritySettings.EspEasyNowPeerMAC[peer]); + log += _peerInfoMap.formatPeerInfo(SecuritySettings.EspEasyNowPeerMAC[peer]); addLog(LOG_LEVEL_ERROR, log); } } @@ -58,7 +58,7 @@ bool ESPEasy_now_handler_t::loop() if (loglevelActiveFor(loglevel)) { String log = F("ESPEasyNow: Message from "); - log += formatMAC(ESPEasy_now_in_queue.front()._mac); + log += _peerInfoMap.formatPeerInfo(ESPEasy_now_in_queue.front()._mac); if (!validPacket) { log += F(" INVALID CHECKSUM!"); @@ -178,7 +178,7 @@ bool ESPEasy_now_handler_t::send(const ESPEasy_Now_packet& packet) { } else { log = F("ESPEasy Now: Sent FAILED to: "); } - log += formatMAC(packet._mac); + log += _peerInfoMap.formatPeerInfo(packet._mac); addLog(LOG_LEVEL_INFO, log); } return success; @@ -194,7 +194,7 @@ WifiEspNowSendStatus ESPEasy_now_handler_t::send(const ESPEasy_Now_packet& packe if (sendStatus == WifiEspNowSendStatus::NONE) { if (loglevelActiveFor(LOG_LEVEL_INFO)) { String log = F("ESPEasy Now: TIMEOUT to: "); - log += formatMAC(packet._mac); + log += _peerInfoMap.formatPeerInfo(packet._mac); addLog(LOG_LEVEL_INFO, log); } } @@ -219,12 +219,15 @@ bool ESPEasy_now_handler_t::handle_DiscoveryAnnounce(const ESPEasy_Now_packet& p meta.nodeName = packet.getString(payload_pos); + _peerInfoMap.addPeer(packet._mac, meta); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { String log; size_t payloadSize = packet.getPayloadSize(); log.reserve(payloadSize + 40); log = F("ESPEasy Now discovery: "); - log += formatMAC(packet._mac); + log += _peerInfoMap.formatPeerInfo(packet._mac); log += '\n'; log += meta.nodeName; @@ -234,7 +237,6 @@ bool ESPEasy_now_handler_t::handle_DiscoveryAnnounce(const ESPEasy_Now_packet& p } addLog(LOG_LEVEL_INFO, log); } - _peerInfoMap.addPeer(packet._mac, meta); return true; } diff --git a/src/src/Helpers/ESPEasy_now_handler.h b/src/src/Helpers/ESPEasy_now_handler.h index 8fd4a30a8e..7da9239b0f 100644 --- a/src/src/Helpers/ESPEasy_now_handler.h +++ b/src/src/Helpers/ESPEasy_now_handler.h @@ -31,24 +31,23 @@ class ESPEasy_now_handler_t { const String & payload); bool getPeerInfo(const uint8_t *mac, - ESPEasy_Now_peerInfo_meta& meta) const; + ESPEasy_Now_peerInfo_meta& meta) const; private: - bool send(const ESPEasy_Now_packet& packet); - WifiEspNowSendStatus send(const ESPEasy_Now_packet& packet, size_t timeout); + bool send(const ESPEasy_Now_packet& packet); + WifiEspNowSendStatus send(const ESPEasy_Now_packet& packet, + size_t timeout); WifiEspNowSendStatus waitForSendStatus(size_t timeout) const; + bool handle_DiscoveryAnnounce(const ESPEasy_Now_packet& packet); - bool handle_DiscoveryAnnounce(const ESPEasy_Now_packet& packet); + bool handle_MQTTControllerMessage(const ESPEasy_Now_packet& packet); - bool handle_MQTTControllerMessage(const ESPEasy_Now_packet& packet); - ESPEasy_Now_peerInfo _peerInfoMap; - };