-
Notifications
You must be signed in to change notification settings - Fork 19
samples: implement WiFi state machine to handle reconnects #434
Conversation
Visit the preview URL for this PR (updated for commit 1adde6d): https://golioth-zephyr-sdk-doxygen-dev--pr434-wifi-conn-mgr-ky2vq2vi.web.app (expires Mon, 30 Oct 2023 14:33:09 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: a389eefadf4b4b68a539327b3459dd66c142cf49 |
06100a3
to
991abee
Compare
991abee
to
b175aff
Compare
57a44fb
to
c63d2f6
Compare
c63d2f6
to
7dfdb0e
Compare
Implement WiFi connectivity state machine running in a dedicated work queue (which runs in a dedicated thread). Network management events from Zephyr are handled there, as well as timeouts and retries when attempting to connect. As a result, WiFi connectivity is bringed back whenever there was a temporary problem with WiFi AP connection. In case WiFi radio is not ready (L1 is down, which results in LOWER_DOWN interface management event/state) wait until it becomes ready (which is required by ESP32 WiFi driver, since it does not handle connect requests otherwise). Initialize and launch WiFi work queue thread automatically by using SYS_INIT(), so that `net_connect()` function does not need to handle WiFi explicitly. Since `net_connect()` handles mostly DHCPv4 setup and waiting to obtain IPv4 address, there is no need to check whether interace is UP at the beginning. DHCPv4 in Zephyr has its own state machine, with network events handling, all it requires is just calling net_dhcpv4_start() even for interfaces that are not operational at the time of function call. Replace waiting for "DHCPv4 bound" event with waiting for "IPv4 address add" event. The latter allows to wait for WiFi to be connected to AP with assigned IP address, while still handling (implicitly) "DHCPv4 bound" event, which is required for ethernet cable connected devices. Signed-off-by: Marcin Niestroj <[email protected]>
7dfdb0e
to
1adde6d
Compare
|
||
if (IS_ENABLED(CONFIG_GOLIOTH_SAMPLE_WIFI)) { | ||
LOG_INF("Connecting to WiFi"); | ||
wifi_connect(iface); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I think it's a lot cleaner to have WiFi separated out from IP network management.
enum wifi_state new_state = map_value - MAP_OFFSET; | ||
int sleep_msec = 0; | ||
|
||
if (map_value - MAP_OFFSET >= WIFI_STATE_WAIT) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a neat trick
#define INV (WIFI_STATE_INVALID + MAP_OFFSET) | ||
#define WAIT(ms) (WIFI_STATE_WAIT + MAP_OFFSET + (ms)) | ||
|
||
static const int wifi_state_change_map[][WIFI_STATE_LAST + 1] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use the State Machine Framework?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked briefly at that framework months ago and... I was just expecting something more I guess. With a hierarchical state machine this might be a good thing to use, but for flat state machine I got the impression that it didn't provide that much tools to speed up development or reuse.
I guess that the real answer could be provided only by trying to reimplement what we have in this PR with State Machine Framework and see how it looks in practice. This approach should be faster and give more precise answer than theoretical considerations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, let's leave this as is for now. I don't want to spend too much time investigating frameworks.
Implement WiFi connectivity state machine running in a dedicated work
queue (which runs in a dedicated thread). Network management events from
Zephyr are handled there, as well as timeouts and retries when attempting
to connect. As a result, WiFi connectivity is bringed back whenever there
was a temporary problem with WiFi AP connection.
In case WiFi radio is not ready (L1 is down, which results in LOWER_DOWN
interface management event/state) wait until it becomes ready (which is
required by ESP32 WiFi driver, since it does not handle connect requests
otherwise).
Initialize and launch WiFi work queue thread automatically by using
SYS_INIT(), so that
net_connect()
function does not need to handle WiFiexplicitly.
Since
net_connect()
handles mostly DHCPv4 setup and waiting to obtainIPv4 address, there is no need to check whether interace is UP at the
beginning. DHCPv4 in Zephyr has its own state machine, with network events
handling, all it requires is just calling net_dhcpv4_start() even for
interfaces that are not operational at the time of function call.
Replace waiting for "DHCPv4 bound" event with waiting for "IPv4 address
add" event. The latter allows to wait for WiFi to be connected to AP with
assigned IP address, while still handling (implicitly) "DHCPv4 bound"
event, which is required for ethernet cable connected devices.