Access point fixes (#137)
* add lingering mode to access point fix bug which prevents active access point from being re-configured
This commit is contained in:
parent
ddbb84454f
commit
555b3efd8d
@ -1,5 +1,5 @@
|
|||||||
import { APSettings, ApProvisionMode } from "./types";
|
import { APSettings, APProvisionMode } from "./types";
|
||||||
|
|
||||||
export const isAPEnabled = ({ provision_mode }: APSettings) => {
|
export const isAPEnabled = ({ provision_mode }: APSettings) => {
|
||||||
return provision_mode === ApProvisionMode.AP_MODE_ALWAYS || provision_mode === ApProvisionMode.AP_MODE_DISCONNECTED;
|
return provision_mode === APProvisionMode.AP_MODE_ALWAYS || provision_mode === APProvisionMode.AP_MODE_DISCONNECTED;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ 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 { isAPEnabled } from './APModes';
|
||||||
import { APSettings, ApProvisionMode } from './types';
|
import { APSettings, APProvisionMode } from './types';
|
||||||
|
|
||||||
type APSettingsFormProps = RestFormProps<APSettings>;
|
type APSettingsFormProps = RestFormProps<APSettings>;
|
||||||
|
|
||||||
@ -24,9 +24,9 @@ class APSettingsForm extends React.Component<APSettingsFormProps> {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={handleValueChange('provision_mode')}
|
onChange={handleValueChange('provision_mode')}
|
||||||
margin="normal">
|
margin="normal">
|
||||||
<MenuItem value={ApProvisionMode.AP_MODE_ALWAYS}>Always</MenuItem>
|
<MenuItem value={APProvisionMode.AP_MODE_ALWAYS}>Always</MenuItem>
|
||||||
<MenuItem value={ApProvisionMode.AP_MODE_DISCONNECTED}>When WiFi Disconnected</MenuItem>
|
<MenuItem value={APProvisionMode.AP_MODE_DISCONNECTED}>When WiFi Disconnected</MenuItem>
|
||||||
<MenuItem value={ApProvisionMode.AP_NEVER}>Never</MenuItem>
|
<MenuItem value={APProvisionMode.AP_NEVER}>Never</MenuItem>
|
||||||
</SelectValidator>
|
</SelectValidator>
|
||||||
{
|
{
|
||||||
isAPEnabled(data) &&
|
isAPEnabled(data) &&
|
||||||
|
@ -1,10 +1,28 @@
|
|||||||
import { Theme } from "@material-ui/core";
|
import { Theme } from "@material-ui/core";
|
||||||
import { APStatus } from "./types";
|
import { APStatus, APNetworkStatus } from "./types";
|
||||||
|
|
||||||
export const apStatusHighlight = ({ active }: APStatus, theme: Theme) => {
|
export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => {
|
||||||
return active ? theme.palette.success.main : theme.palette.info.main;
|
switch (status) {
|
||||||
|
case APNetworkStatus.ACTIVE:
|
||||||
|
return theme.palette.success.main;
|
||||||
|
case APNetworkStatus.INACTIVE:
|
||||||
|
return theme.palette.info.main;
|
||||||
|
case APNetworkStatus.LINGERING:
|
||||||
|
return theme.palette.warning.main;
|
||||||
|
default:
|
||||||
|
return theme.palette.warning.main;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const apStatus = ({ active }: APStatus) => {
|
export const apStatus = ({ status }: APStatus) => {
|
||||||
return active ? "Active" : "Inactive";
|
switch (status) {
|
||||||
|
case APNetworkStatus.ACTIVE:
|
||||||
|
return "Active";
|
||||||
|
case APNetworkStatus.INACTIVE:
|
||||||
|
return "Inactive";
|
||||||
|
case APNetworkStatus.LINGERING:
|
||||||
|
return "Lingering until idle";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,18 +1,24 @@
|
|||||||
export enum ApProvisionMode {
|
export enum APProvisionMode {
|
||||||
AP_MODE_ALWAYS = 0,
|
AP_MODE_ALWAYS = 0,
|
||||||
AP_MODE_DISCONNECTED = 1,
|
AP_MODE_DISCONNECTED = 1,
|
||||||
AP_NEVER = 2
|
AP_NEVER = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum APNetworkStatus {
|
||||||
|
ACTIVE = 0,
|
||||||
|
INACTIVE = 1,
|
||||||
|
LINGERING = 2
|
||||||
|
}
|
||||||
|
|
||||||
export interface APStatus {
|
export interface APStatus {
|
||||||
active: boolean;
|
status: APNetworkStatus;
|
||||||
ip_address: string;
|
ip_address: string;
|
||||||
mac_address: string;
|
mac_address: string;
|
||||||
station_num: number;
|
station_num: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface APSettings {
|
export interface APSettings {
|
||||||
provision_mode: ApProvisionMode;
|
provision_mode: APProvisionMode;
|
||||||
ssid: string;
|
ssid: string;
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,8 @@ APSettingsService::APSettingsService(AsyncWebServer* server, FS* fs, SecurityMan
|
|||||||
_httpEndpoint(APSettings::read, APSettings::update, this, server, AP_SETTINGS_SERVICE_PATH, securityManager),
|
_httpEndpoint(APSettings::read, APSettings::update, this, server, AP_SETTINGS_SERVICE_PATH, securityManager),
|
||||||
_fsPersistence(APSettings::read, APSettings::update, this, fs, AP_SETTINGS_FILE),
|
_fsPersistence(APSettings::read, APSettings::update, this, fs, AP_SETTINGS_FILE),
|
||||||
_dnsServer(nullptr),
|
_dnsServer(nullptr),
|
||||||
_lastManaged(0) {
|
_lastManaged(0),
|
||||||
|
_reconfigureAp(false) {
|
||||||
addUpdateHandler([&](const String& originId) { reconfigureAP(); }, false);
|
addUpdateHandler([&](const String& originId) { reconfigureAP(); }, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ void APSettingsService::begin() {
|
|||||||
|
|
||||||
void APSettingsService::reconfigureAP() {
|
void APSettingsService::reconfigureAP() {
|
||||||
_lastManaged = millis() - MANAGE_NETWORK_DELAY;
|
_lastManaged = millis() - MANAGE_NETWORK_DELAY;
|
||||||
|
_reconfigureAp = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APSettingsService::loop() {
|
void APSettingsService::loop() {
|
||||||
@ -31,14 +33,14 @@ void APSettingsService::manageAP() {
|
|||||||
WiFiMode_t currentWiFiMode = WiFi.getMode();
|
WiFiMode_t currentWiFiMode = WiFi.getMode();
|
||||||
if (_state.provisionMode == AP_MODE_ALWAYS ||
|
if (_state.provisionMode == AP_MODE_ALWAYS ||
|
||||||
(_state.provisionMode == AP_MODE_DISCONNECTED && WiFi.status() != WL_CONNECTED)) {
|
(_state.provisionMode == AP_MODE_DISCONNECTED && WiFi.status() != WL_CONNECTED)) {
|
||||||
if (currentWiFiMode == WIFI_OFF || currentWiFiMode == WIFI_STA) {
|
if (_reconfigureAp || currentWiFiMode == WIFI_OFF || currentWiFiMode == WIFI_STA) {
|
||||||
startAP();
|
startAP();
|
||||||
}
|
}
|
||||||
} else {
|
} else if ((currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA) &&
|
||||||
if (currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA) {
|
(_reconfigureAp || !WiFi.softAPgetStationNum())) {
|
||||||
stopAP();
|
stopAP();
|
||||||
}
|
}
|
||||||
}
|
_reconfigureAp = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APSettingsService::startAP() {
|
void APSettingsService::startAP() {
|
||||||
@ -69,3 +71,12 @@ void APSettingsService::handleDNS() {
|
|||||||
_dnsServer->processNextRequest();
|
_dnsServer->processNextRequest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
APNetworkStatus APSettingsService::getAPNetworkStatus() {
|
||||||
|
WiFiMode_t currentWiFiMode = WiFi.getMode();
|
||||||
|
bool apActive = currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA;
|
||||||
|
if (apActive && _state.provisionMode != AP_MODE_ALWAYS && WiFi.status() == WL_CONNECTED) {
|
||||||
|
return APNetworkStatus::LINGERING;
|
||||||
|
}
|
||||||
|
return apActive ? APNetworkStatus::ACTIVE : APNetworkStatus::INACTIVE;
|
||||||
|
}
|
||||||
|
@ -30,6 +30,12 @@
|
|||||||
#define AP_SETTINGS_FILE "/config/apSettings.json"
|
#define AP_SETTINGS_FILE "/config/apSettings.json"
|
||||||
#define AP_SETTINGS_SERVICE_PATH "/rest/apSettings"
|
#define AP_SETTINGS_SERVICE_PATH "/rest/apSettings"
|
||||||
|
|
||||||
|
enum APNetworkStatus {
|
||||||
|
ACTIVE = 0,
|
||||||
|
INACTIVE,
|
||||||
|
LINGERING
|
||||||
|
};
|
||||||
|
|
||||||
class APSettings {
|
class APSettings {
|
||||||
public:
|
public:
|
||||||
uint8_t provisionMode;
|
uint8_t provisionMode;
|
||||||
@ -43,17 +49,23 @@ class APSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static StateUpdateResult update(JsonObject& root, APSettings& settings) {
|
static StateUpdateResult update(JsonObject& root, APSettings& settings) {
|
||||||
settings.provisionMode = root["provision_mode"] | FACTORY_AP_PROVISION_MODE;
|
APSettings newSettings = {};
|
||||||
|
newSettings.provisionMode = root["provision_mode"] | FACTORY_AP_PROVISION_MODE;
|
||||||
switch (settings.provisionMode) {
|
switch (settings.provisionMode) {
|
||||||
case AP_MODE_ALWAYS:
|
case AP_MODE_ALWAYS:
|
||||||
case AP_MODE_DISCONNECTED:
|
case AP_MODE_DISCONNECTED:
|
||||||
case AP_MODE_NEVER:
|
case AP_MODE_NEVER:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
settings.provisionMode = AP_MODE_ALWAYS;
|
newSettings.provisionMode = AP_MODE_ALWAYS;
|
||||||
}
|
}
|
||||||
settings.ssid = root["ssid"] | FACTORY_AP_SSID;
|
newSettings.ssid = root["ssid"] | FACTORY_AP_SSID;
|
||||||
settings.password = root["password"] | FACTORY_AP_PASSWORD;
|
newSettings.password = root["password"] | FACTORY_AP_PASSWORD;
|
||||||
|
if (newSettings.provisionMode == settings.provisionMode && newSettings.ssid.equals(settings.ssid) &&
|
||||||
|
newSettings.password.equals(settings.password)) {
|
||||||
|
return StateUpdateResult::UNCHANGED;
|
||||||
|
}
|
||||||
|
settings = newSettings;
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -64,6 +76,7 @@ class APSettingsService : public StatefulService<APSettings> {
|
|||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
void loop();
|
void loop();
|
||||||
|
APNetworkStatus getAPNetworkStatus();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HttpEndpoint<APSettings> _httpEndpoint;
|
HttpEndpoint<APSettings> _httpEndpoint;
|
||||||
@ -73,7 +86,8 @@ class APSettingsService : public StatefulService<APSettings> {
|
|||||||
DNSServer* _dnsServer;
|
DNSServer* _dnsServer;
|
||||||
|
|
||||||
// for the mangement delay loop
|
// for the mangement delay loop
|
||||||
unsigned long _lastManaged;
|
volatile unsigned long _lastManaged;
|
||||||
|
volatile boolean _reconfigureAp;
|
||||||
|
|
||||||
void reconfigureAP();
|
void reconfigureAP();
|
||||||
void manageAP();
|
void manageAP();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <APStatus.h>
|
#include <APStatus.h>
|
||||||
|
|
||||||
APStatus::APStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
APStatus::APStatus(AsyncWebServer* server, SecurityManager* securityManager, APSettingsService* apSettingsService) :
|
||||||
|
_apSettingsService(apSettingsService) {
|
||||||
server->on(AP_STATUS_SERVICE_PATH,
|
server->on(AP_STATUS_SERVICE_PATH,
|
||||||
HTTP_GET,
|
HTTP_GET,
|
||||||
securityManager->wrapRequest(std::bind(&APStatus::apStatus, this, std::placeholders::_1),
|
securityManager->wrapRequest(std::bind(&APStatus::apStatus, this, std::placeholders::_1),
|
||||||
@ -11,8 +12,7 @@ void APStatus::apStatus(AsyncWebServerRequest* request) {
|
|||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_AP_STATUS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_AP_STATUS_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
WiFiMode_t currentWiFiMode = WiFi.getMode();
|
root["status"] = _apSettingsService->getAPNetworkStatus();
|
||||||
root["active"] = (currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA);
|
|
||||||
root["ip_address"] = WiFi.softAPIP().toString();
|
root["ip_address"] = WiFi.softAPIP().toString();
|
||||||
root["mac_address"] = WiFi.softAPmacAddress();
|
root["mac_address"] = WiFi.softAPmacAddress();
|
||||||
root["station_num"] = WiFi.softAPgetStationNum();
|
root["station_num"] = WiFi.softAPgetStationNum();
|
||||||
|
@ -14,15 +14,17 @@
|
|||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <IPAddress.h>
|
#include <IPAddress.h>
|
||||||
#include <SecurityManager.h>
|
#include <SecurityManager.h>
|
||||||
|
#include <APSettingsService.h>
|
||||||
|
|
||||||
#define MAX_AP_STATUS_SIZE 1024
|
#define MAX_AP_STATUS_SIZE 1024
|
||||||
#define AP_STATUS_SERVICE_PATH "/rest/apStatus"
|
#define AP_STATUS_SERVICE_PATH "/rest/apStatus"
|
||||||
|
|
||||||
class APStatus {
|
class APStatus {
|
||||||
public:
|
public:
|
||||||
APStatus(AsyncWebServer* server, SecurityManager* securityManager);
|
APStatus(AsyncWebServer* server, SecurityManager* securityManager, APSettingsService* apSettingsService);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
APSettingsService* _apSettingsService;
|
||||||
void apStatus(AsyncWebServerRequest* request);
|
void apStatus(AsyncWebServerRequest* request);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ ESP8266React::ESP8266React(AsyncWebServer* server, FS* fs) :
|
|||||||
_wifiScanner(server, &_securitySettingsService),
|
_wifiScanner(server, &_securitySettingsService),
|
||||||
_wifiStatus(server, &_securitySettingsService),
|
_wifiStatus(server, &_securitySettingsService),
|
||||||
_ntpStatus(server, &_securitySettingsService),
|
_ntpStatus(server, &_securitySettingsService),
|
||||||
_apStatus(server, &_securitySettingsService),
|
_apStatus(server, &_securitySettingsService, &_apSettingsService),
|
||||||
_mqttStatus(server, &_mqttSettingsService, &_securitySettingsService),
|
_mqttStatus(server, &_mqttSettingsService, &_securitySettingsService),
|
||||||
_systemStatus(server, &_securitySettingsService) {
|
_systemStatus(server, &_securitySettingsService) {
|
||||||
#ifdef PROGMEM_WWW
|
#ifdef PROGMEM_WWW
|
||||||
|
Loading…
Reference in New Issue
Block a user