Skip to content

Commit

Permalink
wifi: refactoring / rewrite
Browse files Browse the repository at this point in the history
- replace JustWifi with a custom WiFi module
- re-implemented Core methods that deal with scanning, directly work with the SDK callback
- re-implemented Core method for opmode to avoid dealing with the 2.7.x pseudo modes
- re-implemented Core method for forced-(modem)-sleep (with the intention to merge with OpmodeNull... todo)
- disable reconnect and autoconnect from SDK, avoid unintentionally storing ssid & pass for these and
  make connection routine watch for events instead. timeout is implemented as a local timer
- do not store runtime data that can be retrieved via SDK calls
- settings are loaded only when starting AP or STA, networks are no longer kept in memory
- settings STA ssidN must be unique
- remove char buffer from the event callback
- trigger station-disconnected event when actually disconnected, not when connecting or explicitly requesting it
- generic rssi sorting method for initial connection, do rssi checks while connected to find a better network

Drop (temporarily?) wps and smartconfig. Both are implementable with the new approach,
but come with some weird expectations from the SDK side (no extra heap with wps, broadcasting plain-text
passphrase with smartconfig, storing station config implicitly, etc.).

Both are sort-of fixed with RTOS SDK, but it is still a big question of whether to support them at all in the current state.
  • Loading branch information
mcspr committed Mar 31, 2021
1 parent b6934d3 commit 5a97329
Show file tree
Hide file tree
Showing 15 changed files with 2,471 additions and 788 deletions.
5 changes: 3 additions & 2 deletions code/espurna/alexa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,9 @@ void alexaSetup() {
#endif

// Register wifi callback
wifiRegister([](justwifi_messages_t code, char * parameter) {
if ((MESSAGE_CONNECTED == code) || (MESSAGE_DISCONNECTED == code)) {
wifiRegister([](wifi::Event event) {
if ((event == wifi::Event::StationConnected)
|| (event == wifi::Event::StationDisconnected)) {
_alexaConfigure();
}
});
Expand Down
12 changes: 1 addition & 11 deletions code/espurna/button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,11 +453,7 @@ void buttonEvent(size_t id, ButtonEvent event) {
#endif

case ButtonAction::AccessPoint:
if (wifiState() & WIFI_STATE_AP) {
wifiStartSTA();
} else {
wifiStartAP();
}
wifiToggleAp();
break;

case ButtonAction::Reset:
Expand All @@ -469,15 +465,9 @@ void buttonEvent(size_t id, ButtonEvent event) {
break;

case ButtonAction::Wps:
#if defined(JUSTWIFI_ENABLE_WPS)
wifiStartWPS();
#endif
break;

case ButtonAction::SmartConfig:
#if defined(JUSTWIFI_ENABLE_SMARTCONFIG)
wifiStartSmartConfig();
#endif
break;

case ButtonAction::BrightnessIncrease:
Expand Down
69 changes: 50 additions & 19 deletions code/espurna/config/general.h
Original file line number Diff line number Diff line change
Expand Up @@ -536,26 +536,46 @@
// WIFI
// -----------------------------------------------------------------------------

#ifndef WIFI_CONNECT_TIMEOUT
#define WIFI_CONNECT_TIMEOUT 60000 // Connecting timeout for WIFI in ms
#ifndef WIFI_CONNECT_RETRIES
#define WIFI_CONNECT_RETRIES 3 // Number of times before changing to the next configured network
#endif

#ifndef WIFI_CONNECT_INTERVAL
#define WIFI_CONNECT_INTERVAL 3000 // Time (ms) between connection attempts
#endif

#ifndef WIFI_RECONNECT_INTERVAL
#define WIFI_RECONNECT_INTERVAL 180000 // If could not connect to WIFI, retry after this time in ms
#define WIFI_RECONNECT_INTERVAL 120000 // When all retries on all networks are exhausted, wait for this time (ms) and start from the beginning
#endif

#ifndef WIFI_MAX_NETWORKS
#define WIFI_MAX_NETWORKS 5 // Max number of WIFI connection configurations
#define WIFI_MAX_NETWORKS 5 // Maximum number of WiFi configurations in settings
#endif

#ifndef WIFI_AP_CAPTIVE_SUPPORT
#define WIFI_AP_CAPTIVE_SUPPORT 1 // Captive portal for AP mode
#endif

#ifndef WIFI_AP_CAPTIVE_ENABLED
#define WIFI_AP_CAPTIVE_ENABLED 1 // Enabled by default
#endif

#ifndef WIFI_AP_CAPTIVE
#define WIFI_AP_CAPTIVE 1 // Captive portal enabled when in AP mode
#ifndef WIFI_STA_MODE
#define WIFI_STA_MODE wifi::StaMode::Enabled // By default, turn on STA interface and try to connect to configured networks
// - wifi::StaMode::Enabled (default)
// - wifi::StaMode::Disabled keeps STA disabled
#endif

#ifndef WIFI_AP_MODE
#define WIFI_AP_MODE WiFiApMode::Fallback // By default, fallback to AP mode if no STA connection
// Use WiFiApMode::Enabled to start it when the device boots
// Use WiFiApMode::Disabled to disable AP mode completely
#define WIFI_AP_MODE wifi::ApMode::Fallback // By default, enable AP if there is no STA connection
// - wifi::ApMode::Fallback (default)
// - wifi::ApMode::Enabled keeps AP enabled independent of STA
// - wifi::ApMode::Disabled keeps AP disabled
#endif

#ifndef WIFI_FALLBACK_TIMEOUT
#define WIFI_FALLBACK_TIMEOUT 60000 // When AP is in FALLBACK mode and STA is connected,
// how long to wait until stopping the AP
#endif

#ifndef WIFI_AP_SSID
Expand All @@ -573,15 +593,34 @@
// Use `set wifiApLease# MAC`, where MAC is a valid 12-byte HEX number without colons
#endif

#ifndef WIFI_AP_CHANNEL
#define WIFI_AP_CHANNEL 1
#endif

#ifndef WIFI_SLEEP_MODE
#define WIFI_SLEEP_MODE WIFI_NONE_SLEEP // WIFI_NONE_SLEEP, WIFI_LIGHT_SLEEP or WIFI_MODEM_SLEEP
#endif

#ifndef WIFI_SCAN_NETWORKS
#define WIFI_SCAN_NETWORKS 1 // Perform a network scan before connecting
#define WIFI_SCAN_NETWORKS 1 // Perform a network scan before connecting and when RSSI threshold is reached
#endif

// Optional hardcoded configuration (up to 5 networks, depending on WIFI_MAX_NETWORKS and espurna/wifi_config.h)
#ifndef WIFI_SCAN_RSSI_THRESHOLD
#define WIFI_SCAN_RSSI_THRESHOLD -73 // Consider current network for a reconnection cycle
// when it's RSSI value is below the specified threshold
#endif

#ifndef WIFI_SCAN_RSSI_CHECKS
#define WIFI_SCAN_RSSI_CHECKS 3 // Amount of RSSI threshold checks before starting a scan
#endif

#ifndef WIFI_SCAN_RSSI_CHECK_INTERVAL
#define WIFI_SCAN_RSSI_CHECK_INTERVAL 60000 // Time (ms) between RSSI checks
#endif

// Optional hardcoded configuration
// NOTICE that these values become factory-defaults

#ifndef WIFI1_SSID
#define WIFI1_SSID ""
#endif
Expand Down Expand Up @@ -702,14 +741,6 @@
#define WIFI5_DNS ""
#endif

#ifndef WIFI_RSSI_1M
#define WIFI_RSSI_1M -30 // Calibrate it with your router reading the RSSI at 1m
#endif

#ifndef WIFI_PROPAGATION_CONST
#define WIFI_PROPAGATION_CONST 4 // This is typically something between 2.7 to 4.3 (free space is 2)
#endif

// ref: https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/kconfig.html#config-lwip-esp-gratuitous-arp
// ref: https://github.com/xoseperez/espurna/pull/1877#issuecomment-525612546
//
Expand Down
10 changes: 0 additions & 10 deletions code/espurna/config/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@

#pragma once

// -----------------------------------------------------------------------------
// WIFI
// -----------------------------------------------------------------------------

#define WIFI_STATE_AP 1
#define WIFI_STATE_STA 2
#define WIFI_STATE_AP_STA 3
#define WIFI_STATE_WPS 4
#define WIFI_STATE_SMARTCONFIG 8

// -----------------------------------------------------------------------------
// GPIO
// -----------------------------------------------------------------------------
Expand Down
155 changes: 76 additions & 79 deletions code/espurna/led.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,27 +68,23 @@ void LedPattern::stop() {
// For network-based modes, cycle ON & OFF (time in milliseconds)
// XXX: internals convert these to clock cycles, delay cannot be longer than 25000 / 50000 ms
static const LedDelay _ledDelays[] {
{100, 100}, // Autoconfig
{100, 4900}, // Connected
{4900, 100}, // Connected (inverse)
{100, 900}, // Config / AP
{900, 100}, // Config / AP (inverse)
{500, 500} // Idle
};

enum class LedDelayName {
NetworkAutoconfig,
enum class LedDelayName : int {
NetworkConnected,
NetworkConnectedInverse,
NetworkConfig,
NetworkConfigInverse,
NetworkIdle,
None
NetworkIdle
};

bool _led_update { false };

std::vector<led_t> _leds;
bool _led_update { false };

// -----------------------------------------------------------------------------

Expand Down Expand Up @@ -186,12 +182,17 @@ bool ledStatus(size_t id) {
return false;
}

const LedDelay& _ledDelayFromName(LedDelayName pattern) {
static_assert(
(sizeof(_ledDelays) / sizeof(_ledDelays[0])) <= static_cast<int>(LedDelayName::None),
"Out-of-bounds"
);
return _ledDelays[static_cast<int>(pattern)];
const LedDelay& _ledDelayFromName(LedDelayName name) {
switch (name) {
case LedDelayName::NetworkConnected:
case LedDelayName::NetworkConnectedInverse:
case LedDelayName::NetworkConfig:
case LedDelayName::NetworkConfigInverse:
case LedDelayName::NetworkIdle:
return _ledDelays[static_cast<int>(name)];
}

return _ledDelays[static_cast<int>(LedDelayName::NetworkIdle)];
}

void _ledPattern(led_t& led) {
Expand Down Expand Up @@ -359,83 +360,77 @@ void ledUpdate(bool do_update) {
}

void ledLoop() {
const auto wifi_state = wifiState();

for (size_t id = 0; id < _leds.size(); ++id) {
auto& led = _leds[id];

switch (led.mode()) {

case LED_MODE_MANUAL:
break;
case LED_MODE_MANUAL:
break;

case LED_MODE_WIFI:
if (wifiConnected()) {
_ledBlink(led, LedDelayName::NetworkConnected);
} else if (wifiConnectable()) {
_ledBlink(led, LedDelayName::NetworkConfig);
} else {
_ledBlink(led, LedDelayName::NetworkIdle);
}
break;

case LED_MODE_WIFI:
if ((wifi_state & WIFI_STATE_WPS) || (wifi_state & WIFI_STATE_SMARTCONFIG)) {
_ledBlink(led, LedDelayName::NetworkAutoconfig);
} else if (wifi_state & WIFI_STATE_STA) {
#if RELAY_SUPPORT

case LED_MODE_FINDME_WIFI:
if (wifiConnected()) {
if (relayStatus(_led_relays[id])) {
_ledBlink(led, LedDelayName::NetworkConnected);
} else if (wifi_state & WIFI_STATE_AP) {
} else {
_ledBlink(led, LedDelayName::NetworkConnectedInverse);
}
} else if (wifiConnectable()) {
if (relayStatus(_led_relays[id])) {
_ledBlink(led, LedDelayName::NetworkConfig);
} else {
_ledBlink(led, LedDelayName::NetworkIdle);
_ledBlink(led, LedDelayName::NetworkConfigInverse);
}
} else {
_ledBlink(led, LedDelayName::NetworkIdle);
}
break;

#if RELAY_SUPPORT

case LED_MODE_FINDME_WIFI:
if ((wifi_state & WIFI_STATE_WPS) || (wifi_state & WIFI_STATE_SMARTCONFIG)) {
_ledBlink(led, LedDelayName::NetworkAutoconfig);
} else if (wifi_state & WIFI_STATE_STA) {
if (relayStatus(_led_relays[id])) {
_ledBlink(led, LedDelayName::NetworkConnected);
} else {
_ledBlink(led, LedDelayName::NetworkConnectedInverse);
}
} else if (wifi_state & WIFI_STATE_AP) {
if (relayStatus(_led_relays[id])) {
_ledBlink(led, LedDelayName::NetworkConfig);
} else {
_ledBlink(led, LedDelayName::NetworkConfigInverse);
}
case LED_MODE_RELAY_WIFI:
if (wifiConnected()) {
if (relayStatus(_led_relays[id])) {
_ledBlink(led, LedDelayName::NetworkConnected);
} else {
_ledBlink(led, LedDelayName::NetworkIdle);
_ledBlink(led, LedDelayName::NetworkConnectedInverse);
}
break;

case LED_MODE_RELAY_WIFI:
if ((wifi_state & WIFI_STATE_WPS) || (wifi_state & WIFI_STATE_SMARTCONFIG)) {
_ledBlink(led, LedDelayName::NetworkAutoconfig);
} else if (wifi_state & WIFI_STATE_STA) {
if (relayStatus(_led_relays[id])) {
_ledBlink(led, LedDelayName::NetworkConnected);
} else {
_ledBlink(led, LedDelayName::NetworkConnectedInverse);
}
} else if (wifi_state & WIFI_STATE_AP) {
if (relayStatus(_led_relays[id])) {
_ledBlink(led, LedDelayName::NetworkConfig);
} else {
_ledBlink(led, LedDelayName::NetworkConfigInverse);
}
} else if (wifiConnectable()) {
if (relayStatus(_led_relays[id])) {
_ledBlink(led, LedDelayName::NetworkConfig);
} else {
_ledBlink(led, LedDelayName::NetworkIdle);
_ledBlink(led, LedDelayName::NetworkConfigInverse);
}
break;
} else {
_ledBlink(led, LedDelayName::NetworkIdle);
}
break;

case LED_MODE_FOLLOW:
if (!_led_update) break;
case LED_MODE_FOLLOW:
if (_led_update) {
_ledStatus(led, relayStatus(_led_relays[id]));
break;
}
break;

case LED_MODE_FOLLOW_INVERSE:
if (!_led_update) break;
case LED_MODE_FOLLOW_INVERSE:
if (_led_update) {
led.status(!relayStatus(_led_relays[id]));
_ledStatus(led, !relayStatus(_led_relays[id]));
break;
}
break;

case LED_MODE_FINDME: {
if (!_led_update) break;
case LED_MODE_FINDME:
if (_led_update) {
bool status = true;
for (size_t relayId = 0; relayId < relayCount(); ++relayId) {
if (relayStatus(relayId)) {
Expand All @@ -444,11 +439,11 @@ void ledLoop() {
}
}
_ledStatus(led, status);
break;
}
break;

case LED_MODE_RELAY: {
if (!_led_update) break;
case LED_MODE_RELAY:
if (_led_update) {
bool status = false;
for (size_t relayId = 0; relayId < relayCount(); ++relayId) {
if (relayStatus(relayId)) {
Expand All @@ -457,20 +452,22 @@ void ledLoop() {
}
}
_ledStatus(led, status);
break;
}
break;

#endif // RELAY_SUPPORT == 1
#endif // RELAY_SUPPORT == 1

case LED_MODE_ON:
if (!_led_update) break;
case LED_MODE_ON:
if (_led_update) {
_ledStatus(led, true);
break;
}
break;

case LED_MODE_OFF:
if (!_led_update) break;
case LED_MODE_OFF:
if (_led_update) {
_ledStatus(led, false);
break;
}
break;

}

Expand Down
Loading

0 comments on commit 5a97329

Please sign in to comment.