/ RNode_Firmware_CE_G2 / Remote.h
Remote.h
1 // Copyright (C) 2024, Mark Qvist 2 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 13 // You should have received a copy of the GNU General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 16 #include <WiFi.h> 17 18 #if CONFIG_IDF_TARGET_ESP32 19 #include "esp32/rom/rtc.h" 20 #elif CONFIG_IDF_TARGET_ESP32S2 21 #include "esp32s2/rom/rtc.h" 22 #elif CONFIG_IDF_TARGET_ESP32C3 23 #include "esp32c3/rom/rtc.h" 24 #elif CONFIG_IDF_TARGET_ESP32S3 25 #include "esp32s3/rom/rtc.h" 26 #else 27 #error Target CONFIG_IDF_TARGET is not supported 28 #endif 29 30 #define WIFI_UPDATE_INTERVAL_MS 500 31 #define WR_SOCKET_TIMEOUT 6 32 #define WR_READ_TIMEOUT_MS 86400000 /* 24 hours - hosts often only receive, don't disconnect */ 33 #define WR_RECONNECT_INTERVAL_MS 10000 34 35 uint32_t wifi_update_interval_ms = WIFI_UPDATE_INTERVAL_MS; 36 uint32_t last_wifi_update = 0; 37 uint32_t wr_last_connect_try = 0; 38 uint32_t wr_last_read = 0; 39 40 WiFiClient connection; 41 WiFiServer remote_listener(7633, 1); 42 IPAddress ap_ip(10, 0, 0, 1); 43 IPAddress ap_nm(255, 255, 255, 0); 44 IPAddress wr_device_ip; 45 char wr_hostname[10]; 46 wl_status_t wr_wifi_status = WL_IDLE_STATUS; 47 48 uint8_t wifi_mode = WIFI_OFF; 49 bool wifi_init_ran = false; 50 bool wifi_initialized = false; 51 52 char wr_ssid[33]; 53 char wr_psk[33]; 54 55 extern void host_disconnected(); 56 57 void wifi_dbg(String msg) { Serial.print("[WiFi] "); Serial.println(msg); } 58 59 uint8_t wifi_remote_mode() { return wifi_mode; } 60 61 bool wifi_is_connected() { return (wr_wifi_status == WL_CONNECTED); } 62 bool wifi_host_is_connected() { if (connection) { return true; } else { return false; } } 63 64 void wifi_remote_start_ap() { 65 WiFi.mode(WIFI_AP); 66 if (wr_ssid[0] != 0x00) { 67 if (wr_psk[0] != 0x00) { WiFi.softAP(wr_ssid, wr_psk, wr_channel); } 68 else { WiFi.softAP(wr_ssid, NULL, wr_channel); } 69 } else { 70 if (wr_psk[0] != 0x00) { WiFi.softAP(bt_devname, wr_psk, wr_channel); } 71 else { WiFi.softAP(bt_devname, NULL, wr_channel); } 72 } 73 delay(150); 74 WiFi.softAPConfig(ap_ip, ap_ip, ap_nm); 75 wifi_initialized = true; 76 } 77 78 void wifi_remote_start_sta() { 79 WiFi.mode(WIFI_STA); 80 81 uint8_t ip[4]; bool ip_ok = true; 82 for (uint8_t i = 0; i < 4; i++) { ip[i] = EEPROM.read(config_addr(ADDR_CONF_IP+i)); } 83 if (ip[0]==0x00 && ip[1]==0x00 && ip[2]==0x00 && ip[3]==0x00) { ip_ok = false; } 84 if (ip[0]==0xFF && ip[1]==0xFF && ip[2]==0xFF && ip[3]==0xFF) { ip_ok = false; } 85 86 uint8_t nm[4]; bool nm_ok = true; 87 for (uint8_t i = 0; i < 4; i++) { nm[i] = EEPROM.read(config_addr(ADDR_CONF_NM+i)); } 88 if (nm[0]==0x00 && nm[1]==0x00 && nm[2]==0x00 && nm[3]==0x00) { nm_ok = false; } 89 if (nm[0]==0xFF && nm[1]==0xFF && nm[2]==0xFF && nm[3]==0xFF) { nm_ok = false; } 90 91 if (ip_ok && nm_ok) { 92 IPAddress sta_ip(ip[0], ip[1], ip[2], ip[3]); 93 IPAddress sta_nm(nm[0], nm[1], nm[2], nm[3]); 94 WiFi.config(sta_ip, sta_ip, sta_nm); 95 } 96 97 delay(100); 98 if (wr_ssid[0] != 0x00) { 99 if (wr_psk[0] != 0x00) { WiFi.begin(wr_ssid, wr_psk); } 100 else { WiFi.begin(wr_ssid); } 101 } 102 103 delay(500); 104 wr_wifi_status = WiFi.status(); 105 wifi_initialized = true; 106 wr_last_connect_try = millis(); 107 #if defined(WIFI_PS_MAX_MODEM) 108 WiFi.setSleep(WIFI_PS_MAX_MODEM); 109 #else 110 WiFi.setSleep(true); 111 #endif 112 } 113 114 void wifi_remote_stop() { 115 WiFi.softAPdisconnect(true); 116 WiFi.disconnect(true, true); 117 WiFi.mode(WIFI_MODE_NULL); 118 wifi_initialized = false; 119 } 120 121 void wifi_remote_start() { 122 if (wifi_mode == WR_WIFI_AP) { wifi_remote_start_ap(); } 123 else if (wifi_mode == WR_WIFI_STA) { wifi_remote_start_sta(); } 124 else { wifi_remote_stop(); } 125 126 if (wifi_initialized == true) { 127 remote_listener.begin(); 128 remote_listener.setTimeout(WR_SOCKET_TIMEOUT); 129 wr_state = WR_STATE_ON; 130 } else { remote_listener.end(); wr_state = WR_STATE_OFF; } 131 } 132 133 void wifi_remote_init() { 134 memcpy(wr_hostname, bt_devname, 5); 135 memcpy(wr_hostname+5, bt_devname+6, 4); 136 wr_hostname[9] = 0x00; 137 WiFi.softAPdisconnect(true); 138 WiFi.disconnect(true, true); 139 WiFi.mode(WIFI_MODE_NULL); 140 WiFi.setHostname(wr_hostname); 141 142 wr_ssid[32] = 0x00; wr_psk[32] = 0x00; 143 for (uint8_t i = 0; i < 32; i++) { wr_ssid[i] = EEPROM.read(config_addr(ADDR_CONF_SSID+i)); if (wr_ssid[i] == 0xFF) { wr_ssid[i] = 0x00; } } 144 for (uint8_t i = 0; i < 32; i++) { wr_psk[i] = EEPROM.read(config_addr(ADDR_CONF_PSK+i)); if (wr_psk[i] == 0xFF) { wr_psk[i] = 0x00; } } 145 wr_channel = EEPROM.read(eeprom_addr(ADDR_CONF_WCHN)); if (wr_channel < 1 || wr_channel > 14) { wr_channel = WR_CHANNEL_DEFAULT; } 146 wifi_remote_start(); 147 wifi_init_ran = true; 148 } 149 150 void wifi_remote_close_all() { 151 // wifi_dbg("Close all"); // TODO: Remove debug 152 if (connection) { connection.stop(); } 153 WiFiClient client = remote_listener.available(); 154 while (client) { client.stop(); client = remote_listener.available(); } 155 wr_state = WR_STATE_ON; 156 } 157 158 void wifi_remote_check_active() { 159 if (millis()-wr_last_read >= WR_READ_TIMEOUT_MS) { 160 // wifi_dbg("Connection activity timed out"); // TODO: Remove debug 161 if (connection && connection.connected()) { 162 connection.stop(); 163 wifi_remote_close_all(); 164 host_disconnected(); 165 } 166 } 167 } 168 169 bool wifi_remote_available() { 170 if (connection) { 171 if (connection.connected()) { 172 if (connection.available()) { wr_last_read = millis(); return true; } 173 else { wifi_remote_check_active(); return false; } 174 } else { 175 // wifi_dbg("Client disconnected"); // TODO: Remove debug 176 wifi_remote_close_all(); 177 return false; 178 } 179 } else { 180 WiFiClient client = remote_listener.available(); 181 if (!client) { return false; } 182 else { 183 // wifi_dbg("Client connected"); // TODO: Remove debug 184 connection = client; 185 wr_state = WR_STATE_CONNECTED; 186 wr_last_read = millis(); 187 if (connection.available()) { return true; } 188 else { return false; } 189 } 190 } 191 } 192 193 uint8_t wifi_remote_read() { 194 if (connection && connection.available()) { return connection.read(); } 195 else { 196 // wifi_dbg("Error: No data to read from TCP socket"); // TODO: Remove debug 197 if (connection) { wifi_remote_close_all(); } 198 return 0xC0; 199 } 200 } 201 202 void wifi_remote_write(uint8_t byte) { if (connection) { connection.write(byte); } } 203 void wifi_remote_flush(void) { if (connection) { connection.flush(); } } 204 205 void wifi_update_status() { 206 wr_wifi_status = WiFi.status(); 207 if (wr_wifi_status == WL_CONNECTED) { wr_device_ip = WiFi.localIP(); } 208 if (wifi_mode == WR_WIFI_AP && wifi_initialized) { wr_device_ip = WiFi.softAPIP(); wr_wifi_status = WL_CONNECTED; } 209 if (wifi_init_ran && wifi_mode == WR_WIFI_STA && wr_wifi_status != WL_CONNECTED) { 210 if (millis()-wr_last_connect_try >= WR_RECONNECT_INTERVAL_MS) { wifi_remote_init(); } 211 } 212 } 213 214 void update_wifi() { 215 if (millis()-last_wifi_update >= wifi_update_interval_ms) { 216 wifi_update_status(); 217 last_wifi_update = millis(); 218 } 219 }