8000 Add access point IP address configuration in UI · rjwats/esp8266-react@6ef5df2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6ef5df2

Browse files
authored
Add access point IP address configuration in UI
* Allow ap ip address to be configured via ui * Add missing WiFi status to UI enum * Update package-lock.json
1 parent f2b53a6 commit 6ef5df2

File tree

10 files changed

+2185
-1365
lines changed

10 files changed

+2185
-1365
lines changed

factory_settings.ini

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ build_flags =
66
-D FACTORY_WIFI_HOSTNAME=\"esp-react\"
77

88
; Access point settings
9+
-D FACTORY_AP_PROVISION_MODE=AP_MODE_DISCONNECTED
910
-D FACTORY_AP_SSID=\"ESP8266-React\" ; 1-64 characters
1011
-D FACTORY_AP_PASSWORD=\"esp-react\" ; 8-64 characters
11-
-D FACTORY_AP_PROVISION_MODE=AP_MODE_DISCONNECTED
12+
-D FACTORY_AP_LOCAL_IP=\"192.168.4.1\"
13+
-D FACTORY_AP_GATEWAY_IP=\"192.168.4.1\"
14+
-D FACTORY_AP_SUBNET_MASK=\"255.255.255.0\"
1215

1316
; User credentials for admin and guest user
1417
-D FACTORY_ADMIN_USERNAME=\"admin\"

interface/package-lock.json

Lines changed: 2090 additions & 1350 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

interface/src/ap/APSettingsForm.tsx

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@ import { TextValidator, ValidatorForm, SelectValidator } from 'react-material-ui
44
import MenuItem from '@material-ui/core/MenuItem';
55
import SaveIcon from '@material-ui/icons/Save';
66

7-
import {PasswordValidator, RestFormProps, FormActions, FormButton} from '../components';
7+
import { PasswordValidator, RestFormProps, FormActions, FormButton } from '../components';
88

99
import { isAPEnabled } from './APModes';
1010
import { APSettings, APProvisionMode } from './types';
11+
import { isIP } from '../validators';
1112

1213
type APSettingsFormProps = RestFormProps<APSettings>;
1314

1415
class APSettingsForm extends React.Component<APSettingsFormProps> {
1516

17+
componentWillMount() {
18+
ValidatorForm.addValidationRule('isIP', isIP);
19+
}
20+
1621
render() {
1722
const { data, handleValueChange, saveData, loadData } = this.props;
1823
return (
@@ -53,6 +58,39 @@ class APSettingsForm extends React.Component<APSettingsFormProps> {
5358
onChange={handleValueChange('password')}
5459
margin="normal"
5560
/>
61+
<TextValidator
62+
validators={['required', 'isIP']}
63+
errorMessages={['Local IP is required', 'Must be an IP address']}
64+
name="local_ip"
65+
label="Local IP"
66+
fullWidth
67+
variant="outlined"
68+
value={data.local_ip}
69+
onChange={handleValueChange('local_ip')}
70+
margin="normal"
71+
/>
72+
<TextValidator
73+
validators={['required', 'isIP']}
74+
errorMessages={['Gateway IP is required', 'Must be an IP address']}
75+
name="gateway_ip"
76+
label="Gateway"
77+
fullWidth
78+
variant="outlined"
79+
value={data.gateway_ip}
80+
onChange={handleValueChange('gateway_ip')}
81+
margin="normal"
82+
/>
83+
<TextValidator
84+
validators={['required', 'isIP']}
85+
errorMessages={['Subnet mask is required', 'Must be an IP address']}
86+
name="subnet_mask"
87+
label="Subnet"
88+
fullWidth
89+
variant="outlined"
90+
value={data.subnet_mask}
91+
onChange={handleValueChange('subnet_mask')}
92+
margin="normal"
93+
/>
5694
</Fragment>
5795
}
5896
<FormActions>

interface/src/ap/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,7 @@ export interface APSettings {
2121
provision_mode: APProvisionMode;
2222
ssid: string;
2323
password: string;
24+
local_ip: string;
25+
gateway_ip: string;
26+
subnet_mask: string;
2427
}

interface/src/components/SingleUpload.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, accept, uploadi
6060
}
6161
return "Uploading\u2026";
6262
}
63-
return "Drop file here or click to browse";
63+
return "Drop file or click here";
6464
}
6565

6666
const renderProgress = (progress?: ProgressEvent) => (

interface/src/wifi/WiFiStatus.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const wifiStatusHighlight = ({ status }: WiFiStatus, theme: Theme) => {
77
switch (status) {
88
case WiFiConnectionStatus.WIFI_STATUS_IDLE:
99
case WiFiConnectionStatus.WIFI_STATUS_DISCONNECTED:
10+
case WiFiConnectionStatus.WIFI_STATUS_NO_SHIELD:
1011
return theme.palette.info.main;
1112
case WiFiConnectionStatus.WIFI_STATUS_CONNECTED:
1213
return theme.palette.success.main;
@@ -20,6 +21,8 @@ export const wifiStatusHighlight = ({ status }: WiFiStatus, theme: Theme) => {
2021

2122
export const wifiStatus = ({ status }: WiFiStatus) => {
2223
switch (status) {
24+
case WiFiConnectionStatus.WIFI_STATUS_NO_SHIELD:
25+
return "Inactive";
2326
case WiFiConnectionStatus.WIFI_STATUS_IDLE:
2427
return "Idle";
2528
case WiFiConnectionStatus.WIFI_STATUS_NO_SSID_AVAIL:

interface/src/wifi/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ export enum WiFiConnectionStatus {
44
WIFI_STATUS_CONNECTED = 3,
55
WIFI_STATUS_CONNECT_FAILED = 4,
66
WIFI_STATUS_CONNECTION_LOST = 5,
7-
WIFI_STATUS_DISCONNECTED = 6
7+
WIFI_STATUS_DISCONNECTED = 6,
8+
WIFI_STATUS_NO_SHIELD = 255
89
}
910

1011
export enum WiFiEncryptionType {

lib/framework/APSettingsService.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ void APSettingsService::manageAP() {
4545

4646
void APSettingsService::startAP() {
4747
Serial.println(F("Starting software access point"));
48+
WiFi.softAPConfig(_state.localIP, _state.gatewayIP, _state.subnetMask);
4849
WiFi.softAP(_state.ssid.c_str(), _state.password.c_str());
4950
if (!_dnsServer) {
5051
IPAddress apIp = WiFi.softAPIP();

lib/framework/APSettingsService.h

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <HttpEndpoint.h>
55
#include <FSPersistence.h>
6+
#include <JsonUtils.h>
67

78
#include <DNSServer.h>
89
#include <IPAddress.h>
@@ -15,6 +16,10 @@
1516

1617
#define DNS_PORT 53
1718

19+
#ifndef FACTORY_AP_PROVISION_MODE
20+
#define FACTORY_AP_PROVISION_MODE AP_MODE_DISCONNECTED
21+
#endif
22+
1823
#ifndef FACTORY_AP_SSID
1924
#define FACTORY_AP_SSID "ESP8266-React"
2025
#endif
@@ -23,29 +28,44 @@
2328
#define FACTORY_AP_PASSWORD "esp-react"
2429
#endif
2530

26-
#ifndef FACTORY_AP_PROVISION_MODE
27 A851 -
#define FACTORY_AP_PROVISION_MODE AP_MODE_DISCONNECTED
31+
#ifndef FACTORY_AP_LOCAL_IP
32+
#define FACTORY_AP_LOCAL_IP "192.168.4.1"
33+
#endif
34+
35+
#ifndef FACTORY_AP_GATEWAY_IP
36+
#define FACTORY_AP_GATEWAY_IP "192.168.4.1"
37+
#endif
38+
39+
#ifndef FACTORY_AP_SUBNET_MASK
40+
#define FACTORY_AP_SUBNET_MASK "255.255.255.0"
2841
#endif
2942

3043
#define AP_SETTINGS_FILE "/config/apSettings.json"
3144
#define AP_SETTINGS_SERVICE_PATH "/rest/apSettings"
3245

33-
enum APNetworkStatus {
34-
ACTIVE = 0,
35-
INACTIVE,
36-
LINGERING
37-
};
46+
enum APNetworkStatus { ACTIVE = 0, INACTIVE, LINGERING };
3847

3948
class APSettings {
4049
public:
4150
uint8_t provisionMode;
4251
String ssid;
4352
String password;
53+
IPAddress localIP;
54+
IPAddress gatewayIP;
55+
IPAddress subnetMask;
56+
57+
bool operator==(const APSettings& settings) const {
58+
return provisionMode == settings.provisionMode && ssid == settings.ssid && password == settings.password &&
59+
localIP == settings.localIP && gatewayIP == settings.gatewayIP && subnetMask == settings.subnetMask;
60+
}
4461

4562
static void read(APSettings& settings, JsonObject& root) {
4663
root["provision_mode"] = settings.provisionMode;
4764
root["ssid"] = settings.ssid;
4865
root["password"] = settings.password;
66+
root["local_ip"] = settings.localIP.toString();
67+
root["gateway_ip"] = settings.gatewayIP.toString();
68+
root["subnet_mask"] = settings.subnetMask.toString();
4969
}
5070

5171
static StateUpdateResult update(JsonObject& root, APSettings& settings) {
@@ -61,8 +81,12 @@ class APSettings {
6181
}
6282
newSettings.ssid = root["ssid"] | FACTORY_AP_SSID;
6383
newSettings.password = root["password"] | FACTORY_AP_PASSWORD;
64-
if (newSettings.provisionMode == settings.provisionMode && newSettings.ssid.equals(settings.ssid) &&
65-
newSettings.password.equals(settings.password)) {
84+
85+
JsonUtils::readIP(root, "local_ip", newSettings.localIP, FACTORY_AP_LOCAL_IP);
86+
JsonUtils::readIP(root, "gateway_ip", newSettings.gatewayIP, FACTORY_AP_GATEWAY_IP);
87+
JsonUtils::readIP(root, "subnet_mask", newSettings.subnetMask, FACTORY_AP_SUBNET_MASK);
88+
89+
if (newSettings == settings) {
6690
return StateUpdateResult::UNCHANGED;
6791
}
6892
settings = newSettings;

lib/framework/JsonUtils.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@
77

88
class JsonUtils {
99
public:
10-
static void readIP(JsonObject& root, const String& key, IPAddress& ip) {
10+
static void readIP(JsonObject& root, const String& key, IPAddress& ip, const String& def) {
11+
IPAddress defaultIp = {};
12+
if (!defaultIp.fromString(def)) {
13+
defaultIp = INADDR_NONE;
14+
}
15+
readIP(root, key, ip, defaultIp);
16+
}
17+
static void readIP(JsonObject& root, const String& key, IPAddress& ip, const IPAddress& defaultIp = INADDR_NONE) {
1118
if (!root[key].is<String>() || !ip.fromString(root[key].as<String>())) {
12-
ip = INADDR_NONE;
19+
ip = defaultIp;
1320
}
1421
}
1522
static void writeIP(JsonObject& root, const String& key, const IPAddress& ip) {

0 commit comments

Comments
 (0)
0