From a4cfa75b49349a99fb1fb9cd67daf7c34599949f Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 7 Jul 2020 23:33:34 +0200 Subject: [PATCH] AP IP configurable --- factory_settings.ini | 9 ++++--- interface/src/ap/APSettingsForm.tsx | 40 ++++++++++++++++++++++++++- lib/framework/APSettingsService.cpp | 5 +--- lib/framework/APSettingsService.h | 42 ++++++++++++++++++++++------- lib/framework/JsonUtils.h | 11 ++++++-- 5 files changed, 88 insertions(+), 19 deletions(-) diff --git a/factory_settings.ini b/factory_settings.ini index def783561..056ed53be 100644 --- a/factory_settings.ini +++ b/factory_settings.ini @@ -5,10 +5,13 @@ build_flags = -D FACTORY_WIFI_PASSWORD=\"\" -D FACTORY_WIFI_HOSTNAME=\"ems-esp\" - ; Access point settings - -D FACTORY_AP_SSID=\"ems-esp\" - -D FACTORY_AP_PASSWORD=\"ems-esp-neo\" + ; Access point settings -D FACTORY_AP_PROVISION_MODE=AP_MODE_DISCONNECTED + -D FACTORY_AP_SSID=\"ems-esp\" ; 1-64 characters + -D FACTORY_AP_PASSWORD=\"ems-esp-neo\" ; 8-64 characters + -D FACTORY_AP_LOCAL_IP=\"192.168.4.1\" + -D FACTORY_AP_GATEWAY_IP=\"192.168.4.1\" + -D FACTORY_AP_SUBNET_MASK=\"255.255.255.0\" ; User credentials for admin and guest user -D FACTORY_ADMIN_USERNAME=\"admin\" diff --git a/interface/src/ap/APSettingsForm.tsx b/interface/src/ap/APSettingsForm.tsx index 5b67b23fa..912bf9d6d 100644 --- a/interface/src/ap/APSettingsForm.tsx +++ b/interface/src/ap/APSettingsForm.tsx @@ -4,15 +4,20 @@ import { TextValidator, ValidatorForm, SelectValidator } from 'react-material-ui import MenuItem from '@material-ui/core/MenuItem'; import SaveIcon from '@material-ui/icons/Save'; -import {PasswordValidator, RestFormProps, FormActions, FormButton} from '../components'; +import { PasswordValidator, RestFormProps, FormActions, FormButton } from '../components'; import { isAPEnabled } from './APModes'; import { APSettings, APProvisionMode } from './types'; +import { isIP } from '../validators'; type APSettingsFormProps = RestFormProps; class APSettingsForm extends React.Component { + componentWillMount() { + ValidatorForm.addValidationRule('isIP', isIP); + } + render() { const { data, handleValueChange, saveData, loadData } = this.props; return ( @@ -53,6 +58,39 @@ class APSettingsForm extends React.Component { onChange={handleValueChange('password')} margin="normal" /> + + + } diff --git a/lib/framework/APSettingsService.cpp b/lib/framework/APSettingsService.cpp index 28900094f..66fdd1c04 100644 --- a/lib/framework/APSettingsService.cpp +++ b/lib/framework/APSettingsService.cpp @@ -45,10 +45,7 @@ void APSettingsService::manageAP() { void APSettingsService::startAP() { // Serial.println(F("Starting software access point")); - IPAddress localIP(192, 168, 4, 1); - IPAddress gateway(192, 168, 4, 1); - IPAddress subnet(255, 255, 255, 0); - WiFi.softAPConfig(localIP, gateway, subnet); + WiFi.softAPConfig(_state.localIP, _state.gatewayIP, _state.subnetMask); WiFi.softAP(_state.ssid.c_str(), _state.password.c_str()); if (!_dnsServer) { IPAddress apIp = WiFi.softAPIP(); diff --git a/lib/framework/APSettingsService.h b/lib/framework/APSettingsService.h index e13f4e3fd..910461536 100644 --- a/lib/framework/APSettingsService.h +++ b/lib/framework/APSettingsService.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -15,6 +16,10 @@ #define DNS_PORT 53 +#ifndef FACTORY_AP_PROVISION_MODE +#define FACTORY_AP_PROVISION_MODE AP_MODE_DISCONNECTED +#endif + #ifndef FACTORY_AP_SSID #define FACTORY_AP_SSID "ESP8266-React" #endif @@ -23,29 +28,44 @@ #define FACTORY_AP_PASSWORD "esp-react" #endif -#ifndef FACTORY_AP_PROVISION_MODE -#define FACTORY_AP_PROVISION_MODE AP_MODE_DISCONNECTED +#ifndef FACTORY_AP_LOCAL_IP +#define FACTORY_AP_LOCAL_IP "192.168.4.1" +#endif + +#ifndef FACTORY_AP_GATEWAY_IP +#define FACTORY_AP_GATEWAY_IP "192.168.4.1" +#endif + +#ifndef FACTORY_AP_SUBNET_MASK +#define FACTORY_AP_SUBNET_MASK "255.255.255.0" #endif #define AP_SETTINGS_FILE "/config/apSettings.json" #define AP_SETTINGS_SERVICE_PATH "/rest/apSettings" -enum APNetworkStatus { - ACTIVE = 0, - INACTIVE, - LINGERING -}; +enum APNetworkStatus { ACTIVE = 0, INACTIVE, LINGERING }; class APSettings { public: uint8_t provisionMode; String ssid; String password; + IPAddress localIP; + IPAddress gatewayIP; + IPAddress subnetMask; + + bool operator==(const APSettings& settings) const { + return provisionMode == settings.provisionMode && ssid == settings.ssid && password == settings.password && + localIP == settings.localIP && gatewayIP == settings.gatewayIP && subnetMask == settings.subnetMask; + } static void read(APSettings& settings, JsonObject& root) { root["provision_mode"] = settings.provisionMode; root["ssid"] = settings.ssid; root["password"] = settings.password; + root["local_ip"] = settings.localIP.toString(); + root["gateway_ip"] = settings.gatewayIP.toString(); + root["subnet_mask"] = settings.subnetMask.toString(); } static StateUpdateResult update(JsonObject& root, APSettings& settings) { @@ -61,8 +81,12 @@ class APSettings { } newSettings.ssid = root["ssid"] | FACTORY_AP_SSID; newSettings.password = root["password"] | FACTORY_AP_PASSWORD; - if (newSettings.provisionMode == settings.provisionMode && newSettings.ssid.equals(settings.ssid) && - newSettings.password.equals(settings.password)) { + + JsonUtils::readIP(root, "local_ip", newSettings.localIP, FACTORY_AP_LOCAL_IP); + JsonUtils::readIP(root, "gateway_ip", newSettings.gatewayIP, FACTORY_AP_GATEWAY_IP); + JsonUtils::readIP(root, "subnet_mask", newSettings.subnetMask, FACTORY_AP_SUBNET_MASK); + + if (newSettings == settings) { return StateUpdateResult::UNCHANGED; } settings = newSettings; diff --git a/lib/framework/JsonUtils.h b/lib/framework/JsonUtils.h index 7d956b53f..0c4089831 100644 --- a/lib/framework/JsonUtils.h +++ b/lib/framework/JsonUtils.h @@ -7,9 +7,16 @@ class JsonUtils { public: - static void readIP(JsonObject& root, const String& key, IPAddress& ip) { + static void readIP(JsonObject& root, const String& key, IPAddress& ip, const String& def) { + IPAddress defaultIp = {}; + if (!defaultIp.fromString(def)) { + defaultIp = INADDR_NONE; + } + readIP(root, key, ip, defaultIp); + } + static void readIP(JsonObject& root, const String& key, IPAddress& ip, const IPAddress& defaultIp = INADDR_NONE) { if (!root[key].is() || !ip.fromString(root[key].as())) { - ip = INADDR_NONE; + ip = defaultIp; } } static void writeIP(JsonObject& root, const String& key, const IPAddress& ip) {