From 5c429320a8a2f7219e0f2c80689f3dbff4b84cab Mon Sep 17 00:00:00 2001
From: Dan Halbert <halbert@halwitz.org>
Date: Mon, 26 Dec 2022 12:28:44 -0500
Subject: [PATCH 1/2] Add wifi.radio.connected, wifi.radio.ap_active

---
 ports/espressif/common-hal/wifi/Radio.c   |  8 ++++
 ports/raspberrypi/common-hal/wifi/Radio.c |  8 ++++
 shared-bindings/wifi/Radio.c              | 47 ++++++++++++++---------
 shared-bindings/wifi/Radio.h              |  2 +
 4 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c
index acd6ae53bc..4ca3bf1a6c 100644
--- a/ports/espressif/common-hal/wifi/Radio.c
+++ b/ports/espressif/common-hal/wifi/Radio.c
@@ -242,6 +242,10 @@ void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_
     esp_wifi_set_config(WIFI_IF_AP, config);
 }
 
+bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self) {
+    return self->ap_mode;
+}
+
 void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) {
     set_mode_ap(self, false);
 }
@@ -347,6 +351,10 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t
     return WIFI_RADIO_ERROR_NONE;
 }
 
+bool common_hal_wifi_radio_get_connected(wifi_radio_obj_t *self) {
+    return self->sta_mode && esp_netif_is_netif_up(self->netif);
+}
+
 mp_obj_t common_hal_wifi_radio_get_ap_info(wifi_radio_obj_t *self) {
     if (!esp_netif_is_netif_up(self->netif)) {
         return mp_const_none;
diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c
index 2ed19a96e7..0ef4f8bb76 100644
--- a/ports/raspberrypi/common-hal/wifi/Radio.c
+++ b/ports/raspberrypi/common-hal/wifi/Radio.c
@@ -186,6 +186,10 @@ void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_
     bindings_cyw43_wifi_enforce_pm();
 }
 
+bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self) {
+    return cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_AP) == CYW43_LINK_UP;
+}
+
 void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) {
     if (!common_hal_wifi_radio_get_enabled(self)) {
         mp_raise_RuntimeError(translate("wifi is not enabled"));
@@ -275,6 +279,10 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t
     return WIFI_RADIO_ERROR_UNSPECIFIED;
 }
 
+bool common_hal_wifi_radio_get_connected(wifi_radio_obj_t *self) {
+    return cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_UP;
+}
+
 mp_obj_t common_hal_wifi_radio_get_ap_info(wifi_radio_obj_t *self) {
     mp_raise_NotImplementedError(NULL);
 }
diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c
index fc3cc345b8..9475ee3b31 100644
--- a/shared-bindings/wifi/Radio.c
+++ b/shared-bindings/wifi/Radio.c
@@ -310,7 +310,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_station_obj, wifi_radio_stop_station);
 //|         authmode: Optional[AuthMode] = None,
 //|         max_connections: Optional[int] = 4
 //|     ) -> None:
-//|         """Starts an Access Point with the specified ssid and password.
+//|         """Starts running an access point with the specified ssid and password.
 //|
 //|         If ``channel`` is given, the access point will use that channel unless
 //|         a station is already operating on a different channel.
@@ -376,7 +376,7 @@ STATIC mp_obj_t wifi_radio_start_ap(size_t n_args, const mp_obj_t *pos_args, mp_
 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_start_ap_obj, 1, wifi_radio_start_ap);
 
 //|     def stop_ap(self) -> None:
-//|         """Stops the Access Point."""
+//|         """Stops the access point."""
 //|         ...
 STATIC mp_obj_t wifi_radio_stop_ap(mp_obj_t self) {
     common_hal_wifi_radio_stop_ap(self);
@@ -384,6 +384,16 @@ STATIC mp_obj_t wifi_radio_stop_ap(mp_obj_t self) {
 }
 MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_ap_obj, wifi_radio_stop_ap);
 
+//|     ap_active: bool
+//|     """True if running as an access point. (read-only)"""
+STATIC mp_obj_t wifi_radio_get_ap_active(mp_obj_t self) {
+    return mp_obj_new_bool(common_hal_wifi_radio_get_ap_active(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ap_active_obj, wifi_radio_get_ap_active);
+
+MP_PROPERTY_GETTER(wifi_radio_ap_active_obj,
+    (mp_obj_t)&wifi_radio_get_ap_active_obj);
+
 //|     def connect(
 //|         self,
 //|         ssid: Union[str | ReadableBuffer],
@@ -464,11 +474,20 @@ STATIC mp_obj_t wifi_radio_connect(size_t n_args, const mp_obj_t *pos_args, mp_m
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_connect_obj, 1, wifi_radio_connect);
 
+//|     connected: bool
+//|     """True if connected to an access point (read-only)."""
+STATIC mp_obj_t wifi_radio_get_connected(mp_obj_t self) {
+    return mp_obj_new_bool(common_hal_wifi_radio_get_connected(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_connected_obj, wifi_radio_get_connected);
+
+MP_PROPERTY_GETTER(wifi_radio_connected_obj,
+    (mp_obj_t)&wifi_radio_get_connected_obj);
+
 //|     ipv4_gateway: Optional[ipaddress.IPv4Address]
-//|     """IP v4 Address of the station gateway when connected to an access point. None otherwise."""
+//|     """IP v4 Address of the station gateway when connected to an access point. None otherwise. (read-only)"""
 STATIC mp_obj_t wifi_radio_get_ipv4_gateway(mp_obj_t self) {
     return common_hal_wifi_radio_get_ipv4_gateway(self);
-
 }
 MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_gateway_obj, wifi_radio_get_ipv4_gateway);
 
@@ -476,10 +495,9 @@ MP_PROPERTY_GETTER(wifi_radio_ipv4_gateway_obj,
     (mp_obj_t)&wifi_radio_get_ipv4_gateway_obj);
 
 //|     ipv4_gateway_ap: Optional[ipaddress.IPv4Address]
-//|     """IP v4 Address of the access point gateway, when enabled. None otherwise."""
+//|     """IP v4 Address of the access point gateway, when enabled. None otherwise. (read-only)"""
 STATIC mp_obj_t wifi_radio_get_ipv4_gateway_ap(mp_obj_t self) {
     return common_hal_wifi_radio_get_ipv4_gateway_ap(self);
-
 }
 MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_gateway_ap_obj, wifi_radio_get_ipv4_gateway_ap);
 
@@ -487,10 +505,9 @@ MP_PROPERTY_GETTER(wifi_radio_ipv4_gateway_ap_obj,
     (mp_obj_t)&wifi_radio_get_ipv4_gateway_ap_obj);
 
 //|     ipv4_subnet: Optional[ipaddress.IPv4Address]
-//|     """IP v4 Address of the station subnet when connected to an access point. None otherwise."""
+//|     """IP v4 Address of the station subnet when connected to an access point. None otherwise. (read-only)"""
 STATIC mp_obj_t wifi_radio_get_ipv4_subnet(mp_obj_t self) {
     return common_hal_wifi_radio_get_ipv4_subnet(self);
-
 }
 MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_subnet_obj, wifi_radio_get_ipv4_subnet);
 
@@ -498,10 +515,9 @@ MP_PROPERTY_GETTER(wifi_radio_ipv4_subnet_obj,
     (mp_obj_t)&wifi_radio_get_ipv4_subnet_obj);
 
 //|     ipv4_subnet_ap: Optional[ipaddress.IPv4Address]
-//|     """IP v4 Address of the access point subnet, when enabled. None otherwise."""
+//|     """IP v4 Address of the access point subnet, when enabled. None otherwise. (read-only)"""
 STATIC mp_obj_t wifi_radio_get_ipv4_subnet_ap(mp_obj_t self) {
     return common_hal_wifi_radio_get_ipv4_subnet_ap(self);
-
 }
 MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_subnet_ap_obj, wifi_radio_get_ipv4_subnet_ap);
 
@@ -538,10 +554,9 @@ STATIC mp_obj_t wifi_radio_set_ipv4_address(size_t n_args, const mp_obj_t *pos_a
 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_set_ipv4_address_obj, 1, wifi_radio_set_ipv4_address);
 
 //|     ipv4_address: Optional[ipaddress.IPv4Address]
-//|     """IP v4 Address of the station when connected to an access point. None otherwise."""
+//|     """IP v4 Address of the station when connected to an access point. None otherwise. (read-only)"""
 STATIC mp_obj_t _wifi_radio_get_ipv4_address(mp_obj_t self) {
     return common_hal_wifi_radio_get_ipv4_address(self);
-
 }
 MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_address_obj, _wifi_radio_get_ipv4_address);
 
@@ -552,7 +567,6 @@ MP_PROPERTY_GETTER(wifi_radio_ipv4_address_obj,
 //|     """IP v4 Address of the access point, when enabled. None otherwise."""
 STATIC mp_obj_t wifi_radio_get_ipv4_address_ap(mp_obj_t self) {
     return common_hal_wifi_radio_get_ipv4_address_ap(self);
-
 }
 MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_address_ap_obj, wifi_radio_get_ipv4_address_ap);
 
@@ -563,7 +577,6 @@ MP_PROPERTY_GETTER(wifi_radio_ipv4_address_ap_obj,
 //|     """IP v4 Address of the DNS server to be used."""
 STATIC mp_obj_t wifi_radio_get_ipv4_dns(mp_obj_t self) {
     return common_hal_wifi_radio_get_ipv4_dns(self);
-
 }
 MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_dns_obj, wifi_radio_get_ipv4_dns);
 
@@ -582,7 +595,6 @@ MP_PROPERTY_GETSET(wifi_radio_ipv4_dns_obj,
 //|     """Network object containing BSSID, SSID, authmode, channel, country and RSSI when connected to an access point. None otherwise."""
 STATIC mp_obj_t wifi_radio_get_ap_info(mp_obj_t self) {
     return common_hal_wifi_radio_get_ap_info(self);
-
 }
 MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ap_info_obj, wifi_radio_get_ap_info);
 
@@ -656,12 +668,14 @@ STATIC const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = {
 
     { MP_ROM_QSTR(MP_QSTR_start_ap),    MP_ROM_PTR(&wifi_radio_start_ap_obj) },
     { MP_ROM_QSTR(MP_QSTR_stop_ap),    MP_ROM_PTR(&wifi_radio_stop_ap_obj) },
+    { MP_ROM_QSTR(MP_QSTR_ap_active),   MP_ROM_PTR(&wifi_radio_ap_active_obj) },
 
     { MP_ROM_QSTR(MP_QSTR_start_dhcp),    MP_ROM_PTR(&wifi_radio_start_dhcp_client_obj) },
     { MP_ROM_QSTR(MP_QSTR_stop_dhcp),    MP_ROM_PTR(&wifi_radio_stop_dhcp_client_obj) },
 
     { MP_ROM_QSTR(MP_QSTR_connect),    MP_ROM_PTR(&wifi_radio_connect_obj) },
     // { MP_ROM_QSTR(MP_QSTR_connect_to_enterprise),    MP_ROM_PTR(&wifi_radio_connect_to_enterprise_obj) },
+    { MP_ROM_QSTR(MP_QSTR_connected),    MP_ROM_PTR(&wifi_radio_connected_obj) },
 
     { MP_ROM_QSTR(MP_QSTR_ap_info),    MP_ROM_PTR(&wifi_radio_ap_info_obj) },
     { MP_ROM_QSTR(MP_QSTR_ipv4_dns),    MP_ROM_PTR(&wifi_radio_ipv4_dns_obj) },
@@ -674,9 +688,6 @@ STATIC const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = {
 
     { MP_ROM_QSTR(MP_QSTR_set_ipv4_address),    MP_ROM_PTR(&wifi_radio_set_ipv4_address_obj) },
 
-    // { MP_ROM_QSTR(MP_QSTR_access_point_active),   MP_ROM_PTR(&wifi_radio_access_point_active_obj) },
-    // { MP_ROM_QSTR(MP_QSTR_start_access_point), MP_ROM_PTR(&wifi_radio_start_access_point_obj) },
-
     { MP_ROM_QSTR(MP_QSTR_ping), MP_ROM_PTR(&wifi_radio_ping_obj) },
 };
 
diff --git a/shared-bindings/wifi/Radio.h b/shared-bindings/wifi/Radio.h
index dbaeb9cce8..1fb70ef818 100644
--- a/shared-bindings/wifi/Radio.h
+++ b/shared-bindings/wifi/Radio.h
@@ -95,11 +95,13 @@ extern void common_hal_wifi_radio_stop_station(wifi_radio_obj_t *self);
 
 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 authmodes, uint8_t max_connections);
 extern void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self);
+extern bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self);
 
 extern void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self);
 extern void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self);
 
 extern 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);
+extern bool common_hal_wifi_radio_get_connected(wifi_radio_obj_t *self);
 
 extern mp_obj_t common_hal_wifi_radio_get_ap_info(wifi_radio_obj_t *self);
 extern mp_obj_t common_hal_wifi_radio_get_ipv4_dns(wifi_radio_obj_t *self);

From 0aacb146efd6a9618fda692096b62cf4911a0c29 Mon Sep 17 00:00:00 2001
From: Dan Halbert <halbert@halwitz.org>
Date: Fri, 31 Mar 2023 22:27:21 -0400
Subject: [PATCH 2/2] take wifi.radio.enabled into account

---
 ports/espressif/common-hal/wifi/Radio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c
index 4ca3bf1a6c..0ce535899a 100644
--- a/ports/espressif/common-hal/wifi/Radio.c
+++ b/ports/espressif/common-hal/wifi/Radio.c
@@ -243,7 +243,7 @@ void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_
 }
 
 bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self) {
-    return self->ap_mode;
+    return self->ap_mode && esp_netif_is_netif_up(self->ap_netif);
 }
 
 void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) {