diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a61b56fbd..75847be3d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,7 +42,7 @@ build_ssc: - git clone $GITLAB_SSH_SERVER/yinling/SSC.git - cd SSC # try checkout same branch - - git checkout "${CI_BUILD_REF_NAME}_8266" || echo "Using default branch..." + - git checkout release/v3.2_8266 || echo "Using default branch..." - ./gen_misc_rtos.sh push_master_to_github: diff --git a/SUPPORT_POLICY_CN.md b/SUPPORT_POLICY_CN.md new file mode 100644 index 000000000..4dceb76ab --- /dev/null +++ b/SUPPORT_POLICY_CN.md @@ -0,0 +1,54 @@ +有关 ESP8266 RTOS SDK 的最新支持政策,详见 [支持期限政策](./SUPPORT_POLICY_CN.md)。 +支持期限政策 +================= + +* [English Version](./SUPPORT_POLICY_EN.md) + +ESP8266 RTOS SDK 的每个主要版本和次要版本(如 V3.0、V3.1 等)自其首次稳定版本发布之日起将维护 18 个月。 + +维护意味着 ESP8266 RTOS SDK 团队将会对 GitHub 上的发布分支继续进行 bug 修复、安全修补等,并根据需求定期发布新的 bugfix 版本。 + +在某一版本支持期限结束,停止更新维护 (EOL) 前,建议用户升级到较新的 ESP8266 RTOS SDK 版本。根据《支持期限政策》,我们将停止对 EOL 版本进行 bug 修复。 + +《支持期限政策》不适用于预发布版本(包括 beta、preview、`-rc` 和 `-dev` 版本等)。有时,在发布的版本中存在被标记为 "Preview" 的特定功能,则该功能也不在支持期限内。 + +长期支持版本 +------------ + +有些发布版本(例如 ESP8266 RTOS SDK V3.1)属于长期支持 (LTS) 版本。LTS 版本将自其首次稳定版本发布之日起维护 30 个月(2.5 年)。 + +关于长期维护版本,在 github 上面正式的`第1次`发布该版本 release 的时候,会在标题上额外标注 `(LTS)`,例如: + +``` +ESP8266 RTOS SDK Release v3.4 (LTS) +``` + +后续的维护版本不会再额外标注 `(LTS)`,例如: + +``` +ESP8266 RTOS SDK Release v3.4.1 +``` + +示例 +----- + +ESP8266 RTOS SDK V3.1 于 2019 年 01 月发布,属于 LTS 版本,自正式发布日开始将维护 30 个月至 2021 年 07 月停止。 + +- V3.1 的首个发布版本为 2019 年 01 月发布的 `v3.1`。 +- ESP8266 RTOS SDK 团队将持续进行 bug 修复、安全修补等更新,并 backport 至分支 `release/v3.1`。 +- 定期从 release 分支创建稳定的 bugfix 版本,比如,`v3.1.1`、`v3.1.2` 等,并建议用户保持使用最新的 bugfix 版本。 +- V3.1 的 bugfix 版本发布将持续 30 个月至 2021 年 07 月,届时所有 V3.1.x 将停止更新维护。 + +现有版本 +-------- + +ESP8266 RTOS SDK V3.3 及所有后续更新版本都将遵守该《支持期限政策》。每一版本发布时将同时公布其支持期限。 + +对于该政策公布之日前发布的其他版本,应适用下述支持期限: + +- ESP8266 RTOS SDK V3.3.x 将维护至 2021 年 12 月。 +- ESP8266 RTOS SDK V3.2.x 将维护至 2020 年 12 月。 +- ESP8266 RTOS SDK V3.1.x 作为长期维护版本,将维护至 2021 年 7 月。 +- ESP8266 RTOS SDK V3.0.x 将维护至 2020 年 10 月。 +- ESP8266 RTOS SDK V2.1.x 作为长期维护版本,将维护至 2021 年 4 月。 +- ESP8266 RTOS SDK V2.0.x 及之前的版本均已停止更新维护 (EOL)。 \ No newline at end of file diff --git a/SUPPORT_POLICY_EN.md b/SUPPORT_POLICY_EN.md new file mode 100644 index 000000000..cb8c5533e --- /dev/null +++ b/SUPPORT_POLICY_EN.md @@ -0,0 +1,56 @@ +The latest support policy for ESP8266 RTOS SDK can be found at [Support Policy](./SUPPORT_POLICY_EN.md). + +Support Period Policy +================= + +* [中文版](./SUPPORT_POLICY_CN.md) + +Each ESP8266 RTOS SDK major and minor release (V3.0, V3.1, etc) is supported for 18 months after the initial stable release date. + +Supported means that the ESP8266 RTOS SDK team will continue to apply bug fixes, security fixes, etc to the release branch on GitHub, and periodically make new bugfix releases as needed. + +Users are encouraged to upgrade to a newer ESP8266 RTOS SDK release before the support period finishes and the release becomes End of Life (EOL). It is our policy to not continue fixing bugs in End of Life releases. + +Pre-release versions (betas, previews, -rc and -dev versions, etc) are not covered by any support period. Sometimes a particular feature is marked as "Preview" in a release, which means it is also not covered by the support period. + + +Long Term Support releases +------------ + +Some releases (for example, ESP8266 RTOS SDK V3.1) are designated Long Term Support (LTS). LTS releases are supported for 30 months (2.5 years) after the initial stable release date. + +We will add a `(LTS)` tag when we release a long term support version on GitHub at the first time. For example: + +``` +ESP8266 RTOS SDK Release v3.4 (LTS) +``` + +But we will not add `(LTS)` tag to the following bug fix versions. For example: + +``` +ESP8266 RTOS SDK Release v3.4.1 +``` + +Example +----- + +ESP8266 RTOS SDK V3.1 was released in January 2019 and is a Long Term Support (LTS) release, meaning it will be supported for 30 months until July 2021. + +- The first V3.1 release was `v3.1` in January 2019. +- The ESP8266 RTOS SDK team continues to backport bug fixes, security fixes, etc to the release branch `release/v3.1`。 +- Periodically stable bugfix releases are created from the release branch. For example `v3.1.1`、`v3.1.2`, etc. Users are encouraged to always update to the latest bugfix release. +- V3.1 bugfix releases continue until July 2021, when all V3.1.x releases become End of Life. + +Existing Releases +-------- + +ESP8266 RTOS SDK V3.3 and all newer releases will follow this support period policy. The support period for each release will be announced when the release is made. + +For releases made before the support period policy was announced, the following support periods apply: + +- ESP8266 RTOS SDK V3.2.x will be supported until December 2021. +- ESP8266 RTOS SDK V3.2.x will be supported until December 2020. +- ESP8266 RTOS SDK V3.1.x is Long Term Support (LTS) release, will be supported until July 2021. +- ESP8266 RTOS SDK V3.0.x will be supported until October 2020. +- ESP8266 RTOS SDK V2.1.x is Long Term Support (LTS) release, will be supported until April 2021. +- ESP8266 RTOS SDK V2.0.x and earlier versions are already End of Life. diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index d16d3c6bd..e553f66fa 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -10,6 +10,15 @@ config BOOTLOADER_INIT_SPI_FLASH If your system bootloader is based on v3.0, the option must not be enable, because the v3.0 bootloader don't support this function. +config BOOTLOADER_DISABLE_JTAG_IO + bool "Bootloader disable JTAG I/O" + default n + help + Enable this option, when SoC brings up and bootloader initializes hardware, it will + disable JTAG's I/O and set these GPIOs to be normal I/O with inputting mode. + + If users use JTAG to help develop, please disable this option. + choice LOG_BOOTLOADER_LEVEL bool "Bootloader log verbosity" default LOG_BOOTLOADER_LEVEL_INFO @@ -162,6 +171,14 @@ config BOOTLOADER_HOLD_TIME_GPIO The GPIO must be held low continuously for this period of time after reset before a factory reset or test partition boot (as applicable) is performed. +config BOOTLOADER_STORE_OFFSET + hex "Bootloader store offset in the flash" + default 0x0 + help + Bootloader store offset in the flash, if you have extra private bootloader to boot the + bootloader of the SDK's bootloader, you can set the option to store SDK's bootloader + to other space in the flash instead of "0x0". + endmenu # Bootloader diff --git a/components/bootloader/Makefile.projbuild b/components/bootloader/Makefile.projbuild index 734e30925..070706fd1 100644 --- a/components/bootloader/Makefile.projbuild +++ b/components/bootloader/Makefile.projbuild @@ -18,7 +18,7 @@ SECURE_BOOT_SIGNING_KEY=$(abspath $(call dequote,$(CONFIG_SECURE_BOOT_SIGNING_KE export SECURE_BOOT_SIGNING_KEY # used by bootloader_support component # Has a matching value in bootloader_support esp_flash_partitions.h -BOOTLOADER_OFFSET := 0x0000 +BOOTLOADER_OFFSET := $(CONFIG_BOOTLOADER_STORE_OFFSET) # Custom recursive make for bootloader sub-project # diff --git a/components/bootloader_support/src/bootloader_flash.c b/components/bootloader_support/src/bootloader_flash.c index 23c531f09..f93226b3a 100644 --- a/components/bootloader_support/src/bootloader_flash.c +++ b/components/bootloader_support/src/bootloader_flash.c @@ -268,6 +268,12 @@ esp_err_t bootloader_flash_erase_sector(size_t sector) #include "esp_spi_flash.h" #endif +#ifdef CONFIG_SOC_FULL_ICACHE +#define SOC_CACHE_SIZE 1 // 32KB +#else +#define SOC_CACHE_SIZE 0 // 16KB +#endif + extern void Cache_Read_Disable(); extern void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v); @@ -290,21 +296,48 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size) return NULL; /* can't map twice */ } - /* ToDo: Improve the map policy! */ - - Cache_Read_Disable(); + /* 0: 0x000000 - 0x1fffff */ + /* 1: 0x200000 - 0x3fffff */ + /* 2: 0x400000 - 0x5fffff */ + /* 3: 0x600000 - 0x7fffff */ + + uint32_t region; + uint32_t sub_region; + uint32_t mapped_src; + + if (src_addr < 0x200000) { + region = 0; + } else if (src_addr < 0x400000) { + region = 1; + } else if (src_addr < 0x600000) { + region = 2; + } else if (src_addr < 0x800000) { + region = 3; + } else { + ESP_LOGE(TAG, "flash mapped address %p is invalid", (void *)src_addr); + while (1); + } - /* 0 and 0x100000 address use same mmap addresss 0x40200000 */ - if (src_addr < 0x100000) { - Cache_Read_Enable(0, 0, 0); + /* 0: 0x000000 - 0x0fffff \ */ + /* \ */ + /* 0x40200000 */ + /* / */ + /* 1: 0x100000 - 0x1fffff / */ + mapped_src = src_addr & 0x1fffff; + if (mapped_src < 0x100000) { + sub_region = 0; } else { - Cache_Read_Enable(1, 0, 0); - src_addr -= 0x100000; + sub_region = 1; + mapped_src -= 0x100000; } + Cache_Read_Disable(); + + Cache_Read_Enable(sub_region, region, SOC_CACHE_SIZE); + mapped = true; - return (void *)(0x40200000 + src_addr); + return (void *)(0x40200000 + mapped_src); } void bootloader_munmap(const void *mapping) diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 1c7fef45c..f98f4ff77 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -613,6 +613,17 @@ esp_err_t bootloader_init() static esp_err_t bootloader_main() { +#ifdef CONFIG_BOOTLOADER_DISABLE_JTAG_IO + /* Set GPIO 12-15 to be normal GPIO */ + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); + + /* Set GPIO 12-15 to be input mode */ + GPIO_REG_WRITE(GPIO_ENABLE_W1TC_ADDRESS, BIT12 | BIT13 | BIT14 | BIT15); +#endif + uart_console_configure(); esp_image_header_t fhdr; diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index de4c66631..a792caf83 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -495,15 +495,6 @@ static void set_cache_and_start_app( #include "esp_flash_partitions.h" #include "internal/esp_system_internal.h" -#ifdef CONFIG_SOC_FULL_ICACHE -#define SOC_CACHE_SIZE 1 // 32KB -#else -#define SOC_CACHE_SIZE 0 // 16KB -#endif - -#define ESP_CACHE1_ADDR_MAX 0x100000 -#define ESP_CACHE2_ADDR_MAX 0x200000 - static const char* TAG = "boot"; bool bootloader_utility_load_partition_table(bootloader_state_t* bs) @@ -803,7 +794,6 @@ bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_ void bootloader_utility_load_image(const esp_image_metadata_t* image_data) { void (*user_start)(size_t start_addr); - extern void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v); #if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED) esp_err_t err; @@ -848,22 +838,7 @@ void bootloader_utility_load_image(const esp_image_metadata_t* image_data) copy loaded segments to RAM, set up caches for mapped segments, and start application unpack_load_app(image_data); #else - size_t map; - - if (image_data->start_addr < ESP_CACHE1_ADDR_MAX - && image_data->start_addr + image_data->image_len < ESP_CACHE1_ADDR_MAX) { - map = 0; - } else if (image_data->start_addr >= ESP_CACHE1_ADDR_MAX - && image_data->start_addr < ESP_CACHE2_ADDR_MAX - && image_data->start_addr + image_data->image_len < ESP_CACHE2_ADDR_MAX) { - map = 1; - } else { - ESP_LOGE(TAG, "ERROR: app bin error, start_addr %x image_len %d\n", image_data->start_addr, image_data->image_len); - /* Blocking here to let user judge. */ - while (1); - } - - Cache_Read_Enable(map, 0, SOC_CACHE_SIZE); + bootloader_mmap(image_data->start_addr, image_data->image_len); user_start = (void *)image_data->image.entry_addr; user_start(image_data->start_addr); diff --git a/components/esp8266/Kconfig b/components/esp8266/Kconfig index 67bdcdb49..6eef3d65c 100644 --- a/components/esp8266/Kconfig +++ b/components/esp8266/Kconfig @@ -472,9 +472,12 @@ config ESP_PHY_CALIBRATION_AND_DATA_STORAGE default y help If this option is enabled, NVS will be initialized and calibration data will be loaded from there. - PHY calibration will be skipped on deep sleep wakeup. If calibration data is not found, full calibration - will be performed and stored in NVS. Normally, only partial calibration will be performed. - If this option is disabled, full calibration will be performed. + If calibration data is not found, full calibration will be performed and stored in NVS. Normally, + only partial calibration will be performed. If this option is disabled, full calibration will be performed. + + Full calibration needs 170 - 180ms. + Partial calibration needs 35 - 40ms. + No calibration needs 3.260 - 3.264ms. If it's easy that your board calibrate bad data, choose 'n'. Two cases for example, you should choose 'n': diff --git a/components/esp8266/driver/gpio.c b/components/esp8266/driver/gpio.c index 460cd6f22..a0124f669 100644 --- a/components/esp8266/driver/gpio.c +++ b/components/esp8266/driver/gpio.c @@ -86,7 +86,10 @@ static gpio_isr_func_t *gpio_isr_func = NULL; esp_err_t gpio_pullup_en(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(!RTC_GPIO_IS_VALID_GPIO(gpio_num), "The RTC GPIO of esp8266 can not be pulled up.", ESP_ERR_INVALID_ARG); + + if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); @@ -98,7 +101,10 @@ esp_err_t gpio_pullup_en(gpio_num_t gpio_num) esp_err_t gpio_pullup_dis(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(!RTC_GPIO_IS_VALID_GPIO(gpio_num), "The RTC GPIO of esp8266 can not be pulled up.", ESP_ERR_INVALID_ARG); + + if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); @@ -110,7 +116,10 @@ esp_err_t gpio_pullup_dis(gpio_num_t gpio_num) esp_err_t gpio_pulldown_en(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "The GPIO of esp8266 can not be pulled down except RTC GPIO.", ESP_ERR_INVALID_ARG); + + if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); @@ -122,7 +131,10 @@ esp_err_t gpio_pulldown_en(gpio_num_t gpio_num) esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); - GPIO_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "The GPIO of esp8266 can not be pulled down except RTC GPIO.", ESP_ERR_INVALID_ARG); + + if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) { + return ESP_OK; + } gpio_pin_reg_t pin_reg; pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(gpio_num)); diff --git a/components/esp8266/driver/uart.c b/components/esp8266/driver/uart.c index 66841ffa2..02e4f84d1 100644 --- a/components/esp8266/driver/uart.c +++ b/components/esp8266/driver/uart.c @@ -419,6 +419,11 @@ esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void *), void *arg) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + for (int num = 0; num < UART_NUM_MAX; num++) { + if (p_uart_obj[num] == NULL) { + uart_disable_intr_mask(num, UART_INTR_MASK); + } + } UART_ENTER_CRITICAL(); _xt_isr_mask(1 << ETS_UART_INUM); _xt_isr_attach(ETS_UART_INUM, uart_intr_service, NULL); @@ -587,7 +592,12 @@ static void uart_rx_intr_handler_default(void *param) } if (p_uart->tx_len_tot == 0) { - en_tx_flg = false; + if (tx_fifo_rem == 0) { + en_tx_flg = true; + } else{ + en_tx_flg = false; + } + xSemaphoreGiveFromISR(p_uart->tx_done_sem, &task_woken); if (task_woken == pdTRUE) { portYIELD_FROM_ISR(); diff --git a/components/esp8266/include/esp8266/eagle_soc.h b/components/esp8266/include/esp8266/eagle_soc.h index 0a83c6367..d1345553c 100644 --- a/components/esp8266/include/esp8266/eagle_soc.h +++ b/components/esp8266/include/esp8266/eagle_soc.h @@ -117,6 +117,7 @@ //}} //Interrupt remap control registers define{{ +#define NMI_INT_ENABLE_REG (PERIPHS_DPORT_BASEADDR) #define EDGE_INT_ENABLE_REG (PERIPHS_DPORT_BASEADDR + 0x04) #define WDT_EDGE_INT_ENABLE() SET_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT0) #define TM1_EDGE_INT_ENABLE() SET_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1) diff --git a/components/esp8266/include/esp8266/rom_functions.h b/components/esp8266/include/esp8266/rom_functions.h index cabdb2ebc..012fde057 100644 --- a/components/esp8266/include/esp8266/rom_functions.h +++ b/components/esp8266/include/esp8266/rom_functions.h @@ -42,4 +42,8 @@ int SPIEraseSector(uint32_t sector_num); void Cache_Read_Disable(); void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v); +void rom_software_reboot(void); + +void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data); + #endif diff --git a/components/esp8266/ld/esp8266.ld b/components/esp8266/ld/esp8266.ld index cff625b10..85f3d1762 100644 --- a/components/esp8266/ld/esp8266.ld +++ b/components/esp8266/ld/esp8266.ld @@ -27,7 +27,7 @@ MEMORY iram1_0_seg : org = 0x40100000, len = CONFIG_SOC_IRAM_SIZE /* It is actually mapped to flash. */ - irom0_0_seg : org = 0x40200010 + APP_OFFSET, len = APP_SIZE - 0x10 + irom0_0_seg : org = 0x40200010 + (APP_OFFSET & (0x100000 - 1)), len = APP_SIZE - 0x10 /* RTC memory, persists over deep sleep. */ rtc_seg : org = 0x60001200, len = 0x200 diff --git a/components/esp8266/ld/esp8266.rom.ld b/components/esp8266/ld/esp8266.rom.ld index 944b2929c..4dfe07855 100644 --- a/components/esp8266/ld/esp8266.rom.ld +++ b/components/esp8266/ld/esp8266.rom.ld @@ -64,3 +64,5 @@ PROVIDE ( rom_i2c_readReg = 0x40007268 ); PROVIDE ( rom_i2c_readReg_Mask = 0x4000729c ); PROVIDE ( rom_i2c_writeReg = 0x400072d8 ); PROVIDE ( rom_i2c_writeReg_Mask = 0x4000730c ); + +PROVIDE ( rom_software_reboot = 0x40000080 ); diff --git a/components/esp8266/lib/VERSION b/components/esp8266/lib/VERSION index 5c01ef87c..eca48fe6b 100644 --- a/components/esp8266/lib/VERSION +++ b/components/esp8266/lib/VERSION @@ -1,10 +1,10 @@ gwen: - core: 0dd3307 - net80211: aceeb79 - pp: 522f8df - wpa: 33a48e5 - espnow: da96924 - wps: da96924 + core: bdbba7d + net80211: 3862e3c + pp: bf26f66 + wpa: bf26f66 + espnow: bf26f66 + wps: bf26f66 smartconfig: 2.8.1 - phy: 1055_22 + phy: 1058.15 diff --git a/components/esp8266/lib/libcore.a b/components/esp8266/lib/libcore.a index fc5e7d18d..bb0183b78 100644 Binary files a/components/esp8266/lib/libcore.a and b/components/esp8266/lib/libcore.a differ diff --git a/components/esp8266/lib/libcore_dbg.a b/components/esp8266/lib/libcore_dbg.a index 6f59d7857..e80733b46 100644 Binary files a/components/esp8266/lib/libcore_dbg.a and b/components/esp8266/lib/libcore_dbg.a differ diff --git a/components/esp8266/lib/libespnow.a b/components/esp8266/lib/libespnow.a index e2a9ace91..427232934 100644 Binary files a/components/esp8266/lib/libespnow.a and b/components/esp8266/lib/libespnow.a differ diff --git a/components/esp8266/lib/libespnow_dbg.a b/components/esp8266/lib/libespnow_dbg.a index 9e6c5ef26..94a02f7c0 100644 Binary files a/components/esp8266/lib/libespnow_dbg.a and b/components/esp8266/lib/libespnow_dbg.a differ diff --git a/components/esp8266/lib/libnet80211.a b/components/esp8266/lib/libnet80211.a index f85f007c0..9956faebf 100644 Binary files a/components/esp8266/lib/libnet80211.a and b/components/esp8266/lib/libnet80211.a differ diff --git a/components/esp8266/lib/libnet80211_dbg.a b/components/esp8266/lib/libnet80211_dbg.a index 22cfa8c71..a030f9e70 100644 Binary files a/components/esp8266/lib/libnet80211_dbg.a and b/components/esp8266/lib/libnet80211_dbg.a differ diff --git a/components/esp8266/lib/libphy.a b/components/esp8266/lib/libphy.a old mode 100644 new mode 100755 index e6bb4f88b..eeb014efa Binary files a/components/esp8266/lib/libphy.a and b/components/esp8266/lib/libphy.a differ diff --git a/components/esp8266/lib/libpp.a b/components/esp8266/lib/libpp.a index 7f6691f61..335f524e7 100644 Binary files a/components/esp8266/lib/libpp.a and b/components/esp8266/lib/libpp.a differ diff --git a/components/esp8266/lib/libpp_dbg.a b/components/esp8266/lib/libpp_dbg.a index 52086e39a..a7f80bc6c 100644 Binary files a/components/esp8266/lib/libpp_dbg.a and b/components/esp8266/lib/libpp_dbg.a differ diff --git a/components/esp8266/lib/libwpa.a b/components/esp8266/lib/libwpa.a index 52a28d236..d834e56c6 100644 Binary files a/components/esp8266/lib/libwpa.a and b/components/esp8266/lib/libwpa.a differ diff --git a/components/esp8266/lib/libwpa_dbg.a b/components/esp8266/lib/libwpa_dbg.a index d2b58d64c..579944f12 100644 Binary files a/components/esp8266/lib/libwpa_dbg.a and b/components/esp8266/lib/libwpa_dbg.a differ diff --git a/components/esp8266/lib/libwps.a b/components/esp8266/lib/libwps.a index 071e620bc..66ba093cf 100644 Binary files a/components/esp8266/lib/libwps.a and b/components/esp8266/lib/libwps.a differ diff --git a/components/esp8266/lib/libwps_dbg.a b/components/esp8266/lib/libwps_dbg.a index a4a877c21..95d19a1de 100644 Binary files a/components/esp8266/lib/libwps_dbg.a and b/components/esp8266/lib/libwps_dbg.a differ diff --git a/components/esp8266/source/esp_timer.c b/components/esp8266/source/esp_timer.c index 9caa0fab3..cb4c1f67d 100644 --- a/components/esp8266/source/esp_timer.c +++ b/components/esp8266/source/esp_timer.c @@ -22,6 +22,14 @@ #define ESP_TIMER_HZ CONFIG_FREERTOS_HZ +typedef enum { + ESP_TIMER_INIT = 0, + ESP_TIMER_ONCE, + ESP_TIMER_CYCLE, + ESP_TIMER_STOP, + ESP_TIMER_DELETE, +} esp_timer_state_t; + struct esp_timer { TimerHandle_t os_timer; @@ -29,26 +37,64 @@ struct esp_timer { void *arg; - TickType_t period_ticks; + esp_timer_state_t state; }; static const char *TAG = "esp_timer"; +static esp_err_t delete_timer(esp_timer_handle_t timer) +{ + BaseType_t ret = xTimerDelete(timer->os_timer, portMAX_DELAY); + if (ret == pdPASS) + heap_caps_free(timer); + + return ret == pdPASS ? ESP_OK : ESP_ERR_NO_MEM; +} + /** * @brief FreeRTOS callback function */ static void esp_timer_callback(TimerHandle_t xTimer) { - BaseType_t os_ret; struct esp_timer *timer = (struct esp_timer *)pvTimerGetTimerID(xTimer); timer->cb(timer->arg); - if (!timer->period_ticks) { - os_ret = xTimerStop(timer->os_timer, 0); - if (os_ret != pdPASS) { - ESP_LOGE(TAG, "Set timer from periodic to once error"); + switch (timer->state) { + case ESP_TIMER_INIT: + case ESP_TIMER_STOP: + break; + case ESP_TIMER_CYCLE: { + BaseType_t ret = xTimerReset(timer->os_timer, portMAX_DELAY); + if (ret != pdPASS) { + ESP_LOGE(TAG, "start timer at callback error"); + } else { + ESP_LOGD(TAG, "start timer at callback OK"); + } + break; + } + case ESP_TIMER_ONCE: { + BaseType_t ret = xTimerStop(timer->os_timer, portMAX_DELAY); + if (ret != pdPASS) { + ESP_LOGE(TAG, "stop timer at callback error"); + } else { + timer->state = ESP_TIMER_STOP; + ESP_LOGD(TAG, "stop timer at callback OK"); + } + break; + } + case ESP_TIMER_DELETE: { + esp_err_t ret = delete_timer(timer); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "delete timer at callback error"); + } else { + ESP_LOGD(TAG, "delete timer at callback OK"); + } + break; } + default: + ESP_LOGE(TAG, "timer state error is %d", timer->state); + break; } } @@ -84,17 +130,16 @@ esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, if (!esp_timer) return ESP_ERR_NO_MEM; - esp_timer->cb = create_args->callback; - esp_timer->arg = create_args->arg; - esp_timer->period_ticks = 0; - os_timer = xTimerCreate(create_args->name, portMAX_DELAY, - pdTRUE, + pdFALSE, esp_timer, esp_timer_callback); if (os_timer) { esp_timer->os_timer = os_timer; + esp_timer->cb = create_args->callback; + esp_timer->arg = create_args->arg; + esp_timer->state = ESP_TIMER_INIT; *out_handle = (esp_timer_handle_t)esp_timer; } else { heap_caps_free(esp_timer); @@ -121,14 +166,7 @@ esp_err_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us) os_ret = xTimerChangePeriod(os_timer, ticks, portMAX_DELAY); if (os_ret == pdPASS) { - TickType_t period_ticks = timer->period_ticks; - - timer->period_ticks = 0; - os_ret = xTimerStart(os_timer, portMAX_DELAY); - if (os_ret != pdPASS) { - timer->period_ticks = period_ticks; - return ESP_ERR_INVALID_STATE; - } + timer->state = ESP_TIMER_ONCE; } else { return ESP_ERR_INVALID_STATE; } @@ -153,14 +191,7 @@ esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) os_ret = xTimerChangePeriod(os_timer, ticks, portMAX_DELAY); if (os_ret == pdPASS) { - TickType_t period_ticks = timer->period_ticks; - - timer->period_ticks = ticks; - os_ret = xTimerStart(os_timer, portMAX_DELAY); - if (os_ret != pdPASS) { - timer->period_ticks = period_ticks; - return ESP_ERR_INVALID_STATE; - } + timer->state = ESP_TIMER_CYCLE; } else { return ESP_ERR_INVALID_STATE; } @@ -179,6 +210,8 @@ esp_err_t esp_timer_stop(esp_timer_handle_t timer) BaseType_t os_ret; os_ret = xTimerStop(os_timer, portMAX_DELAY); + if (os_ret == pdPASS) + timer->state = ESP_TIMER_STOP; return os_ret == pdPASS ? ESP_OK : ESP_ERR_INVALID_STATE; } @@ -188,35 +221,46 @@ esp_err_t esp_timer_stop(esp_timer_handle_t timer) */ esp_err_t esp_timer_delete(esp_timer_handle_t timer) { + esp_err_t ret; + assert(timer); - TimerHandle_t os_timer = timer->os_timer; - BaseType_t os_ret; + if (xTimerGetTimerDaemonTaskHandle() == xTaskGetCurrentTaskHandle()) { + timer->state = ESP_TIMER_DELETE; + ret = ESP_OK; + } else { + UBaseType_t prio = uxTaskPriorityGet(NULL); + if (prio >= configTIMER_TASK_PRIORITY) + vTaskPrioritySet(NULL, configTIMER_TASK_PRIORITY - 1); + else + prio = 0; - os_ret = xTimerDelete(os_timer, portMAX_DELAY); - if (os_ret == pdPASS) - heap_caps_free(timer); + ret = delete_timer(timer); + + if (prio) + vTaskPrioritySet(NULL, prio); + } - return os_ret == pdPASS ? ESP_OK : ESP_ERR_INVALID_STATE; + return ret; } int64_t esp_timer_get_time() { - extern esp_tick_t g_cpu_ticks; extern uint64_t g_os_ticks; esp_irqflag_t flag; - esp_tick_t diff_ticks, ticks; + uint64_t diff_ticks, ticks, prev_ticks; uint64_t time; flag = soc_save_local_irq(); time = g_os_ticks * portTICK_PERIOD_MS * 1000; + prev_ticks = soc_get_ccompare() - _xt_tick_divisor; ticks = soc_get_ticks(); - if (ticks >= g_cpu_ticks) { - diff_ticks = ticks - g_cpu_ticks; + if (ticks >= prev_ticks) { + diff_ticks = ticks - prev_ticks; } else { - diff_ticks = ESP_TICKS_MAX - g_cpu_ticks + ticks; + diff_ticks = ESP_TICKS_MAX - prev_ticks + ticks; } time += diff_ticks / (_xt_tick_divisor * configTICK_RATE_HZ / (1000 * 1000)); diff --git a/components/esp8266/source/phy.h b/components/esp8266/source/phy.h index 32c5376d4..b3cd5fd10 100644 --- a/components/esp8266/source/phy.h +++ b/components/esp8266/source/phy.h @@ -26,6 +26,8 @@ uint8_t phy_check_data_table(uint32_t *table, uint8_t, uint8_t); void phy_afterwake_set_rfoption(uint8_t); +void phy_set_powerup_option(uint8_t); + void write_data_to_rtc(uint8_t *); void get_data_from_rtc(uint8_t *); diff --git a/components/esp8266/source/phy_init.c b/components/esp8266/source/phy_init.c index 3f9814127..3dedf5d84 100644 --- a/components/esp8266/source/phy_init.c +++ b/components/esp8266/source/phy_init.c @@ -76,6 +76,7 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat #endif memcpy(local_init_data, init_data->params, 128); + memcpy(local_init_data + 128, calibration_data->rf_cal_data, 128); extern uint32_t* phy_rx_gain_dc_table; phy_rx_gain_dc_table = calibration_data->rx_gain_dc_table; @@ -85,7 +86,10 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat phy_afterwake_set_rfoption(1); if (!cal_data_check) { + phy_set_powerup_option(1); write_data_to_rtc(calibration_data->rf_cal_data); + } else { + phy_set_powerup_option(3); } esp_efuse_mac_get_default(sta_mac); diff --git a/components/freertos/port/esp8266/panic.c b/components/freertos/port/esp8266/panic.c index 036a9329f..683c01f0a 100644 --- a/components/freertos/port/esp8266/panic.c +++ b/components/freertos/port/esp8266/panic.c @@ -17,10 +17,13 @@ #include "esp_attr.h" #include "esp_libc.h" #include "esp_system.h" +#include "esp_task_wdt.h" +#include "internal/esp_system_internal.h" #include "esp8266/eagle_soc.h" #include "esp8266/rom_functions.h" #include "rom/ets_sys.h" +#include "rom/uart.h" #include "esp_err.h" #include "FreeRTOS.h" @@ -30,7 +33,19 @@ #define STACK_VOL_NUM 16 -#ifndef CONFIG_ESP_PANIC_SILENT_REBOOT +#if defined(CONFIG_ESP_PANIC_SILENT_REBOOT) || defined(CONFIG_ESP_PANIC_PRINT_REBOOT) +#define ESP_PANIC_REBOOT +#else +#undef ESP_PANIC_REBOOT +#endif + +#if defined(CONFIG_ESP_PANIC_SILENT_REBOOT) +#undef ESP_PANIC_PRINT +#else +#define ESP_PANIC_PRINT +#endif + +#ifdef ESP_PANIC_PRINT #ifndef DISABLE_FREERTOS /* * @Note: If freeRTOS is updated, the structure must be checked. @@ -123,7 +138,7 @@ static void panic_stack(const uint32_t *reg, const uint32_t *start_stk, const ui * * @return none */ -static __attribute__((noreturn)) void panic_info(void *frame, int wdt) +static void panic_info(void *frame, int wdt) { extern int _chip_nmi_cnt; extern int __g_is_task_overflow; @@ -182,28 +197,64 @@ static __attribute__((noreturn)) void panic_info(void *frame, int wdt) } ets_printf("\r\n"); } +} +#endif /* ESP_PANIC_PRINT */ + +#ifdef ESP_PANIC_REBOOT +static void hardware_restart(void) +{ + CLEAR_WDT_REG_MASK(WDT_CTL_ADDRESS, BIT0); + WDT_REG_WRITE(WDT_OP_ADDRESS, 1); + WDT_REG_WRITE(WDT_OP_ND_ADDRESS, 1); + SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, + WDT_CTL_RSTLEN_MASK, + 7 << WDT_CTL_RSTLEN_LSB, + 0); + SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, + WDT_CTL_RSPMOD_MASK, + 0 << WDT_CTL_RSPMOD_LSB, + 0); + SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, + WDT_CTL_EN_MASK, + 1 << WDT_CTL_EN_LSB, + 0); +} + +static void esp_panic_reset(void) +{ + uart_tx_wait_idle(0); + uart_tx_wait_idle(1); + + esp_reset_reason_set_hint(ESP_RST_PANIC); + + hardware_restart(); -#ifdef CONFIG_ESP_PANIC_PRINT_HALT while (1); -#else - esp_restart(); -#endif } -#endif /* !CONFIG_ESP_PANIC_SILENT_REBOOT */ +#endif void __attribute__((noreturn)) panicHandler(void *frame, int wdt) { -#ifndef CONFIG_ESP_PANIC_SILENT_REBOOT + extern int _chip_nmi_cnt; + + _chip_nmi_cnt = 0; + /* NMI can interrupt exception. */ - vPortEnterCritical(); do { REG_WRITE(INT_ENA_WDEV, 0); } while (REG_READ(INT_ENA_WDEV) != 0); +#ifdef ESP_PANIC_PRINT panic_info(frame, wdt); +#endif + +#ifdef ESP_PANIC_REBOOT + esp_panic_reset(); #else - esp_restart(); -#endif /* !CONFIG_ESP_PANIC_SILENT_REBOOT */ + while (1) { + esp_task_wdt_reset(); + } +#endif } static void esp_error_check_failed_print(const char *msg, esp_err_t rc, const char *file, int line, const char *function, const char *expression) diff --git a/components/freertos/port/esp8266/port.c b/components/freertos/port/esp8266/port.c index b0c314d35..5953c24f3 100644 --- a/components/freertos/port/esp8266/port.c +++ b/components/freertos/port/esp8266/port.c @@ -267,23 +267,37 @@ void esp_dport_close_nmi(void) void IRAM_ATTR vPortETSIntrLock(void) { if (NMIIrqIsOn == 0) { + uint32_t regval = REG_READ(NMI_INT_ENABLE_REG); + vPortEnterCritical(); + + REG_WRITE(NMI_INT_ENABLE_REG, 0); + if (!ESP_NMI_IS_CLOSED()) { do { REG_WRITE(INT_ENA_WDEV, WDEV_TSF0_REACH_INT); } while(REG_READ(INT_ENA_WDEV) != WDEV_TSF0_REACH_INT); } + + REG_WRITE(NMI_INT_ENABLE_REG, regval); } } void IRAM_ATTR vPortETSIntrUnlock(void) { if (NMIIrqIsOn == 0) { + uint32_t regval = REG_READ(NMI_INT_ENABLE_REG); + + REG_WRITE(NMI_INT_ENABLE_REG, 0); + if (!ESP_NMI_IS_CLOSED()) { extern uint32_t WDEV_INTEREST_EVENT; REG_WRITE(INT_ENA_WDEV, WDEV_INTEREST_EVENT); } + + REG_WRITE(NMI_INT_ENABLE_REG, regval); + vPortExitCritical(); } } diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index a215839ef..c65d2ff4b 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -229,6 +229,12 @@ config LWIP_DHCPS_MAX_STATION_NUM After this number is exceeded, DHCP server removes of the oldest device from it's address pool, without notification. +config LWIP_ESP_DHCP_OPTION + bool "Enable DHCP option60 and option61 in discovery and request state" + default n + help + Maybe some routers need add those option to get IP address. + Enable this config to add option60 and option61 in discovery and request state endmenu #DHCP menuconfig LWIP_AUTOIP diff --git a/components/lwip/apps/ping/ping.c b/components/lwip/apps/ping/ping.c index 8b8d5512f..61245b057 100644 --- a/components/lwip/apps/ping/ping.c +++ b/components/lwip/apps/ping/ping.c @@ -57,6 +57,10 @@ #include "lwip/inet.h" #endif /* PING_USE_SOCKETS */ +#ifdef CONFIG_USING_ESP_VFS +#include +#endif + #ifdef ESP_PING #include "esp_ping.h" #include "lwip/ip_addr.h" diff --git a/components/lwip/lwip/src/core/ipv4/dhcp.c b/components/lwip/lwip/src/core/ipv4/dhcp.c index 7590b6bc2..a167ca72d 100644 --- a/components/lwip/lwip/src/core/ipv4/dhcp.c +++ b/components/lwip/lwip/src/core/ipv4/dhcp.c @@ -209,6 +209,12 @@ static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); /* always add the DHCP options trailer to end and pad */ static void dhcp_option_trailer(struct dhcp *dhcp); +#if ESP_DHCP_OPTION +/* set dhcp option61 */ +static void dhcp_option_clientid(struct dhcp *dhcp, struct netif *netif); +/* set dhcp option60 */ +static void dhcp_option_vendor(struct dhcp *dhcp, struct netif *netif); +#endif /** Ensure DHCP PCB is allocated and bound */ static err_t dhcp_inc_pcb_refcount(void) @@ -362,6 +368,10 @@ dhcp_select(struct netif *netif) /* create and initialize the DHCP message header */ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); if (result == ERR_OK) { +#if ESP_DHCP_OPTION + dhcp_option_clientid(dhcp, netif); + dhcp_option_vendor(dhcp, netif); +#endif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); @@ -978,6 +988,10 @@ dhcp_discover(struct netif *netif) if (result == ERR_OK) { LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); +#if ESP_DHCP_OPTION + dhcp_option_clientid(dhcp, netif); + dhcp_option_vendor(dhcp, netif); +#endif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); @@ -985,6 +999,11 @@ dhcp_discover(struct netif *netif) for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); } + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + dhcp_option_trailer(dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); @@ -1142,6 +1161,10 @@ dhcp_renew(struct netif *netif) /* create and initialize the DHCP message header */ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); if (result == ERR_OK) { +#if ESP_DHCP_OPTION + dhcp_option_clientid(dhcp, netif); + dhcp_option_vendor(dhcp, netif); +#endif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); @@ -1194,6 +1217,10 @@ dhcp_rebind(struct netif *netif) /* create and initialize the DHCP message header */ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); if (result == ERR_OK) { +#if ESP_DHCP_OPTION + dhcp_option_clientid(dhcp, netif); + dhcp_option_vendor(dhcp, netif); +#endif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); @@ -1244,6 +1271,10 @@ dhcp_reboot(struct netif *netif) /* create and initialize the DHCP message header */ result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); if (result == ERR_OK) { +#if ESP_DHCP_OPTION + dhcp_option_clientid(dhcp, netif); + dhcp_option_vendor(dhcp, netif); +#endif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN_MIN_REQUIRED); @@ -1255,6 +1286,10 @@ dhcp_reboot(struct netif *netif) dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); } +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + dhcp_option_trailer(dhcp); pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); @@ -1452,6 +1487,76 @@ dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) } #endif /* LWIP_NETIF_HOSTNAME */ +#if ESP_DHCP_OPTION +static void dhcp_option_clientid(struct dhcp *dhcp, struct netif *netif) +{ + if (netif) { + u8_t id_len = NETIF_MAX_HWADDR_LEN + 1; + dhcp_option(dhcp, DHCP_OPTION_CLIENT_ID, id_len); + dhcp_option_byte(dhcp, DHCP_HTYPE_ETH); + for (u8_t i = 0; i < NETIF_MAX_HWADDR_LEN; i++) { + dhcp_option_byte(dhcp, netif->hwaddr[i]); + } + } +} + +static u8_t vendor_class_len = 0; +static char *vendor_class_buf = NULL; +err_t dhcp_set_vendor_class_identifier(u8_t len, char *str) +{ + if (len == 0 || str == NULL) { + return ERR_ARG; + } + + if (vendor_class_buf) { + mem_free(vendor_class_buf); + vendor_class_buf = NULL; + } + + vendor_class_buf = (char *)mem_malloc(len + 1); + + if (vendor_class_buf == NULL) { + return ERR_MEM; + } + + vendor_class_len = len; + memcpy(vendor_class_buf, str, len); + return ERR_OK; +} + +static void dhcp_option_vendor(struct dhcp *dhcp, struct netif *netif) +{ + const char *p = NULL; + u8_t len = 0; + /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME + and 1 byte for trailer) */ + size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; + if (vendor_class_buf && vendor_class_len) { + p = vendor_class_buf; + LWIP_ASSERT("DHCP: vendor_class_len is too long!", vendor_class_len <= available); + len = vendor_class_len; + } else { //use hostname as vendor +#if LWIP_NETIF_HOSTNAME + if (netif->hostname != NULL) { + size_t namelen = strlen(netif->hostname); + if ((namelen > 0) && (namelen < 0xFF)) { + p = netif->hostname; + LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); + len = (u8_t) namelen; + } + } +#endif + } + + if (p) { + dhcp_option(dhcp, DHCP_OPTION_US, (u8_t)len); + while (len--) { + dhcp_option_byte(dhcp, *p++); + } + } +} +#endif + /** * Extract the DHCP message and the DHCP options. * diff --git a/components/lwip/lwip/src/core/ipv4/ip4_addr.c b/components/lwip/lwip/src/core/ipv4/ip4_addr.c index 2d479923b..408a0b588 100644 --- a/components/lwip/lwip/src/core/ipv4/ip4_addr.c +++ b/components/lwip/lwip/src/core/ipv4/ip4_addr.c @@ -160,6 +160,12 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr) u32_t parts[4]; u32_t *pp = parts; +#if ESP_IP4_ATON + char ch; + unsigned long cutoff; + int cutlim; +#endif + c = *cp; for (;;) { /* @@ -181,6 +187,27 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr) base = 8; } } + +#if ESP_IP4_ATON + cutoff =(unsigned long)0xffffffff / (unsigned long)base; + cutlim =(unsigned long)0xffffffff % (unsigned long)base; + for (;;) { + if (isdigit(c)) { + ch = (int)(c - '0'); + if (val > cutoff || (val == cutoff && ch > cutlim)) + return (0); + val = (val * base) + (int)(c - '0'); + c = *++cp; + } else if (base == 16 && isxdigit(c)) { + ch = (int)(c + 10 - (islower(c) ? 'a' : 'A')); + if (val > cutoff || (val == cutoff && ch > cutlim)) + return (0); + val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } +#else for (;;) { if (isdigit(c)) { val = (val * base) + (u32_t)(c - '0'); @@ -192,6 +219,8 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr) break; } } +#endif + if (c == '.') { /* * Internet format: diff --git a/components/lwip/lwip/src/include/lwip/prot/dhcp.h b/components/lwip/lwip/src/include/lwip/prot/dhcp.h index 112953cb8..02ed51d0a 100644 --- a/components/lwip/lwip/src/include/lwip/prot/dhcp.h +++ b/components/lwip/lwip/src/include/lwip/prot/dhcp.h @@ -175,6 +175,9 @@ typedef enum { #define DHCP_OVERLOAD_SNAME 2 #define DHCP_OVERLOAD_SNAME_FILE 3 +#if ESP_DHCP_OPTION +err_t dhcp_set_vendor_class_identifier(u8_t len, char *str); +#endif #ifdef __cplusplus } diff --git a/components/lwip/lwip/src/include/posix/sys/socket.h b/components/lwip/lwip/src/include/posix/sys/socket.h index 03bfd4990..d6068709d 100644 --- a/components/lwip/lwip/src/include/posix/sys/socket.h +++ b/components/lwip/lwip/src/include/posix/sys/socket.h @@ -33,3 +33,9 @@ #include "sdkconfig.h" #include "lwip/sockets.h" + +#if !LWIP_POSIX_SOCKETS_IO_NAMES +#include +#include +#include +#endif /* !LWIP_POSIX_SOCKETS_IO_NAMES */ diff --git a/components/lwip/port/esp8266/include/lwipopts.h b/components/lwip/port/esp8266/include/lwipopts.h index 137789824..29619308c 100644 --- a/components/lwip/port/esp8266/include/lwipopts.h +++ b/components/lwip/port/esp8266/include/lwipopts.h @@ -53,6 +53,7 @@ #include "driver/soc.h" #define ESP_LWIP 1 +#define ESP_IP4_ATON 1 #ifdef CONFIG_ESP_DNS #define ESP_DNS 1 @@ -2273,4 +2274,5 @@ size_t memp_malloc_get_size(size_t type); #define ESP_PING 1 +#define ESP_DHCP_OPTION CONFIG_LWIP_ESP_DHCP_OPTION #endif /* __LWIP_HDR_LWIPOPTS_H__ */ diff --git a/components/mqtt/esp-mqtt/.travis.yml b/components/mqtt/esp-mqtt/.travis.yml index 0b8a45991..521d2930a 100644 --- a/components/mqtt/esp-mqtt/.travis.yml +++ b/components/mqtt/esp-mqtt/.travis.yml @@ -13,6 +13,8 @@ addons: before_install: # Save path to the git respository - PROJECT_PATH=$(pwd) + # Have to checkout a temp branch for later in tree reference + - git checkout -b temporary_ref_branch - CI_COMMIT_SHA=$(git rev-parse HEAD) install: diff --git a/components/mqtt/esp-mqtt/include/mqtt_client.h b/components/mqtt/esp-mqtt/include/mqtt_client.h index 630ba1727..e4e11d42b 100755 --- a/components/mqtt/esp-mqtt/include/mqtt_client.h +++ b/components/mqtt/esp-mqtt/include/mqtt_client.h @@ -45,6 +45,7 @@ typedef enum { - current_data_offset offset of the current data for this event - total_data_len total length of the data received */ + MQTT_EVENT_BEFORE_CONNECT, /*!< The event occurs before connecting */ } esp_mqtt_event_id_t; typedef enum { @@ -103,16 +104,19 @@ typedef struct { const char *client_cert_pem; /*!< Pointer to certificate data in PEM format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_key_pem` has to be provided. */ const char *client_key_pem; /*!< Pointer to private key data in PEM format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_cert_pem` has to be provided. */ esp_mqtt_transport_t transport; /*!< overrides URI transport */ + int refresh_connection_after_ms; /*!< Refresh connection after this value (in milliseconds) */ } esp_mqtt_client_config_t; esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config); esp_err_t esp_mqtt_client_set_uri(esp_mqtt_client_handle_t client, const char *uri); esp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client); +esp_err_t esp_mqtt_client_reconnect(esp_mqtt_client_handle_t client); esp_err_t esp_mqtt_client_stop(esp_mqtt_client_handle_t client); esp_err_t esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic, int qos); esp_err_t esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *topic); int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain); esp_err_t esp_mqtt_client_destroy(esp_mqtt_client_handle_t client); +esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_client_config_t *config); #ifdef __cplusplus } diff --git a/components/mqtt/esp-mqtt/include/mqtt_config.h b/components/mqtt/esp-mqtt/include/mqtt_config.h index c0b4ab754..972f2a1c8 100644 --- a/components/mqtt/esp-mqtt/include/mqtt_config.h +++ b/components/mqtt/esp-mqtt/include/mqtt_config.h @@ -10,6 +10,7 @@ #define MQTT_PROTOCOL_311 CONFIG_MQTT_PROTOCOL_311 #define MQTT_RECONNECT_TIMEOUT_MS (10*1000) +#define MQTT_POLL_READ_TIMEOUT_MS (1000) #if CONFIG_MQTT_BUFFER_SIZE #define MQTT_BUFFER_SIZE_BYTE CONFIG_MQTT_BUFFER_SIZE @@ -61,14 +62,18 @@ #define MQTT_CORE_SELECTION_ENABLED CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED +#ifdef CONFIG_MQTT_DISABLE_API_LOCKS +#define MQTT_DISABLE_API_LOCKS CONFIG_MQTT_DISABLE_API_LOCKS +#endif + #ifdef CONFIG_MQTT_USE_CORE_0 - #define MQTT_TASK_CORE 0 + #define MQTT_TASK_CORE 0 #else - #ifdef CONFIG_MQTT_USE_CORE_1 - #define MQTT_TASK_CORE 1 - #else - #define MQTT_TASK_CORE 0 - #endif + #ifdef CONFIG_MQTT_USE_CORE_1 + #define MQTT_TASK_CORE 1 + #else + #define MQTT_TASK_CORE 0 + #endif #endif diff --git a/components/mqtt/esp-mqtt/lib/include/mqtt_msg.h b/components/mqtt/esp-mqtt/lib/include/mqtt_msg.h index 049c738cb..1a07cae54 100644 --- a/components/mqtt/esp-mqtt/lib/include/mqtt_msg.h +++ b/components/mqtt/esp-mqtt/lib/include/mqtt_msg.h @@ -72,7 +72,8 @@ typedef struct mqtt_message { uint8_t* data; uint32_t length; - + uint32_t fragmented_msg_total_length; /*!< total len of fragmented messages (zero for all other messages) */ + uint32_t fragmented_msg_data_offset; /*!< data offset of fragmented messages (zero for all other messages) */ } mqtt_message_t; typedef struct mqtt_connection @@ -105,6 +106,7 @@ static inline int mqtt_get_type(uint8_t* buffer) { return (buffer[0] & 0xf0) >> static inline int mqtt_get_connect_session_present(uint8_t* buffer) { return buffer[2] & 0x01; } static inline int mqtt_get_connect_return_code(uint8_t* buffer) { return buffer[3]; } static inline int mqtt_get_dup(uint8_t* buffer) { return (buffer[0] & 0x08) >> 3; } +static inline void mqtt_set_dup(uint8_t* buffer) { buffer[0] |= 0x08; } static inline int mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1; } static inline int mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); } diff --git a/components/mqtt/esp-mqtt/lib/include/mqtt_outbox.h b/components/mqtt/esp-mqtt/lib/include/mqtt_outbox.h index a87b4662d..b4f1e4f9f 100644 --- a/components/mqtt/esp-mqtt/lib/include/mqtt_outbox.h +++ b/components/mqtt/esp-mqtt/lib/include/mqtt_outbox.h @@ -15,17 +15,35 @@ struct outbox_item; typedef struct outbox_list_t * outbox_handle_t; typedef struct outbox_item * outbox_item_handle_t; +typedef struct outbox_message * outbox_message_handle_t; + +typedef struct outbox_message { + uint8_t *data; + int len; + int msg_id; + int msg_qos; + int msg_type; + uint8_t *remaining_data; + int remaining_len; +} outbox_message_t; + +typedef enum pending_state { + QUEUED, + TRANSMITTED, + CONFIRMED +} pending_state_t; outbox_handle_t outbox_init(); -outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, uint8_t *data, int len, int msg_id, int msg_type, int tick); -outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox); +outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, outbox_message_handle_t message, int tick); +outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox, pending_state_t pending); outbox_item_handle_t outbox_get(outbox_handle_t outbox, int msg_id); +uint8_t* outbox_item_get_data(outbox_item_handle_t item, size_t *len, uint16_t *msg_id, int *msg_type, int *qos); esp_err_t outbox_delete(outbox_handle_t outbox, int msg_id, int msg_type); esp_err_t outbox_delete_msgid(outbox_handle_t outbox, int msg_id); esp_err_t outbox_delete_msgtype(outbox_handle_t outbox, int msg_type); esp_err_t outbox_delete_expired(outbox_handle_t outbox, int current_tick, int timeout); -esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id); +esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id, pending_state_t pending); int outbox_get_size(outbox_handle_t outbox); esp_err_t outbox_cleanup(outbox_handle_t outbox, int max_size); void outbox_destroy(outbox_handle_t outbox); diff --git a/components/mqtt/esp-mqtt/lib/mqtt_msg.c b/components/mqtt/esp-mqtt/lib/mqtt_msg.c index eb978472b..15eb93e67 100644 --- a/components/mqtt/esp-mqtt/lib/mqtt_msg.c +++ b/components/mqtt/esp-mqtt/lib/mqtt_msg.c @@ -34,7 +34,7 @@ #include "mqtt_config.h" #include "platform.h" -#define MQTT_MAX_FIXED_HEADER_SIZE 3 +#define MQTT_MAX_FIXED_HEADER_SIZE 5 enum mqtt_connect_flag { @@ -105,22 +105,42 @@ static mqtt_message_t* fail_message(mqtt_connection_t* connection) static mqtt_message_t* fini_message(mqtt_connection_t* connection, int type, int dup, int qos, int retain) { - int remaining_length = connection->message.length - MQTT_MAX_FIXED_HEADER_SIZE; + int message_length = connection->message.length - MQTT_MAX_FIXED_HEADER_SIZE; + int total_length = message_length; + int encoded_length = 0; + uint8_t encoded_lens[4] = {0}; + // Check if we have fragmented message and update total_len + if (connection->message.fragmented_msg_total_length) { + total_length = connection->message.fragmented_msg_total_length - MQTT_MAX_FIXED_HEADER_SIZE; + } - if (remaining_length > 127) - { - connection->buffer[0] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); - connection->buffer[1] = 0x80 | (remaining_length % 128); - connection->buffer[2] = remaining_length / 128; - connection->message.length = remaining_length + 3; - connection->message.data = connection->buffer; + // Encode MQTT message length + int len_bytes = 0; // size of encoded message length + do { + encoded_length = total_length % 128; + total_length /= 128; + if (total_length > 0) { + encoded_length |= 0x80; + } + encoded_lens[len_bytes] = encoded_length; + len_bytes++; + } while (total_length > 0); + + // Sanity check for MQTT header + if (len_bytes + 1 > MQTT_MAX_FIXED_HEADER_SIZE) { + return fail_message(connection); } - else - { - connection->buffer[1] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); - connection->buffer[2] = remaining_length; - connection->message.length = remaining_length + 2; - connection->message.data = connection->buffer + 1; + + // Save the header bytes + connection->message.length = message_length + len_bytes + 1; // msg len + encoded_size len + type (1 byte) + int offs = MQTT_MAX_FIXED_HEADER_SIZE - 1 - len_bytes; + connection->message.data = connection->buffer + offs; + connection->message.fragmented_msg_data_offset -= offs; + // type byte + connection->buffer[offs++] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); + // length bytes + for (int j = 0; jbuffer[offs++] = encoded_lens[j]; } return &connection->message; @@ -377,11 +397,17 @@ mqtt_message_t* mqtt_msg_publish(mqtt_connection_t* connection, const char* topi else *message_id = 0; - if (connection->message.length + data_length > connection->buffer_length) - return fail_message(connection); - memcpy(connection->buffer + connection->message.length, data, data_length); - connection->message.length += data_length; - + if (connection->message.length + data_length > connection->buffer_length) { + // Not enough size in buffer -> fragment this message + connection->message.fragmented_msg_data_offset = connection->message.length; + memcpy(connection->buffer + connection->message.length, data, connection->buffer_length - connection->message.length); + connection->message.length = connection->buffer_length; + connection->message.fragmented_msg_total_length = data_length + connection->message.fragmented_msg_data_offset; + } else { + memcpy(connection->buffer + connection->message.length, data, data_length); + connection->message.length += data_length; + connection->message.fragmented_msg_total_length = 0; + } return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain); } diff --git a/components/mqtt/esp-mqtt/lib/mqtt_outbox.c b/components/mqtt/esp-mqtt/lib/mqtt_outbox.c index 300e6987b..403fd9c00 100644 --- a/components/mqtt/esp-mqtt/lib/mqtt_outbox.c +++ b/components/mqtt/esp-mqtt/lib/mqtt_outbox.c @@ -14,9 +14,10 @@ typedef struct outbox_item { int len; int msg_id; int msg_type; + int msg_qos; int tick; int retry_count; - bool pending; + pending_state_t pending; STAILQ_ENTRY(outbox_item) next; } outbox_item_t; @@ -31,22 +32,27 @@ outbox_handle_t outbox_init() return outbox; } -outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, uint8_t *data, int len, int msg_id, int msg_type, int tick) +outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, outbox_message_handle_t message, int tick) { outbox_item_handle_t item = calloc(1, sizeof(outbox_item_t)); ESP_MEM_CHECK(TAG, item, return NULL); - item->msg_id = msg_id; - item->msg_type = msg_type; + item->msg_id = message->msg_id; + item->msg_type = message->msg_type; + item->msg_qos = message->msg_qos; item->tick = tick; - item->len = len; - item->buffer = malloc(len); + item->len = message->len; + item->pending = QUEUED; + item->buffer = malloc(message->len + message->remaining_len); ESP_MEM_CHECK(TAG, item->buffer, { free(item); return NULL; }); - memcpy(item->buffer, data, len); + memcpy(item->buffer, message->data, message->len); + if (message->remaining_data) { + memcpy(item->buffer+message->len, message->remaining_data, message->remaining_len); + } STAILQ_INSERT_TAIL(outbox, item, next); - ESP_LOGD(TAG, "ENQUEUE msgid=%d, msg_type=%d, len=%d, size=%d", msg_id, msg_type, len, outbox_get_size(outbox)); + ESP_LOGD(TAG, "ENQUEUE msgid=%d, msg_type=%d, len=%d, size=%d", message->msg_id, message->msg_type, message->len + message->remaining_len, outbox_get_size(outbox)); return item; } @@ -61,21 +67,34 @@ outbox_item_handle_t outbox_get(outbox_handle_t outbox, int msg_id) return NULL; } -outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox) +outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox, pending_state_t pending) { outbox_item_handle_t item; STAILQ_FOREACH(item, outbox, next) { - if (!item->pending) { + if (item->pending == pending) { return item; } } return NULL; } + +uint8_t* outbox_item_get_data(outbox_item_handle_t item, size_t *len, uint16_t *msg_id, int *msg_type, int *qos) +{ + if (item) { + *len = item->len; + *msg_id = item->msg_id; + *msg_type = item->msg_type; + *qos = item->msg_qos; + return (uint8_t*)item->buffer; + } + return NULL; +} + esp_err_t outbox_delete(outbox_handle_t outbox, int msg_id, int msg_type) { outbox_item_handle_t item, tmp; STAILQ_FOREACH_SAFE(item, outbox, next, tmp) { - if (item->msg_id == msg_id && item->msg_type == msg_type) { + if (item->msg_id == msg_id && (0xFF&(item->msg_type)) == msg_type) { STAILQ_REMOVE(outbox, item, outbox_item, next); free(item->buffer); free(item); @@ -99,11 +118,11 @@ esp_err_t outbox_delete_msgid(outbox_handle_t outbox, int msg_id) } return ESP_OK; } -esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id) +esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id, pending_state_t pending) { outbox_item_handle_t item = outbox_get(outbox, msg_id); if (item) { - item->pending = true; + item->pending = pending; return ESP_OK; } return ESP_FAIL; @@ -150,7 +169,7 @@ int outbox_get_size(outbox_handle_t outbox) esp_err_t outbox_cleanup(outbox_handle_t outbox, int max_size) { while(outbox_get_size(outbox) > max_size) { - outbox_item_handle_t item = outbox_dequeue(outbox); + outbox_item_handle_t item = outbox_dequeue(outbox, CONFIRMED); if (item == NULL) { return ESP_FAIL; } diff --git a/components/mqtt/esp-mqtt/mqtt_client.c b/components/mqtt/esp-mqtt/mqtt_client.c index 9768f72d2..8fe31cc9c 100644 --- a/components/mqtt/esp-mqtt/mqtt_client.c +++ b/components/mqtt/esp-mqtt/mqtt_client.c @@ -13,6 +13,18 @@ /* using uri parser */ #include "http_parser.h" +#ifdef MQTT_DISABLE_API_LOCKS +# define MQTT_API_LOCK(c) +# define MQTT_API_UNLOCK(c) +# define MQTT_API_LOCK_FROM_OTHER_TASK(c) +# define MQTT_API_UNLOCK_FROM_OTHER_TASK(c) +#else +# define MQTT_API_LOCK(c) xSemaphoreTake(c->api_lock, portMAX_DELAY) +# define MQTT_API_UNLOCK(c) xSemaphoreGive(c->api_lock) +# define MQTT_API_LOCK_FROM_OTHER_TASK(c) { if (c->task_handle != xTaskGetCurrentTaskHandle()) { xSemaphoreTake(c->api_lock, portMAX_DELAY); } } +# define MQTT_API_UNLOCK_FROM_OTHER_TASK(c) { if (c->task_handle != xTaskGetCurrentTaskHandle()) { xSemaphoreGive(c->api_lock); } } +#endif /* MQTT_USE_API_LOCKS */ + static const char *TAG = "MQTT_CLIENT"; typedef struct mqtt_state @@ -44,6 +56,7 @@ typedef struct { bool auto_reconnect; void *user_context; int network_timeout_ms; + int refresh_connection_after_ms; } mqtt_config_storage_t; typedef enum { @@ -61,8 +74,9 @@ struct esp_mqtt_client { mqtt_state_t mqtt_state; mqtt_connect_info_t connect_info; mqtt_client_state_t state; - long long keepalive_tick; - long long reconnect_tick; + uint64_t refresh_connection_tick; + uint64_t keepalive_tick; + uint64_t reconnect_tick; int wait_timeout_ms; int auto_reconnect; esp_mqtt_event_t event; @@ -70,105 +84,145 @@ struct esp_mqtt_client { bool wait_for_ping_resp; outbox_handle_t outbox; EventGroupHandle_t status_bits; + SemaphoreHandle_t api_lock; + TaskHandle_t task_handle; }; const static int STOPPED_BIT = BIT0; +const static int RECONNECT_BIT = BIT1; static esp_err_t esp_mqtt_dispatch_event(esp_mqtt_client_handle_t client); -static esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_client_config_t *config); +static esp_err_t esp_mqtt_dispatch_event_with_msgid(esp_mqtt_client_handle_t client); static esp_err_t esp_mqtt_destroy_config(esp_mqtt_client_handle_t client); static esp_err_t esp_mqtt_connect(esp_mqtt_client_handle_t client, int timeout_ms); static esp_err_t esp_mqtt_abort_connection(esp_mqtt_client_handle_t client); static esp_err_t esp_mqtt_client_ping(esp_mqtt_client_handle_t client); static char *create_string(const char *ptr, int len); -static esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_client_config_t *config) +esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_client_config_t *config) { + MQTT_API_LOCK(client); //Copy user configurations to client context esp_err_t err = ESP_OK; - mqtt_config_storage_t *cfg = calloc(1, sizeof(mqtt_config_storage_t)); - ESP_MEM_CHECK(TAG, cfg, return ESP_ERR_NO_MEM); - - client->config = cfg; + mqtt_config_storage_t *cfg; + if (client->config) { + cfg = client->config; + } else { + cfg = calloc(1, sizeof(mqtt_config_storage_t)); + ESP_MEM_CHECK(TAG, cfg, { + MQTT_API_UNLOCK(client); + return ESP_ERR_NO_MEM; + }); + client->config = cfg; + } + if (config->task_prio) { + cfg->task_prio = config->task_prio; + } - cfg->task_prio = config->task_prio; if (cfg->task_prio <= 0) { cfg->task_prio = MQTT_TASK_PRIORITY; } - - cfg->task_stack = config->task_stack; + if (config->task_stack) { + cfg->task_stack = config->task_stack; + } if (cfg->task_stack == 0) { cfg->task_stack = MQTT_TASK_STACK; } + if (config->port) { + cfg->port = config->port; + } + err = ESP_ERR_NO_MEM; if (config->host) { + free(cfg->host); cfg->host = strdup(config->host); ESP_MEM_CHECK(TAG, cfg->host, goto _mqtt_set_config_failed); } - cfg->port = config->port; if (config->username) { + free(client->connect_info.username); client->connect_info.username = strdup(config->username); ESP_MEM_CHECK(TAG, client->connect_info.username, goto _mqtt_set_config_failed); } if (config->password) { + free(client->connect_info.password); client->connect_info.password = strdup(config->password); ESP_MEM_CHECK(TAG, client->connect_info.password, goto _mqtt_set_config_failed); } if (config->client_id) { + free(client->connect_info.client_id); client->connect_info.client_id = strdup(config->client_id); - } else { + ESP_MEM_CHECK(TAG, client->connect_info.client_id, goto _mqtt_set_config_failed); + } else if (client->connect_info.client_id == NULL) { client->connect_info.client_id = platform_create_id_string(); } ESP_MEM_CHECK(TAG, client->connect_info.client_id, goto _mqtt_set_config_failed); ESP_LOGD(TAG, "MQTT client_id=%s", client->connect_info.client_id); if (config->uri) { + free(cfg->uri); cfg->uri = strdup(config->uri); ESP_MEM_CHECK(TAG, cfg->uri, goto _mqtt_set_config_failed); } if (config->lwt_topic) { + free(client->connect_info.will_topic); client->connect_info.will_topic = strdup(config->lwt_topic); ESP_MEM_CHECK(TAG, client->connect_info.will_topic, goto _mqtt_set_config_failed); } - if (config->lwt_msg_len) { + if (config->lwt_msg_len && config->lwt_msg) { + free(client->connect_info.will_message); client->connect_info.will_message = malloc(config->lwt_msg_len); ESP_MEM_CHECK(TAG, client->connect_info.will_message, goto _mqtt_set_config_failed); memcpy(client->connect_info.will_message, config->lwt_msg, config->lwt_msg_len); client->connect_info.will_length = config->lwt_msg_len; } else if (config->lwt_msg) { + free(client->connect_info.will_message); client->connect_info.will_message = strdup(config->lwt_msg); ESP_MEM_CHECK(TAG, client->connect_info.will_message, goto _mqtt_set_config_failed); client->connect_info.will_length = strlen(config->lwt_msg); } + if (config->lwt_qos) { + client->connect_info.will_qos = config->lwt_qos; + } + if (config->lwt_retain) { + client->connect_info.will_retain = config->lwt_retain; + } - client->connect_info.will_qos = config->lwt_qos; - client->connect_info.will_retain = config->lwt_retain; - - client->connect_info.clean_session = 1; - if (config->disable_clean_session) { - client->connect_info.clean_session = false; + if (config->disable_clean_session == client->connect_info.clean_session) { + client->connect_info.clean_session = !config->disable_clean_session; + } + if (config->keepalive) { + client->connect_info.keepalive = config->keepalive; } - client->connect_info.keepalive = config->keepalive; if (client->connect_info.keepalive == 0) { client->connect_info.keepalive = MQTT_KEEPALIVE_TICK; } cfg->network_timeout_ms = MQTT_NETWORK_TIMEOUT_MS; - cfg->user_context = config->user_context; - cfg->event_handle = config->event_handle; - cfg->auto_reconnect = true; - if (config->disable_auto_reconnect) { - cfg->auto_reconnect = false; + if (config->user_context) { + cfg->user_context = config->user_context; } + if (config->event_handle) { + cfg->event_handle = config->event_handle; + } - return err; + if (config->refresh_connection_after_ms) { + cfg->refresh_connection_after_ms = config->refresh_connection_after_ms; + } + + cfg->auto_reconnect = true; + if (config->disable_auto_reconnect == cfg->auto_reconnect) { + cfg->auto_reconnect = !config->disable_auto_reconnect; + } + MQTT_API_UNLOCK(client); + return ESP_OK; _mqtt_set_config_failed: esp_mqtt_destroy_config(client); + MQTT_API_UNLOCK(client); return err; } @@ -179,11 +233,13 @@ static esp_err_t esp_mqtt_destroy_config(esp_mqtt_client_handle_t client) free(cfg->uri); free(cfg->path); free(cfg->scheme); + memset(cfg, 0, sizeof(mqtt_config_storage_t)); free(client->connect_info.will_topic); free(client->connect_info.will_message); free(client->connect_info.client_id); free(client->connect_info.username); free(client->connect_info.password); + memset(&client->connect_info, 0, sizeof(mqtt_connect_info_t)); free(client->config); return ESP_OK; } @@ -255,10 +311,10 @@ static esp_err_t esp_mqtt_abort_connection(esp_mqtt_client_handle_t client) client->wait_timeout_ms = MQTT_RECONNECT_TIMEOUT_MS; client->reconnect_tick = platform_tick_get_ms(); client->state = MQTT_STATE_WAIT_TIMEOUT; - ESP_LOGI(TAG, "Reconnect after %d ms", client->wait_timeout_ms); + ESP_LOGD(TAG, "Reconnect after %d ms", client->wait_timeout_ms); client->event.event_id = MQTT_EVENT_DISCONNECTED; client->wait_for_ping_resp = false; - esp_mqtt_dispatch_event(client); + esp_mqtt_dispatch_event_with_msgid(client); return ESP_OK; } @@ -266,9 +322,13 @@ esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *co { esp_mqtt_client_handle_t client = calloc(1, sizeof(struct esp_mqtt_client)); ESP_MEM_CHECK(TAG, client, return NULL); - + client->api_lock = xSemaphoreCreateMutex(); + if (!client->api_lock) { + free(client); + return NULL; + } esp_mqtt_set_config(client, config); - + MQTT_API_LOCK(client); client->transport_list = esp_transport_list_init(); ESP_MEM_CHECK(TAG, client->transport_list, goto _mqtt_init_failed); @@ -328,13 +388,9 @@ esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *co } } - if (client->config->scheme == NULL) { - client->config->scheme = create_string("mqtt", 4); - ESP_MEM_CHECK(TAG, client->config->scheme, goto _mqtt_init_failed); - } - client->keepalive_tick = platform_tick_get_ms(); client->reconnect_tick = platform_tick_get_ms(); + client->refresh_connection_tick = platform_tick_get_ms(); client->wait_for_ping_resp = false; int buffer_size = config->buffer_size; if (buffer_size <= 0) { @@ -353,9 +409,11 @@ esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *co ESP_MEM_CHECK(TAG, client->outbox, goto _mqtt_init_failed); client->status_bits = xEventGroupCreate(); ESP_MEM_CHECK(TAG, client->status_bits, goto _mqtt_init_failed); + MQTT_API_UNLOCK(client); return client; _mqtt_init_failed: esp_mqtt_client_destroy(client); + MQTT_API_UNLOCK(client); return NULL; } @@ -368,6 +426,7 @@ esp_err_t esp_mqtt_client_destroy(esp_mqtt_client_handle_t client) vEventGroupDelete(client->status_bits); free(client->mqtt_state.in_buffer); free(client->mqtt_state.out_buffer); + vSemaphoreDelete(client->api_lock); free(client); return ESP_OK; } @@ -394,19 +453,16 @@ esp_err_t esp_mqtt_client_set_uri(esp_mqtt_client_handle_t client, const char *u return ESP_FAIL; } - if (client->config->scheme == NULL) { - client->config->scheme = create_string(uri + puri.field_data[UF_SCHEMA].off, puri.field_data[UF_SCHEMA].len); - } + // set uri overrides actual scheme, host, path if configured previously + free(client->config->scheme); + free(client->config->host); + free(client->config->path); - if (client->config->host == NULL) { - client->config->host = create_string(uri + puri.field_data[UF_HOST].off, puri.field_data[UF_HOST].len); - } + client->config->scheme = create_string(uri + puri.field_data[UF_SCHEMA].off, puri.field_data[UF_SCHEMA].len); + client->config->host = create_string(uri + puri.field_data[UF_HOST].off, puri.field_data[UF_HOST].len); + client->config->path = create_string(uri + puri.field_data[UF_PATH].off, puri.field_data[UF_PATH].len); - if (client->config->path == NULL) { - client->config->path = create_string(uri + puri.field_data[UF_PATH].off, puri.field_data[UF_PATH].len); - } if (client->config->path) { -#if MQTT_ENABLE_WSS || MQTT_ENABLE_WS esp_transport_handle_t trans = esp_transport_list_get_transport(client->transport_list, "ws"); if (trans) { esp_transport_ws_set_path(trans, client->config->path); @@ -415,7 +471,6 @@ esp_err_t esp_mqtt_client_set_uri(esp_mqtt_client_handle_t client, const char *u if (trans) { esp_transport_ws_set_path(trans, client->config->path); } -#endif } if (puri.field_data[UF_PORT].len) { @@ -456,9 +511,14 @@ static esp_err_t mqtt_write_data(esp_mqtt_client_handle_t client) return ESP_OK; } -static esp_err_t esp_mqtt_dispatch_event(esp_mqtt_client_handle_t client) +static esp_err_t esp_mqtt_dispatch_event_with_msgid(esp_mqtt_client_handle_t client) { client->event.msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); + return esp_mqtt_dispatch_event(client); +} + +static esp_err_t esp_mqtt_dispatch_event(esp_mqtt_client_handle_t client) +{ client->event.user_context = client->config->user_context; client->event.client = client; @@ -468,32 +528,37 @@ static esp_err_t esp_mqtt_dispatch_event(esp_mqtt_client_handle_t client) return ESP_FAIL; } - -typedef struct { - char *path; - char *buffer; - esp_transport_handle_t parent; -} transport_ws_t; - static void deliver_publish(esp_mqtt_client_handle_t client, uint8_t *message, int length) { - const char *mqtt_topic, *mqtt_data; + const char *mqtt_topic = NULL, *mqtt_data = NULL; uint32_t mqtt_topic_length, mqtt_data_length; - uint32_t mqtt_len, mqtt_offset = 0, total_mqtt_len = 0; - int len_read; + uint32_t mqtt_len = 0, mqtt_offset = 0, total_mqtt_len = 0; + int len_read= length; + int max_to_read = client->mqtt_state.in_buffer_length; + int buffer_offset = 0; esp_transport_handle_t transport = client->transport; do { if (total_mqtt_len == 0) { - mqtt_topic_length = length; - mqtt_topic = mqtt_get_publish_topic(message, &mqtt_topic_length); - mqtt_data_length = length; - mqtt_data = mqtt_get_publish_data(message, &mqtt_data_length); - total_mqtt_len = client->mqtt_state.message_length - client->mqtt_state.message_length_read + mqtt_data_length; - mqtt_len = mqtt_data_length; /* any further reading only the underlying payload */ transport = esp_transport_get_payload_transport_handle(transport); + mqtt_data_length = mqtt_topic_length = length; + if (NULL == (mqtt_topic = mqtt_get_publish_topic(message, &mqtt_topic_length)) || + NULL == (mqtt_data = mqtt_get_publish_data(message, &mqtt_data_length)) ) { + // mqtt header is not complete, continue reading + memmove(client->mqtt_state.in_buffer, message, length); + buffer_offset = length; + message = client->mqtt_state.in_buffer; + max_to_read = client->mqtt_state.in_buffer_length - length; + mqtt_len = 0; + } else { + total_mqtt_len = client->mqtt_state.message_length - client->mqtt_state.message_length_read + mqtt_data_length; + mqtt_len = mqtt_data_length; + mqtt_data_length = client->mqtt_state.message_length - ((uint8_t*)mqtt_data- message); + /* read msg id only once */ + client->event.msg_id = mqtt_get_id(message, length); + } } else { mqtt_len = len_read; mqtt_data = (const char*)client->mqtt_state.in_buffer; @@ -501,15 +566,17 @@ static void deliver_publish(esp_mqtt_client_handle_t client, uint8_t *message, i mqtt_topic_length = 0; } - ESP_LOGD(TAG, "Get data len= %d, topic len=%d", mqtt_len, mqtt_topic_length); - client->event.event_id = MQTT_EVENT_DATA; - client->event.data = (char *)mqtt_data; - client->event.data_len = mqtt_len; - client->event.total_data_len = total_mqtt_len; - client->event.current_data_offset = mqtt_offset; - client->event.topic = (char *)mqtt_topic; - client->event.topic_len = mqtt_topic_length; - esp_mqtt_dispatch_event(client); + if (total_mqtt_len != 0) { + ESP_LOGD(TAG, "Get data len= %d, topic len=%d", mqtt_len, mqtt_topic_length); + client->event.event_id = MQTT_EVENT_DATA; + client->event.data = (char *)mqtt_data; + client->event.data_len = mqtt_len; + client->event.total_data_len = mqtt_data_length; + client->event.current_data_offset = mqtt_offset; + client->event.topic = (char *)mqtt_topic; + client->event.topic_len = mqtt_topic_length; + esp_mqtt_dispatch_event(client); + } mqtt_offset += mqtt_len; if (client->mqtt_state.message_length_read >= client->mqtt_state.message_length) { @@ -517,18 +584,20 @@ static void deliver_publish(esp_mqtt_client_handle_t client, uint8_t *message, i } len_read = esp_transport_read(transport, - (char *)client->mqtt_state.in_buffer, - client->mqtt_state.message_length - client->mqtt_state.message_length_read > client->mqtt_state.in_buffer_length ? - client->mqtt_state.in_buffer_length : client->mqtt_state.message_length - client->mqtt_state.message_length_read, + (char *)client->mqtt_state.in_buffer + buffer_offset, + client->mqtt_state.message_length - client->mqtt_state.message_length_read > max_to_read ? + max_to_read : client->mqtt_state.message_length - client->mqtt_state.message_length_read, client->config->network_timeout_ms); + length = len_read + buffer_offset; + buffer_offset = 0; + max_to_read = client->mqtt_state.in_buffer_length; if (len_read <= 0) { - ESP_LOGE(TAG, "Read error or timeout: %d", errno); + ESP_LOGE(TAG, "Read error or timeout: len_read=%d, errno=%d", len_read, errno); break; } client->mqtt_state.message_length_read += len_read; } while (1); - } static bool is_valid_mqtt_msg(esp_mqtt_client_handle_t client, int msg_type, int msg_id) @@ -549,19 +618,42 @@ static bool is_valid_mqtt_msg(esp_mqtt_client_handle_t client, int msg_type, int return false; } +static void mqtt_enqueue_oversized(esp_mqtt_client_handle_t client, uint8_t *remaining_data, int remaining_len) +{ + ESP_LOGD(TAG, "mqtt_enqueue_oversized id: %d, type=%d successful", + client->mqtt_state.pending_msg_id, client->mqtt_state.pending_msg_type); + //lock mutex + outbox_message_t msg = { 0 }; + if (client->mqtt_state.pending_msg_count > 0) { + client->mqtt_state.pending_msg_count --; + } + msg.data = client->mqtt_state.outbound_message->data; + msg.len = client->mqtt_state.outbound_message->length; + msg.msg_id = client->mqtt_state.pending_msg_id; + msg.msg_type = client->mqtt_state.pending_msg_type; + msg.msg_qos = client->mqtt_state.pending_publish_qos; + msg.remaining_data = remaining_data; + msg.remaining_len = remaining_len; + //Copy to queue buffer + outbox_enqueue(client->outbox, &msg, platform_tick_get_ms()); + + //unlock +} + static void mqtt_enqueue(esp_mqtt_client_handle_t client) { ESP_LOGD(TAG, "mqtt_enqueue id: %d, type=%d successful", client->mqtt_state.pending_msg_id, client->mqtt_state.pending_msg_type); //lock mutex if (client->mqtt_state.pending_msg_count > 0) { + outbox_message_t msg = { 0 }; + msg.data = client->mqtt_state.outbound_message->data; + msg.len = client->mqtt_state.outbound_message->length; + msg.msg_id = client->mqtt_state.pending_msg_id; + msg.msg_type = client->mqtt_state.pending_msg_type; + msg.msg_qos = client->mqtt_state.pending_publish_qos; //Copy to queue buffer - outbox_enqueue(client->outbox, - client->mqtt_state.outbound_message->data, - client->mqtt_state.outbound_message->length, - client->mqtt_state.pending_msg_id, - client->mqtt_state.pending_msg_type, - platform_tick_get_ms()); + outbox_enqueue(client->outbox, &msg, platform_tick_get_ms()); } //unlock } @@ -572,8 +664,9 @@ static esp_err_t mqtt_process_receive(esp_mqtt_client_handle_t client) uint8_t msg_type; uint8_t msg_qos; uint16_t msg_id; + uint32_t transport_message_offset = 0 ; - read_len = esp_transport_read(client->transport, (char *)client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length, 1000); + read_len = esp_transport_read(client->transport, (char *)client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length, 0); if (read_len < 0) { ESP_LOGE(TAG, "Read error or end of stream"); @@ -584,89 +677,116 @@ static esp_err_t mqtt_process_receive(esp_mqtt_client_handle_t client) return ESP_OK; } - msg_type = mqtt_get_type(client->mqtt_state.in_buffer); - msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer); - msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); - - ESP_LOGD(TAG, "msg_type=%d, msg_id=%d", msg_type, msg_id); - switch (msg_type) - { - case MQTT_MSG_TYPE_SUBACK: - if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_SUBSCRIBE, msg_id)) { - ESP_LOGD(TAG, "Subscribe successful"); - client->event.event_id = MQTT_EVENT_SUBSCRIBED; - esp_mqtt_dispatch_event(client); - } - break; - case MQTT_MSG_TYPE_UNSUBACK: - if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_UNSUBSCRIBE, msg_id)) { - ESP_LOGD(TAG, "UnSubscribe successful"); - client->event.event_id = MQTT_EVENT_UNSUBSCRIBED; - esp_mqtt_dispatch_event(client); - } - break; - case MQTT_MSG_TYPE_PUBLISH: - if (msg_qos == 1) { - client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); - } - else if (msg_qos == 2) { - client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); - } + // In case of fragmented packet (when receiving a large publish message), the deliver_publish function will read the rest of the message with more transport read, which means the MQTT message length will be greater than the initial transport read length. That explains that the stopping condition is not the equality here + while ( transport_message_offset < read_len ) { + // If the message was valid, get the type, quality of service and id of the message + msg_type = mqtt_get_type(&client->mqtt_state.in_buffer[transport_message_offset]); + msg_qos = mqtt_get_qos(&client->mqtt_state.in_buffer[transport_message_offset]); + msg_id = mqtt_get_id(&client->mqtt_state.in_buffer[transport_message_offset], read_len - transport_message_offset); + client->mqtt_state.message_length_read = read_len - transport_message_offset; + client->mqtt_state.message_length = mqtt_get_total_length(&client->mqtt_state.in_buffer[transport_message_offset], client->mqtt_state.message_length_read); + + ESP_LOGD(TAG, "msg_type=%d, msg_id=%d", msg_type, msg_id); + + switch (msg_type) + { + case MQTT_MSG_TYPE_SUBACK: + if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_SUBSCRIBE, msg_id)) { + ESP_LOGD(TAG, "Subscribe successful"); + client->event.event_id = MQTT_EVENT_SUBSCRIBED; + esp_mqtt_dispatch_event_with_msgid(client); + } + break; + case MQTT_MSG_TYPE_UNSUBACK: + if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_UNSUBSCRIBE, msg_id)) { + ESP_LOGD(TAG, "UnSubscribe successful"); + client->event.event_id = MQTT_EVENT_UNSUBSCRIBED; + esp_mqtt_dispatch_event_with_msgid(client); + } + break; + case MQTT_MSG_TYPE_PUBLISH: + if (msg_qos == 1) { + client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); + } + else if (msg_qos == 2) { + client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); + } - if (msg_qos == 1 || msg_qos == 2) { - ESP_LOGD(TAG, "Queue response QoS: %d", msg_qos); + if (msg_qos == 1 || msg_qos == 2) { + ESP_LOGD(TAG, "Queue response QoS: %d", msg_qos); - if (mqtt_write_data(client) != ESP_OK) { - ESP_LOGE(TAG, "Error write qos msg repsonse, qos = %d", msg_qos); - // TODO: Shoule reconnect? - // return ESP_FAIL; + if (mqtt_write_data(client) != ESP_OK) { + ESP_LOGE(TAG, "Error write qos msg repsonse, qos = %d", msg_qos); + // TODO: Shoule reconnect? + // return ESP_FAIL; + } } - } - client->mqtt_state.message_length_read = read_len; - client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); - ESP_LOGI(TAG, "deliver_publish, message_length_read=%d, message_length=%d", read_len, client->mqtt_state.message_length); + // Deliver the publish message + ESP_LOGD(TAG, "deliver_publish, message_length_read=%d, message_length=%d", client->mqtt_state.message_length_read, client->mqtt_state.message_length); + deliver_publish(client, &client->mqtt_state.in_buffer[transport_message_offset], client->mqtt_state.message_length_read); + break; + case MQTT_MSG_TYPE_PUBACK: + if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_PUBLISH, msg_id)) { + ESP_LOGD(TAG, "received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish"); + outbox_set_pending(client->outbox, msg_id, CONFIRMED); + client->event.event_id = MQTT_EVENT_PUBLISHED; + esp_mqtt_dispatch_event_with_msgid(client); + } + break; + case MQTT_MSG_TYPE_PUBREC: + ESP_LOGD(TAG, "received MQTT_MSG_TYPE_PUBREC"); + client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); + outbox_set_pending(client->outbox, msg_id, CONFIRMED); + mqtt_write_data(client); + break; + case MQTT_MSG_TYPE_PUBREL: + ESP_LOGD(TAG, "received MQTT_MSG_TYPE_PUBREL"); + client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); + mqtt_write_data(client); + break; + case MQTT_MSG_TYPE_PUBCOMP: + ESP_LOGD(TAG, "received MQTT_MSG_TYPE_PUBCOMP"); + if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_PUBLISH, msg_id)) { + ESP_LOGD(TAG, "Receive MQTT_MSG_TYPE_PUBCOMP, finish QoS2 publish"); + client->event.event_id = MQTT_EVENT_PUBLISHED; + esp_mqtt_dispatch_event_with_msgid(client); + } + break; + case MQTT_MSG_TYPE_PINGRESP: + ESP_LOGD(TAG, "MQTT_MSG_TYPE_PINGRESP"); + client->wait_for_ping_resp = false; + break; + } - deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); - break; - case MQTT_MSG_TYPE_PUBACK: - if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_PUBLISH, msg_id)) { - ESP_LOGD(TAG, "received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish"); - client->event.event_id = MQTT_EVENT_PUBLISHED; - esp_mqtt_dispatch_event(client); - } + transport_message_offset += client->mqtt_state.message_length; + } - break; - case MQTT_MSG_TYPE_PUBREC: - ESP_LOGD(TAG, "received MQTT_MSG_TYPE_PUBREC"); - client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); - mqtt_write_data(client); - break; - case MQTT_MSG_TYPE_PUBREL: - ESP_LOGD(TAG, "received MQTT_MSG_TYPE_PUBREL"); - client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); - mqtt_write_data(client); + return ESP_OK; +} - break; - case MQTT_MSG_TYPE_PUBCOMP: - ESP_LOGD(TAG, "received MQTT_MSG_TYPE_PUBCOMP"); - if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_PUBLISH, msg_id)) { - ESP_LOGD(TAG, "Receive MQTT_MSG_TYPE_PUBCOMP, finish QoS2 publish"); - client->event.event_id = MQTT_EVENT_PUBLISHED; - esp_mqtt_dispatch_event(client); - } - break; - case MQTT_MSG_TYPE_PINGRESP: - ESP_LOGD(TAG, "MQTT_MSG_TYPE_PINGRESP"); - client->wait_for_ping_resp = false; - break; +static esp_err_t mqtt_resend_queued(esp_mqtt_client_handle_t client, outbox_item_handle_t item) +{ + // decode queued data + client->mqtt_state.outbound_message->data = outbox_item_get_data(item, &client->mqtt_state.outbound_message->length, &client->mqtt_state.pending_msg_id, + &client->mqtt_state.pending_msg_type, &client->mqtt_state.pending_publish_qos); + // set duplicate flag for QoS-2 message + if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH &&client->mqtt_state.pending_publish_qos==2) { + mqtt_set_dup(client->mqtt_state.outbound_message->data); } + // try to resend the data + if (mqtt_write_data(client) != ESP_OK) { + ESP_LOGE(TAG, "Error to public data "); + esp_mqtt_abort_connection(client); + return ESP_FAIL; + } return ESP_OK; } static void esp_mqtt_task(void *pv) { esp_mqtt_client_handle_t client = (esp_mqtt_client_handle_t) pv; + uint32_t last_retransmit = 0; client->run = true; //get transport by scheme @@ -684,9 +804,13 @@ static void esp_mqtt_task(void *pv) client->state = MQTT_STATE_INIT; xEventGroupClearBits(client->status_bits, STOPPED_BIT); while (client->run) { - + MQTT_API_LOCK(client); switch ((int)client->state) { case MQTT_STATE_INIT: + xEventGroupClearBits(client->status_bits, RECONNECT_BIT); + client->event.event_id = MQTT_EVENT_BEFORE_CONNECT; + esp_mqtt_dispatch_event_with_msgid(client); + if (client->transport == NULL) { ESP_LOGE(TAG, "There are no transport"); client->run = false; @@ -709,7 +833,8 @@ static void esp_mqtt_task(void *pv) client->event.event_id = MQTT_EVENT_CONNECTED; client->event.session_present = mqtt_get_connect_session_present(client->mqtt_state.in_buffer); client->state = MQTT_STATE_CONNECTED; - esp_mqtt_dispatch_event(client); + esp_mqtt_dispatch_event_with_msgid(client); + client->refresh_connection_tick = platform_tick_get_ms(); break; case MQTT_STATE_CONNECTED: @@ -719,6 +844,21 @@ static void esp_mqtt_task(void *pv) break; } + // resend all non-transmitted messages first + outbox_item_handle_t item = outbox_dequeue(client->outbox, QUEUED); + if (item) { + if (mqtt_resend_queued(client, item) == ESP_OK) { + outbox_set_pending(client->outbox, client->mqtt_state.pending_msg_id, TRANSMITTED); + } + // resend other "transmitted" messages after 1s + } else if (platform_tick_get_ms() - last_retransmit > 1000) { + last_retransmit = platform_tick_get_ms(); + item = outbox_dequeue(client->outbox, TRANSMITTED); + if (item) { + mqtt_resend_queued(client, item); + } + } + if (platform_tick_get_ms() - client->keepalive_tick > client->connect_info.keepalive * 1000 / 2) { //No ping resp from last ping => Disconnected if(client->wait_for_ping_resp){ @@ -737,6 +877,13 @@ static void esp_mqtt_task(void *pv) ESP_LOGD(TAG, "PING sent"); } + if (client->config->refresh_connection_after_ms && + platform_tick_get_ms() - client->refresh_connection_tick > client->config->refresh_connection_after_ms) { + ESP_LOGD(TAG, "Refreshing the connection..."); + esp_mqtt_abort_connection(client); + client->state = MQTT_STATE_INIT; + } + //Delete mesaage after 30 senconds outbox_delete_expired(client->outbox, platform_tick_get_ms(), OUTBOX_EXPIRED_TIMEOUT_MS); // @@ -752,10 +899,22 @@ static void esp_mqtt_task(void *pv) client->state = MQTT_STATE_INIT; client->reconnect_tick = platform_tick_get_ms(); ESP_LOGD(TAG, "Reconnecting..."); + break; } - vTaskDelay(client->wait_timeout_ms / 2 / portTICK_RATE_MS); - break; + MQTT_API_UNLOCK(client); + xEventGroupWaitBits(client->status_bits, RECONNECT_BIT, false, true, + client->wait_timeout_ms / 2 / portTICK_RATE_MS); + // continue the while loop insted of break, as the mutex is unlocked + continue; + } + MQTT_API_UNLOCK(client); + if (MQTT_STATE_CONNECTED == client->state) { + if (esp_transport_poll_read(client->transport, MQTT_POLL_READ_TIMEOUT_MS) < 0) { + ESP_LOGE(TAG, "Poll read error: %d, aborting connection", errno); + esp_mqtt_abort_connection(client); + } } + } esp_transport_close(client->transport); xEventGroupSetBits(client->status_bits, STOPPED_BIT); @@ -771,13 +930,13 @@ esp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client) } #if MQTT_CORE_SELECTION_ENABLED ESP_LOGD(TAG, "Core selection enabled on %u", MQTT_TASK_CORE); - if (xTaskCreatePinnedToCore(esp_mqtt_task, "mqtt_task", client->config->task_stack, client, client->config->task_prio, NULL, MQTT_TASK_CORE) != pdTRUE) { + if (xTaskCreatePinnedToCore(esp_mqtt_task, "mqtt_task", client->config->task_stack, client, client->config->task_prio, &client->task_handle, MQTT_TASK_CORE) != pdTRUE) { ESP_LOGE(TAG, "Error create mqtt task"); return ESP_FAIL; } #else ESP_LOGD(TAG, "Core selection disabled"); - if (xTaskCreate(esp_mqtt_task, "mqtt_task", client->config->task_stack, client, client->config->task_prio, NULL) != pdTRUE) { + if (xTaskCreate(esp_mqtt_task, "mqtt_task", client->config->task_stack, client, client->config->task_prio, &client->task_handle) != pdTRUE) { ESP_LOGE(TAG, "Error create mqtt task"); return ESP_FAIL; } @@ -785,6 +944,18 @@ esp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client) return ESP_OK; } +esp_err_t esp_mqtt_client_reconnect(esp_mqtt_client_handle_t client) +{ + ESP_LOGI(TAG, "Client force reconnect requested"); + if (client->state != MQTT_STATE_WAIT_TIMEOUT) { + ESP_LOGD(TAG, "The client is not waiting for reconnection. Ignore the request"); + return ESP_FAIL; + } + client->wait_timeout_ms = 0; + xEventGroupSetBits(client->status_bits, RECONNECT_BIT); + return ESP_OK; +} + esp_err_t esp_mqtt_client_stop(esp_mqtt_client_handle_t client) { if (client->run) { @@ -816,20 +987,23 @@ int esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic ESP_LOGE(TAG, "Client has not connected"); return -1; } - mqtt_enqueue(client); //move pending msg to outbox (if have) + MQTT_API_LOCK_FROM_OTHER_TASK(client); client->mqtt_state.outbound_message = mqtt_msg_subscribe(&client->mqtt_state.mqtt_connection, topic, qos, &client->mqtt_state.pending_msg_id); client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); client->mqtt_state.pending_msg_count ++; + mqtt_enqueue(client); //move pending msg to outbox (if have) if (mqtt_write_data(client) != ESP_OK) { ESP_LOGE(TAG, "Error to subscribe topic=%s, qos=%d", topic, qos); + MQTT_API_UNLOCK_FROM_OTHER_TASK(client); return -1; } ESP_LOGD(TAG, "Sent subscribe topic=%s, id: %d, type=%d successful", topic, client->mqtt_state.pending_msg_id, client->mqtt_state.pending_msg_type); + MQTT_API_UNLOCK_FROM_OTHER_TASK(client); return client->mqtt_state.pending_msg_id; } @@ -839,7 +1013,7 @@ int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *top ESP_LOGE(TAG, "Client has not connected"); return -1; } - mqtt_enqueue(client); + MQTT_API_LOCK_FROM_OTHER_TASK(client); client->mqtt_state.outbound_message = mqtt_msg_unsubscribe(&client->mqtt_state.mqtt_connection, topic, &client->mqtt_state.pending_msg_id); @@ -847,27 +1021,28 @@ int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *top client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); client->mqtt_state.pending_msg_count ++; + mqtt_enqueue(client); if (mqtt_write_data(client) != ESP_OK) { ESP_LOGE(TAG, "Error to unsubscribe topic=%s", topic); + MQTT_API_UNLOCK_FROM_OTHER_TASK(client); return -1; } ESP_LOGD(TAG, "Sent Unsubscribe topic=%s, id: %d, successful", topic, client->mqtt_state.pending_msg_id); + MQTT_API_UNLOCK_FROM_OTHER_TASK(client); return client->mqtt_state.pending_msg_id; } int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain) { uint16_t pending_msg_id = 0; - if (client->state != MQTT_STATE_CONNECTED) { - ESP_LOGE(TAG, "Client has not connected"); - return -1; - } + if (len <= 0) { len = strlen(data); } + MQTT_API_LOCK_FROM_OTHER_TASK(client); mqtt_message_t *publish_msg = mqtt_msg_publish(&client->mqtt_state.mqtt_connection, topic, data, len, qos, retain, @@ -875,20 +1050,82 @@ int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, /* We have to set as pending all the qos>0 messages) */ if (qos > 0) { - mqtt_enqueue(client); client->mqtt_state.outbound_message = publish_msg; client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); client->mqtt_state.pending_msg_id = pending_msg_id; + client->mqtt_state.pending_publish_qos = qos; client->mqtt_state.pending_msg_count ++; + // by default store as QUEUED (not transmitted yet) + mqtt_enqueue(client); } else { client->mqtt_state.outbound_message = publish_msg; } - if (mqtt_write_data(client) != ESP_OK) { - ESP_LOGE(TAG, "Error to public data to topic=%s, qos=%d", topic, qos); - return -1; + /* Skip sending if not connected (rely on resending) */ + if (client->state != MQTT_STATE_CONNECTED) { + ESP_LOGD(TAG, "Publish: client is not connected"); + goto cannot_publish; + } + + /* Provide support for sending fragmented message if it doesn't fit buffer */ + int remaining_len = len; + const char *current_data = data; + bool sending = true; + + while (sending) { + + if (mqtt_write_data(client) != ESP_OK) { + esp_mqtt_abort_connection(client); + goto cannot_publish; + } + + int data_sent = client->mqtt_state.outbound_message->length - client->mqtt_state.outbound_message->fragmented_msg_data_offset; + remaining_len -= data_sent; + current_data += data_sent; + + if (remaining_len > 0) { + mqtt_connection_t* connection = &client->mqtt_state.mqtt_connection; + ESP_LOGD(TAG, "Sending fragmented message, remains to send %d bytes of %d", remaining_len, len); + if (connection->message.fragmented_msg_data_offset) { + // asked to enqueue oversized message (first time only) + connection->message.fragmented_msg_data_offset = 0; + connection->message.fragmented_msg_total_length = 0; + if (qos > 0) { + // internally enqueue all big messages, as they dont fit 'pending msg' structure + mqtt_enqueue_oversized(client, (uint8_t*)current_data, remaining_len); + } + } + + if (remaining_len > connection->buffer_length) { + // Continue with sending + memcpy(connection->buffer, current_data, connection->buffer_length); + connection->message.length = connection->buffer_length; + sending = true; + } else { + memcpy(connection->buffer, current_data, remaining_len); + connection->message.length = remaining_len; + sending = true; + } + connection->message.data = connection->buffer; + client->mqtt_state.outbound_message = &connection->message; + } else { + // Message was sent correctly + sending = false; + } } + + if (qos > 0) { + outbox_set_pending(client->outbox, pending_msg_id, TRANSMITTED); + } + MQTT_API_UNLOCK_FROM_OTHER_TASK(client); return pending_msg_id; + +cannot_publish: + if (qos == 0) { + ESP_LOGW(TAG, "Publish: Loosing qos0 data when client not connected"); + } + MQTT_API_UNLOCK_FROM_OTHER_TASK(client); + return 0; } diff --git a/components/newlib/newlib/lib/libc.a b/components/newlib/newlib/lib/libc.a index 8e177d186..e34f3baba 100644 Binary files a/components/newlib/newlib/lib/libc.a and b/components/newlib/newlib/lib/libc.a differ diff --git a/components/newlib/newlib/port/esp_newlib.c b/components/newlib/newlib/port/esp_newlib.c index 2a8010488..a84ee0297 100644 --- a/components/newlib/newlib/port/esp_newlib.c +++ b/components/newlib/newlib/port/esp_newlib.c @@ -22,6 +22,9 @@ #include "esp_vfs_dev.h" #endif +#define _STR(_s) #_s +#define STR(_s) _STR(_s) + /* * @brief Initialize global and thread's private reent object data. We add this instead of * newlib's initialization function to avoid some unnecessary cost and unused function. @@ -49,21 +52,23 @@ void esp_reent_init(struct _reent* r) */ int esp_newlib_init(void) { + const char *default_uart_dev = "/dev/uart/" STR(CONFIG_CONSOLE_UART_NUM); + esp_reent_init(_global_impure_ptr); #ifdef CONFIG_USING_ESP_VFS esp_vfs_dev_uart_register(); #endif - _GLOBAL_REENT->_stdout = fopen("/dev/uart/0", "w"); + _GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w"); if (!_GLOBAL_REENT->_stdout) goto err; - _GLOBAL_REENT->_stderr = fopen("/dev/uart/0", "w"); + _GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w"); if (!_GLOBAL_REENT->_stderr) goto err_fail; - _GLOBAL_REENT->_stdin = fopen("/dev/uart/0", "r"); + _GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r"); if (!_GLOBAL_REENT->_stdin) goto err_in; diff --git a/components/newlib/newlib/port/syscall.c b/components/newlib/newlib/port/syscall.c index 99216d328..60f8d5db0 100644 --- a/components/newlib/newlib/port/syscall.c +++ b/components/newlib/newlib/port/syscall.c @@ -158,7 +158,9 @@ void _free_r(struct _reent *r, void *ptr) void abort(void) { - ESP_LOGE("ABORT","Error found and abort!"); +#ifndef CONFIG_ESP_PANIC_SILENT_REBOOT + ets_printf("abort() was called at PC %p on core %d\r\n", __builtin_return_address(0) - 3, xPortGetCoreID()); +#endif /* cause a exception to jump into panic function */ while (1) { diff --git a/components/spi_flash/src/spi_flash.c b/components/spi_flash/src/spi_flash.c index f4c622dfb..93240e9d2 100644 --- a/components/spi_flash/src/spi_flash.c +++ b/components/spi_flash/src/spi_flash.c @@ -430,7 +430,7 @@ void user_spi_flash_dio_to_qio_pre_init(void) to_qio = true; } //ENABLE FLASH QIO 0X31H+BIT2 - } else if (((flash_id & 0xFFFFFF) == 0x1640C8) || ((flash_id & 0xFFFFFF) == 0x1840C8)) { + } else if ((flash_id & 0xFFFF) == 0x40C8) { if (flash_gd25q32c_enable_QIO_mode() == true) { to_qio = true; } diff --git a/docs/en/api-guides/fota-from-old-new.rst b/docs/en/api-guides/fota-from-old-new.rst index d5ca61dc7..312d5f588 100644 --- a/docs/en/api-guides/fota-from-old-new.rst +++ b/docs/en/api-guides/fota-from-old-new.rst @@ -68,7 +68,7 @@ Connect your host PC and the ESP8266 to the same AP. Step 2: Configure and Build ----------------------------- -Here, we use the `SP8266_RTOS_SDK/examples/system/ota `_ example. +Here, we use the :example:`system/ota/native_ota/1MB_flash/new_to_new_with_old` if flash is 1MB or :example:`system/ota/native_ota/2+MB_flash/new_to_new_with_old` if flash is 2MB or larger. Open a new terminal on your PC, set the following configurations, and then compile the example: @@ -119,6 +119,17 @@ Configure the flash size according to your actual development board's flash. - HTTP Server Port: HTTP server port - HTTP GET Filename: Using "ota.ota.bin" which is the target firmware of the example +5. Select connecting to the original AP +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If users want to connect to the original AP of old SDK, then configurate as following: + +:: + + Example Configuration ---> + [*] Connect to the original AP + + 5. Build the project ^^^^^^^^^^^^^^^^^^^^ @@ -150,3 +161,10 @@ Note - This "unpacking workflow" will only be executed when it is an old SDK firmware that upgrade to the new SDK firmware, for example, V2.0 upgrade to V3.1. After that, the FOTA in later versions (for example, V3.1 upgrade to later) will be the `normal FOTA workflow `_. +Inheritance Data +================ + +Users can perfer to the source code :example_file:`system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/ota_example_main.c` to check +how to load original AP's information. + +See structure **old_sysconf** in the file of :component_file:`esp8266/include/internal/esp_system_internal.h` for the organization of this information. diff --git a/docs/en/general-notes/index.rst b/docs/en/general-notes/index.rst index 46cd69bf0..77bbc5a85 100755 --- a/docs/en/general-notes/index.rst +++ b/docs/en/general-notes/index.rst @@ -24,3 +24,14 @@ We split the native OTA example into several sub-examples to let custemors to ch ^^^^^^^^^^^^^^^^^^ For better compatibility, the SDK is in bg mode by default. And application can set it to be bgn mode for reconnecting when it fails to connect some 11n only APs, refer to the `examples/wifi/simple_wifi `_. + +4. JTAG I/O +^^^^^^^^^^^ + +In some cases, if enable JTAG I/O (default options), it will cost some more current so that the hardware will cost more power. +So if users don't use Jtag or these GPIOs directly and want to save more power, please enable this option in the menuconfig: + +:: + + "Bootloader config ---> + [ ] Bootloader disable JTAG I/O" diff --git a/docs/requirements.txt b/docs/requirements.txt index 3676a3c39..0c623e4cd 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -5,9 +5,9 @@ sphinx>=1.8.4 breathe==4.11.1 sphinx-rtd-theme sphinx-notfound-page -sphinxcontrib-blockdiag>=1.5.5 -sphinxcontrib-seqdiag>=0.8.5 -sphinxcontrib-actdiag>=0.8.5 -sphinxcontrib-nwdiag>=0.9.5 +sphinxcontrib-blockdiag>=1.5.5, <2.0.0 +sphinxcontrib-seqdiag>=0.8.5, <2.0.0 +sphinxcontrib-actdiag>=0.8.5, <2.0.0 +sphinxcontrib-nwdiag>=0.9.5, <2.0.0 recommonmark future>=0.16.0 # for ../tools/gen_esp_err_to_name.py diff --git a/examples/protocols/esp-mqtt/ssl/CMakeLists.txt b/examples/protocols/esp-mqtt/ssl/CMakeLists.txt index 13bdd8c21..717181000 100644 --- a/examples/protocols/esp-mqtt/ssl/CMakeLists.txt +++ b/examples/protocols/esp-mqtt/ssl/CMakeLists.txt @@ -6,4 +6,4 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mqtt_ssl) -target_add_binary_data(mqtt_ssl.elf "main/iot_eclipse_org.pem" TEXT) +target_add_binary_data(mqtt_ssl.elf "main/mqtt_eclipse_org.pem" TEXT) diff --git a/examples/protocols/esp-mqtt/ssl/README.md b/examples/protocols/esp-mqtt/ssl/README.md index 3d369bdf9..80b539382 100644 --- a/examples/protocols/esp-mqtt/ssl/README.md +++ b/examples/protocols/esp-mqtt/ssl/README.md @@ -2,7 +2,7 @@ (See the README.md file in the upper level 'examples' directory for more information about examples.) -This example connects to the broker iot.eclipse.org using ssl transport and as a demonstration subscribes/unsubscribes and send a message on certain topic. +This example connects to the broker mqtt.eclipse.org using ssl transport and as a demonstration subscribes/unsubscribes and send a message on certain topic. It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. @@ -22,9 +22,9 @@ make menuconfig * Set ssid and password for the board to connect to AP. -Note how to create a PEM certificate for iot.eclipse.org: +Note how to create a PEM certificate for mqtt.eclipse.org: ``` -openssl s_client -showcerts -connect iot.eclipse.org:8883 /dev/null|openssl x509 -outform PEM >iot_eclipse_org.pem +openssl s_client -showcerts -connect mqtt.eclipse.org:8883 /dev/null|openssl x509 -outform PEM >iot_eclipse_org.pem ``` ### Build and Flash diff --git a/examples/protocols/esp-mqtt/ssl/main/Kconfig.projbuild b/examples/protocols/esp-mqtt/ssl/main/Kconfig.projbuild index 8b4eda41a..7cf18965f 100644 --- a/examples/protocols/esp-mqtt/ssl/main/Kconfig.projbuild +++ b/examples/protocols/esp-mqtt/ssl/main/Kconfig.projbuild @@ -1,31 +1,32 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + config WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. -config BROKER_URI - string "Broker URL" - default "mqtts://iot.eclipse.org:8883" - help - URL of an mqtt broker which this example connects to. + config BROKER_URI + string "Broker URL" + default "mqtts://mqtt.eclipse.org:8883" + help + URL of an mqtt broker which this example connects to. -config BROKER_CERTIFICATE_OVERRIDE - string "Broker certificate override" - default "" - help - Please leave empty if broker certificate included from a textfile; otherwise fill in a base64 part of PEM format certificate + config BROKER_CERTIFICATE_OVERRIDE + string "Broker certificate override" + default "" + help + Please leave empty if broker certificate included from a textfile; otherwise fill in a base64 part of PEM + format certificate -config BROKER_CERTIFICATE_OVERRIDDEN - bool - default y if BROKER_CERTIFICATE_OVERRIDE != "" + config BROKER_CERTIFICATE_OVERRIDDEN + bool + default y if BROKER_CERTIFICATE_OVERRIDE != "" endmenu diff --git a/examples/protocols/esp-mqtt/ssl/main/app_main.c b/examples/protocols/esp-mqtt/ssl/main/app_main.c index 17818e4e4..d53cb9304 100644 --- a/examples/protocols/esp-mqtt/ssl/main/app_main.c +++ b/examples/protocols/esp-mqtt/ssl/main/app_main.c @@ -78,11 +78,11 @@ static void wifi_init(void) } #if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1 -static const uint8_t iot_eclipse_org_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; +static const uint8_t mqtt_eclipse_org_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; #else -extern const uint8_t iot_eclipse_org_pem_start[] asm("_binary_iot_eclipse_org_pem_start"); +extern const uint8_t mqtt_eclipse_org_pem_start[] asm("_binary_mqtt_eclipse_org_pem_start"); #endif -extern const uint8_t iot_eclipse_org_pem_end[] asm("_binary_iot_eclipse_org_pem_end"); +extern const uint8_t mqtt_eclipse_org_pem_end[] asm("_binary_mqtt_eclipse_org_pem_end"); static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) { @@ -123,6 +123,12 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) break; case MQTT_EVENT_ERROR: ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); + if (event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) { + ESP_LOGI(TAG, "Connection refused error: 0x%x", event->error_handle->connect_return_code); + } + break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); break; } return ESP_OK; @@ -134,7 +140,7 @@ static void mqtt_app_start(void) const esp_mqtt_client_config_t mqtt_cfg = { .uri = CONFIG_BROKER_URI, .event_handle = mqtt_event_handler, - .cert_pem = (const char *)iot_eclipse_org_pem_start, + .cert_pem = (const char *)mqtt_eclipse_org_pem_start, }; ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); diff --git a/examples/protocols/esp-mqtt/ssl/main/component.mk b/examples/protocols/esp-mqtt/ssl/main/component.mk index 797c4a1f6..597752fb9 100644 --- a/examples/protocols/esp-mqtt/ssl/main/component.mk +++ b/examples/protocols/esp-mqtt/ssl/main/component.mk @@ -1 +1 @@ -COMPONENT_EMBED_TXTFILES := iot_eclipse_org.pem +COMPONENT_EMBED_TXTFILES := mqtt_eclipse_org.pem diff --git a/examples/protocols/esp-mqtt/ssl/main/iot_eclipse_org.pem b/examples/protocols/esp-mqtt/ssl/main/mqtt_eclipse_org.pem similarity index 100% rename from examples/protocols/esp-mqtt/ssl/main/iot_eclipse_org.pem rename to examples/protocols/esp-mqtt/ssl/main/mqtt_eclipse_org.pem diff --git a/examples/protocols/esp-mqtt/ssl/mqtt_ssl_example_test.py b/examples/protocols/esp-mqtt/ssl/mqtt_ssl_example_test.py index 3ea27c096..ef9d1a9d6 100644 --- a/examples/protocols/esp-mqtt/ssl/mqtt_ssl_example_test.py +++ b/examples/protocols/esp-mqtt/ssl/mqtt_ssl_example_test.py @@ -86,8 +86,8 @@ def test_examples_protocol_mqtt_ssl(env, extra_data): client.on_connect = on_connect client.on_message = on_message client.tls_set(None, - None, - None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1, ciphers=None) + None, + None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None) client.tls_insecure_set(True) print("Connecting...") client.connect(broker_url, broker_port, 60) @@ -117,5 +117,6 @@ def test_examples_protocol_mqtt_ssl(env, extra_data): event_stop_client.set() thread1.join() + if __name__ == '__main__': test_examples_protocol_mqtt_ssl() diff --git a/examples/protocols/esp-mqtt/ssl_mutual_auth/main/Kconfig.projbuild b/examples/protocols/esp-mqtt/ssl_mutual_auth/main/Kconfig.projbuild index 176d8fb33..ed4e69168 100644 --- a/examples/protocols/esp-mqtt/ssl_mutual_auth/main/Kconfig.projbuild +++ b/examples/protocols/esp-mqtt/ssl_mutual_auth/main/Kconfig.projbuild @@ -1,15 +1,15 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + config WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. endmenu diff --git a/examples/protocols/esp-mqtt/ssl_mutual_auth/main/app_main.c b/examples/protocols/esp-mqtt/ssl_mutual_auth/main/app_main.c index adf5db9a9..cd0117fe2 100644 --- a/examples/protocols/esp-mqtt/ssl_mutual_auth/main/app_main.c +++ b/examples/protocols/esp-mqtt/ssl_mutual_auth/main/app_main.c @@ -122,6 +122,9 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) case MQTT_EVENT_ERROR: ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); + break; } return ESP_OK; } diff --git a/examples/protocols/esp-mqtt/tcp/main/Kconfig.projbuild b/examples/protocols/esp-mqtt/tcp/main/Kconfig.projbuild index 71f95ea8f..57d9b4339 100644 --- a/examples/protocols/esp-mqtt/tcp/main/Kconfig.projbuild +++ b/examples/protocols/esp-mqtt/tcp/main/Kconfig.projbuild @@ -1,25 +1,25 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + config WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. -config BROKER_URL - string "Broker URL" - default "mqtt://iot.eclipse.org" - help - URL of the broker to connect to + config BROKER_URL + string "Broker URL" + default "mqtt://mqtt.eclipse.org" + help + URL of the broker to connect to -config BROKER_URL_FROM_STDIN - bool - default y if BROKER_URL = "FROM_STDIN" + config BROKER_URL_FROM_STDIN + bool + default y if BROKER_URL = "FROM_STDIN" endmenu diff --git a/examples/protocols/esp-mqtt/tcp/main/app_main.c b/examples/protocols/esp-mqtt/tcp/main/app_main.c index ea37a7409..b78e9d82b 100644 --- a/examples/protocols/esp-mqtt/tcp/main/app_main.c +++ b/examples/protocols/esp-mqtt/tcp/main/app_main.c @@ -69,6 +69,9 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) case MQTT_EVENT_ERROR: ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); + break; } return ESP_OK; } diff --git a/examples/protocols/esp-mqtt/tcp/mqtt_tcp_example_test.py b/examples/protocols/esp-mqtt/tcp/mqtt_tcp_example_test.py index e2568d527..05e51420e 100644 --- a/examples/protocols/esp-mqtt/tcp/mqtt_tcp_example_test.py +++ b/examples/protocols/esp-mqtt/tcp/mqtt_tcp_example_test.py @@ -1,36 +1,53 @@ import re import os import sys -from socket import * +import socket from threading import Thread import struct import time -msgid=-1 + +try: + import IDF +except ImportError: + # this is a test case write with tiny-test-fw. + # to run test cases outside tiny-test-fw, + # we need to set environment variable `TEST_FW_PATH`, + # then get and insert `TEST_FW_PATH` to sys path before import FW module + test_fw_path = os.getenv("TEST_FW_PATH") + if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + import IDF + +import DUT + +msgid = -1 + def get_my_ip(): - s1 = socket(AF_INET, SOCK_DGRAM) + s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s1.connect(("8.8.8.8", 80)) my_ip = s1.getsockname()[0] s1.close() return my_ip + def mqqt_server_sketch(my_ip, port): global msgid print("Starting the server on {}".format(my_ip)) s = None try: - s=socket(AF_INET, SOCK_STREAM) + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(60) s.bind((my_ip, port)) s.listen(1) - q,addr=s.accept() + q,addr = s.accept() q.settimeout(30) print("connection accepted") - except: + except Exception: print("Local server on {}:{} listening/accepting failure: {}" - "Possibly check permissions or firewall settings" - "to accept connections on this address".format(my_ip, port, sys.exc_info()[0])) + "Possibly check permissions or firewall settings" + "to accept connections on this address".format(my_ip, port, sys.exc_info()[0])) raise data = q.recv(1024) # check if received initial empty message @@ -47,20 +64,6 @@ def mqqt_server_sketch(my_ip, port): s.close() print("server closed") -# this is a test case write with tiny-test-fw. -# to run test cases outside tiny-test-fw, -# we need to set environment variable `TEST_FW_PATH`, -# then get and insert `TEST_FW_PATH` to sys path before import FW module -test_fw_path = os.getenv("TEST_FW_PATH") -if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - -import TinyFW -import IDF -import DUT - - - @IDF.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_mqtt_qos1(env, extra_data): @@ -76,14 +79,14 @@ def test_examples_protocol_mqtt_qos1(env, extra_data): # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "mqtt_tcp.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("mqtt_tcp_bin_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("mqtt_tcp_size", bin_size//1024) + IDF.log_performance("mqtt_tcp_bin_size", "{}KB".format(bin_size // 1024)) + IDF.check_performance("mqtt_tcp_size", bin_size // 1024) # 1. start mqtt broker sketch host_ip = get_my_ip() - thread1 = Thread(target = mqqt_server_sketch, args = (host_ip,1883)) + thread1 = Thread(target=mqqt_server_sketch, args=(host_ip,1883)) thread1.start() # 2. start the dut test and wait till client gets IP address - dut1.start_app() + dut1.start_app() # waiting for getting the IP address try: ip_address = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) @@ -91,10 +94,10 @@ def test_examples_protocol_mqtt_qos1(env, extra_data): except DUT.ExpectTimeout: raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') - print ("writing to device: {}".format("mqtt://" + host_ip + "\n")) + print("writing to device: {}".format("mqtt://" + host_ip + "\n")) dut1.write("mqtt://" + host_ip + "\n") thread1.join() - print ("Message id received from server: {}".format(msgid)) + print("Message id received from server: {}".format(msgid)) # 3. check the message id was enqueued and then deleted msgid_enqueued = dut1.expect(re.compile(r"OUTBOX: ENQUEUE msgid=([0-9]+)"), timeout=30) msgid_deleted = dut1.expect(re.compile(r"OUTBOX: DELETED msgid=([0-9]+)"), timeout=30) @@ -105,5 +108,6 @@ def test_examples_protocol_mqtt_qos1(env, extra_data): print("Failure!") raise ValueError('Mismatch of msgid: received: {}, enqueued {}, deleted {}'.format(msgid, msgid_enqueued, msgid_deleted)) + if __name__ == '__main__': test_examples_protocol_mqtt_qos1() diff --git a/examples/protocols/esp-mqtt/ws/README.md b/examples/protocols/esp-mqtt/ws/README.md index 619519d92..905d20809 100644 --- a/examples/protocols/esp-mqtt/ws/README.md +++ b/examples/protocols/esp-mqtt/ws/README.md @@ -2,7 +2,7 @@ (See the README.md file in the upper level 'examples' directory for more information about examples.) -This example connects to the broker iot.eclipse.org over web sockets as a demonstration subscribes/unsubscribes and send a message on certain topic. +This example connects to the broker mqtt.eclipse.org over web sockets as a demonstration subscribes/unsubscribes and send a message on certain topic. It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. diff --git a/examples/protocols/esp-mqtt/ws/main/Kconfig.projbuild b/examples/protocols/esp-mqtt/ws/main/Kconfig.projbuild index 5223e885f..ee66ba883 100644 --- a/examples/protocols/esp-mqtt/ws/main/Kconfig.projbuild +++ b/examples/protocols/esp-mqtt/ws/main/Kconfig.projbuild @@ -1,21 +1,21 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + config WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. -config BROKER_URI - string "Broker URL" - default "ws://iot.eclipse.org:80/ws" - help - URL of an mqtt broker which this example connects to. + config BROKER_URI + string "Broker URL" + default "ws://mqtt.eclipse.org:80/mqtt" + help + URL of an mqtt broker which this example connects to. endmenu diff --git a/examples/protocols/esp-mqtt/ws/main/app_main.c b/examples/protocols/esp-mqtt/ws/main/app_main.c index 6b1e18c8a..8ac59ac74 100644 --- a/examples/protocols/esp-mqtt/ws/main/app_main.c +++ b/examples/protocols/esp-mqtt/ws/main/app_main.c @@ -66,6 +66,9 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) case MQTT_EVENT_ERROR: ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); + break; } return ESP_OK; } diff --git a/examples/protocols/esp-mqtt/ws/mqtt_ws_example_test.py b/examples/protocols/esp-mqtt/ws/mqtt_ws_example_test.py index b4919bfb6..58b8d5e37 100644 --- a/examples/protocols/esp-mqtt/ws/mqtt_ws_example_test.py +++ b/examples/protocols/esp-mqtt/ws/mqtt_ws_example_test.py @@ -82,7 +82,6 @@ def test_examples_protocol_mqtt_ws(env, extra_data): client = mqtt.Client(transport="websockets") client.on_connect = on_connect client.on_message = on_message - client.ws_set_options(path="/ws", headers=None) print("Connecting...") client.connect(broker_url, broker_port, 60) except Exception: @@ -111,5 +110,6 @@ def test_examples_protocol_mqtt_ws(env, extra_data): event_stop_client.set() thread1.join() + if __name__ == '__main__': test_examples_protocol_mqtt_ws() diff --git a/examples/protocols/esp-mqtt/wss/CMakeLists.txt b/examples/protocols/esp-mqtt/wss/CMakeLists.txt index 7ba5e6295..f94926163 100644 --- a/examples/protocols/esp-mqtt/wss/CMakeLists.txt +++ b/examples/protocols/esp-mqtt/wss/CMakeLists.txt @@ -6,4 +6,4 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mqtt_websocket_secure) -target_add_binary_data(mqtt_websocket_secure.elf "main/iot_eclipse_org.pem" TEXT) +target_add_binary_data(mqtt_websocket_secure.elf "main/mqtt_eclipse_org.pem" TEXT) diff --git a/examples/protocols/esp-mqtt/wss/README.md b/examples/protocols/esp-mqtt/wss/README.md index 43d829ccb..c92500eaa 100644 --- a/examples/protocols/esp-mqtt/wss/README.md +++ b/examples/protocols/esp-mqtt/wss/README.md @@ -1,7 +1,7 @@ # ESP-MQTT MQTT over WSS Sample application (See the README.md file in the upper level 'examples' directory for more information about examples.) -This example connects to the broker iot.eclipse.org over secure websockets and as a demonstration subscribes/unsubscribes and send a message on certain topic. +This example connects to the broker mqtt.eclipse.org over secure websockets and as a demonstration subscribes/unsubscribes and send a message on certain topic. It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. @@ -21,10 +21,10 @@ make menuconfig * Set ssid and password for the board to connect to AP. -Note how to create a PEM certificate for iot.eclipse.org: +Note how to create a PEM certificate for mqtt.eclipse.org: ``` -openssl s_client -showcerts -connect iot.eclipse.org:8883 /dev/null|openssl x509 -outform PEM >iot_eclipse_org.pem +openssl s_client -showcerts -connect mqtt.eclipse.org:8883 /dev/null|openssl x509 -outform PEM >iot_eclipse_org.pem ``` ### Build and Flash diff --git a/examples/protocols/esp-mqtt/wss/main/Kconfig.projbuild b/examples/protocols/esp-mqtt/wss/main/Kconfig.projbuild index 964d436f6..a91485b79 100644 --- a/examples/protocols/esp-mqtt/wss/main/Kconfig.projbuild +++ b/examples/protocols/esp-mqtt/wss/main/Kconfig.projbuild @@ -1,31 +1,32 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + config WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. -config BROKER_URI - string "Broker URL" - default "wss://iot.eclipse.org:443/ws" - help - URL of an mqtt broker which this example connects to. + config BROKER_URI + string "Broker URL" + default "wss://mqtt.eclipse.org:443/mqtt" + help + URL of an mqtt broker which this example connects to. -config BROKER_CERTIFICATE_OVERRIDE - string "Server certificate override" - default "" - help - Please leave empty if server certificate included from a textfile; otherwise fill in a base64 part of PEM format certificate + config BROKER_CERTIFICATE_OVERRIDE + string "Server certificate override" + default "" + help + Please leave empty if server certificate included from a textfile; otherwise fill in a base64 part of PEM + format certificate -config BROKER_CERTIFICATE_OVERRIDDEN - bool - default y if BROKER_CERTIFICATE_OVERRIDE != "" + config BROKER_CERTIFICATE_OVERRIDDEN + bool + default y if BROKER_CERTIFICATE_OVERRIDE != "" endmenu diff --git a/examples/protocols/esp-mqtt/wss/main/app_main.c b/examples/protocols/esp-mqtt/wss/main/app_main.c index 06f6307dc..1db484806 100644 --- a/examples/protocols/esp-mqtt/wss/main/app_main.c +++ b/examples/protocols/esp-mqtt/wss/main/app_main.c @@ -78,11 +78,11 @@ static void wifi_init(void) } #if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1 -static const uint8_t iot_eclipse_org_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; +static const uint8_t mqtt_eclipse_org_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; #else -extern const uint8_t iot_eclipse_org_pem_start[] asm("_binary_iot_eclipse_org_pem_start"); +extern const uint8_t mqtt_eclipse_org_pem_start[] asm("_binary_mqtt_eclipse_org_pem_start"); #endif -extern const uint8_t iot_eclipse_org_pem_end[] asm("_binary_iot_eclipse_org_pem_end"); +extern const uint8_t mqtt_eclipse_org_pem_end[] asm("_binary_mqtt_eclipse_org_pem_end"); static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) { @@ -124,6 +124,9 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) case MQTT_EVENT_ERROR: ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); + break; } return ESP_OK; } @@ -133,7 +136,7 @@ static void mqtt_app_start(void) const esp_mqtt_client_config_t mqtt_cfg = { .uri = CONFIG_BROKER_URI, .event_handle = mqtt_event_handler, - .cert_pem = (const char *)iot_eclipse_org_pem_start, + .cert_pem = (const char *)mqtt_eclipse_org_pem_start, }; ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); diff --git a/examples/protocols/esp-mqtt/wss/main/component.mk b/examples/protocols/esp-mqtt/wss/main/component.mk index 797c4a1f6..597752fb9 100644 --- a/examples/protocols/esp-mqtt/wss/main/component.mk +++ b/examples/protocols/esp-mqtt/wss/main/component.mk @@ -1 +1 @@ -COMPONENT_EMBED_TXTFILES := iot_eclipse_org.pem +COMPONENT_EMBED_TXTFILES := mqtt_eclipse_org.pem diff --git a/examples/protocols/esp-mqtt/wss/main/iot_eclipse_org.pem b/examples/protocols/esp-mqtt/wss/main/mqtt_eclipse_org.pem similarity index 100% rename from examples/protocols/esp-mqtt/wss/main/iot_eclipse_org.pem rename to examples/protocols/esp-mqtt/wss/main/mqtt_eclipse_org.pem diff --git a/examples/protocols/esp-mqtt/wss/mqtt_wss_example_test.py b/examples/protocols/esp-mqtt/wss/mqtt_wss_example_test.py index 6aac644c6..15ca2834a 100644 --- a/examples/protocols/esp-mqtt/wss/mqtt_wss_example_test.py +++ b/examples/protocols/esp-mqtt/wss/mqtt_wss_example_test.py @@ -84,8 +84,8 @@ def test_examples_protocol_mqtt_wss(env, extra_data): client.on_connect = on_connect client.on_message = on_message client.tls_set(None, - None, - None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1, ciphers=None) + None, + None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None) print("Connecting...") client.connect(broker_url, broker_port, 60) except Exception: @@ -114,5 +114,6 @@ def test_examples_protocol_mqtt_wss(env, extra_data): event_stop_client.set() thread1.join() + if __name__ == '__main__': test_examples_protocol_mqtt_wss() diff --git a/examples/system/factory-test/components/rf_test/lib/VERSION b/examples/system/factory-test/components/rf_test/lib/VERSION new file mode 100644 index 000000000..59207e074 --- /dev/null +++ b/examples/system/factory-test/components/rf_test/lib/VERSION @@ -0,0 +1,2 @@ +gwen: + librftest: 1058_13 diff --git a/examples/system/factory-test/components/rf_test/lib/librftest.a b/examples/system/factory-test/components/rf_test/lib/librftest.a old mode 100644 new mode 100755 index 8feb0222b..60dbfc03c Binary files a/examples/system/factory-test/components/rf_test/lib/librftest.a and b/examples/system/factory-test/components/rf_test/lib/librftest.a differ diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/README.md b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/README.md index edff927e5..e14e4324f 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/README.md +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/README.md @@ -101,6 +101,13 @@ Configurate the flash size: (X) 1 MB ``` +If you want to connect to the original AP of old SDK, then configurate as following: + +``` + Example Configuration ---> + [*] Connect to the original AP +``` + Save your changes, and type `make ota` to build the example to generate the real OTA binary firmware. The name of final generated binary firmware is `ota.v2_to_v3.ota.bin` and the binary firmware locates at directory of `build`. diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/Kconfig.projbuild b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/Kconfig.projbuild index c5a0b69ff..5ac58b65d 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/Kconfig.projbuild +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/Kconfig.projbuild @@ -1,14 +1,22 @@ menu "Example Configuration" +config CONNECT_ORIGINAL_AP + bool "Connect to the original AP" + default n + help + Connect to the original AP of old SDK + config WIFI_SSID string "WiFi SSID" default "myssid" + depends on !CONNECT_ORIGINAL_AP help SSID (network name) for the example to connect to. config WIFI_PASSWORD string "WiFi Password" default "myssid" + depends on !CONNECT_ORIGINAL_AP help WiFi password (WPA or WPA2) for the example to use. diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/ota_example_main.c b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/ota_example_main.c index a8188b9c3..53bb569c8 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/ota_example_main.c +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/ota_example_main.c @@ -15,6 +15,9 @@ #include "freertos/task.h" #include "freertos/event_groups.h" +#ifdef CONFIG_CONNECT_ORIGINAL_AP +#include "internal/esp_system_internal.h" +#endif #include "esp_system.h" #include "esp_wifi.h" #include "esp_event_loop.h" @@ -105,18 +108,48 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) static void initialise_wifi(void) { - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); +#ifdef CONFIG_CONNECT_ORIGINAL_AP + int ret; + uint32_t addr; + struct old_sysconf *sysconf; + wifi_config_t wifi_config = { 0 }; + + if (!(addr = esp_get_old_sysconf_addr())) { + ESP_LOGE(TAG, "Current firmware does not update from old SDK firmware"); + return ; + } + + if (!(sysconf = malloc(sizeof(struct old_sysconf)))) { + ESP_LOGE(TAG, "No enough memory for old system config"); + return ; + } + + if ((ret = spi_flash_read(addr, sysconf, sizeof(struct old_sysconf))) != ESP_OK) { + free(sysconf); + ESP_LOGE(TAG, "read old system config from flash error %d", ret); + return ; + } + + memcpy(&wifi_config.sta.ssid, sysconf->ap_ssid[sysconf->ap_index].ssid, sysconf->ap_ssid[sysconf->ap_index].len); + memcpy(&wifi_config.sta.password, sysconf->ap_ssid[sysconf->ap_index].passwd, 32); + + free(sysconf); +#else wifi_config_t wifi_config = { .sta = { .ssid = EXAMPLE_WIFI_SSID, .password = EXAMPLE_WIFI_PASS, }, }; +#endif + + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); + ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); + ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/README.md b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/README.md index 824287f2b..b921e9ac1 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/README.md +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/README.md @@ -93,6 +93,13 @@ If you old SDK storing RF parameters is customized and want the new firmware to [*] Load old RF Parameters ``` +If you want to connect to the original AP of old SDK, then configurate as following: + +``` + Example Configuration ---> + [*] Connect to the original AP +``` + Save your changes, and type `make ota` to build the example to generate the real OTA binary firmware. The name of final generated binary firmware is `ota.v2_to_v3.ota.bin` and the binary firmware locates at directory of `build`. diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/Kconfig.projbuild b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/Kconfig.projbuild index c5a0b69ff..5ac58b65d 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/Kconfig.projbuild +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/Kconfig.projbuild @@ -1,14 +1,22 @@ menu "Example Configuration" +config CONNECT_ORIGINAL_AP + bool "Connect to the original AP" + default n + help + Connect to the original AP of old SDK + config WIFI_SSID string "WiFi SSID" default "myssid" + depends on !CONNECT_ORIGINAL_AP help SSID (network name) for the example to connect to. config WIFI_PASSWORD string "WiFi Password" default "myssid" + depends on !CONNECT_ORIGINAL_AP help WiFi password (WPA or WPA2) for the example to use. diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/ota_example_main.c b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/ota_example_main.c index a8188b9c3..53bb569c8 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/ota_example_main.c +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/ota_example_main.c @@ -15,6 +15,9 @@ #include "freertos/task.h" #include "freertos/event_groups.h" +#ifdef CONFIG_CONNECT_ORIGINAL_AP +#include "internal/esp_system_internal.h" +#endif #include "esp_system.h" #include "esp_wifi.h" #include "esp_event_loop.h" @@ -105,18 +108,48 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) static void initialise_wifi(void) { - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); +#ifdef CONFIG_CONNECT_ORIGINAL_AP + int ret; + uint32_t addr; + struct old_sysconf *sysconf; + wifi_config_t wifi_config = { 0 }; + + if (!(addr = esp_get_old_sysconf_addr())) { + ESP_LOGE(TAG, "Current firmware does not update from old SDK firmware"); + return ; + } + + if (!(sysconf = malloc(sizeof(struct old_sysconf)))) { + ESP_LOGE(TAG, "No enough memory for old system config"); + return ; + } + + if ((ret = spi_flash_read(addr, sysconf, sizeof(struct old_sysconf))) != ESP_OK) { + free(sysconf); + ESP_LOGE(TAG, "read old system config from flash error %d", ret); + return ; + } + + memcpy(&wifi_config.sta.ssid, sysconf->ap_ssid[sysconf->ap_index].ssid, sysconf->ap_ssid[sysconf->ap_index].len); + memcpy(&wifi_config.sta.password, sysconf->ap_ssid[sysconf->ap_index].passwd, 32); + + free(sysconf); +#else wifi_config_t wifi_config = { .sta = { .ssid = EXAMPLE_WIFI_SSID, .password = EXAMPLE_WIFI_PASS, }, }; +#endif + + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); + ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); + ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); diff --git a/examples/wifi/simple_wifi/main/simple_wifi.c b/examples/wifi/simple_wifi/main/simple_wifi.c index 975d393e0..4286025c6 100644 --- a/examples/wifi/simple_wifi/main/simple_wifi.c +++ b/examples/wifi/simple_wifi/main/simple_wifi.c @@ -122,6 +122,14 @@ void wifi_init_sta() }, }; + /* Setting a password implies station will connect to all security modes including WEP/WPA. + * However these modes are deprecated and not advisable to be used. Incase your Access point + * doesn't support WPA2, these mode can be enabled by commenting below line */ + + if (strlen(EXAMPLE_ESP_WIFI_PASS)) { + wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + } + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); ESP_ERROR_CHECK(esp_wifi_start() ); diff --git a/tools/idf_monitor.py b/tools/idf_monitor.py index 86b53538c..772b2fc84 100755 --- a/tools/idf_monitor.py +++ b/tools/idf_monitor.py @@ -98,11 +98,6 @@ def esp_openlog(project_name): DEFAULT_TOOLCHAIN_PREFIX = "xtensa-esp32-elf-" -def is_ascii(b): - if b > '\x7f': - return False - return True - def get_time_stamp(): ct = time.time() local_time = time.localtime(ct) @@ -334,8 +329,6 @@ def handle_serial_input(self, data): # this may need to be made more efficient, as it pushes out a byte # at a time to the console for b in data: - if is_ascii(b) == False: - continue if self.enable_time == 'y' and self.next_line == True: self.console.write_bytes(get_time_stamp() + ": ") self.next_line = False