Skip to content

Commit b9baf4a

Browse files
committed
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>
1 parent 8987b39 commit b9baf4a

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

docs/library/network.WLAN.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,17 @@ Methods
8585
* ``STAT_GOT_IP`` -- connection successful.
8686

8787
When called with one argument *param* should be a string naming the status
88-
parameter to retrieve. Supported parameters in WiFI STA mode are: ``'rssi'``.
88+
parameter to retrieve, and different parameters are supported depending on the
89+
mode the WiFi is in.
90+
91+
In STA mode, passing ``'rssi'`` returns a signal strength indicator value, whose
92+
format varies depending on the port (currently supported on ESP32 and ESP8266).
93+
94+
In AP mode, passing ``'stations'`` returns a list of connected WiFi stations
95+
(currently supported on ports/boards that use the CYW43 WiFi driver, and the
96+
ESP32 and ESP8266 ports). The format of the station information entries varies
97+
across ports, providing either the raw BSSID of the connected station, the IP
98+
address of the connected station, or both.
8999

90100
.. method:: WLAN.isconnected()
91101

ports/esp8266/network_wlan.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,37 @@ static mp_obj_t esp_disconnect(mp_obj_t self_in) {
170170
}
171171
static MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect);
172172

173+
static mp_obj_t build_stations_tuple(void) {
174+
mp_uint_t count = wifi_softap_get_station_num();
175+
if (count == 0) {
176+
return mp_const_empty_tuple;
177+
}
178+
mp_obj_tuple_t *stations = NULL;
179+
struct station_info *info = wifi_softap_get_station_info();
180+
if (info == NULL) {
181+
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("no station info available"));
182+
}
183+
nlr_buf_t nlr;
184+
if (nlr_push(&nlr) == 0) {
185+
stations = MP_OBJ_TO_PTR(mp_obj_new_tuple(count, NULL));
186+
struct station_info *current = info;
187+
size_t station_index = 0;
188+
mp_obj_t entry[2] = { 0 };
189+
while (current != NULL && station_index < count) {
190+
entry[0] = mp_obj_new_bytes(current->bssid, sizeof(current->bssid));
191+
entry[1] = netutils_format_ipv4_addr((uint8_t *)&current->ip.addr, NETUTILS_BIG);
192+
stations->items[station_index++] = mp_obj_new_tuple(2, entry);
193+
current = STAILQ_NEXT(current, next);
194+
}
195+
nlr_pop();
196+
} else {
197+
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
198+
stations = NULL;
199+
}
200+
wifi_softap_free_station_info();
201+
return stations != NULL ? MP_OBJ_FROM_PTR(stations) : MP_OBJ_NULL;
202+
}
203+
173204
static mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) {
174205
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
175206
if (n_args == 1) {
@@ -185,6 +216,12 @@ static mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) {
185216
if (self->if_id == STATION_IF) {
186217
return MP_OBJ_NEW_SMALL_INT(wifi_station_get_rssi());
187218
}
219+
break;
220+
case MP_QSTR_stations:
221+
if (self->if_id == SOFTAP_IF) {
222+
return build_stations_tuple();
223+
}
224+
break;
188225
}
189226
mp_raise_ValueError(MP_ERROR_TEXT("unknown status param"));
190227
}

0 commit comments

Comments
 (0)