diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c index 81daea2b..e5050fc1 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c @@ -1394,6 +1394,16 @@ bool ftp_terminate (void) { return res; } +//------------------------- +bool ftp_stop_requested() { + if ((FtpTaskHandle == NULL) || (ftp_mutex == NULL)) return false; + if (xSemaphoreTake(ftp_mutex, FTP_MUTEX_TIMEOUT_MS / portTICK_PERIOD_MS) !=pdTRUE) return false; + + bool res = (ftp_stop == 1); + xSemaphoreGive(ftp_mutex); + return res; +} + //------------------------------- int32_t ftp_get_maxstack (void) { if ((FtpTaskHandle == NULL) || (ftp_mutex == NULL)) return -1; diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h index 78aeee6f..4836df13 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h @@ -79,6 +79,7 @@ bool ftp_disable (void); bool ftp_reset (void); int ftp_getstate(); bool ftp_terminate (void); +bool ftp_stop_requested(); int32_t ftp_get_maxstack (void); #endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c index f0abb6ca..cb764c70 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c @@ -723,6 +723,16 @@ bool telnet_terminate (void) { return true; } +//---------------------------- +bool telnet_stop_requested() { + if ((TelnetTaskHandle == NULL) || (telnet_mutex == NULL)) return false; + if (xSemaphoreTake(telnet_mutex, TELNET_MUTEX_TIMEOUT_MS / portTICK_PERIOD_MS) !=pdTRUE) return false; + + bool res = (telnet_stop == 1); + xSemaphoreGive(telnet_mutex); + return res; +} + //---------------------------------- int32_t telnet_get_maxstack (void) { if ((TelnetTaskHandle == NULL) || (telnet_mutex == NULL)) return -1; diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h index a39850da..d4f64b98 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h @@ -79,6 +79,7 @@ bool telnet_isenabled (void); bool telnet_reset (void); int telnet_getstate(); bool telnet_terminate (void); +bool telnet_stop_requested(); int32_t telnet_get_maxstack (void); #endif diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_adc.c b/MicroPython_BUILD/components/micropython/esp32/machine_adc.c index dd158e38..c59e6007 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_adc.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_adc.c @@ -39,68 +39,185 @@ #include "py/runtime.h" #include "py/mphal.h" #include "modmachine.h" +#include "machine_pin.h" #define ADC1_CHANNEL_HALL ADC1_CHANNEL_MAX typedef struct _madc_obj_t { mp_obj_base_t base; int gpio_id; - adc1_channel_t adc1_id; + adc_unit_t adc_num; + adc1_channel_t adc_chan; adc_atten_t atten; adc_bits_width_t width; } madc_obj_t; -static uint16_t adc_chan_used = 0; +static uint16_t adc1_chan_used = 0; +static uint16_t adc2_chan_used = 0; static int8_t adc_width = -1; +static int8_t last_adc_width = -1; +static int8_t last_adc_num = -1; static uint32_t adc_vref = 1100; +static uint32_t last_adc_vref = 0; +static adc_atten_t last_atten = ADC_ATTEN_MAX; +static adc_atten_t last_atten2 = ADC_ATTEN_MAX; +static esp_adc_cal_characteristics_t characteristics; +static const uint8_t adc1_gpios[ADC1_CHANNEL_MAX] = {36, 37, 38, 39, 32, 33, 34, 35}; +static const uint8_t adc2_gpios[ADC2_CHANNEL_MAX] = {4, 0, 2, 15, 13, 12, 14, 27, 25, 26}; + +//------------------------------------- +static void set_width(madc_obj_t *self) +{ + if (adc_width != self->width) { + if (self->adc_num == ADC_UNIT_1) { + esp_err_t err = adc1_config_width(self->width); + if (err != ESP_OK) mp_raise_ValueError("Set width Error"); + } + else { + adc_set_data_width(self->adc_num, self->width); + } + adc_width = self->width; + } +} + +//----------------------------------------------------- +static int get_adc_channel(adc_unit_t adc_num, int pin) +{ + int channel = -1; + if (adc_num == ADC_UNIT_1) { + for (int i=0; i < ADC1_CHANNEL_MAX; i++) { + if (adc1_gpios[i] == pin) { + channel = i; + break; + } + } + } + else { + for (int i=0; i < ADC2_CHANNEL_MAX; i++) { + if (adc2_gpios[i] == pin) { + channel = i; + break; + } + } + } + return channel; +} + +//------------------------------------------------------------------------------------------------------------ +STATIC mp_obj_t madc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + enum { ARG_pin, ARG_unit }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_unit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADC_UNIT_1}}, + }; + // parse arguments + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); -//---------------------------------------------------------------------------------------------------------- -STATIC mp_obj_t madc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { esp_err_t err = 0; mp_arg_check_num(n_args, n_kw, 1, 1, true); int pin_id = 0; - if (MP_OBJ_IS_INT(args[0])) pin_id = mp_obj_get_int(args[0]); - else pin_id = machine_pin_get_id(args[0]); + pin_id = machine_pin_get_gpio(args[ARG_pin].u_obj); madc_obj_t *self = m_new_obj(madc_obj_t);; self->base.type = &machine_adc_type; - if ((pin_id != ADC1_CHANNEL_HALL) && ((pin_id < 32) || (pin_id > 39))) mp_raise_ValueError("invalid Pin for ADC"); - - self->atten = ADC_ATTEN_0db; + self->adc_num = args[ARG_unit].u_int; + if ((self->adc_num != ADC_UNIT_1) && (self->adc_num != ADC_UNIT_2)) { + mp_raise_ValueError("invalid ADC unit (1 and 2 allowed)"); + } + self->atten = ADC_ATTEN_DB_0; self->width = ADC_WIDTH_BIT_12; - if (pin_id != ADC1_CHANNEL_HALL) { - if (pin_id > 35) self->adc1_id = ADC1_CHANNEL_0 + (pin_id-36); - else self->adc1_id = ADC1_CHANNEL_4 + (pin_id-32); - if ((adc_chan_used & 0x0100) && ((self->adc1_id == 36) || (self->adc1_id == 39))) mp_raise_ValueError("hall used, cannot use pins 36 & 39"); - adc_chan_used |= (1 << self->adc1_id); - self->gpio_id = pin_id; - self->gpio_id = pin_id; - err = adc1_config_channel_atten(self->adc1_id, ADC_ATTEN_0db); - if (err != ESP_OK) mp_raise_ValueError("Parameter Error"); + if (pin_id != ADC1_CHANNEL_HALL) { + int channel = get_adc_channel(self->adc_num, pin_id); + if (channel < 0) mp_raise_ValueError("invalid Pin for ADC"); + self->adc_chan = channel; + self->gpio_id = pin_id; + + if (self->adc_num == ADC_UNIT_1) { + if ((adc1_chan_used & 0x0100) && ((pin_id == 36) || (pin_id == 39))) mp_raise_ValueError("hall used, cannot use pins 36 & 39"); + if (adc1_chan_used & (1 << self->adc_chan)) mp_raise_ValueError("pin already used for adc"); + adc1_chan_used |= (1 << self->adc_chan); + + err = adc_gpio_init(self->adc_num, self->adc_chan); + if (err != ESP_OK) mp_raise_ValueError("Error configuring ADC gpio"); + err = adc1_config_channel_atten(self->adc_chan, ADC_ATTEN_DB_0); + if (err != ESP_OK) mp_raise_ValueError("Error configuring attenuation"); + } + else { + if (adc2_chan_used & (1 << self->adc_chan)) mp_raise_ValueError("pin already used for adc"); + adc2_chan_used |= (1 << self->adc_chan); + + gpio_pad_select_gpio(self->gpio_id); + gpio_set_direction(self->gpio_id, GPIO_MODE_DISABLE); + gpio_set_pull_mode(self->gpio_id, GPIO_FLOATING); + + adc_gpio_init(self->adc_num, self->adc_chan); + if (err != ESP_OK) mp_raise_ValueError("Error configuring ADC gpio"); + if (last_atten2 != self->atten) { + adc2_config_channel_atten(self->adc_chan, self->atten); + last_atten2 = self->atten; + } + } } else { - if (adc_chan_used & 0x09) mp_raise_ValueError("adc on gpio 36 or 39 used"); - self->adc1_id = ADC1_CHANNEL_HALL; + self->adc_num = ADC_UNIT_1; + if (adc1_chan_used & 0x09) mp_raise_ValueError("adc on gpio 36 or 39 used"); + if (adc1_chan_used & 0x0100) mp_raise_ValueError("hall already used"); + adc1_chan_used |= 0x0100; + self->adc_chan = ADC1_CHANNEL_HALL; self->gpio_id = GPIO_NUM_MAX; } - if (adc_width != self->width) { - err = adc1_config_width(self->width); - if (err != ESP_OK) mp_raise_ValueError("Set width Error"); - adc_width = self->width; - } + set_width(self); return MP_OBJ_FROM_PTR(self); } +//------------------------------------------- +STATIC mp_obj_t madc_deinit(mp_obj_t self_in) +{ + madc_obj_t *self = self_in; + if (self->gpio_id < 0) return mp_const_none; + + if (self->adc_num == ADC_UNIT_1) { + if (self->adc_chan == ADC1_CHANNEL_HALL) { + adc1_chan_used &= 0x00FF; + gpio_pad_select_gpio(36); + gpio_pad_select_gpio(39); + } + else { + adc1_chan_used &= (~(1 << self->adc_chan) & 0x1FF); + gpio_pad_select_gpio(self->gpio_id); + gpio_set_direction(self->gpio_id, GPIO_MODE_INPUT); + gpio_set_pull_mode(self->gpio_id, GPIO_FLOATING); + } + } + else { + adc2_chan_used &= (~(1 << self->adc_chan) & 0x3FF); + gpio_pad_select_gpio(self->gpio_id); + gpio_set_direction(self->gpio_id, GPIO_MODE_INPUT); + gpio_set_pull_mode(self->gpio_id, GPIO_FLOATING); + } + self->gpio_id = -1; + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(madc_deinit_obj, madc_deinit); + //--------------------------------------------------------------------------------------- STATIC void madc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { madc_obj_t *self = self_in; + + if (self->gpio_id < 0) { + mp_printf(print, "ADC( deinitialized )"); + return; + } + char satten[16]; char spin[8]; if (self->atten == ADC_ATTEN_DB_0) sprintf(satten, "0dB (1.1V)"); @@ -112,22 +229,32 @@ STATIC void madc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ if (self->gpio_id == GPIO_NUM_MAX) sprintf(spin, "HALL"); else sprintf(spin, "Pin(%u)", self->gpio_id); - mp_printf(print, "ADC(%s: width=%u bits, atten=%s, Vref=%u mV)", spin, self->width+9, satten, adc_vref); + mp_printf(print, "ADC(%s: unit=ADC%d, chan=%d, width=%u bits, atten=%s, Vref=%u mV)", spin, self->adc_num, self->adc_chan, self->width+9, satten, adc_vref); } //---------------------------------------------- STATIC mp_obj_t madc_readraw(mp_obj_t self_in) { madc_obj_t *self = self_in; - if (adc_width != self->width) { - esp_err_t err = adc1_config_width(self->width); - if (err != ESP_OK) mp_raise_ValueError("Set width Error"); - adc_width = self->width; - } - - int val = 0; - if (self->gpio_id == GPIO_NUM_MAX) val= hall_sensor_read(); - else val = adc1_get_raw(self->adc1_id); - if (val == -1) mp_raise_ValueError("Parameter Error"); + if (self->gpio_id < 0) { + mp_raise_ValueError("Not initialized"); + } + + int val = 0; + if (self->adc_num == ADC_UNIT_1) { + set_width(self); + + if (self->gpio_id == GPIO_NUM_MAX) val= hall_sensor_read(); + else val = adc1_get_raw(self->adc_chan); + if (val == -1) mp_raise_ValueError("Parameter Error (ADC raw read)"); + } + else { + if (last_atten2 != self->atten) { + adc2_config_channel_atten(self->adc_chan, self->atten); + last_atten2 = self->atten; + } + esp_err_t err = adc2_get_raw(self->adc_chan, self->atten, &val); + if (err != ESP_OK) mp_raise_ValueError("Cannot read, ADC2 used by Wi-Fi"); + } return MP_OBJ_NEW_SMALL_INT(val); } @@ -136,21 +263,34 @@ MP_DEFINE_CONST_FUN_OBJ_1(madc_readraw_obj, madc_readraw); //------------------------------------------- STATIC mp_obj_t madc_read(mp_obj_t self_in) { madc_obj_t *self = self_in; - esp_adc_cal_characteristics_t characteristics; - if (adc_width != self->width) { - esp_err_t err = adc1_config_width(self->width); - if (err != ESP_OK) mp_raise_ValueError("Set width Error"); - } + if (self->gpio_id < 0) { + mp_raise_ValueError("Not initialized"); + } + + set_width(self); int adc_val = 0; if (self->gpio_id == GPIO_NUM_MAX) adc_val= hall_sensor_read(); else { - // Deprecated - //esp_adc_cal_get_characteristics(adc_vref, self->atten, self->width, &characteristics); - //adc_val = adc1_to_voltage(self->adc1_id, &characteristics); - - esp_adc_cal_value_t adc_val = esp_adc_cal_characterize(ADC_UNIT_1, self->atten, self->width, adc_vref, &characteristics); - esp_adc_cal_get_voltage(self->adc1_id, &characteristics, &adc_val); + if ((last_adc_num != self->adc_num) || (last_adc_vref != adc_vref) || (last_atten != self->atten) || (last_adc_width != self->width)) { + // New characterization needed + esp_adc_cal_value_t cal_val = esp_adc_cal_characterize(self->adc_num, self->atten, self->width, adc_vref, &characteristics); + last_adc_vref = adc_vref; + last_atten = self->atten; + last_adc_width = self->width; + last_adc_num = self->adc_num; + + ESP_LOGD("MOD_ADC", "Characterize ADC_UNIT_%d: Vref used: %s", self->adc_num, (cal_val == 0) ? "eFuse" : (cal_val == 1) ? "Two point" : "Default"); + } + if ((self->adc_num == ADC_UNIT_2) && (last_atten2 != self->atten)) { + adc2_config_channel_atten(self->adc_chan, self->atten); + last_atten2 = self->atten; + } + esp_err_t err = esp_adc_cal_get_voltage(self->adc_chan, &characteristics, (uint32_t *)&adc_val); + if (err != ESP_OK) { + if (self->adc_num == ADC_UNIT_2) mp_raise_ValueError("Cannot read, ADC2 used by Wi-Fi"); + else mp_raise_ValueError("Error reading"); + } } return MP_OBJ_NEW_SMALL_INT(adc_val); } @@ -159,13 +299,26 @@ MP_DEFINE_CONST_FUN_OBJ_1(madc_read_obj, madc_read); //--------------------------------------------------------------- STATIC mp_obj_t madc_atten(mp_obj_t self_in, mp_obj_t atten_in) { madc_obj_t *self = self_in; - if (self->gpio_id == GPIO_NUM_MAX) return mp_const_none; + if (self->gpio_id < 0) { + mp_raise_ValueError("Not initialized"); + } + + if (self->gpio_id == GPIO_NUM_MAX) return mp_const_none; adc_atten_t atten = mp_obj_get_int(atten_in); if ((atten < ADC_ATTEN_DB_0) || (atten > ADC_ATTEN_DB_11)) mp_raise_ValueError("Unsupported atten value"); - esp_err_t err = adc1_config_channel_atten(self->adc1_id, atten); - if (err != ESP_OK) mp_raise_ValueError("Parameter Error"); + esp_err_t err; + if (self->adc_num == ADC_UNIT_1) { + err = adc1_config_channel_atten(self->adc_chan, atten); + if (err != ESP_OK) mp_raise_ValueError("Parameter Error (config attenuation)"); + } + else { + if (last_atten2 != atten) { + adc2_config_channel_atten(self->adc_chan, atten); + last_atten2 = self->atten; + } + } self->atten = atten; return mp_const_none; } @@ -174,7 +327,11 @@ MP_DEFINE_CONST_FUN_OBJ_2(madc_atten_obj, madc_atten); //--------------------------------------------------------------- STATIC mp_obj_t madc_width(mp_obj_t self_in, mp_obj_t width_in) { madc_obj_t *self = self_in; - if (self->gpio_id == GPIO_NUM_MAX) return mp_const_none; + if (self->gpio_id < 0) { + mp_raise_ValueError("Not initialized"); + } + + if (self->gpio_id == GPIO_NUM_MAX) return mp_const_none; adc_bits_width_t width = mp_obj_get_int(width_in); if ((width < ADC_WIDTH_9Bit) || (width > ADC_WIDTH_12Bit)) mp_raise_ValueError("Unsupported width value"); @@ -224,6 +381,7 @@ STATIC const mp_rom_map_elem_t madc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_atten), MP_ROM_PTR(&madc_atten_obj) }, { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&madc_width_obj) }, { MP_ROM_QSTR(MP_QSTR_vref), MP_ROM_PTR(&madc_vref_togpio_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&madc_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_HALL), MP_ROM_INT(ADC1_CHANNEL_MAX) }, diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_pin.c b/MicroPython_BUILD/components/micropython/esp32/machine_pin.c index c51541cf..b10b4b9d 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_pin.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_pin.c @@ -165,7 +165,7 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ // configure the pin for gpio if (rtc_gpio_is_valid_gpio(self->id)) rtc_gpio_deinit(self->id); - if (self->id < 28) gpio_pad_select_gpio(self->id); + gpio_pad_select_gpio(self->id); // set initial value (do this before configuring mode/pull) if (args[ARG_value].u_obj != MP_OBJ_NULL) { diff --git a/MicroPython_BUILD/components/micropython/esp32/main.c b/MicroPython_BUILD/components/micropython/esp32/main.c index 61fd8b18..b9ff4495 100644 --- a/MicroPython_BUILD/components/micropython/esp32/main.c +++ b/MicroPython_BUILD/components/micropython/esp32/main.c @@ -270,10 +270,19 @@ void micropython_entry(void) { // === Set esp32 log levels while running MicroPython === if (CONFIG_MICRO_PY_LOG_LEVEL < CONFIG_LOG_DEFAULT_LEVEL) esp_log_level_set("*", CONFIG_MICRO_PY_LOG_LEVEL); - esp_log_level_set("wifi", ESP_LOG_ERROR); - esp_log_level_set("rmt", ESP_LOG_ERROR); + if ((CONFIG_LOG_DEFAULT_LEVEL > ESP_LOG_WARN) && (CONFIG_MICRO_PY_LOG_LEVEL > ESP_LOG_WARN)){ + esp_log_level_set("wifi", ESP_LOG_WARN); + esp_log_level_set("rmt", ESP_LOG_WARN); + esp_log_level_set("tcpip_adapter", ESP_LOG_WARN); + esp_log_level_set("event", ESP_LOG_WARN); + esp_log_level_set("nvs", ESP_LOG_WARN); + esp_log_level_set("phy_init", ESP_LOG_WARN); + esp_log_level_set("wl_flash", ESP_LOG_WARN); + esp_log_level_set("RTC_MODULE", ESP_LOG_WARN); + } #ifdef CONFIG_MICROPY_USE_OTA - esp_log_level_set("OTA_UPDATE", ESP_LOG_DEBUG); + if (CONFIG_LOG_DEFAULT_LEVEL >= ESP_LOG_DEBUG) esp_log_level_set("OTA_UPDATE", ESP_LOG_DEBUG); + else esp_log_level_set("OTA_UPDATE", CONFIG_LOG_DEFAULT_LEVEL); #endif nvs_flash_init(); diff --git a/MicroPython_BUILD/components/micropython/esp32/modmachine.c b/MicroPython_BUILD/components/micropython/esp32/modmachine.c index 4b759b23..d21108cc 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modmachine.c +++ b/MicroPython_BUILD/components/micropython/esp32/modmachine.c @@ -52,6 +52,7 @@ #include "esp_log.h" #include "esp_err.h" #include "esp_pm.h" +#include "esp_wifi.h" #include "driver/uart.h" #include "py/obj.h" @@ -64,6 +65,7 @@ #include "mpsleep.h" #include "machine_rtc.h" #include "uart.h" +#include "modnetwork.h" #if MICROPY_PY_MACHINE @@ -176,7 +178,7 @@ static void RTC_IRAM_ATTR wake_stub() if ((machine_rtc_config.deepsleep_time) && (machine_rtc_config.deepsleep_interval)) { // == Set the out pin to active level if configured if (machine_rtc_config.stub_outpin >= 0) { - if (machine_rtc_config.stub_outpin < 28) gpio_pad_select_gpio(machine_rtc_config.stub_outpin); + gpio_pad_select_gpio(machine_rtc_config.stub_outpin); if (machine_rtc_config.stub_outpin < 32) gpio_output_set(machine_rtc_config.stub_outpin_level << machine_rtc_config.stub_outpin, (machine_rtc_config.stub_outpin_level ? 0 : 1) << machine_rtc_config.stub_outpin, @@ -279,6 +281,17 @@ void prepareSleepReset(uint8_t hrst, char *msg) if (!hrst) { if (msg) mp_hal_stdout_tx_str(msg); + // stop and deinitialize WiFi + if (wifi_network_state == WIFI_STATE_STARTED) { + wifi_network_state = WIFI_STATE_STOPPED; + wifi_sta_isconnected = false; + wifi_sta_has_ipaddress = false; + wifi_sta_changed_ipaddress = false; + wifi_ap_isconnected = false; + wifi_ap_sta_isconnected = false; + esp_wifi_stop(); + esp_wifi_deinit(); + } // deinitialise peripherals //ToDo: deinitialize other peripherals, threads, services, ... machine_pins_deinit(); diff --git a/MicroPython_BUILD/components/micropython/esp32/modnetwork.c b/MicroPython_BUILD/components/micropython/esp32/modnetwork.c index 627d66ae..781f376e 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modnetwork.c +++ b/MicroPython_BUILD/components/micropython/esp32/modnetwork.c @@ -47,7 +47,6 @@ #include "py/mperrno.h" #include "netutils.h" #include "esp_wifi.h" -#include "esp_wifi_types.h" #include "esp_log.h" #include "esp_event_loop.h" #include "esp_log.h" @@ -60,6 +59,10 @@ #include "modnetwork.h" #define MODNETWORK_INCLUDE_CONSTANTS (1) +//#define MPY_WIFI_USED_STORAGE WIFI_STORAGE_FLASH +#define MPY_WIFI_USED_STORAGE WIFI_STORAGE_RAM + +static const char *MODNETTWORK_TAG = "[modnetwork]"; NORETURN void _esp_exceptions(esp_err_t e) { switch (e) { @@ -174,7 +177,7 @@ static inline void esp_exceptions(esp_err_t e) { #define ESP_EXCEPTIONS(x) do { esp_exceptions(x); } while (0); // global variables -int wifi_network_state = -1; +int wifi_network_state = WIFI_STATE_NOTINIT; bool wifi_sta_isconnected = false; bool wifi_sta_has_ipaddress = false; bool wifi_sta_changed_ipaddress = false; @@ -182,17 +185,15 @@ bool wifi_ap_isconnected = false; bool wifi_ap_sta_isconnected = false; const mp_obj_type_t wlan_if_type; -const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA}; -const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP}; +const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA, WIFI_MODE_STA}; +const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP, WIFI_MODE_AP}; //static wifi_config_t wifi_ap_config = { 0 }; static wifi_config_t wifi_sta_config = { 0 }; -// Set to "true" if the STA interface is requested to be connected by the -// user, used for automatic reconnect. -static bool wifi_sta_connected = false; - -static uint8_t _isConnected = 0; +// Set to "true" if the STA interface is requested to be automatically reconnected. +static bool wifi_sta_reconnect = false; +static bool sta_isStarted = false; static mp_obj_t event_callback = NULL; static mp_obj_t probereq_callback = NULL; @@ -221,7 +222,6 @@ static void processPROBEREQRECVED(const uint8_t *frame, int len, int rssi) //------------------------------------------------------ static void processEvent_callback(system_event_t *event) { - if (wifi_network_state < 2) return; if (event->event_id >= SYSTEM_EVENT_MAX) return; mp_sched_carg_t *carg = NULL; @@ -362,62 +362,60 @@ static void processEvent_callback(system_event_t *event) } } +//------------------------ +static void tryReconnect() +{ + if (wifi_sta_reconnect) { + wifi_mode_t mode; + if (esp_wifi_get_mode(&mode) == ESP_OK) { + if (mode & WIFI_MODE_STA) { + if (sta_isStarted) { + // STA is active and started, attempt to reconnect. + esp_err_t res = esp_wifi_connect(); + if (res != ESP_OK) { + ESP_LOGD(MODNETTWORK_TAG, "error attempting to reconnect: (%d)", res-ESP_ERR_WIFI_BASE); + } + } + } + } + } +} // This function is called by the system-event task and so runs in a different // thread to the main MicroPython task. It must not raise any Python exceptions. //-------------------------------------------------------------- static esp_err_t event_handler(void *ctx, system_event_t *event) { - if (wifi_network_state < 2) return ESP_OK; - if (wifi_mutex) xSemaphoreTake(wifi_mutex, 1000); - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - ESP_LOGI("wifi", "STA_START"); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI("network", "GOT_IP"); - _isConnected = 1; - break; - case SYSTEM_EVENT_STA_DISCONNECTED: { - // This is a workaround as ESP32 WiFi library doesn't currently auto-reconnect. - _isConnected = 0; - system_event_sta_disconnected_t *disconn = &event->event_info.disconnected; - ESP_LOGI("wifi", "STA_DISCONNECTED, reason:%d", disconn->reason); - switch (disconn->reason) { - case WIFI_REASON_BEACON_TIMEOUT: - ESP_LOGD("wifi", "beacon timeout"); - // AP has dropped out; try to reconnect. - break; - case WIFI_REASON_NO_AP_FOUND: - ESP_LOGD("wifi", "no AP found"); - // AP may not exist, or it may have momentarily dropped out; try to reconnect. - break; - case WIFI_REASON_AUTH_FAIL: - ESP_LOGD("wifi", "authentication failed"); - wifi_sta_connected = false; - break; - default: - // Let other errors through and try to reconnect. - break; - } - if (wifi_sta_connected) { - wifi_mode_t mode; - if (esp_wifi_get_mode(&mode) == ESP_OK) { - if (mode & WIFI_MODE_STA) { - // STA is active so attempt to reconnect. - esp_err_t e = esp_wifi_connect(); - if (e != ESP_OK) { - ESP_LOGD("wifi", "error attempting to reconnect: (%d)", e); - } - else wifi_sta_connected = true; - } + + if (wifi_network_state == WIFI_STATE_STARTED) { + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + sta_isStarted = true; + tryReconnect(); + break; + case SYSTEM_EVENT_STA_STOP: + sta_isStarted = false; + break; + case SYSTEM_EVENT_STA_DISCONNECTED: { + // This is a workaround as ESP32 WiFi library doesn't currently auto-reconnect. + system_event_sta_disconnected_t *disconn = &event->event_info.disconnected; + switch (disconn->reason) { + case WIFI_REASON_AUTH_FAIL: + wifi_sta_reconnect = false; + break; + case WIFI_REASON_ASSOC_LEAVE: + sta_isStarted = false; + break; + default: + // Let other errors through and try to reconnect. + break; } + tryReconnect(); + break; + } + default: + break; } - break; - } - default: - ESP_LOGD("network", "event %d", event->event_id); - break; } #ifdef CONFIG_MICROPY_USE_MDNS @@ -425,7 +423,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) #endif // === Handle events callbacks === - processEvent_callback(event); + if (wifi_network_state == WIFI_STATE_STARTED) processEvent_callback(event); if (wifi_mutex) xSemaphoreGive(wifi_mutex); return ESP_OK; @@ -439,191 +437,258 @@ STATIC void require_if(mp_obj_t wlan_if, int if_no) { } } -//-------------------------------------- -static void _wifi_init(wifi_mode_t mode) -{ - esp_err_t ret = 0; - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); +//-------------------------------- +STATIC mp_obj_t esp_initialize() { + if (wifi_network_state < WIFI_STATE_INIT) { + // This is executed only once + ESP_LOGD(MODNETTWORK_TAG, "Initializing TCP/IP"); + tcpip_adapter_init(); + ESP_LOGD(MODNETTWORK_TAG, "Initializing Event Loop"); + ESP_EXCEPTIONS( esp_event_loop_init(event_handler, NULL) ); + ESP_LOGD(MODNETTWORK_TAG, "Event loop initialized"); - ESP_LOGD("modnetwork", "Initializing WiFi"); - ret = esp_wifi_init(&cfg); - if (ret != ESP_OK) { - ESP_LOGE("modnetwork", "Error initializing WiFi (%d)", ret); - mp_raise_OSError(ret); - } - ret = esp_wifi_set_storage(WIFI_STORAGE_FLASH); - if (ret != ESP_OK) { - ESP_LOGE("modnetwork", "Error initializing WiFi storage (%d)", ret); - mp_raise_OSError(ret); - } - ESP_LOGD("modnetwork", "Initialized"); - esp_wifi_set_mode(mode); - if (ret != ESP_OK) { - ESP_LOGE("modnetwork", "Error setting WiFi mode (%d)", ret); - mp_raise_OSError(ret); - } - ret = esp_wifi_start(); - if (ret != ESP_OK) { - ESP_LOGE("modnetwork", "Error starting WiFi(%d)", ret); - mp_raise_OSError(ret); + // create mutex's + if (wifi_mutex == NULL) wifi_mutex = xSemaphoreCreateMutex(); + if (probereq_mutex == NULL) probereq_mutex = xSemaphoreCreateMutex(); + // add probe requests handler + esp_wifi_set_sta_rx_probe_req(processPROBEREQRECVED); + + wifi_network_state = WIFI_STATE_INIT; } - ESP_LOGD("modnetwork", "Started, mode %d", mode); + return mp_const_none; } +STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_initialize_obj, esp_initialize); +#if (WIFI_MODE_STA & WIFI_MODE_AP != WIFI_MODE_NULL || WIFI_MODE_STA | WIFI_MODE_AP != WIFI_MODE_APSTA) +#error WIFI_MODE_STA and WIFI_MODE_AP are supposed to be bitfields! +#endif + + +// Return WLAN object for given WiFi mode (default: STA) +// Does not start WiFi if not started ! //------------------------------------------------------------- STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) { - if (wifi_network_state < 0) { + if (wifi_network_state < WIFI_STATE_INIT) { mp_raise_ValueError("TCT/IP Adapter not initialized"); } - int if_id = 0; - wifi_mode_t wifi_mode = WIFI_MODE_NULL; + // Default mode + int if_id = WIFI_IF_STA; - if (wifi_network_state == 2) { - // wifi started, get mode - esp_err_t ret = esp_wifi_get_mode(&wifi_mode); - if (ret != ESP_OK) { - mp_raise_ValueError("Cannot get current wifi mode"); - } - if (wifi_mode == WIFI_MODE_STA) if_id = WIFI_IF_STA; - else if_id = WIFI_IF_AP; - if (n_args > 0) { - // Get required WiFi mode - if_id = mp_obj_get_int(args[0]); - if ((if_id != WIFI_IF_STA) && (if_id != WIFI_IF_AP)) { - mp_raise_ValueError("invalid WLAN interface identifier"); - } - // check required mode - if (((if_id == WIFI_IF_STA) && (wifi_mode != WIFI_MODE_STA)) || - ((if_id == WIFI_IF_AP) && (wifi_mode != WIFI_MODE_AP))) { - mp_raise_ValueError("WiFi already started in different mode"); - } + if (n_args > 0) { + // Get required WiFi mode + if_id = mp_obj_get_int(args[0]); + if ((if_id != WIFI_IF_STA) && (if_id != WIFI_IF_AP)) { + mp_raise_ValueError("invalid WLAN interface identifier"); } - } - else { - // wifi not started - if (n_args > 0) { - // Get required WiFi mode - if_id = mp_obj_get_int(args[0]); - if ((if_id != WIFI_IF_STA) && (if_id != WIFI_IF_AP)) { - mp_raise_ValueError("invalid WLAN interface identifier"); - } - // set required mode mode - if (if_id == WIFI_IF_STA) wifi_mode = WIFI_MODE_STA; - else wifi_mode = WIFI_MODE_AP; - } - else { - // set default mode: STA - if_id = WIFI_IF_STA; - wifi_mode = WIFI_MODE_STA; - } - wifi_network_state = 1; - if (n_args > 1) { - // we have the 2nd argument: active - bool active = mp_obj_is_true(args[1]); - if (active) { - // Start wifi in requested mode - wifi_mode_t mode; - if (if_id == WIFI_IF_STA) mode = WIFI_MODE_STA; - else mode = WIFI_MODE_AP; - _wifi_init(mode); - wifi_network_state = 2; - } - } - } + } // Return the WLAN object if (if_id == WIFI_IF_STA) return MP_OBJ_FROM_PTR(&wlan_sta_obj); return MP_OBJ_FROM_PTR(&wlan_ap_obj); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 2, get_wlan); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan); -//-------------------------------- -STATIC mp_obj_t esp_initialize() { - if (wifi_network_state < 0) { - // This is executed only once - ESP_LOGD("modnetwork", "Initializing TCP/IP"); - tcpip_adapter_init(); - ESP_LOGD("modnetwork", "Initializing Event Loop"); - ESP_EXCEPTIONS( esp_event_loop_init(event_handler, NULL) ); - ESP_LOGD("modnetwork", "esp_event_loop_init done"); - // create mutex's - if (wifi_mutex == NULL) wifi_mutex = xSemaphoreCreateMutex(); - if (probereq_mutex == NULL) probereq_mutex = xSemaphoreCreateMutex(); - // add probe requests handler - esp_wifi_set_sta_rx_probe_req(processPROBEREQRECVED); +//---------------------- +static void _init_wifi() +{ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_err_t ret = esp_wifi_init(&cfg); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error initializing WiFi (%d)", ret); + mp_raise_OSError(ret); + } + ret = esp_wifi_set_storage(MPY_WIFI_USED_STORAGE); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error initializing WiFi storage (%d)", ret); + mp_raise_OSError(ret); + } + ESP_LOGD(MODNETTWORK_TAG, "WiFi Initialized"); + wifi_network_state = WIFI_STATE_STOPPED; +} + +// Initialize WiFi if needed, set the requested mode and start WiFi +//------------------------------------------------------ +static void _wifi_init(wifi_mode_t mode, bool reconnect) +{ + if (wifi_network_state < WIFI_STATE_STOPPED) _init_wifi(); + + esp_err_t ret = 0; + if (wifi_network_state == WIFI_STATE_STARTED) { + // Stop WiFi + wifi_network_state = WIFI_STATE_STOPPED; + wifi_sta_isconnected = false; + wifi_sta_has_ipaddress = false; + wifi_sta_changed_ipaddress = false; + wifi_ap_isconnected = false; + wifi_ap_sta_isconnected = false; + ret = esp_wifi_stop(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error stopping WiFi (%d)", ret); + goto exit_error; + } + ESP_LOGD(MODNETTWORK_TAG, "WiFi Stopped"); + } - wifi_network_state = 0; + // Set WiFi mode + esp_wifi_set_mode(mode); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error setting WiFi mode (%d)", ret); + goto exit_error; } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_initialize_obj, esp_initialize); + // Start WiFi + ret = esp_wifi_start(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error starting WiFi (%d)", ret); + goto exit_error; + } + wifi_sta_reconnect = reconnect; -#if (WIFI_MODE_STA & WIFI_MODE_AP != WIFI_MODE_NULL || WIFI_MODE_STA | WIFI_MODE_AP != WIFI_MODE_APSTA) -#error WIFI_MODE_STA and WIFI_MODE_AP are supposed to be bitfields! -#endif + wifi_network_state = WIFI_STATE_STARTED; + ESP_LOGD(MODNETTWORK_TAG, "WiFi Started, mode %d", mode); + return; + +exit_error: + wifi_network_state = WIFI_STATE_INIT; + ret = esp_wifi_stop(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error stopping WiFi (%d)", ret); + } + vTaskDelay(5 / portTICK_PERIOD_MS); + esp_wifi_deinit(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error deinitializing WiFi (%d)", ret); + } + vTaskDelay(5 / portTICK_PERIOD_MS); + mp_raise_OSError(ret); +} -// Activate (start) Wifi +// Activate (start) or deactivate (stop) Wifi //------------------------------------------------------------- STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) { - if (wifi_network_state < 1) { - ESP_LOGW("modnetwork", "WiFi not initialized"); + if (wifi_network_state < WIFI_STATE_INIT) { + ESP_LOGW(MODNETTWORK_TAG, "WiFi not initialized"); return mp_const_false; } - if (n_args < 2) { - // Return wifi status (started/not started) - if (wifi_network_state == 2) return mp_const_true; - else return mp_const_false; - } wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); + wifi_mode_t mode; + + if (n_args < 2) goto exit; // Get requested action bool active = mp_obj_is_true(args[1]); - if ((!active) && (wifi_network_state == 2)) { - // == wifi started, deactivation requested == - wifi_network_state = 1; - wifi_sta_isconnected = false; - wifi_sta_has_ipaddress = false; - wifi_sta_changed_ipaddress = false; - wifi_ap_isconnected = false; - wifi_ap_sta_isconnected = false; - esp_wifi_stop(); - esp_wifi_deinit(); + if (active) { + // === WiFi activation requested === + if (wifi_network_state == WIFI_STATE_STARTED) { + // WiFi already started, check mode + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error getting WiFi mode (%d)", ret); + return mp_const_false; + } + // If requested mode is already started, just return + if (self->wifi_mode & mode) return mp_const_true; + // Restart WiFi adding a new mode + _wifi_init(mode | self->wifi_mode, (mode & WIFI_MODE_STA) & wifi_sta_reconnect); + } + else { + // Start WiFi + _wifi_init(self->wifi_mode, false); + } } - else if ((active) && (wifi_network_state == 1)) { - // == wifi NOT started, activation requested == - wifi_mode_t mode; - if (self->if_id == WIFI_IF_STA) mode = WIFI_MODE_STA; - else mode = WIFI_MODE_AP; - _wifi_init(mode); - wifi_network_state = 2; + else { + // === WiFi deactivation requested === + if (wifi_network_state == WIFI_STATE_STARTED) { + // Get current mode + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error getting WiFi mode (%d)", ret); + return mp_const_false; + } + if (self->wifi_mode & mode) { + wifi_mode_t new_mode = mode & ~self->wifi_mode; + if (new_mode == 0) { + // No mode is active, stop and deinitialize WiFi + wifi_network_state = WIFI_STATE_INIT; + wifi_sta_isconnected = false; + wifi_sta_has_ipaddress = false; + wifi_sta_changed_ipaddress = false; + wifi_ap_isconnected = false; + wifi_ap_sta_isconnected = false; + ret = esp_wifi_stop(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error stopping WiFi (%d)", ret); + } + vTaskDelay(5 / portTICK_PERIOD_MS); + esp_wifi_deinit(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error deinitializing WiFi (%d)", ret); + } + vTaskDelay(5 / portTICK_PERIOD_MS); + ESP_LOGI(MODNETTWORK_TAG, "WiFi Stopped"); + } + else { + _wifi_init(new_mode, (new_mode & WIFI_MODE_STA) & wifi_sta_reconnect); + } + } + } } - // Return new wifi status - if (wifi_network_state == 2) return mp_const_true; - else return mp_const_false; + +exit: + // === Return wifi status (started/not started) === + if (wifi_network_state != WIFI_STATE_STARTED) return mp_const_false; + // Get current mode + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error getting WiFi mode (%d)", ret); + return mp_const_false; + } + if (self->wifi_mode & mode) return mp_const_true; + return mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active); +//------------------------------------------ +static bool _check_wifi_started(bool except) +{ + if (wifi_network_state < WIFI_STATE_STARTED) { + if (except) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "WiFi not started")); + } + else { + ESP_LOGW(MODNETTWORK_TAG, "WiFi not started"); + return false; + } + } + return true; +} + // Connect to access point (only in STA mode) //---------------------------------------------------------------- STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *args) { - if (wifi_network_state < 2) { - ESP_LOGW("modnetwork", "WiFi not started"); - return mp_const_none; + if (!_check_wifi_started(false)) return mp_const_none; + + wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (self->wifi_mode != WIFI_MODE_STA) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Not supported in AP mode")); } - wifi_mode_t mode; + + wifi_mode_t mode; esp_err_t ret = esp_wifi_get_mode(&mode); if (ret != ESP_OK) { - ESP_LOGE("modnetwork", "Error getting WiFi mode (%d)", ret); + ESP_LOGE(MODNETTWORK_TAG, "Error getting WiFi mode (%d)", ret); return mp_const_none; } // Only connect if in STA mode - if ((mode & WIFI_MODE_STA) == 0) return mp_const_none; + if ((mode & WIFI_MODE_STA) == 0) { + ESP_LOGE(MODNETTWORK_TAG, "STA mode not started"); + return mp_const_none; + } mp_uint_t len; const char *p; @@ -642,7 +707,7 @@ STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *args) { } ret = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config); if (ret != ESP_OK) { - ESP_LOGE("modnetwork", "Error configuring WiFi (%d)", ret); + ESP_LOGE(MODNETTWORK_TAG, "Error configuring WiFi (%d)", ret); return mp_const_none; } } @@ -650,9 +715,9 @@ STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *args) { MP_THREAD_GIL_EXIT(); ret = esp_wifi_connect(); MP_THREAD_GIL_ENTER(); - if (ret == ESP_OK) wifi_sta_connected = true; + if (ret == ESP_OK) wifi_sta_reconnect = true; else { - ESP_LOGE("modnetwork", "Error connecting to AP (%d)", ret); + ESP_LOGE(MODNETTWORK_TAG, "Error connecting to AP (%d)", ret); } return mp_const_none; @@ -661,16 +726,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_connect_obj, 1, 7, esp_connect); //------------------------------------------------ STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) { - if (wifi_network_state < 2) { - ESP_LOGW("modnetwork", "WiFi not started"); - return mp_const_none; + if (!_check_wifi_started(false)) return mp_const_none; + + wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->wifi_mode != WIFI_MODE_STA) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Not supported in AP mode")); } - if (wifi_sta_connected) { + + if (wifi_sta_reconnect) { esp_err_t ret = esp_wifi_disconnect(); if (ret != ESP_OK) { - ESP_LOGW("modnetwork", "Error disconnecting from AP (%d)", ret); + ESP_LOGW(MODNETTWORK_TAG, "Error disconnecting from AP (%d)", ret); } - else wifi_sta_connected = false; + else wifi_sta_reconnect = false; } return mp_const_none; } @@ -678,11 +746,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect); //--------------------------------------------------------------- STATIC mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) { - if (wifi_network_state < 2) { - ESP_LOGW("modnetwork", "WiFi not started"); - return mp_const_none; - } - if (n_args == 1) { + if (!_check_wifi_started(false)) return mp_const_none; + + if (n_args == 1) { // no arguments: return None until link status is implemented return mp_const_none; } @@ -714,10 +780,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_status_obj, 1, 2, esp_status); //------------------------------------------------------------- STATIC mp_obj_t esp_scan(size_t n_args, const mp_obj_t *args) { - if (wifi_network_state < 2) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "WiFi not started")); - } - // check that STA mode is active + _check_wifi_started(true); + + // check that STA mode is active wifi_mode_t mode; esp_err_t ret = esp_wifi_get_mode(&mode); if (ret != ESP_OK) { @@ -759,18 +824,20 @@ STATIC mp_obj_t esp_scan(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_scan_obj, 1, 2, esp_scan); -//------------------------------------------------- -STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) { - if (wifi_network_state < 2) { - return mp_obj_new_bool(false); - } - wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); +//-------------------------------------------------------------------- +STATIC mp_obj_t esp_isconnected(size_t n_args, const mp_obj_t *args) { + if (!_check_wifi_started(false)) return mp_obj_new_bool(false); + + wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); + bool check_clients = true; + if (n_args > 1) check_clients = mp_obj_is_true(args[1]); + if (self->if_id == WIFI_IF_STA) { return mp_obj_new_bool(((wifi_sta_isconnected) && (wifi_sta_has_ipaddress))); } else { - bool res = false; - if (wifi_ap_isconnected) { + bool res = wifi_ap_isconnected; + if ((res) && (check_clients)) { wifi_sta_list_t sta; esp_wifi_ap_get_sta_list(&sta); res = (sta.num != 0); @@ -778,46 +845,56 @@ STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) { return mp_obj_new_bool(res); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isconnected_obj, esp_isconnected); - -//---------------------------------------------- -STATIC mp_obj_t esp_isactive(mp_obj_t self_in) { - if (wifi_network_state < 2) { - return mp_obj_new_bool(false); - } +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_isconnected_obj, 1, 2, esp_isconnected); +//--------------------------- +static bool wifi_is_started() +{ wifi_mode_t wifi_mode; esp_err_t ret = esp_wifi_get_mode(&wifi_mode); - if (ret != ESP_OK) return mp_obj_new_bool(false); + if (ret != ESP_OK) return false; + + bool sta_f = ((wifi_sta_isconnected) && (wifi_sta_has_ipaddress)); + bool ap_f = wifi_ap_isconnected; + if (wifi_mode == WIFI_MODE_STA) return sta_f; + else if (wifi_mode == WIFI_MODE_AP) return ap_f; + else if (wifi_mode == WIFI_MODE_APSTA) return (sta_f | ap_f); + return false; +} - if (wifi_mode == WIFI_MODE_STA) return mp_obj_new_bool(((wifi_sta_isconnected) && (wifi_sta_has_ipaddress))); - else if (wifi_mode == WIFI_MODE_AP) return mp_obj_new_bool(wifi_ap_isconnected); - return mp_obj_new_bool(false); +//---------------------------------------------- +STATIC mp_obj_t esp_isactive(mp_obj_t self_in) { + if (wifi_network_state < WIFI_STATE_STARTED) return mp_obj_new_bool(false); + + return mp_obj_new_bool(wifi_is_started()); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isactive_obj, esp_isactive); //----------------------------------------------------------------- STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { - if (wifi_network_state < 2) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "WiFi not started")); - } - wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (wifi_network_state < WIFI_STATE_INIT) { + mp_raise_ValueError("TCT/IP Adapter not initialized"); + } + + wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); tcpip_adapter_ip_info_t info; tcpip_adapter_dns_info_t dns_info; + tcpip_adapter_get_ip_info(self->if_id, &info); tcpip_adapter_get_dns_info(self->if_id, TCPIP_ADAPTER_DNS_MAIN, &dns_info); if (n_args == 1) { - // get configuration + // === Get configuration === mp_obj_t tuple[4] = { netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&info.netmask, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&info.gw, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&dns_info.ip, NETUTILS_BIG), }; + // Return tuple: (ip, netmask, gateway, dns_ip) return mp_obj_new_tuple(4, tuple); } else { - // set configuration parameters + // === set configuration parameters from tuple: (ip, netmask, gateway, dns_ip) === mp_obj_t *items; mp_obj_get_array_fixed_n(args[1], 4, &items); @@ -858,13 +935,83 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig); +//-------------------------------------------------------------------------------------- +static mp_obj_t get_config_param(uintptr_t arg, wlan_if_obj_t *self, wifi_config_t *cfg) +{ + mp_obj_t val = mp_const_none; + + #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) + mp_obj_tuple_t *t; + switch (arg) { + case QS(MP_QSTR_mac): { + uint8_t mac[6]; + if (esp_wifi_get_mac(self->if_id, mac) != ESP_OK) val = mp_const_false; + else val = mp_obj_new_bytes(mac, sizeof(mac)); + break; + } + case QS(MP_QSTR_essid): + if (self->if_id == WIFI_IF_AP) val = mp_obj_new_str((char*)cfg->ap.ssid, cfg->ap.ssid_len); + break; + case QS(MP_QSTR_hidden): + if (self->if_id == WIFI_IF_AP) val = mp_obj_new_bool(cfg->ap.ssid_hidden); + break; + case QS(MP_QSTR_authmode): + if (self->if_id == WIFI_IF_AP) { + t = mp_obj_new_tuple(2, NULL); + t->items[0] = MP_OBJ_NEW_SMALL_INT(cfg->ap.authmode); + t->items[1] = mp_obj_new_str(wifi_auth_modes[cfg->ap.authmode], strlen(wifi_auth_modes[cfg->ap.authmode])); + val = MP_OBJ_FROM_PTR(t); + } + break; + case QS(MP_QSTR_mode): + t = mp_obj_new_tuple(2, NULL); + t->items[0] = MP_OBJ_NEW_SMALL_INT(self->if_id); + if (self->if_id == WIFI_IF_STA) + t->items[1] = mp_obj_new_str("STA_IF", 6); + else t->items[1] = mp_obj_new_str("AP_IF", 5); + val = MP_OBJ_FROM_PTR(t); + break; + case QS(MP_QSTR_wifimode): + t = mp_obj_new_tuple(2, NULL); + wifi_mode_t mode; + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret == ESP_OK) { + t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); + if (mode ==WIFI_MODE_STA) t->items[1] = mp_obj_new_str("STA", 3); + else if (mode ==WIFI_MODE_AP) t->items[1] = mp_obj_new_str("AP", 2); + else if (mode ==WIFI_MODE_APSTA) t->items[1] = mp_obj_new_str("APSTA", 5); + else t->items[1] = mp_obj_new_str("Unknown", 7); + } + else { + t->items[0] = MP_OBJ_NEW_SMALL_INT(0); + t->items[1] = mp_obj_new_str("Unknown", 7); + } + val = MP_OBJ_FROM_PTR(t); + break; + case QS(MP_QSTR_channel): + if (self->if_id == WIFI_IF_AP) val = MP_OBJ_NEW_SMALL_INT(cfg->ap.channel); + break; + case QS(MP_QSTR_dhcp_hostname): { + const char *s; + if (tcpip_adapter_get_hostname(self->if_id, &s) != ESP_OK) val = mp_const_false; + else val = mp_obj_new_str(s, strlen(s)); + break; + } + default: + val = mp_obj_new_str("Unknown config param", 20); + } + #undef QS + + return val; +} + // Set or get wifi configuration parameters //--------------------------------------------------------------------------------- STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - if (wifi_network_state < 2) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "WiFi not started")); - } - if (n_args != 1 && kwargs->used != 0) { + //_check_wifi_started(true); + if (wifi_network_state < WIFI_STATE_STOPPED) _init_wifi(); + + if (n_args != 1 && kwargs->used != 0) { mp_raise_TypeError("either pos or kw args are allowed"); } @@ -930,7 +1077,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs break; } default: - goto unknown; + mp_raise_ValueError("unknown config param"); } #undef QS @@ -948,68 +1095,49 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs // Get config if (n_args != 2) { - mp_raise_TypeError("can query only one parameter"); + mp_raise_TypeError("only one query argument allowed"); } - int req_if = -1; mp_obj_t val; - - #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) - mp_obj_tuple_t *t; - switch ((uintptr_t)args[1]) { - case QS(MP_QSTR_mac): { - uint8_t mac[6]; - ESP_EXCEPTIONS(esp_wifi_get_mac(self->if_id, mac)); - return mp_obj_new_bytes(mac, sizeof(mac)); - } - case QS(MP_QSTR_essid): - req_if = WIFI_IF_AP; - val = mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len); - break; - case QS(MP_QSTR_hidden): - req_if = WIFI_IF_AP; - val = mp_obj_new_bool(cfg.ap.ssid_hidden); - break; - case QS(MP_QSTR_authmode): - req_if = WIFI_IF_AP; - t = mp_obj_new_tuple(2, NULL); - t->items[0] = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode); - t->items[1] = mp_obj_new_str(wifi_auth_modes[cfg.ap.authmode], strlen(wifi_auth_modes[cfg.ap.authmode])); - val = MP_OBJ_FROM_PTR(t); - break; - case QS(MP_QSTR_wifimode): - t = mp_obj_new_tuple(2, NULL); - t->items[0] = MP_OBJ_NEW_SMALL_INT(self->if_id); - if (self->if_id == WIFI_IF_STA) - t->items[1] = mp_obj_new_str("STA_IF", 6); - else t->items[1] = mp_obj_new_str("AP_IF", 5); - val = MP_OBJ_FROM_PTR(t); - break; - case QS(MP_QSTR_channel): - req_if = WIFI_IF_AP; - val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel); - break; - case QS(MP_QSTR_dhcp_hostname): { - const char *s; - ESP_EXCEPTIONS(tcpip_adapter_get_hostname(self->if_id, &s)); - val = mp_obj_new_str(s, strlen(s)); - break; - } - default: - goto unknown; + #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) + bool get_all = ((uintptr_t)args[1] == QS(MP_QSTR_all)); + + if (get_all) { + // Get all config parameters + mp_obj_dict_t *dct = mp_obj_new_dict(0); + + val = get_config_param(QS(MP_QSTR_mac), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("mac", 3), val); + val = get_config_param(QS(MP_QSTR_essid), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("essid", 5), val); + val = get_config_param(QS(MP_QSTR_hidden), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("hidden", 6), val); + val = get_config_param(QS(MP_QSTR_authmode), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("authmode", 8), val); + val = get_config_param(QS(MP_QSTR_mode), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("mode", 4), val); + val = get_config_param(QS(MP_QSTR_wifimode), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("wifimode", 8), val); + val = get_config_param(QS(MP_QSTR_channel), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("channel", 7), val); + val = get_config_param(QS(MP_QSTR_dhcp_hostname), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("dhcp_hostname", 13), val); + + val = dct; } - #undef QS - - // We post-check interface requirements to save on code size - if (req_if >= 0) { - require_if(args[0], req_if); + else { + // Get one config parameter + val = get_config_param((uintptr_t)args[1], self, &cfg); + if (val == mp_const_none) { + mp_raise_msg(&mp_type_OSError, self->if_id == WIFI_IF_STA ? "AP required" : "STA required"); + } + if (val == mp_const_false) { + mp_raise_msg(&mp_type_OSError, "Parameter not available"); + } } + #undef QS return val; - -unknown: - mp_raise_ValueError("unknown config param"); - return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config); @@ -1054,17 +1182,17 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_probereq_callback_obj, 1, 2, esp_ //======================================================== STATIC const mp_map_elem_t wlan_if_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_active), (mp_obj_t)&esp_active_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&esp_connect_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&esp_disconnect_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_status), (mp_obj_t)&esp_status_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&esp_scan_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&esp_isconnected_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_isactive), (mp_obj_t)&esp_isactive_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_config), (mp_obj_t)&esp_config_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&esp_ifconfig_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_eventCB), (mp_obj_t)&esp_callback_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_probereqCB), (mp_obj_t)&esp_probereq_callback_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_active), (mp_obj_t)&esp_active_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&esp_connect_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&esp_disconnect_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_status), (mp_obj_t)&esp_status_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&esp_scan_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&esp_isconnected_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_wifiactive), (mp_obj_t)&esp_isactive_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_config), (mp_obj_t)&esp_config_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&esp_ifconfig_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_eventCB), (mp_obj_t)&esp_callback_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_probereqCB), (mp_obj_t)&esp_probereq_callback_obj }, }; STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table); @@ -1091,6 +1219,45 @@ extern const mp_obj_type_t mqtt_type; #if defined(CONFIG_MICROPY_USE_TELNET) || defined(CONFIG_MICROPY_USE_FTPSERVER) #include "mpthreadport.h" + +//----------------------------- +static mp_obj_t get_listen_ip() +{ + if ((wifi_network_state == WIFI_STATE_STARTED) && (wifi_is_started())) { + wifi_mode_t mode; + tcpip_adapter_if_t tcpip_if = TCPIP_ADAPTER_IF_MAX; + int n_if = 0; + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret == ESP_OK) { + if (mode == WIFI_MODE_STA) { + n_if = 1; + tcpip_if = TCPIP_ADAPTER_IF_STA; + } + else if (mode == WIFI_MODE_AP) { + n_if = 1; + tcpip_if = TCPIP_ADAPTER_IF_AP; + } + else if (mode == WIFI_MODE_APSTA) n_if = 2; + } + if (n_if > 0) { + tcpip_adapter_ip_info_t info; + mp_obj_t ip_tuple[n_if]; + if (n_if == 1) { + tcpip_adapter_get_ip_info(tcpip_if, &info); + ip_tuple[0] = netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG); + } + else { + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &info); + ip_tuple[0] = netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG); + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &info); + ip_tuple[1] = netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG); + } + return mp_obj_new_tuple(n_if, ip_tuple); + } + } + return mp_const_none; +} + #endif //============================== @@ -1109,17 +1276,10 @@ STATIC mp_obj_t mod_network_startTelnet(mp_uint_t n_args, const mp_obj_t *pos_ar 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); - if (wifi_network_state < 2) { - ESP_LOGE("[Telnet_start]", "WiFi not started"); + if ((wifi_network_state < WIFI_STATE_STARTED) || (!wifi_is_started())) { + ESP_LOGE("[Telnet_start]", "WiFi not started or not connected"); return mp_const_false; } - wifi_mode_t wifi_mode = WIFI_MODE_MAX; - esp_err_t res = esp_wifi_get_mode(&wifi_mode); - if ((res != ESP_OK) || ((wifi_mode != WIFI_MODE_STA) && (wifi_mode != WIFI_MODE_AP))) { - ESP_LOGE("[Telnet_start]", "Error, (res=%d, mode=%d)", res, wifi_mode); - return mp_const_false; - } - ESP_LOGD("[Telnet_start]", "WiFi mode: %s", (wifi_mode == WIFI_MODE_STA) ? "STA" : "AP"); if (MP_OBJ_IS_STR(args[0].u_obj)) { snprintf(telnet_user, TELNET_USER_PASS_LEN_MAX, mp_obj_str_get_str(args[0].u_obj)); @@ -1176,7 +1336,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_network_TelnetMaxStack_obj, mod_network_Tel //-------------------------------------- STATIC mp_obj_t mod_network_stateTelnet() { - mp_obj_t tuple[2]; + mp_obj_t tuple[3]; char state[16] = {'\0'}; int telnet_state = telnet_getstate(); @@ -1191,8 +1351,9 @@ STATIC mp_obj_t mod_network_stateTelnet() tuple[0] = mp_obj_new_int(telnet_state); tuple[1] = mp_obj_new_str(state, strlen(state)); + tuple[2] = get_listen_ip(); - return mp_obj_new_tuple(2, tuple); + return mp_obj_new_tuple(3, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_network_stateTelnet_obj, mod_network_stateTelnet); @@ -1234,17 +1395,10 @@ STATIC mp_obj_t mod_network_startFtp(mp_uint_t n_args, const mp_obj_t *pos_args, 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); - if (wifi_network_state < 2) { - ESP_LOGE("[Ftp_start]", "WiFi not started"); + if ((wifi_network_state < WIFI_STATE_STARTED) || (!wifi_is_started())) { + ESP_LOGE("[Ftp_start]", "WiFi not started or not connected"); return mp_const_false; } - wifi_mode_t wifi_mode = WIFI_MODE_MAX; - esp_err_t res = esp_wifi_get_mode(&wifi_mode); - if ((res != ESP_OK) || ((wifi_mode != WIFI_MODE_STA) && (wifi_mode != WIFI_MODE_AP))) { - ESP_LOGE("[Ftp_start]", "Error, (res=%d, mode=%d)", res, wifi_mode); - return mp_const_false; - } - ESP_LOGD("[Ftp_start]", "WiFi mode: %s", (wifi_mode == WIFI_MODE_STA) ? "STA" : "AP"); if (MP_OBJ_IS_STR(args[0].u_obj)) { snprintf(ftp_user, FTP_USER_PASS_LEN_MAX, mp_obj_str_get_str(args[0].u_obj)); @@ -1304,7 +1458,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_network_FtpMaxStack_obj, mod_network_FtpMax //------------------------------------ STATIC mp_obj_t mod_network_stateFtp() { - mp_obj_t tuple[4]; + mp_obj_t tuple[5]; char state[20] = {'\0'}; int ftp_state, ftp_substate; @@ -1339,8 +1493,9 @@ STATIC mp_obj_t mod_network_stateFtp() else if (ftp_substate == E_FTP_STE_SUB_DATA_CONNECTED) sprintf(state, "Data: Connected"); else sprintf(state, "Unknown"); tuple[3] = mp_obj_new_str(state, strlen(state)); + tuple[4] = get_listen_ip(); - return mp_obj_new_tuple(4, tuple); + return mp_obj_new_tuple(5, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_network_stateFtp_obj, mod_network_stateFtp); @@ -1369,12 +1524,32 @@ const mp_obj_type_t network_ftp_type = { extern const mp_obj_type_t mdns_type; #endif +//-------------------------------------------------------------------- +STATIC mp_obj_t esp_wlan_callback(size_t n_args, const mp_obj_t *args) +{ + if (n_args == 0) { + if (event_callback == NULL) return mp_const_false; + return mp_const_true; + } + + if (wifi_mutex) xSemaphoreTake(wifi_mutex, 1000); + if ((MP_OBJ_IS_FUN(args[0])) || (MP_OBJ_IS_METH(args[0]))) { + event_callback = args[0]; + } + else event_callback = NULL; + if (wifi_mutex) xSemaphoreGive(wifi_mutex); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_wlan_callback_obj, 0, 1, esp_wlan_callback); + //============================================================== STATIC const mp_map_elem_t mp_module_network_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) }, { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&esp_initialize_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_wlan_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_WLANcallback), (mp_obj_t)&esp_wlan_callback_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj }, #ifdef CONFIG_MICROPY_USE_ETHERNET { MP_OBJ_NEW_QSTR(MP_QSTR_LAN), (mp_obj_t)&get_lan_obj }, diff --git a/MicroPython_BUILD/components/micropython/esp32/modnetwork.h b/MicroPython_BUILD/components/micropython/esp32/modnetwork.h index 7e6210a4..a2b5af81 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modnetwork.h +++ b/MicroPython_BUILD/components/micropython/esp32/modnetwork.h @@ -24,14 +24,23 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #ifndef MICROPY_INCLUDED_ESP32_MODNETWORK_H #define MICROPY_INCLUDED_ESP32_MODNETWORK_H +#include "esp_wifi_types.h" + +#define WIFI_STATE_NOTINIT -1 +#define WIFI_STATE_INIT 0 +#define WIFI_STATE_STOPPED 1 +#define WIFI_STATE_STARTED 2 + enum { PHY_LAN8720, PHY_TLK110 }; typedef struct _wlan_if_obj_t { mp_obj_base_t base; int if_id; + wifi_mode_t wifi_mode; } wlan_if_obj_t; typedef void (*wifi_sta_rx_probe_req_t)(const uint8_t *frame, int len, int rssi); diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/microWebSrv.py b/MicroPython_BUILD/components/micropython/esp32/modules/microWebSrv.py index a6b5b6cd..ddeea334 100755 --- a/MicroPython_BUILD/components/micropython/esp32/modules/microWebSrv.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules/microWebSrv.py @@ -245,7 +245,7 @@ def _serverProcess(self) : def Start(self, threaded=True, stackSize=8192) : if not self._started : - if not network.WLAN().isactive(): + if not network.WLAN().wifiactive(): print("WLAN not connected!") return gc.collect() diff --git a/MicroPython_BUILD/components/micropython/esp32/modules_examples/uftpserver.py b/MicroPython_BUILD/components/micropython/esp32/modules_examples/uftpserver.py index b4eee5df..d3ce4c10 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modules_examples/uftpserver.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules_examples/uftpserver.py @@ -148,8 +148,8 @@ def ftpserver(timeout = 300, inthread = False, prnip = True): if prnip: print ("Starting ftp server. Version 1.2") - if not network.WLAN().isconnected(): - print("Not connected!") + if not network.WLAN().wifiactive(): + print("WiFi not started!") return DATA_PORT = 1050 diff --git a/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c b/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c index eca4e801..665814cd 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c +++ b/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c @@ -700,29 +700,20 @@ int mp_thread_replAcceptMsg(int8_t accept) { #if defined(CONFIG_MICROPY_USE_TELNET) || defined(CONFIG_MICROPY_USE_FTPSERVER) // Check if WiFi connection is available -//---------------------- -static int _check_wifi() +//----------------------- +static bool _check_wifi() { - if (wifi_network_state < 2) return 2; + if (wifi_network_state < 2) return false; - tcpip_adapter_if_t if_type; - tcpip_adapter_ip_info_t info; + bool res = 0; wifi_mode_t wifi_mode; esp_err_t ret = esp_wifi_get_mode(&wifi_mode); - if (ret != ESP_OK) return 0; - if (wifi_mode == WIFI_MODE_AP) if_type = TCPIP_ADAPTER_IF_AP; - else if (wifi_mode == WIFI_MODE_STA) if_type = TCPIP_ADAPTER_IF_STA; - else return 2; - - ret = tcpip_adapter_get_ip_info(if_type, &info); - if (ret != ESP_OK) return 0; - if (info.ip.addr == 0) return 0; - - if ((wifi_mode == WIFI_MODE_STA) && ((!wifi_sta_isconnected) || (!wifi_sta_has_ipaddress))) return 0; - else if ((wifi_mode == WIFI_MODE_AP) && (!wifi_ap_isconnected)) return 0; - - return 1; + if (ret == ESP_OK) { + if ((wifi_mode & WIFI_MODE_STA) && ((wifi_sta_isconnected) && (wifi_sta_has_ipaddress))) res = true; + if ((wifi_mode & WIFI_MODE_AP) && wifi_ap_isconnected) res = true; + } + return res; } #endif @@ -730,45 +721,40 @@ static int _check_wifi() //=================================== void telnet_task (void *pvParameters) { - int res; // Initialize telnet, create rx buffer and mutex telnet_init(); // Check if WiFi connection is available - res = _check_wifi(); - while ( res == 0) { + while (!_check_wifi()) { vTaskDelay(1000 / portTICK_PERIOD_MS); - res = _check_wifi(); + if (telnet_stop_requested()) goto exit; } - if (res == 2) goto exit; // We have WiFi connection, enable telnet telnet_enable(); while (1) { - res = telnet_run(); + int res = telnet_run(); if ( res < 0) { if (res == -1) { ESP_LOGD("[Telnet]", "\nRun Error"); } + // -2 is returned if Telnet stop was requested by user break; } vTaskDelay(1); // ---- Check if WiFi is still available ---- - res = _check_wifi(); - if (res == 0) { + if (!_check_wifi()) { bool was_enabled = telnet_isenabled(); telnet_disable(); - while ( res == 0) { + while (!_check_wifi()) { vTaskDelay(200 / portTICK_PERIOD_MS); - res = _check_wifi(); - if (res == 2) goto exit; + if (telnet_stop_requested()) goto exit; } if (was_enabled) telnet_enable(); } - else if (res == 2) break; // ------------------------------------------ } exit: @@ -802,17 +788,14 @@ uintptr_t mp_thread_createTelnetTask(size_t stack_size) //================================ void ftp_task (void *pvParameters) { - int res; uint64_t elapsed, time_ms = mp_hal_ticks_ms(); // Initialize ftp, create rx buffer and mutex ftp_init(); - res = _check_wifi(); - while ( res == 0) { + while (!_check_wifi()) { vTaskDelay(1000 / portTICK_PERIOD_MS); - res = _check_wifi(); + if (ftp_stop_requested()) goto exit; } - if (res == 2) goto exit; // We have WiFi connection, enable ftp ftp_enable(); @@ -822,29 +805,27 @@ void ftp_task (void *pvParameters) elapsed = mp_hal_ticks_ms() - time_ms; time_ms = mp_hal_ticks_ms(); - res = ftp_run(elapsed); + int res = ftp_run(elapsed); if (res < 0) { if (res == -1) { ESP_LOGD("[Ftp]", "\nRun Error"); } + // -2 is returned if Ftp stop was requested by user break; } vTaskDelay(1); // ---- Check if WiFi is still available ---- - res = _check_wifi(); - if (res == 0) { + if (!_check_wifi()) { bool was_enabled = ftp_isenabled(); ftp_disable(); - while ( res == 0) { + while (!_check_wifi()) { vTaskDelay(200 / portTICK_PERIOD_MS); - res = _check_wifi(); - if (res == 2) goto exit; + if (ftp_stop_requested()) goto exit; } if (was_enabled) ftp_enable(); } - else if (res == 2) break; // ------------------------------------------ } exit: diff --git a/MicroPython_BUILD/components/micropython/esp32/mpversion.h b/MicroPython_BUILD/components/micropython/esp32/mpversion.h index f97137c1..79b5e865 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpversion.h +++ b/MicroPython_BUILD/components/micropython/esp32/mpversion.h @@ -24,12 +24,12 @@ * THE SOFTWARE. */ -#define MICROPY_GIT_TAG "ESP32_LoBo_v3.2.9" +#define MICROPY_GIT_TAG "ESP32_LoBo_v3.2.10" #define MICROPY_GIT_HASH "gbae9709a" -#define MICROPY_BUILD_DATE "2018-04-12" +#define MICROPY_BUILD_DATE "2018-04-15" #define MICROPY_VERSION_MAJOR (3) #define MICROPY_VERSION_MINOR (2) -#define MICROPY_VERSION_MICRO (9) -#define MICROPY_VERSION_STRING "3.2.9" +#define MICROPY_VERSION_MICRO (10) +#define MICROPY_VERSION_STRING "3.2.10" #define MICROPY_CORE_VERSION "59dda71" #define MICROPY_CORE_DATE "2018-04-10" diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip index f6342c3f..1715006a 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip index 452bbad4..43ffe31c 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip index 4e18c820..2f115a3b 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip index 47cd5338..a9afbb4f 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip index bc0c719f..78cf9503 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip index cfd70fd2..1e54afcd 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip differ diff --git a/MicroPython_BUILD/firmware/esp32/MicroPython.bin b/MicroPython_BUILD/firmware/esp32/MicroPython.bin index 85538bd3..f72b9196 100644 Binary files a/MicroPython_BUILD/firmware/esp32/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32/bootloader/bootloader.bin index a6d8cebd..1eb80594 100644 Binary files a/MicroPython_BUILD/firmware/esp32/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin index 219894ba..3cc8a9ff 100644 Binary files a/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin index 3c847866..eba0c0e2 100644 Binary files a/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin index 5c3dddab..c39bc31f 100644 Binary files a/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin index 9e5e22d2..57824051 100644 Binary files a/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram/MicroPython.bin index 36572238..b888569d 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_psram/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_psram/bootloader/bootloader.bin index cfea4379..bbf03a48 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_psram/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin index 878eeb76..f367953f 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin index 4ad4fa01..bffbd191 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin index 568d8845..9b2988e0 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin index ec8d9f5f..ef9fd221 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin differ