diff --git a/devices/button/button_esp8266/button_esp8266.ino b/devices/button/button_esp8266/button_esp8266.ino index 520dce8..ae83cf1 100755 --- a/devices/button/button_esp8266/button_esp8266.ino +++ b/devices/button/button_esp8266/button_esp8266.ino @@ -1,6 +1,8 @@ -#define DEVICE_TYPE "button" -#define CHANNEL_NUM 3 -#define FW_VERSION "1.0.0 alpha" +#include + +const char* DEVICE_TYPE = "button"; +const char* FW_VERSION = "1.0.0 alpha"; +const uint8_t CHANNEL_NUM = 3; #include #include "ButtonLogic.h" diff --git a/devices/relay/relay_esp8266/relay_esp8266.ino b/devices/relay/relay_esp8266/relay_esp8266.ino index 9adfe68..aabc978 100755 --- a/devices/relay/relay_esp8266/relay_esp8266.ino +++ b/devices/relay/relay_esp8266/relay_esp8266.ino @@ -1,6 +1,8 @@ -#define DEVICE_TYPE "relay" -#define CHANNEL_NUM 1 -#define FW_VERSION "1.0.1 beta" +#include + +const char* DEVICE_TYPE = "relay"; +const char* FW_VERSION = "1.0.1 beta"; +const uint8_t CHANNEL_NUM = 1; #include #include "RelayLogic.h" // вот тут находятся каналы и функции управления diff --git a/devices/sh_core_esp8266/src/REST_API.cpp b/devices/sh_core_esp8266/src/REST_API.cpp index 06b67b7..9972db5 100755 --- a/devices/sh_core_esp8266/src/REST_API.cpp +++ b/devices/sh_core_esp8266/src/REST_API.cpp @@ -120,6 +120,10 @@ static void handleAbout() { IPAddress ip = WiFi.localIP(); + if(deviceMode == DEVICE_MODE_SETUP) { + serverBaseUrl = "0.0.0.0"; + } + String json = "{"; json += "\"device_name\":\"" + deviceName + "\","; json += "\"device_type\":\"" + String(DEVICE_TYPE) + "\","; diff --git a/devices/sh_core_esp8266/src/WebHandlers.cpp b/devices/sh_core_esp8266/src/WebHandlers.cpp index 1dcc27b..5fc6f43 100755 --- a/devices/sh_core_esp8266/src/WebHandlers.cpp +++ b/devices/sh_core_esp8266/src/WebHandlers.cpp @@ -1,19 +1,114 @@ #include "sh_core_esp8266.h" #include +static String json_escape(const String &s) { + String out; + out.reserve(s.length() + 8); + + for (uint16_t i = 0; i < s.length(); i++) { + char c = s[i]; + switch (c) { + case '\"': out += F("\\\""); break; + case '\\': out += F("\\\\"); break; + case '\b': out += F("\\b"); break; + case '\f': out += F("\\f"); break; + case '\n': out += F("\\n"); break; + case '\r': out += F("\\r"); break; + case '\t': out += F("\\t"); break; + default: + if ((uint8_t)c < 0x20) { + out += F("\\u00"); + const char hex[] = "0123456789ABCDEF"; + out += hex[((uint8_t)c >> 4) & 0x0F]; + out += hex[(uint8_t)c & 0x0F]; + } else { + out += c; + } + } + } + + return out; +} + +static int rssi_to_percent(int rssi) { + // Типичные значения: -100 (очень плохо) .. -50 (очень хорошо) + if (rssi <= -100) return 0; + if (rssi >= -50) return 100; + return 2 * (rssi + 100); // -100->0, -50->100 +} + +static String html_escape(const String &s) { + String out; + out.reserve(s.length() + 10); + for (uint16_t i = 0; i < s.length(); i++) { + char c = s[i]; + if (c == '&') out += F("&"); + else if (c == '<') out += F("<"); + else if (c == '>') out += F(">"); + else if (c == '\"') out += F("""); + else out += c; + } + return out; +} + +static String wifi_scan_json() { + // Для сканирования STA должен быть включён (AP+STA ок) + WiFi.mode(WIFI_AP_STA); + + int n = WiFi.scanNetworks(/*async=*/false, /*hidden=*/true); + + String json; + json.reserve(256); + + if (n <= 0) { + json = F("{\"status\":\"ok\",\"count\":0,\"networks\":[]}"); + WiFi.scanDelete(); + return json; + } + + json += F("{\"status\":\"ok\",\"count\":"); + json += String(n); + json += F(",\"networks\":["); + + for (int i = 0; i < n; i++) { + if (i) json += ','; + + String ssid = WiFi.SSID(i); + int rssi = WiFi.RSSI(i); + int p = rssi_to_percent(rssi); + + bool enc = (WiFi.encryptionType(i) != ENC_TYPE_NONE); + + // (опционально) bssid/channel/hidden — если нужно, можно добавить + json += F("{\"ssid\":\""); + json += json_escape(ssid); + json += F("\",\"rssi\":"); + json += String(rssi); + json += F(",\"signal\":"); + json += String(p); + json += F(",\"secured\":"); + json += (enc ? F("true") : F("false")); + json += F("}"); + } + + json += F("]}"); + + WiFi.scanDelete(); + return json; +} + static String render_wifi_setup_page() { String html = wifi_setup_page; if (savedSSID.length() > 0) { html.replace("{{LAST_SSID}}", savedSSID); } else { - html.replace("{{LAST_SSID}}", "(не задано)"); + html.replace("{{LAST_SSID}}", "(Empty)"); } return html; } - // -------------------- handlers -------------------- static void handleRoot() { auto mode = WiFi.getMode(); @@ -23,7 +118,7 @@ return; } - String msg = "ESP8266 device\nID: " + getUniqueID() + "\nVersion: "; + String msg = "ESP SmartHome Device\nID: " + getUniqueID() + "\nVersion: "; msg += FW_VERSION; server.send(200, "text/plain; charset=utf-8", msg); @@ -116,6 +211,10 @@ ESP.restart(); } +static void handle_wifi_scan() { + String body = wifi_scan_json(); + server.send(200, F("application/json; charset=utf-8"), body); +} // -------------------- routes register -------------------- void registerWebUiRoutes() { @@ -126,5 +225,5 @@ server.on("/wifi_confirm", HTTP_POST, handleWIFICredsStayConfirmed); server.on("/setup", HTTP_GET, handleSetupGetUi); server.on("/setup", HTTP_POST, handleSetupPostUi); - + server.on("/wifi_scan", HTTP_GET, handle_wifi_scan); } diff --git a/devices/sh_core_esp8266/src/WebPages.cpp b/devices/sh_core_esp8266/src/WebPages.cpp index 8775699..2a25721 100755 --- a/devices/sh_core_esp8266/src/WebPages.cpp +++ b/devices/sh_core_esp8266/src/WebPages.cpp @@ -14,42 +14,138 @@
-

WiFi setup

-

- Connect the device to your home WiFi network. -

-
-
- - -
-
- - -
-
- -
-
-
-
-
Последняя попытка подключения к Wi-Fi:
- {{LAST_SSID}} - -
- +
+

WiFi setup

+

+ Connect the device to your home WiFi network. +

+ +
+ + +
+
+ + +
+
+ +
+
+
+
Last Wi-Fi SSID:
+ {{LAST_SSID}} + +
+ +
+
+
+
+

- ESP-01 Relay + ESP SmartHome Device

+ + )HTML"; diff --git a/devices/sh_core_esp8266/src/sh_core_esp8266.cpp b/devices/sh_core_esp8266/src/sh_core_esp8266.cpp index 4926a79..7f1df8b 100644 --- a/devices/sh_core_esp8266/src/sh_core_esp8266.cpp +++ b/devices/sh_core_esp8266/src/sh_core_esp8266.cpp @@ -8,7 +8,7 @@ DeviceMode deviceMode = DEVICE_MODE_SETUP; String deviceName = "Unknown"; -String serverBaseUrl = ""; +String serverBaseUrl = "0.0.0.0"; String authToken = ""; // -------------------- WiFi connect strategy -------------------- @@ -135,7 +135,7 @@ static void wifi_enable_ap_if_needed() { if (ap_enabled) return; - String ap_ssid = "ESP-RELAY-"; + String ap_ssid = "SH-DEVICE-"; ap_ssid += String(ESP.getChipId(), HEX); const char* ap_pass = "noAccess"; diff --git a/devices/sh_core_esp8266/src/sh_core_esp8266.h b/devices/sh_core_esp8266/src/sh_core_esp8266.h index 9bfad12..1363b58 100755 --- a/devices/sh_core_esp8266/src/sh_core_esp8266.h +++ b/devices/sh_core_esp8266/src/sh_core_esp8266.h @@ -9,13 +9,9 @@ #include // -------------------- compile-time defaults -------------------- -#ifndef FW_VERSION - #define FW_VERSION "0.0.0" -#endif - -#ifndef DEVICE_TYPE - #define DEVICE_TYPE "unknown" -#endif +extern const char* DEVICE_TYPE; +extern const char* FW_VERSION; +extern const uint8_t CHANNEL_NUM; // -------------------- EEPROM layout (ядро) -------------------- // 0..31 - SSID (макс 32 байта, включая '\0')