Browse Source

Access point fixes (#137)

* add lingering mode to access point fix bug which prevents active access point from being re-configured
master
rjwats 4 years ago
committed by GitHub
parent
commit
555b3efd8d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      interface/src/ap/APModes.ts
  2. 8
      interface/src/ap/APSettingsForm.tsx
  3. 28
      interface/src/ap/APStatus.ts
  4. 12
      interface/src/ap/types.ts
  5. 23
      lib/framework/APSettingsService.cpp
  6. 24
      lib/framework/APSettingsService.h
  7. 6
      lib/framework/APStatus.cpp
  8. 4
      lib/framework/APStatus.h
  9. 2
      lib/framework/ESP8266React.cpp

4
interface/src/ap/APModes.ts

@ -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;
} }

8
interface/src/ap/APSettingsForm.tsx

@ -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_DISCONNECTED}>When WiFi Disconnected</MenuItem>
<MenuItem value={ApProvisionMode.AP_NEVER}>Never</MenuItem>
<MenuItem value={APProvisionMode.AP_MODE_ALWAYS}>Always</MenuItem>
<MenuItem value={APProvisionMode.AP_MODE_DISCONNECTED}>When WiFi Disconnected</MenuItem>
<MenuItem value={APProvisionMode.AP_NEVER}>Never</MenuItem>
</SelectValidator> </SelectValidator>
{ {
isAPEnabled(data) && isAPEnabled(data) &&

28
interface/src/ap/APStatus.ts

@ -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) => {
return active ? theme.palette.success.main : theme.palette.info.main;
export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => {
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) => {
return active ? "Active" : "Inactive";
export const apStatus = ({ status }: APStatus) => {
switch (status) {
case APNetworkStatus.ACTIVE:
return "Active";
case APNetworkStatus.INACTIVE:
return "Inactive";
case APNetworkStatus.LINGERING:
return "Lingering until idle";
default:
return "Unknown";
}
}; };

12
interface/src/ap/types.ts

@ -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;
} }

23
lib/framework/APSettingsService.cpp

@ -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 {
if (currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA) {
stopAP();
}
} else if ((currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA) &&
(_reconfigureAp || !WiFi.softAPgetStationNum())) {
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;
}

24
lib/framework/APSettingsService.h

@ -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;
}
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)) {
return StateUpdateResult::UNCHANGED;
} }
settings.ssid = root["ssid"] | FACTORY_AP_SSID;
settings.password = root["password"] | FACTORY_AP_PASSWORD;
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();

6
lib/framework/APStatus.cpp

@ -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["active"] = (currentWiFiMode == WIFI_AP || currentWiFiMode == WIFI_AP_STA);
root["status"] = _apSettingsService->getAPNetworkStatus();
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();

4
lib/framework/APStatus.h

@ -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);
}; };

2
lib/framework/ESP8266React.cpp

@ -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…
Cancel
Save