8000 Merge pull request #8820 from romkey/8790-ap-connected-devices · ladyada/circuitpython@c219d89 · GitHub
[go: up one dir, main page]

Skip to content

Commit c219d89

Browse files
authored
Merge pull request adafruit#8820 from romkey/8790-ap-connected-devices
New methods to get list of associated stations in access point mode and get maximum number of stations that can be associated
2 parents 135f4f9 + 5396482 commit c219d89

File tree

5 files changed

+112
-0
lines changed

5 files changed

+112
-0
lines changed

ports/espressif/common-hal/wifi/Radio.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,44 @@ void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) {
250250
set_mode_ap(self, false);
251251
}
252252

253+
mp_obj_t common_hal_wifi_radio_get_stations_ap(wifi_radio_obj_t *self) {
254+
wifi_sta_list_t esp_sta_list;
255+
esp_err_t result;
256+
257+
result = esp_wifi_ap_get_sta_list(&esp_sta_list);
258+
if (result != ESP_OK) {
259+
return mp_const_none;
260+
}
261+
262+
esp_netif_pair_mac_ip_t mac_ip_pair[esp_sta_list.num];
263+
for (int i = 0; i < esp_sta_list.num; i++) {
264+
memcpy(mac_ip_pair[i].mac, esp_sta_list.sta[i].mac, MAC_ADDRESS_LENGTH);
265+
mac_ip_pair[i].ip.addr = 0;
266+
}
267+
268+
result = esp_netif_dhcps_get_clients_by_mac(self->ap_netif, esp_sta_list.num, mac_ip_pair);
269+
if (result != ESP_OK) {
270+
return mp_const_none;
271+
}
272+
273+
mp_obj_t mp_sta_list = mp_obj_new_list(0, NULL);
274+
for (int i = 0; i < esp_sta_list.num; i++) {
275+
mp_obj_t elems[3] = {
276+
mp_obj_new_bytes(esp_sta_list.sta[i].mac, MAC_ADDRESS_LENGTH),
277+
MP_OBJ_NEW_SMALL_INT(esp_sta_list.sta[i].rssi),
278+
mp_const_none
279+
};
280+
281+
if (mac_ip_pair[i].ip.addr) {
282+
elems[2] = common_hal_ipaddress_new_ipv4address(mac_ip_pair[i].ip.addr);
283+
}
284+
285+
mp_obj_list_append(mp_sta_list, namedtuple_make_new((const mp_obj_type_t *)&wifi_radio_station_type, 3, 0, elems));
286+
}
287+
288+
return mp_sta_list;
289+
}
290+
253291
wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, mp_float_t timeout, uint8_t *bssid, size_t bssid_len) {
254292
if (!common_hal_wifi_radio_get_enabled(self)) {
255293
mp_raise_RuntimeError(MP_ERROR_TEXT("wifi is not enabled"));

ports/raspberrypi/common-hal/wifi/Radio.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,51 @@ void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) {
244244
bindings_cyw43_wifi_enforce_pm();
245245
}
246246

247+
// There's no published API for the DHCP server to retrieve lease information
248+
// This code depends on undocumented internal structures and is likely to break in the future
249+
static uint32_t cyw43_dhcps_get_ip_addr(dhcp_server_t *dhcp_server, uint8_t *mac_address) {
250+
for (int i = 0; i < DHCPS_MAX_IP; i++) {
251+
if (memcmp(dhcp_server->lease[i].mac, mac_address, MAC_ADDRESS_LENGTH) == 0) {
252+
return (dhcp_server->ip.addr & 0x00FFFFFF) + ((DHCPS_BASE_IP + i) << 24);
253+
}
254+
}
255+
256+
return 0;
257+
}
258+
259+
mp_obj_t common_hal_wifi_radio_get_stations_ap(wifi_radio_obj_t *self) {
260+
int max_stas;
261+
int num_stas;
262+
263+
if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_AP) != CYW43_LINK_UP) {
264+
return mp_const_none;
265+
}
266+
267+
cyw43_wifi_ap_get_max_stas(&cyw43_state, &max_stas);
268+
269+
uint8_t macs[max_stas * MAC_ADDRESS_LENGTH];
270+
271+
cyw43_wifi_ap_get_stas(&cyw43_state, &num_stas, macs);
272+
273+
mp_obj_t mp_sta_list = mp_obj_new_list(0, NULL);
274+
for (int i = 0; i < num_stas; i++) {
275+
mp_obj_t elems[3] = {
276+
mp_obj_new_bytes(&macs[i * MAC_ADDRESS_LENGTH], MAC_ADDRESS_LENGTH),
277+
mp_const_none,
278+
mp_const_none
279+
};
280+
281+
uint32_t ipv4_addr = cyw43_dhcps_get_ip_addr(&cyw43_state.dhcp_server, &macs[i * MAC_ADDRESS_LENGTH]);
282+
if (ipv4_addr) {
283+
elems[2] = common_hal_ipaddress_new_ipv4address(ipv4_addr);
284+
}
285+
286+
mp_obj_list_append(mp_sta_list, namedtuple_make_new((const mp_obj_type_t *)&wifi_radio_station_type, 3, 0, elems));
287+
}
288+
289+
return mp_sta_list;
290+
}
291+
247292
static bool connection_unchanged(wifi_radio_obj_t *self, const uint8_t *ssid, size_t ssid_len) {
248293
if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) != CYW43_LINK_UP) {
249294
return false;

shared-bindings/wifi/Radio.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,20 @@ STATIC mp_obj_t wifi_radio_get_ap_info(mp_obj_t self) {
661661
}
662662
MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ap_info_obj, wifi_radio_get_ap_info);
663663

664+
//| stations_ap: None
665+
//| """In AP mode, returns list of named tuples, each of which contains:
666+
//| mac: bytearray (read-only)
667+
//| rssi: int (read-only, None on Raspberry Pi Pico W)
668+
//| ipv4_address: ipv4_address (read-only, None if station connected but no address assigned yet or self-assigned address)"""
669+
STATIC mp_obj_t wifi_radio_get_stations_ap(mp_obj_t self) {
670+
return common_hal_wifi_radio_get_stations_ap(self);
671+
}
672+
673+
MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_stations_ap_obj, wifi_radio_get_stations_ap);
674+
675+
MP_PROPERTY_GETTER(wifi_radio_stations_ap_obj,
676+
(mp_obj_t)&wifi_radio_get_stations_ap_obj);
677+
664678
//| def start_dhcp(self) -> None:
665679
//| """Starts the station DHCP client."""
666680
//| ...
@@ -750,6 +764,7 @@ STATIC const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = {
750764
{ MP_ROM_QSTR(MP_QSTR_start_ap), MP_ROM_PTR(&wifi_radio_start_ap_obj) },
751765
{ MP_ROM_QSTR(MP_QSTR_stop_ap), MP_ROM_PTR(&wifi_radio_stop_ap_obj) },
752766
{ MP_ROM_QSTR(MP_QSTR_ap_active), MP_ROM_PTR(&wifi_radio_ap_active_obj) },
767+
{ MP_ROM_QSTR(MP_QSTR_stations_ap), MP_ROM_PTR(&wifi_radio_stations_ap_obj) },
753768

754769
{ MP_ROM_QSTR(MP_QSTR_start_dhcp), MP_ROM_PTR(&wifi_radio_start_dhcp_client_obj) },
755770
{ MP_ROM_QSTR(MP_QSTR_stop_dhcp), MP_ROM_PTR(&wifi_radio_stop_dhcp_client_obj) },
@@ -783,3 +798,13 @@ MP_DEFINE_CONST_OBJ_TYPE(
783798
MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS,
784799
locals_dict, &wifi_radio_locals_dict
785800
);
801+
802+
const mp_obj_namedtuple_type_t wifi_radio_station_type = {
803+
NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_WifiRadioStation),
804+
.n_fields = 3,
805+
.fields = {
806+
MP_QSTR_mac_address,
807+
MP_QSTR_rssi,
808+
MP_QSTR_ipv4_address,
809+
},
810+
};

shared-bindings/wifi/Radio.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@
3232
#include "common-hal/wifi/Radio.h"
3333

3434
#include "py/objstr.h"
35+
#include "py/objnamedtuple.h"
3536

3637
extern const mp_obj_type_t wifi_radio_type;
38+
extern const mp_obj_namedtuple_type_t wifi_radio_station_type;
3739

3840
typedef enum {
3941
// 0 is circuitpython-specific; 1-53 are IEEE; 200+ are Espressif
@@ -96,6 +98,7 @@ extern void common_hal_wifi_radio_stop_station(wifi_radio_obj_t *self);
9698
extern void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, uint32_t authmode, uint8_t max_connections);
9799
extern void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self);
98100
extern bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self);
101+
extern mp_obj_t common_hal_wifi_radio_get_stations_ap(wifi_radio_obj_t *self);
99102

100103
extern void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self);
101104
extern void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self);

shared-bindings/wifi/__init__.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ STATIC const mp_rom_map_elem_t wifi_module_globals_table[] = {
5959
{ MP_ROM_QSTR(MP_QSTR_Network), MP_ROM_PTR(&wifi_network_type) },
6060
{ MP_ROM_QSTR(MP_QSTR_Packet), MP_ROM_PTR(&wifi_packet_type) },
6161
{ MP_ROM_QSTR(MP_QSTR_Radio), MP_ROM_PTR(&wifi_radio_type) },
62+
{ MP_ROM_QSTR(MP_QSTR_Station), MP_ROM_PTR(&wifi_radio_station_type) },
6263

6364
// Properties
6465
{ MP_ROM_QSTR(MP_QSTR_radio), MP_ROM_PTR(&common_hal_wifi_radio_obj) },

0 commit comments

Comments
 (0)
0