esp8266/network_wlan: Allow enumerating connected stations in AP mode.

This commit introduces the ability to obtain a list of stations
connected to the device when in soft-AP mode.

A new parameter ("stations") to pass to WLAN.status is supported,
returning a tuple of (bssid, ipv4) entries, one per connected station.
An empty tuple is returned if no stations are connected, and an
exception is raised if an error occurred whilst building the python
objects to return to the interpreter.

Documentation is also updated to cover the new parameter.

This fixes #5395.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
This commit is contained in:
Alessandro Gatti
2025-02-15 00:58:01 +01:00
committed by Damien George
parent 6fba1e406b
commit 4d034f817c
2 changed files with 41 additions and 1 deletions

View File

@@ -85,7 +85,18 @@ Methods
* ``STAT_GOT_IP`` -- connection successful.
When called with one argument *param* should be a string naming the status
parameter to retrieve. Supported parameters in WiFI STA mode are: ``'rssi'``.
parameter to retrieve, and different parameters are supported depending on the
mode the WiFi is in.
In STA mode, passing ``'rssi'`` returns a signal strength indicator value, whose
format varies depending on the port (this is available on all ports that support
WiFi network interfaces, except for CC3200).
In AP mode, passing ``'stations'`` returns a list of connected WiFi stations
(this is available on all ports that support WiFi network interfaces, except for
CC3200). The format of the station information entries varies across ports,
providing either the raw BSSID of the connected station, the IP address of the
connected station, or both.
.. method:: WLAN.isconnected()

View File

@@ -170,6 +170,29 @@ static mp_obj_t esp_disconnect(mp_obj_t self_in) {
}
static MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect);
static void build_stations_list_cleanup_callback(void *station_info) {
if (station_info != NULL) {
wifi_softap_free_station_info();
}
}
static mp_obj_t build_stations_list(void) {
struct station_info *info = wifi_softap_get_station_info();
MP_DEFINE_NLR_JUMP_CALLBACK_FUNCTION_1(ctx, build_stations_list_cleanup_callback, (void *)info);
nlr_push_jump_callback(&ctx.callback, mp_call_function_1_from_nlr_jump_callback);
mp_obj_list_t *stations = MP_OBJ_TO_PTR(mp_obj_new_list(0, NULL));
struct station_info *current = info;
mp_obj_t entry[2] = { 0 };
while (current != NULL) {
entry[0] = mp_obj_new_bytes(current->bssid, sizeof(current->bssid));
entry[1] = netutils_format_ipv4_addr((uint8_t *)&current->ip.addr, NETUTILS_BIG);
mp_obj_list_append(stations, mp_obj_new_tuple(2, entry));
current = STAILQ_NEXT(current, next);
}
nlr_pop_jump_callback(true);
return MP_OBJ_FROM_PTR(stations);
}
static mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args == 1) {
@@ -185,6 +208,12 @@ static mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) {
if (self->if_id == STATION_IF) {
return MP_OBJ_NEW_SMALL_INT(wifi_station_get_rssi());
}
break;
case MP_QSTR_stations:
if (self->if_id == SOFTAP_IF) {
return build_stations_list();
}
break;
}
mp_raise_ValueError(MP_ERROR_TEXT("unknown status param"));
}