From c62ab6e09a4dda33b75bcb0ee5fed800b756e564 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 5 Aug 2020 12:53:35 -0700 Subject: [PATCH] Add ipaddress --- ports/esp32s2/common-hal/wifi/Network.c | 15 +- ports/esp32s2/common-hal/wifi/Radio.c | 51 ++++- ports/esp32s2/common-hal/wifi/Radio.h | 2 + .../esp32s2/common-hal/wifi/ScannedNetworks.c | 7 +- ports/esp32s2/common-hal/wifi/__init__.c | 40 +++- py/circuitpy_defns.mk | 5 + py/circuitpy_mpconfig.h | 7 + py/circuitpy_mpconfig.mk | 3 + shared-bindings/ipaddress/IPv4Address.c | 180 ++++++++++++++++++ shared-bindings/ipaddress/IPv4Address.h | 38 ++++ shared-bindings/ipaddress/__init__.c | 65 +++++++ shared-bindings/ipaddress/__init__.h | 34 ++++ shared-bindings/wifi/Network.c | 39 +++- shared-bindings/wifi/Network.h | 2 + shared-bindings/wifi/Radio.c | 28 +-- shared-bindings/wifi/Radio.h | 4 +- shared-module/ipaddress/IPv4Address.c | 39 ++++ shared-module/ipaddress/IPv4Address.h | 37 ++++ shared-module/ipaddress/__init__.c | 35 ++++ shared-module/ipaddress/__init__.h | 36 ++++ 20 files changed, 634 insertions(+), 33 deletions(-) create mode 100644 shared-bindings/ipaddress/IPv4Address.c create mode 100644 shared-bindings/ipaddress/IPv4Address.h create mode 100644 shared-bindings/ipaddress/__init__.c create mode 100644 shared-bindings/ipaddress/__init__.h create mode 100644 shared-module/ipaddress/IPv4Address.c create mode 100644 shared-module/ipaddress/IPv4Address.h create mode 100644 shared-module/ipaddress/__init__.c create mode 100644 shared-module/ipaddress/__init__.h diff --git a/ports/esp32s2/common-hal/wifi/Network.c b/ports/esp32s2/common-hal/wifi/Network.c index a270fd9dcc..0320e8f92f 100644 --- a/ports/esp32s2/common-hal/wifi/Network.c +++ b/ports/esp32s2/common-hal/wifi/Network.c @@ -26,6 +26,19 @@ #include "shared-bindings/wifi/Network.h" +#include + +#include "py/obj.h" + mp_obj_t common_hal_wifi_network_get_ssid(wifi_network_obj_t *self) { - return mp_const_none; + const char* cstr = (const char*) self->record.ssid; + return mp_obj_new_str(cstr, strlen(cstr)); +} + +mp_obj_t common_hal_wifi_network_get_rssi(wifi_network_obj_t *self) { + return mp_obj_new_int(self->record.rssi); +} + +mp_obj_t common_hal_wifi_network_get_channel(wifi_network_obj_t *self) { + return mp_obj_new_int(self->record.primary); } diff --git a/ports/esp32s2/common-hal/wifi/Radio.c b/ports/esp32s2/common-hal/wifi/Radio.c index a2944dd52c..623ba9e345 100644 --- a/ports/esp32s2/common-hal/wifi/Radio.c +++ b/ports/esp32s2/common-hal/wifi/Radio.c @@ -26,7 +26,11 @@ #include "shared-bindings/wifi/Radio.h" +#include + +#include "lib/utils/interrupt_char.h" #include "py/runtime.h" +#include "shared-bindings/ipaddress/IPv4Address.h" #include "shared-bindings/wifi/ScannedNetworks.h" #include "esp-idf/components/esp_wifi/include/esp_wifi.h" @@ -103,16 +107,51 @@ void common_hal_wifi_radio_stop_scanning_networks(wifi_radio_obj_t *self) { ESP_EARLY_LOGI(TAG, "stop scan done"); } -bool common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t* ssid, size_t ssid_len, uint8_t* password, size_t password_len, mp_float_t timeout) { +bool 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) { // check enabled - wifi_config_t config; - esp_err_t result = esp_wifi_set_config(ESP_IF_WIFI_STA, &config); + wifi_config_t* config = &self->sta_config; + memcpy(&config->sta.ssid, ssid, ssid_len); + config->sta.ssid[ssid_len] = 0; + if (password_len > 0) { + memcpy(&config->sta.password, password, password_len); + } + config->sta.password[password_len] = 0; + config->sta.channel = channel; + ESP_EARLY_LOGI(TAG, "connecting to %s", config->sta.ssid); + esp_err_t result = esp_wifi_set_config(ESP_IF_WIFI_STA, config); + if (result != ESP_OK) { + ESP_EARLY_LOGI(TAG, "config fail %d", result); + } result = esp_wifi_connect(); - return result == ESP_OK; + if (result != ESP_OK) { + ESP_EARLY_LOGI(TAG, "connect fail %d", result); + } + + EventBits_t bits; + do { + RUN_BACKGROUND_TASKS; + bits = xEventGroupWaitBits(self->event_group_handle, + WIFI_CONNECTED_BIT | WIFI_DISCONNECTED_BIT, + pdTRUE, + pdTRUE, + 0); + } while ((bits & (WIFI_CONNECTED_BIT | WIFI_DISCONNECTED_BIT)) == 0 && !mp_hal_is_interrupted()); + if ((bits & WIFI_DISCONNECTED_BIT) != 0) { + return false; + } + return true; } -mp_obj_t common_hal_wifi_radio_get_ip_address(wifi_radio_obj_t *self) { - return mp_const_none; +mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) { + if (!esp_netif_is_netif_up(self->netif)) { + return mp_const_none; + } + esp_netif_ip_info_t ip_info; + esp_err_t result = esp_netif_get_ip_info(self->netif, &ip_info); + if (result != ESP_OK) { + ESP_EARLY_LOGI(TAG, "get ip fail %d", result); + } + return common_hal_ipaddress_new_ipv4address(ip_info.ip.addr); } mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address) { diff --git a/ports/esp32s2/common-hal/wifi/Radio.h b/ports/esp32s2/common-hal/wifi/Radio.h index 11b30799ac..e7dce94776 100644 --- a/ports/esp32s2/common-hal/wifi/Radio.h +++ b/ports/esp32s2/common-hal/wifi/Radio.h @@ -35,6 +35,8 @@ // Event bits for the Radio event group. #define WIFI_SCAN_DONE_BIT BIT0 +#define WIFI_CONNECTED_BIT BIT1 +#define WIFI_DISCONNECTED_BIT BIT2 typedef struct { mp_obj_base_t base; diff --git a/ports/esp32s2/common-hal/wifi/ScannedNetworks.c b/ports/esp32s2/common-hal/wifi/ScannedNetworks.c index 248defa574..060e13f8ea 100644 --- a/ports/esp32s2/common-hal/wifi/ScannedNetworks.c +++ b/ports/esp32s2/common-hal/wifi/ScannedNetworks.c @@ -29,6 +29,7 @@ #include #include "lib/utils/interrupt_char.h" +#include "py/gc.h" #include "py/objstr.h" #include "py/runtime.h" #include "shared-bindings/wifi/__init__.h" @@ -45,7 +46,10 @@ static void wifi_scannednetworks_done(wifi_scannednetworks_obj_t *self) { self->done = true; ESP_EARLY_LOGI(TAG, "free %x", self->results); if (self->results != NULL) { - m_free(self->results); + // Check to see if the heap is still active. If not, it'll be freed automatically. + if (gc_alloc_possible()) { + m_free(self->results); + } self->results = NULL; } } @@ -137,7 +141,6 @@ mp_obj_t common_hal_wifi_scannednetworks_next(wifi_scannednetworks_obj_t *self) static uint8_t scan_pattern[] = {6, 1, 11, 3, 9, 13, 2, 4, 8, 12, 5, 7, 10, 14}; void wifi_scannednetworks_scan_next_channel(wifi_scannednetworks_obj_t *self) { - uint8_t next_channel = sizeof(scan_pattern); while (self->current_channel_index < sizeof(scan_pattern)) { next_channel = scan_pattern[self->current_channel_index]; diff --git a/ports/esp32s2/common-hal/wifi/__init__.c b/ports/esp32s2/common-hal/wifi/__init__.c index d4a1d9892e..1dc9ef9a89 100644 --- a/ports/esp32s2/common-hal/wifi/__init__.c +++ b/ports/esp32s2/common-hal/wifi/__init__.c @@ -41,9 +41,32 @@ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { ESP_LOGI(TAG, "event %x", event_id); wifi_radio_obj_t* radio = arg; - if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_SCAN_DONE) { - xEventGroupSetBits(radio->event_group_handle, WIFI_SCAN_DONE_BIT); + if (event_base == WIFI_EVENT) { + if (event_id == WIFI_EVENT_SCAN_DONE) { + ESP_LOGI(TAG, "scan done"); + xEventGroupSetBits(radio->event_group_handle, WIFI_SCAN_DONE_BIT); + } else if (event_id == WIFI_EVENT_STA_START) { + ESP_LOGI(TAG, "station start"); + + } else if (event_id == WIFI_EVENT_STA_STOP) { + ESP_LOGI(TAG, "station stop"); + + } else if (event_id == WIFI_EVENT_STA_CONNECTED) { + ESP_LOGI(TAG, "connected to ap"); + } else if (event_id == WIFI_EVENT_STA_DISCONNECTED) { + ESP_LOGI(TAG, "disconnected"); + wifi_event_sta_disconnected_t* d = (wifi_event_sta_disconnected_t*) event_data; + ESP_LOGI(TAG, "reason %d", d->reason); + if (event_id != WIFI_REASON_ASSOC_LEAVE) { + // reconnect + } + xEventGroupSetBits(radio->event_group_handle, WIFI_DISCONNECTED_BIT); + } else if (event_id == WIFI_EVENT_STA_AUTHMODE_CHANGE) { + ESP_LOGI(TAG, "auth change"); + + } } + // esp_wifi_connect(); // if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { // esp_wifi_connect(); @@ -56,12 +79,13 @@ static void event_handler(void* arg, esp_event_base_t event_base, // xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); // } // ESP_LOGI(TAG,"connect to the AP fail"); - // } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { - // ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; - // ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); - // s_retry_num = 0; - // xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); - // } + // } else + if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); + // s_retry_num = 0; + xEventGroupSetBits(radio->event_group_handle, WIFI_CONNECTED_BIT); + } } static bool wifi_inited; diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index caf65d27ef..1a5145c8ba 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -168,6 +168,9 @@ endif ifeq ($(CIRCUITPY_I2CPERIPHERAL),1) SRC_PATTERNS += i2cperipheral/% endif +ifeq ($(CIRCUITPY_IPADDRESS),1) +SRC_PATTERNS += ipaddress/% +endif ifeq ($(CIRCUITPY_MATH),1) SRC_PATTERNS += math/% endif @@ -408,6 +411,8 @@ SRC_SHARED_MODULE_ALL = \ fontio/__init__.c \ framebufferio/FramebufferDisplay.c \ framebufferio/__init__.c \ + ipaddress/IPv4Address.c \ + ipaddress/__init__.c \ sdcardio/SDCard.c \ sdcardio/__init__.c \ gamepad/GamePad.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 2db20ca1d1..8ff2ddc67d 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -420,6 +420,13 @@ extern const struct _mp_obj_module_t i2cperipheral_module; #define I2CPERIPHERAL_MODULE #endif +#if CIRCUITPY_IPADDRESS +extern const struct _mp_obj_module_t ipaddress_module; +#define IPADDRESS_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_ipaddress), (mp_obj_t)&ipaddress_module }, +#else +#define IPADDRESS_MODULE +#endif + #if CIRCUITPY_MATH extern const struct _mp_obj_module_t math_module; #define MATH_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index abbd5a9a0b..499e87aed0 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -120,6 +120,9 @@ CFLAGS += -DCIRCUITPY_GNSS=$(CIRCUITPY_GNSS) CIRCUITPY_I2CPERIPHERAL ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_I2CPERIPHERAL=$(CIRCUITPY_I2CPERIPHERAL) +CIRCUITPY_IPADDRESS ?= $(CIRCUITPY_WIFI) +CFLAGS += -DCIRCUITPY_IPADDRESS=$(CIRCUITPY_IPADDRESS) + CIRCUITPY_MATH ?= 1 CFLAGS += -DCIRCUITPY_MATH=$(CIRCUITPY_MATH) diff --git a/shared-bindings/ipaddress/IPv4Address.c b/shared-bindings/ipaddress/IPv4Address.c new file mode 100644 index 0000000000..3cef7516df --- /dev/null +++ b/shared-bindings/ipaddress/IPv4Address.c @@ -0,0 +1,180 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "py/objproperty.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/ipaddress/IPv4Address.h" + +//| class IPv4Address: +//| """Encapsulates an IPv4 address.""" +//| + +//| def __init__(self, address: Union[str, int]) -> None: +//| """Create a new Address object encapsulating the address value. +//| +//| The value itself can be one of:""" +//| ... +//| +STATIC mp_obj_t ipaddress_ipv4address_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_address }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_address, MP_ARG_OBJ | MP_ARG_REQUIRED }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + ipaddress_ipv4address_obj_t *self = m_new_obj(ipaddress_ipv4address_obj_t); + self->base.type = &ipaddress_ipv4address_type; + + const mp_obj_t address = args[ARG_address].u_obj; + mp_buffer_info_t buf_info; + mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ); + if (buf_info.len != 4) { + mp_raise_ValueError_varg(translate("Address must be %d bytes long"), 4); + } + + common_hal_ipaddress_ipv4address_construct(self, buf_info.buf, buf_info.len); + + return MP_OBJ_FROM_PTR(self); +} + +//| packed: bytes +//| """The bytes that make up the address (read-only).""" +//| +STATIC mp_obj_t ipaddress_ipv4address_get_packed(mp_obj_t self_in) { + ipaddress_ipv4address_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return common_hal_ipaddress_ipv4address_get_packed(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(ipaddress_ipv4address_get_packed_obj, ipaddress_ipv4address_get_packed); + +const mp_obj_property_t ipaddress_ipv4address_packed_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&ipaddress_ipv4address_get_packed_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| version: int +//| """4 for IPv4, 6 for IPv6""" +//| +STATIC mp_obj_t ipaddress_ipv4address_get_version(mp_obj_t self_in) { + ipaddress_ipv4address_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_buffer_info_t buf_info; + mp_obj_t address_bytes = common_hal_ipaddress_ipv4address_get_packed(self); + mp_get_buffer_raise(address_bytes, &buf_info, MP_BUFFER_READ); + mp_int_t version = 6; + if (buf_info.len == 4) { + version = 4; + } + + return MP_OBJ_NEW_SMALL_INT(version); +} +MP_DEFINE_CONST_FUN_OBJ_1(ipaddress_ipv4address_get_version_obj, ipaddress_ipv4address_get_version); + +const mp_obj_property_t ipaddress_ipv4address_version_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&ipaddress_ipv4address_get_version_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| def __eq__(self, other: Address) -> bool: +//| """Two Address objects are equal if their addresses and address types are equal.""" +//| ... +//| +STATIC mp_obj_t ipaddress_ipv4address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + switch (op) { + // Two Addresses are equal if their address bytes and address_type are equal + case MP_BINARY_OP_EQUAL: + if (MP_OBJ_IS_TYPE(rhs_in, &ipaddress_ipv4address_type)) { + ipaddress_ipv4address_obj_t *lhs = MP_OBJ_TO_PTR(lhs_in); + ipaddress_ipv4address_obj_t *rhs = MP_OBJ_TO_PTR(rhs_in); + return mp_obj_new_bool( + mp_obj_equal(common_hal_ipaddress_ipv4address_get_packed(lhs), + common_hal_ipaddress_ipv4address_get_packed(rhs))); + + } else { + return mp_const_false; + } + + default: + return MP_OBJ_NULL; // op not supported + } +} + +//| def __hash__(self) -> int: +//| """Returns a hash for the Address data.""" +//| ... +//| +STATIC mp_obj_t ipaddress_ipv4address_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + switch (op) { + // Two Addresses are equal if their address bytes and address_type are equal + case MP_UNARY_OP_HASH: { + mp_obj_t bytes = common_hal_ipaddress_ipv4address_get_packed(MP_OBJ_TO_PTR(self_in)); + GET_STR_HASH(bytes, h); + if (h == 0) { + GET_STR_DATA_LEN(bytes, data, len); + h = qstr_compute_hash(data, len); + } + return MP_OBJ_NEW_SMALL_INT(h); + } + default: + return MP_OBJ_NULL; // op not supported + } +} + +STATIC void ipaddress_ipv4address_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + ipaddress_ipv4address_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_buffer_info_t buf_info; + mp_obj_t address_bytes = common_hal_ipaddress_ipv4address_get_packed(self); + mp_get_buffer_raise(address_bytes, &buf_info, MP_BUFFER_READ); + + const uint8_t *buf = (uint8_t *) buf_info.buf; + mp_printf(print, "%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]); +} + +STATIC const mp_rom_map_elem_t ipaddress_ipv4address_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_packed), MP_ROM_PTR(&ipaddress_ipv4address_packed_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(ipaddress_ipv4address_locals_dict, ipaddress_ipv4address_locals_dict_table); + +const mp_obj_type_t ipaddress_ipv4address_type = { + { &mp_type_type }, + .name = MP_QSTR_Address, + .make_new = ipaddress_ipv4address_make_new, + .print = ipaddress_ipv4address_print, + .unary_op = ipaddress_ipv4address_unary_op, + .binary_op = ipaddress_ipv4address_binary_op, + .locals_dict = (mp_obj_dict_t*)&ipaddress_ipv4address_locals_dict +}; diff --git a/shared-bindings/ipaddress/IPv4Address.h b/shared-bindings/ipaddress/IPv4Address.h new file mode 100644 index 0000000000..cf66b92b35 --- /dev/null +++ b/shared-bindings/ipaddress/IPv4Address.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_IPADDRESS_IPV4ADDRESS_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_IPADDRESS_IPV4ADDRESS_H + +#include "shared-module/ipaddress/IPv4Address.h" + +extern const mp_obj_type_t ipaddress_ipv4address_type; + +mp_obj_t common_hal_ipaddress_new_ipv4address(mp_int_t value); +void common_hal_ipaddress_ipv4address_construct(ipaddress_ipv4address_obj_t* self, uint8_t* buf, size_t len); +mp_obj_t common_hal_ipaddress_ipv4address_get_packed(ipaddress_ipv4address_obj_t* self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_IPADDRESS_IPV4ADDRESS_H diff --git a/shared-bindings/ipaddress/__init__.c b/shared-bindings/ipaddress/__init__.c new file mode 100644 index 0000000000..f9427ab847 --- /dev/null +++ b/shared-bindings/ipaddress/__init__.c @@ -0,0 +1,65 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/objexcept.h" +#include "py/runtime.h" +#include "shared-bindings/ipaddress/__init__.h" +#include "shared-bindings/ipaddress/IPv4Address.h" + +//| """ +//| The `ipaddress` module provides types for IP addresses. It is a subset of CPython's ipaddress +//| module. +//| """ +//| + +//| def ip_address(obj: Union[int]) -> IPv4Address: +//| """Return a corresponding IP address object or raise ValueError if not possible.""" +//| ... +//| + +STATIC mp_obj_t ipaddress_ip_address(mp_obj_t ip_in) { + mp_int_t value; + if (!mp_obj_get_int_maybe(ip_in, &value)) { + mp_raise_ValueError(translate("Only raw int supported for ip.")); + } + + return common_hal_ipaddress_new_ipv4address(value); +} +MP_DEFINE_CONST_FUN_OBJ_1(ipaddress_ip_address_obj, ipaddress_ip_address); + +STATIC const mp_rom_map_elem_t ipaddress_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ipaddress) }, + { MP_ROM_QSTR(MP_QSTR_ip_address), MP_ROM_PTR(&ipaddress_ip_address_obj) }, + { MP_ROM_QSTR(MP_QSTR_IPv4Address), MP_ROM_PTR(&ipaddress_ipv4address_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(ipaddress_module_globals, ipaddress_module_globals_table); + + +const mp_obj_module_t ipaddress_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&ipaddress_module_globals, +}; diff --git a/shared-bindings/ipaddress/__init__.h b/shared-bindings/ipaddress/__init__.h new file mode 100644 index 0000000000..a31629ccae --- /dev/null +++ b/shared-bindings/ipaddress/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_IPADDRESS___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS_IPADDRESS___INIT___H + +#include "shared-module/ipaddress/__init__.h" + +mp_obj_t common_hal_ipaddress_new_ipv4address(mp_int_t value); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_IPADDRESS___INIT___H diff --git a/shared-bindings/wifi/Network.c b/shared-bindings/wifi/Network.c index b4d389dcc9..b6d5e0901e 100644 --- a/shared-bindings/wifi/Network.c +++ b/shared-bindings/wifi/Network.c @@ -42,7 +42,7 @@ //| //| ssid: str -//| """True when the wifi network is enabled.""" +//| """String id of the network""" //| STATIC mp_obj_t wifi_network_get_ssid(mp_obj_t self) { return common_hal_wifi_network_get_ssid(self); @@ -57,8 +57,45 @@ const mp_obj_property_t wifi_network_ssid_obj = { (mp_obj_t)&mp_const_none_obj }, }; + +//| rssi: int +//| """Signal strength of the network""" +//| +STATIC mp_obj_t wifi_network_get_rssi(mp_obj_t self) { + return common_hal_wifi_network_get_rssi(self); + +} +MP_DEFINE_CONST_FUN_OBJ_1(wifi_network_get_rssi_obj, wifi_network_get_rssi); + +const mp_obj_property_t wifi_network_rssi_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&wifi_network_get_rssi_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + + +//| channel: int +//| """Channel number the network is operating on""" +//| +STATIC mp_obj_t wifi_network_get_channel(mp_obj_t self) { + return common_hal_wifi_network_get_channel(self); + +} +MP_DEFINE_CONST_FUN_OBJ_1(wifi_network_get_channel_obj, wifi_network_get_channel); + +const mp_obj_property_t wifi_network_channel_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&wifi_network_get_channel_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + + STATIC const mp_rom_map_elem_t wifi_network_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ssid), MP_ROM_PTR(&wifi_network_ssid_obj) }, + { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&wifi_network_rssi_obj) }, + { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&wifi_network_channel_obj) }, }; STATIC MP_DEFINE_CONST_DICT(wifi_network_locals_dict, wifi_network_locals_dict_table); diff --git a/shared-bindings/wifi/Network.h b/shared-bindings/wifi/Network.h index 8a3d10ca74..6a7f7be4a0 100644 --- a/shared-bindings/wifi/Network.h +++ b/shared-bindings/wifi/Network.h @@ -36,5 +36,7 @@ const mp_obj_type_t wifi_network_type; extern mp_obj_t common_hal_wifi_network_get_ssid(wifi_network_obj_t *self); +extern mp_obj_t common_hal_wifi_network_get_rssi(wifi_network_obj_t *self); +extern mp_obj_t common_hal_wifi_network_get_channel(wifi_network_obj_t *self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_WIFI_NETWORK_H diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index c5bee83114..1d14235730 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -102,16 +102,18 @@ STATIC mp_obj_t wifi_radio_stop_scanning_networks(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_scanning_networks_obj, wifi_radio_stop_scanning_networks); -//| def connect(self, ssid: ReadableBuffer, password: ReadableBuffer = b"", *, timeout: Optional[float] = None) -> bool: -//| """""" +//| def connect(self, ssid: ReadableBuffer, password: ReadableBuffer = b"", *, channel: Optional[int] = 0, timeout: Optional[float] = None) -> bool: +//| """Connects to the given ssid and waits for an ip address. Reconnections are handled +//| automatically once one connection succeeds.""" //| ... //| STATIC mp_obj_t wifi_radio_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_ssid, ARG_password, ARG_timeout }; + enum { ARG_ssid, ARG_password, ARG_channel, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_password, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; wifi_radio_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -136,22 +138,22 @@ STATIC mp_obj_t wifi_radio_connect(size_t n_args, const mp_obj_t *pos_args, mp_m mp_get_buffer_raise(args[ARG_password].u_obj, &password, MP_BUFFER_READ); } - return mp_obj_new_bool(common_hal_wifi_radio_connect(self, ssid.buf, ssid.len, password.buf, password.len, timeout)); + return mp_obj_new_bool(common_hal_wifi_radio_connect(self, ssid.buf, ssid.len, password.buf, password.len, args[ARG_channel].u_int, timeout)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_connect_obj, 1, wifi_radio_connect); -//| ip_address: Optional[ipaddress.IPAddress] -//| """IP Address of the radio when connected to an access point. None otherwise.""" +//| ipv4_address: Optional[ipaddress.IPv4Address] +//| """IP v4 Address of the radio when connected to an access point. None otherwise.""" //| -STATIC mp_obj_t wifi_radio_get_ip_address(mp_obj_t self) { - return common_hal_wifi_radio_get_ip_address(self); +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_ip_address_obj, wifi_radio_get_ip_address); +MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_address_obj, wifi_radio_get_ipv4_address); -const mp_obj_property_t wifi_radio_ip_address_obj = { +const mp_obj_property_t wifi_radio_ipv4_address_obj = { .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&wifi_radio_get_ip_address_obj, + .proxy = { (mp_obj_t)&wifi_radio_get_ipv4_address_obj, (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; @@ -179,7 +181,7 @@ STATIC const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = { { 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_ip_address), MP_ROM_PTR(&wifi_radio_ip_address_obj) }, + { MP_ROM_QSTR(MP_QSTR_ipv4_address), MP_ROM_PTR(&wifi_radio_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 c3bdac5ba8..3890885aeb 100644 --- a/shared-bindings/wifi/Radio.h +++ b/shared-bindings/wifi/Radio.h @@ -43,9 +43,9 @@ extern mp_obj_t common_hal_wifi_radio_get_mac_address(wifi_radio_obj_t *self); extern mp_obj_t common_hal_wifi_radio_start_scanning_networks(wifi_radio_obj_t *self); extern void common_hal_wifi_radio_stop_scanning_networks(wifi_radio_obj_t *self); -extern bool common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t* ssid, size_t ssid_len, uint8_t* password, size_t password_len, mp_float_t timeout); +extern bool 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); -extern mp_obj_t common_hal_wifi_radio_get_ip_address(wifi_radio_obj_t *self); +extern mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self); extern mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address); diff --git a/shared-module/ipaddress/IPv4Address.c b/shared-module/ipaddress/IPv4Address.c new file mode 100644 index 0000000000..f573d9d0a2 --- /dev/null +++ b/shared-module/ipaddress/IPv4Address.c @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/obj.h" + +#include "shared-bindings/ipaddress/__init__.h" +#include "shared-bindings/ipaddress/IPv4Address.h" + + +void common_hal_ipaddress_ipv4address_construct(ipaddress_ipv4address_obj_t* self, uint8_t* buf, size_t len) { + self->ip_bytes = mp_obj_new_bytes(buf, len); +} + +mp_obj_t common_hal_ipaddress_ipv4address_get_packed(ipaddress_ipv4address_obj_t* self) { + return self->ip_bytes; +} diff --git a/shared-module/ipaddress/IPv4Address.h b/shared-module/ipaddress/IPv4Address.h new file mode 100644 index 0000000000..3f2bde0911 --- /dev/null +++ b/shared-module/ipaddress/IPv4Address.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS_IPV4ADDRESS_H +#define MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS_IPV4ADDRESS_H + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + mp_obj_t ip_bytes; +} ipaddress_ipv4address_obj_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS_IPV4ADDRESS_H diff --git a/shared-module/ipaddress/__init__.c b/shared-module/ipaddress/__init__.c new file mode 100644 index 0000000000..e5d857d5dd --- /dev/null +++ b/shared-module/ipaddress/__init__.c @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/ipaddress/__init__.h" +#include "shared-bindings/ipaddress/IPv4Address.h" + +mp_obj_t common_hal_ipaddress_new_ipv4address(mp_int_t value) { + ipaddress_ipv4address_obj_t* self = m_new_obj(ipaddress_ipv4address_obj_t); + self->base.type = &ipaddress_ipv4address_type; + common_hal_ipaddress_ipv4address_construct(self, (uint8_t*) &value, 4); + return self; +} diff --git a/shared-module/ipaddress/__init__.h b/shared-module/ipaddress/__init__.h new file mode 100644 index 0000000000..7d5f2c2207 --- /dev/null +++ b/shared-module/ipaddress/__init__.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS___INIT___H +#define MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS___INIT___H + +#include + +#include "py/obj.h" + +mp_obj_t common_hal_ipaddress_new_ipv4(uint32_t value); + +#endif // MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS___INIT___H