diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index 8ee1c80926..6451cb1414 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -398,6 +398,35 @@ mp_obj_t common_hal_wifi_radio_get_ipv4_dns(wifi_radio_obj_t *self) { return common_hal_ipaddress_new_ipv4address(self->dns_info.ip.u_addr.ip4.addr); } +void common_hal_wifi_radio_set_ipv4_dns(wifi_radio_obj_t *self, mp_obj_t ipv4_dns_addr) { + esp_netif_dns_info_t dns_addr; + ipaddress_ipaddress_to_esp_idf_ip4(ipv4_dns_addr, &dns_addr.ip.u_addr.ip4); + esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_addr); +} + +void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self) { + esp_netif_dhcpc_start(self->netif); +} + +void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self) { + esp_netif_dhcpc_stop(self->netif); +} + +void common_hal_wifi_radio_set_ipv4_address(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway, mp_obj_t ipv4_dns) { + common_hal_wifi_radio_stop_dhcp_client(self); // Must stop DHCP to set a manual address + + esp_netif_ip_info_t ip_info; + ipaddress_ipaddress_to_esp_idf_ip4(ipv4, &ip_info.ip); + ipaddress_ipaddress_to_esp_idf_ip4(netmask, &ip_info.netmask); + ipaddress_ipaddress_to_esp_idf_ip4(gateway, &ip_info.gw); + + esp_netif_set_ip_info(self->netif, &ip_info); + + if (ipv4_dns != MP_OBJ_NULL) { + common_hal_wifi_radio_set_ipv4_dns(self, ipv4_dns); + } +} + mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address, mp_float_t timeout) { esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG(); ipaddress_ipaddress_to_esp_idf(ip_address, &ping_config.target_addr); diff --git a/ports/espressif/common-hal/wifi/__init__.c b/ports/espressif/common-hal/wifi/__init__.c index cb9b028aba..36cf27a69f 100644 --- a/ports/espressif/common-hal/wifi/__init__.c +++ b/ports/espressif/common-hal/wifi/__init__.c @@ -189,6 +189,16 @@ void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_addre IP_ADDR4(esp_ip_address, bytes[0], bytes[1], bytes[2], bytes[3]); } +void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address) { + if (!mp_obj_is_type(ip_address, &ipaddress_ipv4address_type)) { + mp_raise_ValueError(translate("Only IPv4 addresses supported")); + } + mp_obj_t packed = common_hal_ipaddress_ipv4address_get_packed(ip_address); + size_t len; + const char *bytes = mp_obj_str_get_data(packed, &len); + esp_netif_set_ip4_addr(esp_ip_address, bytes[0], bytes[1], bytes[2], bytes[3]); +} + void common_hal_wifi_gc_collect(void) { common_hal_wifi_radio_gc_collect(&common_hal_wifi_radio_obj); } diff --git a/ports/espressif/common-hal/wifi/__init__.h b/ports/espressif/common-hal/wifi/__init__.h index be91dca758..4258f1643f 100644 --- a/ports/espressif/common-hal/wifi/__init__.h +++ b/ports/espressif/common-hal/wifi/__init__.h @@ -30,9 +30,11 @@ #include "py/obj.h" #include "lwip/api.h" +#include "components/esp_wifi/include/esp_wifi.h" void wifi_reset(void); void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address); +void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address); #endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_WIFI___INIT___H diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index e79d7047b3..cb5090d0f4 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -414,6 +414,28 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_subnet_ap_obj, wifi_radio_get_ipv4 MP_PROPERTY_GETTER(wifi_radio_ipv4_subnet_ap_obj, (mp_obj_t)&wifi_radio_get_ipv4_subnet_ap_obj); +//| def set_ipv4_address(self, *, ipv4: ipaddress.IPv4Address, netmask: ipaddress.IPv4Address, gateway: ipaddress.IPv4Address, ipv4_dns: Optional[ipaddress.IPv4Address]) -> None: +//| """Sets the IP v4 address of the station. Must include the netmask and gateway. DNS address is optional. +//| Setting the address manually will stop the DHCP client.""" +//| ... +STATIC mp_obj_t wifi_radio_set_ipv4_address(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_ipv4, ARG_netmask, ARG_gateway, ARG_ipv4_dns }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_ipv4, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, }, + { MP_QSTR_netmask, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, }, + { MP_QSTR_gateway, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, }, + { MP_QSTR_ipv4_dns, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + }; + + wifi_radio_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + common_hal_wifi_radio_set_ipv4_address(self, args[ARG_ipv4].u_obj, args[ARG_netmask].u_obj, args[ARG_gateway].u_obj, args[ARG_ipv4_dns].u_obj); + return mp_const_none; +} +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.""" //| @@ -438,8 +460,8 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_address_ap_obj, wifi_radio_get_ipv MP_PROPERTY_GETTER(wifi_radio_ipv4_address_ap_obj, (mp_obj_t)&wifi_radio_get_ipv4_address_ap_obj); -//| ipv4_dns: Optional[ipaddress.IPv4Address] -//| """IP v4 Address of the DNS server in use when connected to an access point. None otherwise.""" +//| ipv4_dns: ipaddress.IPv4Address +//| """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); @@ -447,8 +469,16 @@ STATIC mp_obj_t wifi_radio_get_ipv4_dns(mp_obj_t self) { } MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_dns_obj, wifi_radio_get_ipv4_dns); -MP_PROPERTY_GETTER(wifi_radio_ipv4_dns_obj, - (mp_obj_t)&wifi_radio_get_ipv4_dns_obj); +STATIC mp_obj_t wifi_radio_set_ipv4_dns(mp_obj_t self, mp_obj_t ipv4_dns_addr) { + common_hal_wifi_radio_set_ipv4_dns(self, ipv4_dns_addr); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(wifi_radio_set_ipv4_dns_obj, wifi_radio_set_ipv4_dns); + +MP_PROPERTY_GETSET(wifi_radio_ipv4_dns_obj, + (mp_obj_t)&wifi_radio_get_ipv4_dns_obj, + (mp_obj_t)&wifi_radio_set_ipv4_dns_obj); //| ap_info: Optional[Network] //| """Network object containing BSSID, SSID, authmode, channel, country and RSSI when connected to an access point. None otherwise.""" @@ -459,6 +489,26 @@ STATIC mp_obj_t wifi_radio_get_ap_info(mp_obj_t self) { } MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ap_info_obj, wifi_radio_get_ap_info); +//| def start_dhcp(self) -> None: +//| """Starts the DHCP client.""" +//| ... +//| +STATIC mp_obj_t wifi_radio_start_dhcp_client(mp_obj_t self) { + common_hal_wifi_radio_start_dhcp_client(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_start_dhcp_client_obj, wifi_radio_start_dhcp_client); + +//| def stop_dhcp(self) -> None: +//| """Stops the DHCP client. Needed to assign a static IP address.""" +//| ... +//| +STATIC mp_obj_t wifi_radio_stop_dhcp_client(mp_obj_t self) { + common_hal_wifi_radio_stop_dhcp_client(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_dhcp_client_obj, wifi_radio_stop_dhcp_client); + MP_PROPERTY_GETTER(wifi_radio_ap_info_obj, (mp_obj_t)&wifi_radio_get_ap_info_obj); @@ -509,6 +559,9 @@ 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_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) }, @@ -521,6 +574,8 @@ STATIC const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ipv4_address), MP_ROM_PTR(&wifi_radio_ipv4_address_obj) }, { MP_ROM_QSTR(MP_QSTR_ipv4_address_ap), MP_ROM_PTR(&wifi_radio_ipv4_address_ap_obj) }, + { 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) }, diff --git a/shared-bindings/wifi/Radio.h b/shared-bindings/wifi/Radio.h index cee9f6ef15..09a66b2e63 100644 --- a/shared-bindings/wifi/Radio.h +++ b/shared-bindings/wifi/Radio.h @@ -91,10 +91,14 @@ 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, uint8_t authmode, uint8_t max_connections); extern void common_hal_wifi_radio_stop_ap(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 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); +extern void common_hal_wifi_radio_set_ipv4_dns(wifi_radio_obj_t *self, mp_obj_t ipv4_dns_addr); extern mp_obj_t common_hal_wifi_radio_get_ipv4_gateway(wifi_radio_obj_t *self); extern mp_obj_t common_hal_wifi_radio_get_ipv4_gateway_ap(wifi_radio_obj_t *self); extern mp_obj_t common_hal_wifi_radio_get_ipv4_subnet(wifi_radio_obj_t *self); @@ -102,6 +106,8 @@ extern mp_obj_t common_hal_wifi_radio_get_ipv4_subnet_ap(wifi_radio_obj_t *self) extern mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self); extern mp_obj_t common_hal_wifi_radio_get_ipv4_address_ap(wifi_radio_obj_t *self); +extern void common_hal_wifi_radio_set_ipv4_address(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway, mp_obj_t ipv4_dns_addr); + extern mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address, mp_float_t timeout); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_WIFI_RADIO_H