supla-device
Loading...
Searching...
No Matches
esp_wifi.h
1// SPDX-FileCopyrightText: AC SOFTWARE SP. Z O.O.
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#ifndef SRC_SUPLA_NETWORK_ESP_WIFI_H_
5#define SRC_SUPLA_NETWORK_ESP_WIFI_H_
6
7#include <Arduino.h>
8
9#include <supla/input_noise_guard.h>
10#include <supla/log_wrapper.h>
11#include <supla/network/arduino_netif_config.h>
12#include <supla/network/wifi_scan_result.h>
13#include <supla/time.h>
14#include <supla/tools.h>
15
16#ifdef ARDUINO_ARCH_ESP8266
17#include <ESP8266WiFi.h>
18
19// workaround for incompatible names in ESP8266 and ESP32 boards
20#define WIFI_MODE_AP WIFI_AP
21#define WIFI_MODE_STA WIFI_STA
22
23#else
24#include <WiFi.h>
25#endif
26
27#include "../supla_lib_config.h"
28#include "netif_wifi.h"
29
30namespace Supla {
31class ESPWifi : public Supla::Wifi {
32 public:
33 ESPWifi(const char *wifiSsid = nullptr,
34 const char *wifiPassword = nullptr,
35 unsigned char *ip = nullptr)
36 : Wifi(wifiSsid, wifiPassword, ip) {
37 }
38
39
40 bool isReady() override {
41 return WiFi.status() == WL_CONNECTED;
42 }
43
44 static void printConnectionDetails() {
45 SUPLA_LOG_INFO("Connected BSSID: %s", WiFi.BSSIDstr().c_str());
46 SUPLA_LOG_INFO("local IP: %s", WiFi.localIP().toString().c_str());
47 SUPLA_LOG_INFO("subnetMask: %s", WiFi.subnetMask().toString().c_str());
48 SUPLA_LOG_INFO("gatewayIP: %s", WiFi.gatewayIP().toString().c_str());
49 int rssi = WiFi.RSSI();
50 SUPLA_LOG_INFO("Signal strength (RSSI): %d dBm", rssi);
51 }
52
53 void setup() override {
54 // ESP8266: for some reason when hostname is longer than 30 bytes, Wi-Fi
55 // connection can't be esablished. So as a workaround, we truncate hostname
56 // to 30 bytes
57 hostname[30] = '\0';
58 if (!wifiConfigured) {
59 // ESP32 requires setHostname to be called before begin...
60 WiFi.setHostname(hostname);
61 wifiConfigured = true;
62#ifdef ARDUINO_ARCH_ESP8266
63 gotIpEventHandler =
64 WiFi.onStationModeGotIP([](const WiFiEventStationModeGotIP &event) {
65 (void)(event);
66 ESPWifi::printConnectionDetails();
67 });
68 disconnectedEventHandler = WiFi.onStationModeDisconnected(
69 [](const WiFiEventStationModeDisconnected &event) {
70 (void)(event);
71 SUPLA_LOG_INFO("WiFi station disconnected");
72 });
73#else
74 WiFiEventId_t event_gotIP = WiFi.onEvent(
75 [](WiFiEvent_t event, WiFiEventInfo_t info) {
76 Supla::InputNoiseGuard::NotifyWifiStaConnected();
77 ESPWifi::printConnectionDetails();
78 },
79 WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
80
81 (void)(event_gotIP);
82
83 WiFiEventId_t event_disconnected = WiFi.onEvent(
84 [](WiFiEvent_t event, WiFiEventInfo_t info) {
85 SUPLA_LOG_INFO("WiFi Station disconnected");
86 // ESP32 doesn't reconnect automatically after lost connection
87 Supla::InputNoiseGuard::NotifyWifiStaDisconnected();
88 if (mode != Supla::DEVICE_MODE_CONFIG) {
89 WiFi.reconnect();
90 }
91 },
92 WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
93
94 (void)(event_disconnected);
95#endif
96 } else {
97 if (mode == Supla::DEVICE_MODE_CONFIG) {
98 Supla::InputNoiseGuard::NotifyWifiTransition();
99 WiFi.mode(WIFI_MODE_AP);
100 } else {
101 Supla::InputNoiseGuard::NotifyWifiTransition();
102 WiFi.mode(WIFI_MODE_STA);
103 }
104 SUPLA_LOG_INFO("WiFi: resetting WiFi connection");
105 DisconnectProtocols();
106 Supla::InputNoiseGuard::NotifyWifiTransition();
107 WiFi.disconnect();
108 }
109
110 if (mode == Supla::DEVICE_MODE_CONFIG) {
111 SUPLA_LOG_INFO("WiFi: enter config mode with SSID: \"%s\"", hostname);
112 Supla::InputNoiseGuard::NotifyWifiTransition();
113 WiFi.mode(WIFI_AP_STA);
114 Supla::InputNoiseGuard::NotifyWifiTransition();
115 WiFi.softAP(hostname, nullptr, 6);
116 startConfigModeScan();
117
118 } else {
119 SUPLA_LOG_INFO("WiFi: establishing connection with SSID: \"%s\"", ssid);
120 Supla::InputNoiseGuard::NotifyWifiTransition();
121 WiFi.mode(WIFI_MODE_STA);
122 if (hasStaticIpConfig()) {
123 const auto &cfg = getNetifConfig();
124 IPAddress localIp = toArduinoIpAddress(cfg.ip);
125 IPAddress gateway = toArduinoIpAddress(cfg.gateway);
126 IPAddress subnet = toArduinoIpAddress(cfg.netmask);
127 IPAddress dns1 = toArduinoIpAddress(cfg.dns1);
128 IPAddress dns2 = toArduinoIpAddress(cfg.dns2);
129 if (!WiFi.config(localIp, gateway, subnet, dns1, dns2)) {
130 SUPLA_LOG_WARNING("WiFi static IP config failed, continuing");
131 }
132 }
133 Supla::InputNoiseGuard::NotifyWifiTransition();
134 WiFi.begin(ssid, password);
135 // ESP8266 requires setHostname to be called after begin...
136 WiFi.setHostname(hostname);
137 }
138
139 yield();
140 allowDisable = true;
141 }
142
143 bool iterate() override {
144 if (!configModeScanInProgress) {
145 return Supla::Wifi::iterate();
146 }
147
148 int scanResult = WiFi.scanComplete();
149 if (scanResult == WIFI_SCAN_RUNNING) {
150 return false;
151 }
152
153 configModeScanInProgress = false;
154 auto cache = Supla::WifiScanResultCache::Instance();
155 cache->beginUpdate();
156
157 if (scanResult >= 0) {
158 for (int i = 0; i < scanResult; i++) {
159 cache->addOrUpdate(WiFi.SSID(i).c_str(), WiFi.RSSI(i), WiFi.channel(i));
160 }
161 cache->finishUpdate(millis());
162 SUPLA_LOG_INFO("WiFi: config mode scan completed (%d networks)",
163 scanResult);
164 } else {
165 cache->clear();
166 SUPLA_LOG_WARNING("WiFi: config mode scan failed (%d)", scanResult);
167 }
168
169 WiFi.scanDelete();
170 return Supla::Wifi::iterate();
171 }
172
173 void startConfigModeScan() override {
174 if (mode != Supla::DEVICE_MODE_CONFIG || configModeScanInProgress) {
175 return;
176 }
177
178 WiFi.scanDelete();
179 int scanResult = WiFi.scanNetworks(true, true);
180 configModeScanInProgress = (scanResult == WIFI_SCAN_RUNNING);
181 if (!configModeScanInProgress && scanResult >= 0) {
182 auto cache = Supla::WifiScanResultCache::Instance();
183 cache->beginUpdate();
184 for (int i = 0; i < scanResult; i++) {
185 cache->addOrUpdate(WiFi.SSID(i).c_str(), WiFi.RSSI(i), WiFi.channel(i));
186 }
187 cache->finishUpdate(millis());
188 WiFi.scanDelete();
189 SUPLA_LOG_INFO("WiFi: config mode scan completed (%d networks)",
190 scanResult);
191 } else if (!configModeScanInProgress) {
192 SUPLA_LOG_WARNING("WiFi: config mode scan start failed (%d)",
193 scanResult);
194 } else {
195 SUPLA_LOG_INFO("WiFi: config mode scan started");
196 }
197 }
198
199 void disable() override {
200 if (!allowDisable) {
201 return;
202 }
203
204 allowDisable = false;
205 configModeScanInProgress = false;
206 SUPLA_LOG_DEBUG("[%s] disabling WiFi connection", getIntfName());
207 DisconnectProtocols();
208 WiFi.scanDelete();
209 Supla::InputNoiseGuard::NotifyWifiTransition();
210 WiFi.softAPdisconnect(true);
211 Supla::InputNoiseGuard::NotifyWifiTransition();
212 WiFi.disconnect(true);
213 Supla::InputNoiseGuard::NotifyWifiTransition();
214 WiFi.mode(WIFI_OFF);
215 }
216
217 // DEPRECATED, use setSSLEnabled instead
218 void enableSSL(bool value) {
219 setSSLEnabled(value);
220 }
221
222 void fillStateData(TDSC_ChannelState *channelState) override {
223 channelState->Fields |= SUPLA_CHANNELSTATE_FIELD_IPV4 |
224 SUPLA_CHANNELSTATE_FIELD_MAC |
225 SUPLA_CHANNELSTATE_FIELD_WIFIRSSI |
226 SUPLA_CHANNELSTATE_FIELD_WIFISIGNALSTRENGTH;
227 channelState->IPv4 = WiFi.localIP();
228 getMacAddr(channelState->MAC);
229 int rssi = WiFi.RSSI();
230 channelState->WiFiRSSI = rssi;
231 channelState->WiFiSignalStrength = Supla::rssiToSignalStrength(rssi);
232 }
233
234 bool getMacAddr(uint8_t *out) override {
235#ifdef ARDUINO_ARCH_ESP8266
236 WiFi.macAddress(out);
237#else
238#ifdef ESP_ARDUINO_VERSION_MAJOR
239#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
240 // Code for version 3.x
241 ::Network.macAddress(out);
242#else
243 // Code for version 2.x
244 WiFi.macAddress(out);
245#endif
246#endif
247#endif
248 return true;
249 }
250
251 void uninit() override {
252 disable();
253 }
254
255 uint32_t getIP() override {
256 return WiFi.localIP();
257 }
258
259 const char *getIntfName() const override {
260 return "Wi-Fi";
261 }
262
263 protected:
264 bool wifiConfigured = false;
265 bool configModeScanInProgress = false;
266 bool allowDisable = false;
267
268#ifdef ARDUINO_ARCH_ESP8266
269 WiFiEventHandler gotIpEventHandler, disconnectedEventHandler;
270#endif
271
272 bool isConfigModeScanInProgress() const override {
273 return configModeScanInProgress;
274 }
275};
276
277}; // namespace Supla
278
279#endif // SRC_SUPLA_NETWORK_ESP_WIFI_H_
Definition ip_address.h:15
Definition esp_wifi.h:31
Definition netif_wifi.h:16
Definition proto.h:2705