diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 889062099..fec764904 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -277,6 +277,10 @@ jobs: variant: 4M - platform: OpenESP32S2 variant: 4M + - platform: OpenESP32C5 + variant: 4M + - platform: OpenESP32C61 + variant: 4M steps: - name: Source checkout uses: actions/checkout@v4 @@ -285,7 +289,7 @@ jobs: with: repository: espressif/esp-idf path: sdk/esp-idf - ref: v5.3.3 + ref: v5.5-beta1 submodules: recursive - uses: actions/setup-python@v5 with: @@ -315,6 +319,58 @@ jobs: output/${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }}/${{ matrix.platform }}_${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }}.img output/${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }}/${{ matrix.platform }}_${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }}.factory.bin if-no-files-found: warn + + build_8266: + name: Build ESP8266 + needs: refs + runs-on: ubuntu-latest + defaults: + run: + shell: bash + container: + image: coatldev/six:latest + strategy: + fail-fast: false + matrix: + include: + - platform: OpenESP8266 + variant: default + steps: + - name: Source checkout + uses: actions/checkout@v4 + - name: SDK checkout + uses: actions/checkout@v4 + with: + repository: espressif/ESP8266_RTOS_SDK + path: sdk/ESP8266_RTOS_SDK + ref: release/v3.4 + submodules: recursive + fetch-tags: true + fetch-depth: '200' + - name: Install dependencies + run: | + apt-get update && apt-get -y install cmake + pip2 install virtualenv + patch -p1 -d sdk/ESP8266_RTOS_SDK < platforms/ESP8266/sdk.patch + python2 -m pip install --user -r sdk/ESP8266_RTOS_SDK/requirements.txt + python3 -m pip install esptool + - name: Run make + run: | + cd sdk/ESP8266_RTOS_SDK + ./install.sh > /dev/null + . ./export.sh + . ./add_path.sh + cd ../.. + make APP_VERSION=${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }} APP_NAME=${{ matrix.platform }} VARIANT="${{ matrix.variant }}" ${{ matrix.platform }} + - name: Save build assets + uses: actions/upload-artifact@v4 + with: + name: ${{ env.APP_NAME }}_${{ needs.refs.outputs.version }}_${{ matrix.platform }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }} + path: | + output/${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }}/${{ matrix.platform }}_${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }}.img + output/${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }}/${{ matrix.platform }}_2MB_${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }}.factory.bin + output/${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }}/${{ matrix.platform }}_1MB_${{ needs.refs.outputs.version }}${{ matrix.variant != 'default' && '_' || '' }}${{ matrix.variant != 'default' && matrix.variant || '' }}.factory.bin + if-no-files-found: warn build_beken: name: Build beken alt @@ -376,7 +432,7 @@ jobs: merge: name: Merge Artifacts runs-on: ubuntu-22.04 - needs: [refs, build, build2, build_idf, build_beken] + needs: [refs, build, build2, build_idf, build_beken, build_8266] #if: always() && needs.refs.outputs.new_release == 'true' && (github.ref == 'refs/heads/main' || github.ref_name == 'alpha') steps: - name: Merge Artifacts diff --git a/.gitmodules b/.gitmodules index 6060d544c..28296d853 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,7 +28,7 @@ [submodule "sdk/esp-idf"] path = sdk/esp-idf url = https://github.com/espressif/esp-idf.git - branch = release/v5.3 + branch = release/v5.5 [submodule "sdk/OpenTR6260"] path = sdk/OpenTR6260 url = https://github.com/NonPIayerCharacter/OpenTR6260.git @@ -56,14 +56,16 @@ [submodule "libraries/berry"] path = libraries/berry url = https://github.com/berry-lang/berry.git - branch = master - + branch = master [submodule "sdk/OpenXR872"] path = sdk/OpenXR872 url = https://github.com/openshwprojects/OpenXR872 branch = main - [submodule "sdk/OpenXR806"] path = sdk/OpenXR806 url = https://github.com/openshwprojects/OpenXR806 branch = master +[submodule "sdk/ESP8266_RTOS_SDK"] + path = sdk/ESP8266_RTOS_SDK + url = https://github.com/espressif/ESP8266_RTOS_SDK + branch = release/v3.4 diff --git a/Makefile b/Makefile index 644568c83..a952a277c 100644 --- a/Makefile +++ b/Makefile @@ -226,6 +226,17 @@ endif sh platforms/ESP-IDF/pre_build.sh; \ else echo "prebuild for ESP-IDF not found ... "; \ fi + +prebuild_ESP8266: berry + #git submodule update --init --recursive --depth=1 sdk/ESP8266_RTOS_SDK + -rm platforms/ESP8266/sdkconfig + -rm platforms/ESP8266/partitions.csv + cp platforms/ESP8266/partitions-2mb.csv platforms/ESP8266/partitions.csv + @if [ -e platforms/ESP8266/pre_build.sh ]; then \ + echo "prebuild found for ESP8266"; \ + sh platforms/ESP8266/pre_build.sh; \ + else echo "prebuild for ESP8266 not found ... "; \ + fi prebuild_OpenTR6260: berry git submodule update --init --recursive --depth=1 sdk/OpenTR6260 @@ -447,6 +458,22 @@ OpenESP32C2: prebuild_ESPIDF esptool.py -c esp32c2 merge_bin -o output/$(APP_VERSION)/OpenESP32C2_$(APP_VERSION).factory.bin --flash_mode dio --flash_size $(ESP_FSIZE) 0x0 ./platforms/ESP-IDF/build-c2/bootloader/bootloader.bin 0x8000 ./platforms/ESP-IDF/build-c2/partition_table/partition-table.bin 0x10000 ./platforms/ESP-IDF/build-c2/OpenBeken.bin cp ./platforms/ESP-IDF/build-c2/OpenBeken.bin output/$(APP_VERSION)/OpenESP32C2_$(APP_VERSION).img +.PHONY: OpenESP32C5 +OpenESP32C5: prebuild_ESPIDF + IDF_TARGET="esp32c5" APP_VERSION=$(APP_VERSION) OBK_VARIANT=$(OBK_VARIANT) cmake platforms/ESP-IDF -B platforms/ESP-IDF/build-c5 + IDF_TARGET="esp32c5" APP_VERSION=$(APP_VERSION) OBK_VARIANT=$(OBK_VARIANT) cmake --build ./platforms/ESP-IDF/build-c5 -j $(shell nproc) + mkdir -p output/$(APP_VERSION) + esptool.py -c esp32c5 merge_bin -o output/$(APP_VERSION)/OpenESP32C5_$(APP_VERSION).factory.bin --flash_mode dio --flash_size $(ESP_FSIZE) 0x0 ./platforms/ESP-IDF/build-c5/bootloader/bootloader.bin 0x8000 ./platforms/ESP-IDF/build-c5/partition_table/partition-table.bin 0x10000 ./platforms/ESP-IDF/build-c5/OpenBeken.bin + cp ./platforms/ESP-IDF/build-c5/OpenBeken.bin output/$(APP_VERSION)/OpenESP32C5_$(APP_VERSION).img + +.PHONY: OpenESP32C61 +OpenESP32C61: prebuild_ESPIDF + IDF_TARGET="esp32c61" APP_VERSION=$(APP_VERSION) OBK_VARIANT=$(OBK_VARIANT) cmake platforms/ESP-IDF -B platforms/ESP-IDF/build-c61 + IDF_TARGET="esp32c61" APP_VERSION=$(APP_VERSION) OBK_VARIANT=$(OBK_VARIANT) cmake --build ./platforms/ESP-IDF/build-c61 -j $(shell nproc) + mkdir -p output/$(APP_VERSION) + esptool.py -c esp32c61 merge_bin -o output/$(APP_VERSION)/OpenESP32C61_$(APP_VERSION).factory.bin --flash_mode dio --flash_size $(ESP_FSIZE) 0x0 ./platforms/ESP-IDF/build-c61/bootloader/bootloader.bin 0x8000 ./platforms/ESP-IDF/build-c61/partition_table/partition-table.bin 0x10000 ./platforms/ESP-IDF/build-c61/OpenBeken.bin + cp ./platforms/ESP-IDF/build-c61/OpenBeken.bin output/$(APP_VERSION)/OpenESP32C61_$(APP_VERSION).img + .PHONY: OpenESP32C6 OpenESP32C6: prebuild_ESPIDF IDF_TARGET="esp32c6" APP_VERSION=$(APP_VERSION) OBK_VARIANT=$(OBK_VARIANT) cmake platforms/ESP-IDF -B platforms/ESP-IDF/build-c6 @@ -470,6 +497,18 @@ OpenESP32S3: prebuild_ESPIDF mkdir -p output/$(APP_VERSION) esptool.py -c esp32s3 merge_bin -o output/$(APP_VERSION)/OpenESP32S3_$(APP_VERSION).factory.bin --flash_mode dio --flash_size $(ESP_FSIZE) 0x0 ./platforms/ESP-IDF/build-s3/bootloader/bootloader.bin 0x8000 ./platforms/ESP-IDF/build-s3/partition_table/partition-table.bin 0x10000 ./platforms/ESP-IDF/build-s3/OpenBeken.bin cp ./platforms/ESP-IDF/build-s3/OpenBeken.bin output/$(APP_VERSION)/OpenESP32S3_$(APP_VERSION).img + +.PHONY: OpenESP8266 +OpenESP8266: prebuild_ESP8266 + APP_VERSION=$(APP_VERSION) OBK_VARIANT=$(OBK_VARIANT) cmake platforms/ESP8266 -B platforms/ESP8266/build + APP_VERSION=$(APP_VERSION) OBK_VARIANT=$(OBK_VARIANT) cmake --build ./platforms/ESP8266/build -j $(shell nproc) + mkdir -p output/$(APP_VERSION) + python3 -m esptool -c esp8266 merge_bin -o output/$(APP_VERSION)/OpenESP8266_2MB_$(APP_VERSION).factory.bin --flash_mode dio --flash_size 2MB 0x0 ./platforms/ESP8266/build/bootloader/bootloader.bin 0x8000 ./platforms/ESP8266/build/partition_table/partition-table.bin 0x10000 ./platforms/ESP8266/build/OpenBeken.bin + cp ./platforms/ESP8266/build/OpenBeken.bin output/$(APP_VERSION)/OpenESP8266_$(APP_VERSION).img + -rm platforms/ESP-IDF/partitions.csv + cp platforms/ESP8266/partitions-1mb.csv platforms/ESP8266/partitions.csv + cd platforms/ESP8266/ && idf.py partition_table + python3 -m esptool -c esp8266 merge_bin -o output/$(APP_VERSION)/OpenESP8266_1MB_$(APP_VERSION).factory.bin --flash_mode dio --flash_size 1MB 0x0 ./platforms/ESP8266/build/bootloader/bootloader.bin 0x8000 ./platforms/ESP8266/build/partition_table/partition-table.bin 0x10000 ./platforms/ESP8266/build/OpenBeken.bin .PHONY: OpenTR6260 OpenTR6260: prebuild_OpenTR6260 @@ -580,36 +619,40 @@ OpenECR6600: prebuild_OpenECR6600 mkdir -p output/$(APP_VERSION) cp $(ECRDIR)/build/OpenBeken/ECR6600F_standalone_OpenBeken_allinone.bin output/$(APP_VERSION)/OpenECR6600_$(APP_VERSION).bin cp $(ECRDIR)/build/OpenBeken/ECR6600F_OpenBeken_Compress_ota_packeg.bin output/$(APP_VERSION)/OpenECR6600_$(APP_VERSION)_ota.img + +# Add custom Makefile if required +-include custom.mk # clean .o files and output directory .PHONY: clean clean: - $(MAKE) -C sdk/OpenBK7231T/platforms/bk7231t/bk7231t_os APP_BIN_NAME=$(APP_NAME) USER_SW_VER=$(APP_VERSION) clean - $(MAKE) -C sdk/OpenBK7231N/platforms/bk7231n/bk7231n_os APP_BIN_NAME=$(APP_NAME) USER_SW_VER=$(APP_VERSION) clean - $(MAKE) -C sdk/OpenXR809/src clean - $(MAKE) -C sdk/OpenXR809/project/oxr_sharedApp/gcc clean - $(MAKE) -C sdk/OpenXR806/src clean - $(MAKE) -C sdk/OpenXR806/project/demo/sharedApp/gcc clean - $(MAKE) -C sdk/OpenXR872/src clean - $(MAKE) -C sdk/OpenXR872/project/demo/hello_demo/gcc clean - $(MAKE) -C sdk/OpenW800 clean - $(MAKE) -C sdk/OpenW600 clean - $(MAKE) -C sdk/OpenTR6260/scripts tr6260s1_clean - $(MAKE) -C sdk/OpenRTL87X0C/project/OpenBeken/GCC-RELEASE clean - $(MAKE) -C sdk/OpenRTL8710A_B/project/obk_amebaz/GCC-RELEASE clean - $(MAKE) -C sdk/OpenRTL8710A_B/project/obk_ameba1/GCC-RELEASE clean - $(MAKE) -C sdk/beken_freertos_sdk clean - test -d ./sdk/OpenLN882H/build && cmake --build ./sdk/OpenLN882H/build --target clean - test -d ./platforms/ESP-IDF/build-32 && cmake --build ./platforms/ESP-IDF/build-32 --target clean - test -d ./platforms/ESP-IDF/build-c3 && cmake --build ./platforms/ESP-IDF/build-c3 --target clean - test -d ./platforms/ESP-IDF/build-c2 && cmake --build ./platforms/ESP-IDF/build-c2 --target clean - test -d ./platforms/ESP-IDF/build-c6 && cmake --build ./platforms/ESP-IDF/build-c6 --target clean - test -d ./platforms/ESP-IDF/build-s2 && cmake --build ./platforms/ESP-IDF/build-s2 --target clean - test -d ./platforms/ESP-IDF/build-s3 && cmake --build ./platforms/ESP-IDF/build-s3 --target clean - cd sdk/OpenECR6600 && make BOARD_DIR=$(ECRDIR)/Boards/ecr6600/standalone APP_NAME=OpenBeken TOPDIR=$(ECRDIR) GCC_PATH=$(ECRDIR)/tool/nds32le-elf-mculib-v3s/bin/ clean - -# Add custom Makefile if required --include custom.mk + -test -d ./sdk/OpenBK7231T && $(MAKE) -C sdk/OpenBK7231T/platforms/bk7231t/bk7231t_os APP_BIN_NAME=$(APP_NAME) USER_SW_VER=$(APP_VERSION) clean + -test -d ./sdk/OpenBK7231N && $(MAKE) -C sdk/OpenBK7231N/platforms/bk7231n/bk7231n_os APP_BIN_NAME=$(APP_NAME) USER_SW_VER=$(APP_VERSION) clean + -test -d ./sdk/OpenXR809 && $(MAKE) -C sdk/OpenXR809/src clean + -test -d ./sdk/OpenXR809 && $(MAKE) -C sdk/OpenXR809/project/oxr_sharedApp/gcc clean + -test -d ./sdk/OpenXR806 && $(MAKE) -C sdk/OpenXR806/src clean + -test -d ./sdk/OpenXR806 && $(MAKE) -C sdk/OpenXR806/project/demo/sharedApp/gcc clean + -test -d ./sdk/OpenXR872 && $(MAKE) -C sdk/OpenXR872/src clean + -test -d ./sdk/OpenXR872 && $(MAKE) -C sdk/OpenXR872/project/demo/hello_demo/gcc clean + -test -d ./sdk/OpenW800 && $(MAKE) -C sdk/OpenW800 clean + -test -d ./sdk/OpenW600 && $(MAKE) -C sdk/OpenW600 clean + -test -d ./sdk/OpenTR6260 && $(MAKE) -C sdk/OpenTR6260/scripts tr6260s1_clean + -test -d ./sdk/OpenRTL87X0C && $(MAKE) -C sdk/OpenRTL87X0C/project/OpenBeken/GCC-RELEASE clean + -test -d ./sdk/OpenRTL8710A_B && $(MAKE) -C sdk/OpenRTL8710A_B/project/obk_amebaz/GCC-RELEASE clean + -test -d ./sdk/OpenRTL8710A_B && $(MAKE) -C sdk/OpenRTL8710A_B/project/obk_ameba1/GCC-RELEASE clean + -test -d ./sdk/beken_freertos_sdk && $(MAKE) -C sdk/beken_freertos_sdk clean + -test -d ./sdk/OpenLN882H/build && cmake --build ./sdk/OpenLN882H/build --target clean + -test -d ./platforms/ESP-IDF/build-32 && cmake --build ./platforms/ESP-IDF/build-32 --target clean + -test -d ./platforms/ESP-IDF/build-c3 && cmake --build ./platforms/ESP-IDF/build-c3 --target clean + -test -d ./platforms/ESP-IDF/build-c2 && cmake --build ./platforms/ESP-IDF/build-c2 --target clean + -test -d ./platforms/ESP-IDF/build-c6 && cmake --build ./platforms/ESP-IDF/build-c6 --target clean + -test -d ./platforms/ESP-IDF/build-s2 && cmake --build ./platforms/ESP-IDF/build-s2 --target clean + -test -d ./platforms/ESP-IDF/build-s3 && cmake --build ./platforms/ESP-IDF/build-s3 --target clean + -test -d ./platforms/ESP-IDF/build-c5 && cmake --build ./platforms/ESP-IDF/build-c5 --target clean + -test -d ./platforms/ESP-IDF/build-c61 && cmake --build ./platforms/ESP-IDF/build-c61 --target clean + -test -d ./platforms/ESP8266/build && cmake --build ./platforms/ESP8266/build --target clean + -test -d ./sdk/OpenECR6600 && cd sdk/OpenECR6600 && make BOARD_DIR=$(ECRDIR)/Boards/ecr6600/standalone APP_NAME=OpenBeken TOPDIR=$(ECRDIR) GCC_PATH=$(ECRDIR)/tool/nds32le-elf-mculib-v3s/bin/ clean + -$(RM) -r $(BUILD_DIR) # Example upload command - import the following snippet into Node-RED and update the IPs in the variables below # This will stage the rbl binary on the Node-RED server and trigger a OTA request to for the BK chip to pull it automatically diff --git a/custom.mk b/custom.mk index 2d39ed49d..720c0187a 100644 --- a/custom.mk +++ b/custom.mk @@ -61,11 +61,6 @@ $(BUILD_DIR)/%.c.o: %.c @echo "Compiling: $< -> $@" $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ -.PHONY: clean - -clean: - $(RM) -r $(BUILD_DIR) - -include $(DEPS) diff --git a/libraries/mqtt_patched.c b/libraries/mqtt_patched.c new file mode 100644 index 000000000..bab876d49 --- /dev/null +++ b/libraries/mqtt_patched.c @@ -0,0 +1,1485 @@ +/** + * @file + * MQTT client + * + * @defgroup mqtt MQTT client + * @ingroup apps + * @verbinclude mqtt_client.txt + */ + +/* + * Copyright (c) 2016 Erik Andersson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack + * + * Author: Erik Andersson + * + * + * @todo: + * - Handle large outgoing payloads for PUBLISH messages + * - Fix restriction of a single topic in each (UN)SUBSCRIBE message (protocol has support for multiple topics) + * - Add support for legacy MQTT protocol version + * + * Please coordinate changes and requests with Erik Andersson + * Erik Andersson + * + */ + +#define MQTT_OUTPUT_RINGBUF_SIZE 2048 +#define MQTT_VAR_HEADER_BUFFER_LEN 256 +#define MQTT_REQ_MAX_IN_FLIGHT 16 + +#include "lwip/apps/mqtt.h" +#include "lwip/apps/mqtt_priv.h" +#include "lwip/timeouts.h" +#include "lwip/ip_addr.h" +#include "lwip/mem.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/altcp.h" +#include "lwip/altcp_tcp.h" +#include "lwip/altcp_tls.h" +#include + +#if LWIP_TCP && LWIP_CALLBACK_API + +/** + * MQTT_DEBUG: Default is off. + */ +#if !defined MQTT_DEBUG || defined __DOXYGEN__ +#define MQTT_DEBUG LWIP_DBG_OFF +#endif + +#define MQTT_DEBUG_TRACE (MQTT_DEBUG | LWIP_DBG_TRACE) +#define MQTT_DEBUG_STATE (MQTT_DEBUG | LWIP_DBG_STATE) +#define MQTT_DEBUG_WARN (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define MQTT_DEBUG_WARN_STATE (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) +#define MQTT_DEBUG_SERIOUS (MQTT_DEBUG | LWIP_DBG_LEVEL_SERIOUS) + + + +/** + * MQTT client connection states + */ +enum { + TCP_DISCONNECTED, + TCP_CONNECTING, + MQTT_CONNECTING, + MQTT_CONNECTED +}; + +/** + * MQTT control message types + */ +enum mqtt_message_type { + MQTT_MSG_TYPE_CONNECT = 1, + MQTT_MSG_TYPE_CONNACK = 2, + MQTT_MSG_TYPE_PUBLISH = 3, + MQTT_MSG_TYPE_PUBACK = 4, + MQTT_MSG_TYPE_PUBREC = 5, + MQTT_MSG_TYPE_PUBREL = 6, + MQTT_MSG_TYPE_PUBCOMP = 7, + MQTT_MSG_TYPE_SUBSCRIBE = 8, + MQTT_MSG_TYPE_SUBACK = 9, + MQTT_MSG_TYPE_UNSUBSCRIBE = 10, + MQTT_MSG_TYPE_UNSUBACK = 11, + MQTT_MSG_TYPE_PINGREQ = 12, + MQTT_MSG_TYPE_PINGRESP = 13, + MQTT_MSG_TYPE_DISCONNECT = 14 +}; + +/** Helpers to extract control packet type and qos from first byte in fixed header */ +#define MQTT_CTL_PACKET_TYPE(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0xf0) >> 4) +#define MQTT_CTL_PACKET_QOS(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0x6) >> 1) + +/** + * MQTT connect flags, only used in CONNECT message + */ +enum mqtt_connect_flag { + MQTT_CONNECT_FLAG_USERNAME = 1 << 7, + MQTT_CONNECT_FLAG_PASSWORD = 1 << 6, + MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5, + MQTT_CONNECT_FLAG_WILL = 1 << 2, + MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1 +}; + + +static void mqtt_cyclic_timer(void *arg); + +#if defined(LWIP_DEBUG) +static const char *const mqtt_message_type_str[15] = { + "UNDEFINED", + "CONNECT", + "CONNACK", + "PUBLISH", + "PUBACK", + "PUBREC", + "PUBREL", + "PUBCOMP", + "SUBSCRIBE", + "SUBACK", + "UNSUBSCRIBE", + "UNSUBACK", + "PINGREQ", + "PINGRESP", + "DISCONNECT" +}; + +/** + * Message type value to string + * @param msg_type see enum mqtt_message_type + * + * @return Control message type text string + */ +static const char * +mqtt_msg_type_to_str(u8_t msg_type) +{ + if (msg_type >= LWIP_ARRAYSIZE(mqtt_message_type_str)) { + msg_type = 0; + } + return mqtt_message_type_str[msg_type]; +} + +#endif + + +/** + * Generate MQTT packet identifier + * @param client MQTT client + * @return New packet identifier, range 1 to 65535 + */ +static u16_t +msg_generate_packet_id(mqtt_client_t *client) +{ + client->pkt_id_seq++; + if (client->pkt_id_seq == 0) { + client->pkt_id_seq++; + } + return client->pkt_id_seq; +} + +/*--------------------------------------------------------------------------------------------------------------------- */ +/* Output ring buffer */ + +/** Add single item to ring buffer */ +static void +mqtt_ringbuf_put(struct mqtt_ringbuf_t *rb, u8_t item) +{ + rb->buf[rb->put] = item; + rb->put++; + if (rb->put >= MQTT_OUTPUT_RINGBUF_SIZE) { + rb->put = 0; + } +} + +/** Return pointer to ring buffer get position */ +static u8_t * +mqtt_ringbuf_get_ptr(struct mqtt_ringbuf_t *rb) +{ + return &rb->buf[rb->get]; +} + +static void +mqtt_ringbuf_advance_get_idx(struct mqtt_ringbuf_t *rb, u16_t len) +{ + LWIP_ASSERT("mqtt_ringbuf_advance_get_idx: len < MQTT_OUTPUT_RINGBUF_SIZE", len < MQTT_OUTPUT_RINGBUF_SIZE); + + rb->get += len; + if (rb->get >= MQTT_OUTPUT_RINGBUF_SIZE) { + rb->get = rb->get - MQTT_OUTPUT_RINGBUF_SIZE; + } +} + +/** Return number of bytes in ring buffer */ +static u16_t +mqtt_ringbuf_len(struct mqtt_ringbuf_t *rb) +{ + u32_t len = rb->put - rb->get; + if (len > 0xFFFF) { + len += MQTT_OUTPUT_RINGBUF_SIZE; + } + return (u16_t)len; +} + +/** Return number of bytes free in ring buffer */ +#define mqtt_ringbuf_free(rb) (MQTT_OUTPUT_RINGBUF_SIZE - mqtt_ringbuf_len(rb)) + +/** Return number of bytes possible to read without wrapping around */ +#define mqtt_ringbuf_linear_read_length(rb) LWIP_MIN(mqtt_ringbuf_len(rb), (MQTT_OUTPUT_RINGBUF_SIZE - (rb)->get)) + +/** + * Try send as many bytes as possible from output ring buffer + * @param rb Output ring buffer + * @param tpcb TCP connection handle + */ +static void +mqtt_output_send(struct mqtt_ringbuf_t *rb, struct altcp_pcb *tpcb) +{ + err_t err; + u8_t wrap = 0; + u16_t ringbuf_lin_len = mqtt_ringbuf_linear_read_length(rb); + u16_t send_len = altcp_sndbuf(tpcb); + LWIP_ASSERT("mqtt_output_send: tpcb != NULL", tpcb != NULL); + + if (send_len == 0 || ringbuf_lin_len == 0) { + return; + } + + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_output_send: tcp_sndbuf: %d bytes, ringbuf_linear_available: %d, get %d, put %d\n", + send_len, ringbuf_lin_len, rb->get, rb->put)); + + if (send_len > ringbuf_lin_len) { + /* Space in TCP output buffer is larger than available in ring buffer linear portion */ + send_len = ringbuf_lin_len; + /* Wrap around if more data in ring buffer after linear portion */ + wrap = (mqtt_ringbuf_len(rb) > ringbuf_lin_len); + } + err = altcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY | (wrap ? TCP_WRITE_FLAG_MORE : 0)); + if ((err == ERR_OK) && wrap) { + mqtt_ringbuf_advance_get_idx(rb, send_len); + /* Use the lesser one of ring buffer linear length and TCP send buffer size */ + send_len = LWIP_MIN(altcp_sndbuf(tpcb), mqtt_ringbuf_linear_read_length(rb)); + err = altcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY); + } + + if (err == ERR_OK) { + mqtt_ringbuf_advance_get_idx(rb, send_len); + /* Flush */ + altcp_output(tpcb); + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_output_send: Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); + } +} + + + +/*--------------------------------------------------------------------------------------------------------------------- */ +/* Request queue */ + +/** + * Create request item + * @param r_objs Pointer to request objects + * @param r_objs_len Number of array entries + * @param pkt_id Packet identifier of request + * @param cb Packet callback to call when requests lifetime ends + * @param arg Parameter following callback + * @return Request or NULL if failed to create + */ +static struct mqtt_request_t * +mqtt_create_request(struct mqtt_request_t *r_objs, size_t r_objs_len, u16_t pkt_id, mqtt_request_cb_t cb, void *arg) +{ + struct mqtt_request_t *r = NULL; + u8_t n; + LWIP_ASSERT("mqtt_create_request: r_objs != NULL", r_objs != NULL); + for (n = 0; n < r_objs_len; n++) { + /* Item point to itself if not in use */ + if (r_objs[n].next == &r_objs[n]) { + r = &r_objs[n]; + r->next = NULL; + r->cb = cb; + r->arg = arg; + r->pkt_id = pkt_id; + break; + } + } + return r; +} + + +/** + * Append request to pending request queue + * @param tail Pointer to request queue tail pointer + * @param r Request to append + */ +static void +mqtt_append_request(struct mqtt_request_t **tail, struct mqtt_request_t *r) +{ + struct mqtt_request_t *head = NULL; + s16_t time_before = 0; + struct mqtt_request_t *iter; + + LWIP_ASSERT("mqtt_append_request: tail != NULL", tail != NULL); + + /* Iterate trough queue to find head, and count total timeout time */ + for (iter = *tail; iter != NULL; iter = iter->next) { + time_before += iter->timeout_diff; + head = iter; + } + + LWIP_ASSERT("mqtt_append_request: time_before <= MQTT_REQ_TIMEOUT", time_before <= MQTT_REQ_TIMEOUT); + r->timeout_diff = MQTT_REQ_TIMEOUT - time_before; + if (head == NULL) { + *tail = r; + } else { + head->next = r; + } +} + + +/** + * Delete request item + * @param r Request item to delete + */ +static void +mqtt_delete_request(struct mqtt_request_t *r) +{ + if (r != NULL) { + r->next = r; + } +} + +/** + * Remove a request item with a specific packet identifier from request queue + * @param tail Pointer to request queue tail pointer + * @param pkt_id Packet identifier of request to take + * @return Request item if found, NULL if not + */ +static struct mqtt_request_t * +mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id) +{ + struct mqtt_request_t *iter = NULL, *prev = NULL; + LWIP_ASSERT("mqtt_take_request: tail != NULL", tail != NULL); + /* Search all request for pkt_id */ + for (iter = *tail; iter != NULL; iter = iter->next) { + if (iter->pkt_id == pkt_id) { + break; + } + prev = iter; + } + + /* If request was found */ + if (iter != NULL) { + /* unchain */ + if (prev == NULL) { + *tail = iter->next; + } else { + prev->next = iter->next; + } + /* If exists, add remaining timeout time for the request to next */ + if (iter->next != NULL) { + iter->next->timeout_diff += iter->timeout_diff; + } + iter->next = NULL; + } + return iter; +} + +/** + * Handle requests timeout + * @param tail Pointer to request queue tail pointer + * @param t Time since last call in seconds + */ +static void +mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t) +{ + struct mqtt_request_t *r; + LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL); + r = *tail; + while (t > 0 && r != NULL) { + if (t >= r->timeout_diff) { + t -= (u8_t)r->timeout_diff; + /* Unchain */ + *tail = r->next; + /* Notify upper layer about timeout */ + if (r->cb != NULL) { + r->cb(r->arg, ERR_TIMEOUT); + } + mqtt_delete_request(r); + /* Tail might be be modified in callback, so re-read it in every iteration */ + r = *(struct mqtt_request_t *const volatile *)tail; + } else { + r->timeout_diff -= t; + t = 0; + } + } +} + +/** + * Free all request items + * @param tail Pointer to request queue tail pointer + */ +static void +mqtt_clear_requests(struct mqtt_request_t **tail) +{ + struct mqtt_request_t *iter, *next; + LWIP_ASSERT("mqtt_clear_requests: tail != NULL", tail != NULL); + for (iter = *tail; iter != NULL; iter = next) { + next = iter->next; + mqtt_delete_request(iter); + } + *tail = NULL; +} +/** + * Initialize all request items + * @param r_objs Pointer to request objects + * @param r_objs_len Number of array entries + */ +static void +mqtt_init_requests(struct mqtt_request_t *r_objs, size_t r_objs_len) +{ + u8_t n; + LWIP_ASSERT("mqtt_init_requests: r_objs != NULL", r_objs != NULL); + for (n = 0; n < r_objs_len; n++) { + /* Item pointing to itself indicates unused */ + r_objs[n].next = &r_objs[n]; + } +} + +/*--------------------------------------------------------------------------------------------------------------------- */ +/* Output message build helpers */ + + +static void +mqtt_output_append_u8(struct mqtt_ringbuf_t *rb, u8_t value) +{ + mqtt_ringbuf_put(rb, value); +} + +static +void mqtt_output_append_u16(struct mqtt_ringbuf_t *rb, u16_t value) +{ + mqtt_ringbuf_put(rb, value >> 8); + mqtt_ringbuf_put(rb, value & 0xff); +} + +static void +mqtt_output_append_buf(struct mqtt_ringbuf_t *rb, const void *data, u16_t length) +{ + u16_t n; + for (n = 0; n < length; n++) { + mqtt_ringbuf_put(rb, ((const u8_t *)data)[n]); + } +} + +static void +mqtt_output_append_string(struct mqtt_ringbuf_t *rb, const char *str, u16_t length) +{ + u16_t n; + mqtt_ringbuf_put(rb, length >> 8); + mqtt_ringbuf_put(rb, length & 0xff); + for (n = 0; n < length; n++) { + mqtt_ringbuf_put(rb, str[n]); + } +} + +/** + * Append fixed header + * @param rb Output ring buffer + * @param msg_type see enum mqtt_message_type + * @param fdup MQTT DUP flag + * @param fqos MQTT QoS field + * @param fretain MQTT retain flag + * @param r_length Remaining length after fixed header + */ + +static void +mqtt_output_append_fixed_header(struct mqtt_ringbuf_t *rb, u8_t msg_type, u8_t fdup, + u8_t fqos, u8_t fretain, u16_t r_length) +{ + /* Start with control byte */ + mqtt_output_append_u8(rb, (((msg_type & 0x0f) << 4) | ((fdup & 1) << 3) | ((fqos & 3) << 1) | (fretain & 1))); + /* Encode remaining length field */ + do { + mqtt_output_append_u8(rb, (r_length & 0x7f) | (r_length >= 128 ? 0x80 : 0)); + r_length >>= 7; + } while (r_length > 0); +} + + +/** + * Check output buffer space + * @param rb Output ring buffer + * @param r_length Remaining length after fixed header + * @return 1 if message will fit, 0 if not enough buffer space + */ +static u8_t +mqtt_output_check_space(struct mqtt_ringbuf_t *rb, u16_t r_length) +{ + /* Start with length of type byte + remaining length */ + u16_t total_len = 1 + r_length; + + LWIP_ASSERT("mqtt_output_check_space: rb != NULL", rb != NULL); + + /* Calculate number of required bytes to contain the remaining bytes field and add to total*/ + do { + total_len++; + r_length >>= 7; + } while (r_length > 0); + + return (total_len <= mqtt_ringbuf_free(rb)); +} + + +/** + * Close connection to server + * @param client MQTT client + * @param reason Reason for disconnection + */ +static void +mqtt_close(mqtt_client_t *client, mqtt_connection_status_t reason) +{ + LWIP_ASSERT("mqtt_close: client != NULL", client != NULL); + + /* Bring down TCP connection if not already done */ + if (client->conn != NULL) { + err_t res; + altcp_recv(client->conn, NULL); + altcp_err(client->conn, NULL); + altcp_sent(client->conn, NULL); + res = altcp_close(client->conn); + if (res != ERR_OK) { + altcp_abort(client->conn); + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_close: Close err=%s\n", lwip_strerr(res))); + } + client->conn = NULL; + } + + /* Remove all pending requests */ + mqtt_clear_requests(&client->pend_req_queue); + /* Stop cyclic timer */ + sys_untimeout(mqtt_cyclic_timer, client); + + /* Notify upper layer of disconnection if changed state */ + if (client->conn_state != TCP_DISCONNECTED) { + + client->conn_state = TCP_DISCONNECTED; + if (client->connect_cb != NULL) { + client->connect_cb(client, client->connect_arg, reason); + } + } +} + + +/** + * Interval timer, called every MQTT_CYCLIC_TIMER_INTERVAL seconds in MQTT_CONNECTING and MQTT_CONNECTED states + * @param arg MQTT client + */ +static void +mqtt_cyclic_timer(void *arg) +{ + u8_t restart_timer = 1; + mqtt_client_t *client = (mqtt_client_t *)arg; + LWIP_ASSERT("mqtt_cyclic_timer: client != NULL", client != NULL); + + if (client->conn_state == MQTT_CONNECTING) { + client->cyclic_tick++; + if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= MQTT_CONNECT_TIMOUT) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_cyclic_timer: CONNECT attempt to server timed out\n")); + /* Disconnect TCP */ + mqtt_close(client, MQTT_CONNECT_TIMEOUT); + restart_timer = 0; + } + } else if (client->conn_state == MQTT_CONNECTED) { + /* Handle timeout for pending requests */ + mqtt_request_time_elapsed(&client->pend_req_queue, MQTT_CYCLIC_TIMER_INTERVAL); + + /* keep_alive > 0 means keep alive functionality shall be used */ + if (client->keep_alive > 0) { + + client->server_watchdog++; + /* If reception from server has been idle for 1.5*keep_alive time, server is considered unresponsive */ + if ((client->server_watchdog * MQTT_CYCLIC_TIMER_INTERVAL) > (client->keep_alive + client->keep_alive / 2)) { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_cyclic_timer: Server incoming keep-alive timeout\n")); + mqtt_close(client, MQTT_CONNECT_TIMEOUT); + restart_timer = 0; + } + + /* If time for a keep alive message to be sent, transmission has been idle for keep_alive time */ + client->cyclic_tick++; + if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= client->keep_alive) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_cyclic_timer: Sending keep-alive message to server\n")); + if (mqtt_output_check_space(&client->output, 0) != 0) { + mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0, 0); + client->cyclic_tick = 0; + } + } + } + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_cyclic_timer: Timer should not be running in state %d\n", client->conn_state)); + restart_timer = 0; + } + if (restart_timer) { + sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL * 1000, mqtt_cyclic_timer, arg); + } +} + + +/** + * Send PUBACK, PUBREC or PUBREL response message + * @param client MQTT client + * @param msg PUBACK, PUBREC or PUBREL + * @param pkt_id Packet identifier + * @param qos QoS value + * @return ERR_OK if successful, ERR_MEM if out of memory + */ +static err_t +pub_ack_rec_rel_response(mqtt_client_t *client, u8_t msg, u16_t pkt_id, u8_t qos) +{ + err_t err = ERR_OK; + if (mqtt_output_check_space(&client->output, 2)) { + mqtt_output_append_fixed_header(&client->output, msg, 0, qos, 0, 2); + mqtt_output_append_u16(&client->output, pkt_id); + mqtt_output_send(&client->output, client->conn); + } else { + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("pub_ack_rec_rel_response: OOM creating response: %s with pkt_id: %d\n", + mqtt_msg_type_to_str(msg), pkt_id)); + err = ERR_MEM; + } + return err; +} + +/** + * Subscribe response from server + * @param r Matching request + * @param result Result code from server + */ +static void +mqtt_incoming_suback(struct mqtt_request_t *r, u8_t result) +{ + if (r->cb != NULL) { + r->cb(r->arg, result < 3 ? ERR_OK : ERR_ABRT); + } +} + + +/** + * Complete MQTT message received or buffer full + * @param client MQTT client + * @param fixed_hdr_len length of fixed header + * @param length length received part + * @param remaining_length Remaining length of complete message + */ +static mqtt_connection_status_t +mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_len, u16_t length, u32_t remaining_length, + u8_t *var_hdr_payload) +{ + mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED; + + /* Control packet type */ + u8_t pkt_type = MQTT_CTL_PACKET_TYPE(client->rx_buffer[0]); + u16_t pkt_id = 0; + + LWIP_ASSERT("fixed_hdr_len <= client->msg_idx", fixed_hdr_len <= client->msg_idx); + LWIP_ERROR("buffer length mismatch", fixed_hdr_len + length <= MQTT_VAR_HEADER_BUFFER_LEN, + return MQTT_CONNECT_DISCONNECTED); + + if (pkt_type == MQTT_MSG_TYPE_CONNACK) { + if (client->conn_state == MQTT_CONNECTING) { + if (length < 2) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short CONNACK message\n")); + goto out_disconnect; + } + /* Get result code from CONNACK */ + res = (mqtt_connection_status_t)var_hdr_payload[1]; + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_message_received: Connect response code %d\n", res)); + if (res == MQTT_CONNECT_ACCEPTED) { + /* Reset cyclic_tick when changing to connected state */ + client->cyclic_tick = 0; + client->conn_state = MQTT_CONNECTED; + /* Notify upper layer */ + if (client->connect_cb != NULL) { + client->connect_cb(client, client->connect_arg, res); + } + } + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_message_received: Received CONNACK in connected state\n")); + } + } else if (pkt_type == MQTT_MSG_TYPE_PINGRESP) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ( "mqtt_message_received: Received PINGRESP from server\n")); + + } else if (pkt_type == MQTT_MSG_TYPE_PUBLISH) { + u16_t payload_offset = 0; + u16_t payload_length = length; + u8_t qos = MQTT_CTL_PACKET_QOS(client->rx_buffer[0]); + + if (client->msg_idx == (u32_t)(fixed_hdr_len + length)) { + /* First publish message frame. Should have topic and pkt id*/ + size_t var_hdr_payload_bufsize = sizeof(client->rx_buffer) - fixed_hdr_len; + u8_t *topic; + u16_t after_topic; + u8_t bkp; + u16_t topic_len; + u16_t qos_len = (qos ? 2U : 0U); + if (length < 2 + qos_len) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short PUBLISH packet\n")); + goto out_disconnect; + } + topic_len = var_hdr_payload[0]; + topic_len = (topic_len << 8) + (u16_t)(var_hdr_payload[1]); + if ((topic_len > length - (2 + qos_len)) || + (topic_len > var_hdr_payload_bufsize - (2 + qos_len))) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short PUBLISH packet (topic)\n")); + goto out_disconnect; + } + + topic = var_hdr_payload + 2; + after_topic = 2 + topic_len; + /* Check buffer length, add one byte even for QoS 0 so that zero termination will fit */ + if ((after_topic + (qos ? 2U : 1U)) > var_hdr_payload_bufsize) { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_message_received: Receive buffer can not fit topic + pkt_id\n")); + goto out_disconnect; + } + + /* id for QoS 1 and 2 */ + if (qos > 0) { + if (length < after_topic + 2U) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short PUBLISH packet (after_topic)\n")); + goto out_disconnect; + } + client->inpub_pkt_id = ((u16_t)var_hdr_payload[after_topic] << 8) + (u16_t)var_hdr_payload[after_topic + 1]; + after_topic += 2; + } else { + client->inpub_pkt_id = 0; + } + /* Take backup of byte after topic */ + bkp = topic[topic_len]; + /* Zero terminate string */ + topic[topic_len] = 0; + /* Payload data remaining in receive buffer */ + payload_length = length - after_topic; + payload_offset = after_topic; + + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_incoming_publish: Received message with QoS %d at topic: %s, payload length %"U32_F"\n", + qos, topic, remaining_length + payload_length)); + if (client->pub_cb != NULL) { + client->pub_cb(client->inpub_arg, (const char *)topic, remaining_length + payload_length); + } + /* Restore byte after topic */ + topic[topic_len] = bkp; + } + if (payload_length > 0 || remaining_length == 0) { + if (length < (size_t)(payload_offset + payload_length)) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short packet (payload)\n")); + goto out_disconnect; + } + if (client->data_cb != NULL) { + client->data_cb(client->inpub_arg, var_hdr_payload + payload_offset, payload_length, remaining_length == 0 ? MQTT_DATA_FLAG_LAST : 0); + } + /* Reply if QoS > 0 */ + if (remaining_length == 0 && qos > 0) { + /* Send PUBACK for QoS 1 or PUBREC for QoS 2 */ + u8_t resp_msg = (qos == 1) ? MQTT_MSG_TYPE_PUBACK : MQTT_MSG_TYPE_PUBREC; + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_incoming_publish: Sending publish response: %s with pkt_id: %d\n", + mqtt_msg_type_to_str(resp_msg), client->inpub_pkt_id)); + pub_ack_rec_rel_response(client, resp_msg, client->inpub_pkt_id, 0); + } + } + } else { + if (length < 2) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short message\n")); + goto out_disconnect; + } + /* Get packet identifier */ + pkt_id = (u16_t)var_hdr_payload[0] << 8; + pkt_id |= (u16_t)var_hdr_payload[1]; + if (pkt_id == 0) { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_message_received: Got message with illegal packet identifier: 0\n")); + goto out_disconnect; + } + if (pkt_type == MQTT_MSG_TYPE_PUBREC) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_message_received: PUBREC, sending PUBREL with pkt_id: %d\n", pkt_id)); + pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBREL, pkt_id, 1); + + } else if (pkt_type == MQTT_MSG_TYPE_PUBREL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_message_received: PUBREL, sending PUBCOMP response with pkt_id: %d\n", pkt_id)); + pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBCOMP, pkt_id, 0); + + } else if (pkt_type == MQTT_MSG_TYPE_SUBACK || pkt_type == MQTT_MSG_TYPE_UNSUBACK || + pkt_type == MQTT_MSG_TYPE_PUBCOMP || pkt_type == MQTT_MSG_TYPE_PUBACK) { + struct mqtt_request_t *r = mqtt_take_request(&client->pend_req_queue, pkt_id); + if (r != NULL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_message_received: %s response with id %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); + if (pkt_type == MQTT_MSG_TYPE_SUBACK) { + if (length < 3) { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_message_received: To small SUBACK packet\n")); + goto out_disconnect; + } else { + mqtt_incoming_suback(r, var_hdr_payload[2]); + } + } else if (r->cb != NULL) { + r->cb(r->arg, ERR_OK); + } + mqtt_delete_request(r); + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ( "mqtt_message_received: Received %s reply, with wrong pkt_id: %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); + } + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ( "mqtt_message_received: Received unknown message type: %d\n", pkt_type)); + goto out_disconnect; + } + } + return res; +out_disconnect: + return MQTT_CONNECT_DISCONNECTED; +} + + +/** + * MQTT incoming message parser + * @param client MQTT client + * @param p PBUF chain of received data + * @return Connection status + */ +static mqtt_connection_status_t +mqtt_parse_incoming(mqtt_client_t *client, struct pbuf *p) +{ + u16_t in_offset = 0; + u32_t msg_rem_len = 0; + u8_t fixed_hdr_len = 0; + u8_t b = 0; + + while (p->tot_len > in_offset) { + /* We ALWAYS parse the header here first. Even if the header was not + included in this segment, we re-parse it here by buffering it in + client->rx_buffer. client->msg_idx keeps track of this. */ + if ((fixed_hdr_len < 2) || ((b & 0x80) != 0)) { + + if (fixed_hdr_len < client->msg_idx) { + /* parse header from old pbuf (buffered in client->rx_buffer) */ + b = client->rx_buffer[fixed_hdr_len]; + } else { + /* parse header from this pbuf and save it in client->rx_buffer in case + it comes in segmented */ + b = pbuf_get_at(p, in_offset++); + client->rx_buffer[client->msg_idx++] = b; + } + fixed_hdr_len++; + + if (fixed_hdr_len >= 2) { + /* fixed header contains at least 2 bytes but can contain more, depending on + 'remaining length'. All bytes but the last of this have 0x80 set to + indicate more bytes are coming. */ + msg_rem_len |= (u32_t)(b & 0x7f) << ((fixed_hdr_len - 2) * 7); + if ((b & 0x80) == 0) { + /* fixed header is done */ + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_parse_incoming: Remaining length after fixed header: %"U32_F"\n", msg_rem_len)); + if (msg_rem_len == 0) { + /* Complete message with no extra headers of payload received */ + mqtt_message_received(client, fixed_hdr_len, 0, 0, NULL); + client->msg_idx = 0; + fixed_hdr_len = 0; + } else { + /* Bytes remaining in message (changes remaining length if this is + not the first segment of this message) */ + msg_rem_len = (msg_rem_len + fixed_hdr_len) - client->msg_idx; + } + } + } + } else { + /* Fixed header has been parsed, parse variable header */ + u16_t cpy_len, buffer_space; + u8_t *var_hdr_payload; + mqtt_connection_status_t res; + + /* Allow to copy the lesser one of available length in input data or bytes remaining in message */ + cpy_len = (u16_t)LWIP_MIN((u16_t)(p->tot_len - in_offset), msg_rem_len); + + /* Limit to available space in buffer */ + buffer_space = MQTT_VAR_HEADER_BUFFER_LEN - fixed_hdr_len; + if (cpy_len > buffer_space) { + cpy_len = buffer_space; + } + /* Adjust cpy_len to ensure zero-copy operation for remaining parts of current message */ + if (client->msg_idx >= MQTT_VAR_HEADER_BUFFER_LEN) { + if (cpy_len > (p->len - in_offset)) + cpy_len = p->len - in_offset; + } + var_hdr_payload = (u8_t*)pbuf_get_contiguous(p, client->rx_buffer + fixed_hdr_len, + buffer_space, cpy_len, in_offset); + + /* Advance get and put indexes */ + client->msg_idx += cpy_len; + in_offset += cpy_len; + msg_rem_len -= cpy_len; + + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_parse_incoming: msg_idx: %"U32_F", cpy_len: %"U16_F", remaining %"U32_F"\n", client->msg_idx, cpy_len, msg_rem_len)); + /* Whole or partial message received */ + res = mqtt_message_received(client, fixed_hdr_len, cpy_len, msg_rem_len, var_hdr_payload); + if (res != MQTT_CONNECT_ACCEPTED) { + return res; + } + if (msg_rem_len == 0) { + /* Reset parser state */ + client->msg_idx = 0; + /* msg_tot_len = 0; */ + fixed_hdr_len = 0; + } + } + } + return MQTT_CONNECT_ACCEPTED; +} + + +/** + * TCP received callback function. @see tcp_recv_fn + * @param arg MQTT client + * @param p PBUF chain of received data + * @param err Passed as return value if not ERR_OK + * @return ERR_OK or err passed into callback + */ +static err_t +mqtt_tcp_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + LWIP_ASSERT("mqtt_tcp_recv_cb: client != NULL", client != NULL); + LWIP_ASSERT("mqtt_tcp_recv_cb: client->conn == pcb", client->conn == pcb); + + if (p == NULL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_tcp_recv_cb: Recv pbuf=NULL, remote has closed connection\n")); + mqtt_close(client, MQTT_CONNECT_DISCONNECTED); + } else { + mqtt_connection_status_t res; + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_tcp_recv_cb: Recv err=%d\n", err)); + pbuf_free(p); + return err; + } + + /* Tell remote that data has been received */ + altcp_recved(pcb, p->tot_len); + res = mqtt_parse_incoming(client, p); + pbuf_free(p); + + if (res != MQTT_CONNECT_ACCEPTED) { + mqtt_close(client, res); + } + /* If keep alive functionality is used */ + if (client->keep_alive != 0) { + /* Reset server alive watchdog */ + client->server_watchdog = 0; + } + + } + return ERR_OK; +} + + +/** + * TCP data sent callback function. @see tcp_sent_fn + * @param arg MQTT client + * @param tpcb TCP connection handle + * @param len Number of bytes sent + * @return ERR_OK + */ +static err_t +mqtt_tcp_sent_cb(void *arg, struct altcp_pcb *tpcb, u16_t len) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + + LWIP_UNUSED_ARG(tpcb); + LWIP_UNUSED_ARG(len); + + if (client->conn_state == MQTT_CONNECTED) { + struct mqtt_request_t *r; + + /* Reset keep-alive send timer and server watchdog */ + client->cyclic_tick = 0; + client->server_watchdog = 0; + /* QoS 0 publish has no response from server, so call its callbacks here */ + while ((r = mqtt_take_request(&client->pend_req_queue, 0)) != NULL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_tcp_sent_cb: Calling QoS 0 publish complete callback\n")); + if (r->cb != NULL) { + r->cb(r->arg, ERR_OK); + } + mqtt_delete_request(r); + } + /* Try send any remaining buffers from output queue */ + mqtt_output_send(&client->output, client->conn); + } + return ERR_OK; +} + +/** + * TCP error callback function. @see tcp_err_fn + * @param arg MQTT client + * @param err Error encountered + */ +static void +mqtt_tcp_err_cb(void *arg, err_t err) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + LWIP_UNUSED_ARG(err); /* only used for debug output */ + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_tcp_err_cb: TCP error callback: error %d, arg: %p\n", err, arg)); + LWIP_ASSERT("mqtt_tcp_err_cb: client != NULL", client != NULL); + /* Set conn to null before calling close as pcb is already deallocated*/ + client->conn = NULL; + mqtt_close(client, MQTT_CONNECT_DISCONNECTED); +} + +/** + * TCP poll callback function. @see tcp_poll_fn + * @param arg MQTT client + * @param tpcb TCP connection handle + * @return err ERR_OK + */ +static err_t +mqtt_tcp_poll_cb(void *arg, struct altcp_pcb *tpcb) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + if (client->conn_state == MQTT_CONNECTED) { + /* Try send any remaining buffers from output queue */ + mqtt_output_send(&client->output, tpcb); + } + return ERR_OK; +} + +/** + * TCP connect callback function. @see tcp_connected_fn + * @param arg MQTT client + * @param err Always ERR_OK, mqtt_tcp_err_cb is called in case of error + * @return ERR_OK + */ +static err_t +mqtt_tcp_connect_cb(void *arg, struct altcp_pcb *tpcb, err_t err) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_tcp_connect_cb: TCP connect error %d\n", err)); + return err; + } + + /* Initiate receiver state */ + client->msg_idx = 0; + + /* Setup TCP callbacks */ + altcp_recv(tpcb, mqtt_tcp_recv_cb); + altcp_sent(tpcb, mqtt_tcp_sent_cb); + altcp_poll(tpcb, mqtt_tcp_poll_cb, 2); + + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_tcp_connect_cb: TCP connection established to server\n")); + /* Enter MQTT connect state */ + client->conn_state = MQTT_CONNECTING; + + /* Start cyclic timer */ + sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL * 1000, mqtt_cyclic_timer, client); + client->cyclic_tick = 0; + + /* Start transmission from output queue, connect message is the first one out*/ + mqtt_output_send(&client->output, client->conn); + + return ERR_OK; +} + + + +/*---------------------------------------------------------------------------------------------------- */ +/* Public API */ + + +/** + * @ingroup mqtt + * MQTT publish function. + * @param client MQTT client + * @param topic Publish topic string + * @param payload Data to publish (NULL is allowed) + * @param payload_length Length of payload (0 is allowed) + * @param qos Quality of service, 0 1 or 2 + * @param retain MQTT retain flag + * @param cb Callback to call when publish is complete or has timed out + * @param arg User supplied argument to publish callback + * @return ERR_OK if successful + * ERR_CONN if client is disconnected + * ERR_MEM if short on memory + */ +err_t +mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, + mqtt_request_cb_t cb, void *arg) +{ + struct mqtt_request_t *r; + u16_t pkt_id; + size_t topic_strlen; + size_t total_len; + u16_t topic_len; + u16_t remaining_length; + + LWIP_ASSERT_CORE_LOCKED(); + LWIP_ASSERT("mqtt_publish: client != NULL", client); + LWIP_ASSERT("mqtt_publish: topic != NULL", topic); + LWIP_ERROR("mqtt_publish: TCP disconnected", (client->conn_state != TCP_DISCONNECTED), return ERR_CONN); + + topic_strlen = strlen(topic); + LWIP_ERROR("mqtt_publish: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); + topic_len = (u16_t)topic_strlen; + total_len = 2 + topic_len + payload_length; + + if (qos > 0) { + total_len += 2; + /* Generate pkt_id id for QoS1 and 2 */ + pkt_id = msg_generate_packet_id(client); + } else { + /* Use reserved value pkt_id 0 for QoS 0 in request handle */ + pkt_id = 0; + } + LWIP_ERROR("mqtt_publish: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); + remaining_length = (u16_t)total_len; + + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_publish: Publish with payload length %d to topic \"%s\"\n", payload_length, topic)); + + r = mqtt_create_request(client->req_list, LWIP_ARRAYSIZE(client->req_list), pkt_id, cb, arg); + if (r == NULL) { + return ERR_MEM; + } + + if (mqtt_output_check_space(&client->output, remaining_length) == 0) { + mqtt_delete_request(r); + return ERR_MEM; + } + /* Append fixed header */ + mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain, remaining_length); + + /* Append Topic */ + mqtt_output_append_string(&client->output, topic, topic_len); + + /* Append packet if for QoS 1 and 2*/ + if (qos > 0) { + mqtt_output_append_u16(&client->output, pkt_id); + } + + /* Append optional publish payload */ + if ((payload != NULL) && (payload_length > 0)) { + mqtt_output_append_buf(&client->output, payload, payload_length); + } + + mqtt_append_request(&client->pend_req_queue, r); + // mqtt_output_send(&client->output, client->conn); + return ERR_OK; +} + + +/** + * @ingroup mqtt + * MQTT subscribe/unsubscribe function. + * @param client MQTT client + * @param topic topic to subscribe to + * @param qos Quality of service, 0 1 or 2 (only used for subscribe) + * @param cb Callback to call when subscribe/unsubscribe response is received + * @param arg User supplied argument to publish callback + * @param sub 1 for subscribe, 0 for unsubscribe + * @return ERR_OK if successful, @see err_t enum for other results + */ +err_t +mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub) +{ + size_t topic_strlen; + size_t total_len; + u16_t topic_len; + u16_t remaining_length; + u16_t pkt_id; + struct mqtt_request_t *r; + + LWIP_ASSERT_CORE_LOCKED(); + LWIP_ASSERT("mqtt_sub_unsub: client != NULL", client); + LWIP_ASSERT("mqtt_sub_unsub: topic != NULL", topic); + + topic_strlen = strlen(topic); + LWIP_ERROR("mqtt_sub_unsub: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); + topic_len = (u16_t)topic_strlen; + /* Topic string, pkt_id, qos for subscribe */ + total_len = topic_len + 2 + 2 + (sub != 0); + LWIP_ERROR("mqtt_sub_unsub: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); + remaining_length = (u16_t)total_len; + + LWIP_ASSERT("mqtt_sub_unsub: qos < 3", qos < 3); + if (client->conn_state == TCP_DISCONNECTED) { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_sub_unsub: Can not (un)subscribe in disconnected state\n")); + return ERR_CONN; + } + + pkt_id = msg_generate_packet_id(client); + r = mqtt_create_request(client->req_list, LWIP_ARRAYSIZE(client->req_list), pkt_id, cb, arg); + if (r == NULL) { + return ERR_MEM; + } + + if (mqtt_output_check_space(&client->output, remaining_length) == 0) { + mqtt_delete_request(r); + return ERR_MEM; + } + + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_sub_unsub: Client (un)subscribe to topic \"%s\", id: %d\n", topic, pkt_id)); + + mqtt_output_append_fixed_header(&client->output, sub ? MQTT_MSG_TYPE_SUBSCRIBE : MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0, remaining_length); + /* Packet id */ + mqtt_output_append_u16(&client->output, pkt_id); + /* Topic */ + mqtt_output_append_string(&client->output, topic, topic_len); + /* QoS */ + if (sub != 0) { + mqtt_output_append_u8(&client->output, LWIP_MIN(qos, 2)); + } + + mqtt_append_request(&client->pend_req_queue, r); + //mqtt_output_send(&client->output, client->conn); + return ERR_OK; +} + + +/** + * @ingroup mqtt + * Set callback to handle incoming publish requests from server + * @param client MQTT client + * @param pub_cb Callback invoked when publish starts, contain topic and total length of payload + * @param data_cb Callback for each fragment of payload that arrives + * @param arg User supplied argument to both callbacks + */ +void +mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t pub_cb, + mqtt_incoming_data_cb_t data_cb, void *arg) +{ + LWIP_ASSERT_CORE_LOCKED(); + LWIP_ASSERT("mqtt_set_inpub_callback: client != NULL", client != NULL); + client->data_cb = data_cb; + client->pub_cb = pub_cb; + client->inpub_arg = arg; +} + +/** + * @ingroup mqtt + * Create a new MQTT client instance + * @return Pointer to instance on success, NULL otherwise + */ +mqtt_client_t * +mqtt_client_new(void) +{ + LWIP_ASSERT_CORE_LOCKED(); + return (mqtt_client_t *)mem_calloc(1, sizeof(mqtt_client_t)); +} + +/** + * @ingroup mqtt + * Free MQTT client instance + * @param client Pointer to instance to be freed + */ +void +mqtt_client_free(mqtt_client_t *client) +{ + mem_free(client); +} + +/** + * @ingroup mqtt + * Connect to MQTT server + * @param client MQTT client + * @param ip_addr Server IP + * @param port Server port + * @param cb Connection state change callback + * @param arg User supplied argument to connection callback + * @param client_info Client identification and connection options + * @return ERR_OK if successful, @see err_t enum for other results + */ +err_t +mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port, mqtt_connection_cb_t cb, void *arg, + const struct mqtt_connect_client_info_t *client_info) +{ + err_t err; + size_t len; + u16_t client_id_length; + /* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */ + u16_t remaining_length = 2 + 4 + 1 + 1 + 2; + u8_t flags = 0, will_topic_len = 0, will_msg_len = 0; + u16_t client_user_len = 0, client_pass_len = 0; + mqtt_incoming_data_cb_t data_cb; + mqtt_incoming_publish_cb_t pub_cb; + void *inpub_arg; + + LWIP_ASSERT_CORE_LOCKED(); + LWIP_ASSERT("mqtt_client_connect: client != NULL", client != NULL); + LWIP_ASSERT("mqtt_client_connect: ip_addr != NULL", ip_addr != NULL); + LWIP_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL); + LWIP_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL); + + if (client->conn_state != TCP_DISCONNECTED) { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_client_connect: Already connected\n")); + return ERR_ISCONN; + } + + /* Wipe clean, but keep callbacks */ + data_cb = client->data_cb; + pub_cb = client->pub_cb; + inpub_arg = client->inpub_arg; + memset(client, 0, sizeof(mqtt_client_t)); + client->data_cb = data_cb; + client->pub_cb = pub_cb; + client->inpub_arg = inpub_arg; + + client->connect_arg = arg; + client->connect_cb = cb; + client->keep_alive = client_info->keep_alive; + mqtt_init_requests(client->req_list, LWIP_ARRAYSIZE(client->req_list)); + + /* Build connect message */ + if (client_info->will_topic != NULL && client_info->will_msg != NULL) { + flags |= MQTT_CONNECT_FLAG_WILL; + flags |= (client_info->will_qos & 3) << 3; + if (client_info->will_retain) { + flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; + } + len = strlen(client_info->will_topic); + LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL); + LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL); + will_topic_len = (u8_t)len; + len = strlen(client_info->will_msg); + LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL); + will_msg_len = (u8_t)len; + len = remaining_length + 2 + will_topic_len + 2 + will_msg_len; + LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); + remaining_length = (u16_t)len; + } + if (client_info->client_user != NULL && client_info->client_user[0] != NULL) { + flags |= MQTT_CONNECT_FLAG_USERNAME; + len = strlen(client_info->client_user); + LWIP_ERROR("mqtt_client_connect: client_info->client_user length overflow", len <= 0xFFFF, return ERR_VAL); + LWIP_ERROR("mqtt_client_connect: client_info->client_user length must be > 0", len > 0, return ERR_VAL); + client_user_len = (u16_t)len; + len = remaining_length + 2 + client_user_len; + LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); + remaining_length = (u16_t)len; + } + if (client_info->client_pass != NULL && client_info->client_pass[0] != NULL) { + flags |= MQTT_CONNECT_FLAG_PASSWORD; + len = strlen(client_info->client_pass); + LWIP_ERROR("mqtt_client_connect: client_info->client_pass length overflow", len <= 0xFFFF, return ERR_VAL); + LWIP_ERROR("mqtt_client_connect: client_info->client_pass length must be > 0", len > 0, return ERR_VAL); + client_pass_len = (u16_t)len; + len = remaining_length + 2 + client_pass_len; + LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); + remaining_length = (u16_t)len; + } + + /* Don't complicate things, always connect using clean session */ + flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; + + len = strlen(client_info->client_id); + LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL); + client_id_length = (u16_t)len; + len = remaining_length + 2 + client_id_length; + LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); + remaining_length = (u16_t)len; + + if (mqtt_output_check_space(&client->output, remaining_length) == 0) { + return ERR_MEM; + } + +#if LWIP_ALTCP && LWIP_ALTCP_TLS + if (client_info->tls_config) { + client->conn = altcp_tls_new(client_info->tls_config, IP_GET_TYPE(ip_addr)); + } else +#endif + { + client->conn = altcp_tcp_new_ip_type(IP_GET_TYPE(ip_addr)); + } + if (client->conn == NULL) { + return ERR_MEM; + } + + /* Set arg pointer for callbacks */ + altcp_arg(client->conn, client); + /* Any local address, pick random local port number */ + err = altcp_bind(client->conn, IP_ADDR_ANY, 0); + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_client_connect: Error binding to local ip/port, %d\n", err)); + goto tcp_fail; + } + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_client_connect: Connecting to host: %s at port:%"U16_F"\n", ipaddr_ntoa(ip_addr), port)); + + /* Connect to server */ + err = altcp_connect(client->conn, ip_addr, port, mqtt_tcp_connect_cb); + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_client_connect: Error connecting to remote ip/port, %d\n", err)); + goto tcp_fail; + } + /* Set error callback */ + altcp_err(client->conn, mqtt_tcp_err_cb); + client->conn_state = TCP_CONNECTING; + + /* Append fixed header */ + mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length); + /* Append Protocol string */ + mqtt_output_append_string(&client->output, "MQTT", 4); + /* Append Protocol level */ + mqtt_output_append_u8(&client->output, 4); + /* Append connect flags */ + mqtt_output_append_u8(&client->output, flags); + /* Append keep-alive */ + mqtt_output_append_u16(&client->output, client_info->keep_alive); + /* Append client id */ + mqtt_output_append_string(&client->output, client_info->client_id, client_id_length); + /* Append will message if used */ + if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) { + mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len); + mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len); + } + /* Append user name if given */ + if ((flags & MQTT_CONNECT_FLAG_USERNAME) != 0) { + mqtt_output_append_string(&client->output, client_info->client_user, client_user_len); + } + /* Append password if given */ + if ((flags & MQTT_CONNECT_FLAG_PASSWORD) != 0) { + mqtt_output_append_string(&client->output, client_info->client_pass, client_pass_len); + } + return ERR_OK; + +tcp_fail: + altcp_abort(client->conn); + client->conn = NULL; + return err; +} + + +/** + * @ingroup mqtt + * Disconnect from MQTT server + * @param client MQTT client + */ +void +mqtt_disconnect(mqtt_client_t *client) +{ + LWIP_ASSERT_CORE_LOCKED(); + LWIP_ASSERT("mqtt_disconnect: client != NULL", client); + /* If connection in not already closed */ + if (client->conn_state != TCP_DISCONNECTED) { + /* Set conn_state before calling mqtt_close to prevent callback from being called */ + client->conn_state = TCP_DISCONNECTED; + mqtt_close(client, (mqtt_connection_status_t)0); + } +} + +/** + * @ingroup mqtt + * Check connection with server + * @param client MQTT client + * @return 1 if connected to server, 0 otherwise + */ +u8_t +mqtt_client_is_connected(mqtt_client_t *client) +{ + LWIP_ASSERT_CORE_LOCKED(); + LWIP_ASSERT("mqtt_client_is_connected: client != NULL", client); + return client->conn_state == MQTT_CONNECTED; +} + +#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/platforms/ESP-IDF/CMakeLists.txt b/platforms/ESP-IDF/CMakeLists.txt index 7648a7a8d..b3ddb227e 100644 --- a/platforms/ESP-IDF/CMakeLists.txt +++ b/platforms/ESP-IDF/CMakeLists.txt @@ -1,9 +1,6 @@ cmake_minimum_required(VERSION 3.16.0) include($ENV{IDF_PATH}/tools/cmake/project.cmake) add_compile_definitions(PLATFORM_ESPIDF=1) -add_compile_definitions(MQTT_OUTPUT_RINGBUF_SIZE=2048) -add_compile_definitions(MQTT_VAR_HEADER_BUFFER_LEN=256) -add_compile_definitions(MQTT_REQ_MAX_IN_FLIGHT=16) add_compile_definitions(LWIP_NOASSERT=1) add_definitions( -DUSER_SW_VER="$ENV{APP_VERSION}" ) add_definitions( -DOBK_VARIANT=$ENV{OBK_VARIANT} ) @@ -11,4 +8,5 @@ include_directories("$ENV{IDF_PATH}/../../libraries/berry/src") include_directories("$ENV{IDF_PATH}/../../include") set(PROJECT_VER "$ENV{APP_VERSION}") project(OpenBeken) -idf_build_set_property(COMPILE_OPTIONS "-Wno-format-truncation" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-Wno-error=format-truncation" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-Wno-error=incompatible-pointer-types" APPEND) diff --git a/platforms/ESP-IDF/main/CMakeLists.txt b/platforms/ESP-IDF/main/CMakeLists.txt index 51907e91b..a8db87567 100644 --- a/platforms/ESP-IDF/main/CMakeLists.txt +++ b/platforms/ESP-IDF/main/CMakeLists.txt @@ -6,8 +6,6 @@ set(BERRY_MODULEPATH "${OBK_SRCS}berry/modules") include($ENV{IDF_PATH}/../../libraries/berry.cmake) set(PROJ_ALL_SRC - ${OBKM_SRC} - ${BERRY_SRC_C} ${OBK_SRCS}hal/espidf/hal_adc_espidf.c ${OBK_SRCS}hal/espidf/hal_flashConfig_espidf.c ${OBK_SRCS}hal/espidf/hal_flashVars_espidf.c @@ -16,8 +14,9 @@ set(PROJ_ALL_SRC ${OBK_SRCS}hal/espidf/hal_pins_espidf.c ${OBK_SRCS}hal/espidf/hal_wifi_espidf.c ${OBK_SRCS}hal/espidf/hal_uart_espidf.c - $ENV{IDF_PATH}/components/lwip/lwip/src/apps/mqtt/mqtt.c - app.c + ${OBKM_SRC} + ${BERRY_SRC_C} + ../../../libraries/mqtt_patched.c ) idf_component_register(SRCS ${PROJ_ALL_SRC} WHOLE_ARCHIVE - PRIV_REQUIRES mqtt lwip esp_wifi nvs_flash esp_driver_tsens esp_driver_gpio esp_pm esp_partition app_update esp_adc esp_driver_uart esp_driver_ledc) + PRIV_REQUIRES mqtt lwip esp_wifi nvs_flash esp_driver_tsens esp_driver_gpio esp_pm esp_partition app_update esp_adc esp_driver_uart esp_driver_ledc spi_flash) diff --git a/platforms/ESP-IDF/main/app.c b/platforms/ESP-IDF/main/app.c deleted file mode 100644 index 83dd620ab..000000000 --- a/platforms/ESP-IDF/main/app.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include "esp_wifi.h" -#include "esp_sleep.h" -#include "hal/wdt_hal.h" - -void app_main(void); - -void Main_Init(); -void Main_OnEverySecond(); -float g_wifi_temperature = 0; - -#ifndef CONFIG_IDF_TARGET_ESP32 - -#include "driver/temperature_sensor.h" - -#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2) -#define TEMP_STACK_SIZE 1024 -#else -#define TEMP_STACK_SIZE 384 -#endif - -temperature_sensor_handle_t temp_handle = NULL; - -void temp_func(void* pvParameters) -{ - for(;;) - { - temperature_sensor_enable(temp_handle); - temperature_sensor_get_celsius(temp_handle, &g_wifi_temperature); - temperature_sensor_disable(temp_handle); - vTaskDelay(10000 / portTICK_PERIOD_MS); - } -} - -#endif - -void app_main(void) -{ - esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); - esp_netif_init(); - esp_event_loop_create_default(); -#ifndef CONFIG_IDF_TARGET_ESP32 - temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80); - temperature_sensor_install(&temp_sensor_config, &temp_handle); - xTaskCreate(temp_func, "IntTemp", TEMP_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL); -#endif - - Main_Init(); - - while(1) - { - wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT(); - wdt_hal_write_protect_disable(&rtc_wdt_ctx); - wdt_hal_feed(&rtc_wdt_ctx); - wdt_hal_write_protect_enable(&rtc_wdt_ctx); - Main_OnEverySecond(); - sys_delay_ms(1000); - } -} diff --git a/platforms/ESP-IDF/pre_build.sh b/platforms/ESP-IDF/pre_build.sh index dab1f180b..e7e422a69 100644 --- a/platforms/ESP-IDF/pre_build.sh +++ b/platforms/ESP-IDF/pre_build.sh @@ -2,7 +2,6 @@ # It allows you to make changes to the SDK, for example.. # For example, you can use changed files in the SDK for the automated build during the checks for a PR without changing the SDK itself: # So your PR needs a modified define in the SDK, for example ? This script can make this change directly before the build. - # # # As an example you will find a script below which will copy all content of the "override" @@ -27,7 +26,6 @@ #done ## restore IFS to whatever it was before ... #IFS=$OFS - # you can also use all other commands to change files, like # sed -i "s/#define FOO bar/#define FOO baz/" sdk/esp-idf/components/esp_driver_ledc/src/ledc.c # or, let's assume you made a local change to your SDK @@ -37,5 +35,4 @@ # # and then in pre_build.sh you apply this patch with: # -# patch -p 1 -d sdk/esp-idf < platforms/ESP_IDF/my_change.diff - +# patch -p 1 -d sdk/esp-idf < platforms/ESP_IDF/my_change.diff \ No newline at end of file diff --git a/platforms/ESP-IDF/sdkconfig.defaults.esp32c5 b/platforms/ESP-IDF/sdkconfig.defaults.esp32c5 new file mode 100644 index 000000000..953cfed73 --- /dev/null +++ b/platforms/ESP-IDF/sdkconfig.defaults.esp32c5 @@ -0,0 +1,3 @@ +CONFIG_PM_ENABLE=y +CONFIG_PM_DFS_INIT_AUTO=y +CONFIG_PARTITION_TABLE_CUSTOM=y \ No newline at end of file diff --git a/platforms/ESP-IDF/sdkconfig.defaults.esp32c61 b/platforms/ESP-IDF/sdkconfig.defaults.esp32c61 new file mode 100644 index 000000000..953cfed73 --- /dev/null +++ b/platforms/ESP-IDF/sdkconfig.defaults.esp32c61 @@ -0,0 +1,3 @@ +CONFIG_PM_ENABLE=y +CONFIG_PM_DFS_INIT_AUTO=y +CONFIG_PARTITION_TABLE_CUSTOM=y \ No newline at end of file diff --git a/platforms/ESP8266/.gitignore b/platforms/ESP8266/.gitignore new file mode 100644 index 000000000..86be639bf --- /dev/null +++ b/platforms/ESP8266/.gitignore @@ -0,0 +1,3 @@ +build* +sdkconfig +partitions.csv \ No newline at end of file diff --git a/platforms/ESP8266/CMakeLists.txt b/platforms/ESP8266/CMakeLists.txt new file mode 100644 index 000000000..976d6535b --- /dev/null +++ b/platforms/ESP8266/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.13.0) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +idf_build_set_property(COMPILE_OPTIONS "-DPLATFORM_ESP8266=1" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-DLWIP_NOASSERT=1" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-DUSER_SW_VER=\"$ENV{APP_VERSION}\"" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-DOBK_VARIANT=$ENV{OBK_VARIANT}" APPEND) +include_directories("$ENV{IDF_PATH}/../../libraries/berry/src") +include_directories("$ENV{IDF_PATH}/../../include") +set(PROJECT_VER "$ENV{APP_VERSION}") +project(OpenBeken) +idf_build_set_property(COMPILE_OPTIONS "-Wno-error=format-truncation" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-Wno-error=incompatible-pointer-types" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-Wno-error=pointer-sign" APPEND) +idf_build_set_property(COMPILE_OPTIONS "-Wno-error=main" APPEND) diff --git a/platforms/ESP8266/main/CMakeLists.txt b/platforms/ESP8266/main/CMakeLists.txt new file mode 100644 index 000000000..56669e2c8 --- /dev/null +++ b/platforms/ESP8266/main/CMakeLists.txt @@ -0,0 +1,21 @@ +set(OBK_SRCS "../../../src/") +include($ENV{IDF_PATH}/../../platforms/obk_main.cmake) + +set(BERRY_SRCPATH "../../../libraries/berry/src") +set(BERRY_MODULEPATH "${OBK_SRCS}berry/modules") +include($ENV{IDF_PATH}/../../libraries/berry.cmake) +set(PROJ_ALL_SRC + ${OBK_SRCS}hal/espidf/hal_adc_espidf.c + ${OBK_SRCS}hal/espidf/hal_flashConfig_espidf.c + ${OBK_SRCS}hal/espidf/hal_flashVars_espidf.c + ${OBK_SRCS}hal/espidf/hal_generic_espidf.c + ${OBK_SRCS}hal/espidf/hal_main_espidf.c + ${OBK_SRCS}hal/espidf/hal_pins_espidf.c + ${OBK_SRCS}hal/espidf/hal_wifi_espidf.c + ${OBK_SRCS}hal/espidf/hal_uart_espidf.c + ${OBKM_SRC} + ${BERRY_SRC_C} + ../../../libraries/mqtt_patched.c +) +idf_component_register(SRCS ${PROJ_ALL_SRC} + PRIV_REQUIRES lwip nvs_flash app_update) \ No newline at end of file diff --git a/platforms/ESP8266/partitions-1mb.csv b/platforms/ESP8266/partitions-1mb.csv new file mode 100644 index 000000000..826c7be82 --- /dev/null +++ b/platforms/ESP8266/partitions-1mb.csv @@ -0,0 +1,4 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, , 0x7000, +factory, app, factory, 0x10000, 0xE0000, +lfs, data, spiffs, , 0x10000, \ No newline at end of file diff --git a/platforms/ESP8266/partitions-2mb.csv b/platforms/ESP8266/partitions-2mb.csv new file mode 100644 index 000000000..c9b8829ca --- /dev/null +++ b/platforms/ESP8266/partitions-2mb.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +otadata, data, ota, , 0x2000, +app0, app, ota_0, 0x10000, 0xE0000, +lfs, data, spiffs, , 0x20000, +app1, app, ota_1, 0x110000, 0xE0000, +nvs, data, nvs, , 0x10000, \ No newline at end of file diff --git a/platforms/ESP8266/pre_build.sh b/platforms/ESP8266/pre_build.sh new file mode 100644 index 000000000..c93f18797 --- /dev/null +++ b/platforms/ESP8266/pre_build.sh @@ -0,0 +1,40 @@ +# This script will be called just before starting build process for ESP8266 +# It allows you to make changes to the SDK, for example.. +# For example, you can use changed files in the SDK for the automated build during the checks for a PR without changing the SDK itself: +# So your PR needs a modified define in the SDK, for example ? This script can make this change directly before the build. +# +# +# +# As an example you will find a script below which will copy all content of the "override" +# directory to the corresponding location in the SDK +# +#DIRNAME=$(dirname $0); +#echo "PREBUILD script! Executed from $DIRNAME!" +# allow whitspace in file or path, so take only newline as seperator +#OFS=$IFS +#IFS=' +#' +#for X in $(find platforms/ESP-IDF/override/ -type f);do +# # script is executed from main app directory, so take found file and path as source +# S=${X}; +# # destination is path stripped from path to override +# # so inside "override" we have the full path to the file +# # starting with "sdk/esp-idf/..." +# D=${X#platforms/ESP-IDF/override/}; +# # if file is present, we replace it, otherwise file is added ... +# [ -e $D ] && echo "PREBUILD: replacing file\n\t$D\n\twith file\n\t$S" || echo "PREBUILD: adding file\n\t$S\n\tas\n\t$D" +# cp $S $D; +#done +## restore IFS to whatever it was before ... +#IFS=$OFS +# +# you can also use all other commands to change files, like +# sed -i "s/#define FOO bar/#define FOO baz/" sdk/esp-idf/components/esp_driver_ledc/src/ledc.c +# or, let's assume you made a local change to your SDK +# and make a diff from that change (inside sdk/esp-idf/) +# git diff > ../../platforms/ESP-IDF/my_change.diff +# ( or make the diff and copy this file to platforms/ESP-IDF) +# +# and then in pre_build.sh you apply this patch with: +# +# patch -p 1 -d sdk/esp-idf < platforms/ESP_IDF/my_change.diff \ No newline at end of file diff --git a/platforms/ESP8266/sdk.patch b/platforms/ESP8266/sdk.patch new file mode 100644 index 000000000..f797a2cf8 --- /dev/null +++ b/platforms/ESP8266/sdk.patch @@ -0,0 +1,170 @@ +commit 185db7d2b13a2a8c18c8ed5abce9a80de259fa7b +Author: NonPIayerCharacter <18557343+NonPIayerCharacter@users.noreply.github.com> +Date: Tue Jul 1 22:45:37 2025 +0000 + + for OBK + +diff --git a/components/pthread/CMakeLists.txt b/components/pthread/CMakeLists.txt +index 653799ad5a61ea87fbba15a3fea325a0dca46fa2..df5a961a6514aaa894cfde381406e077baeff635 100644 +--- a/components/pthread/CMakeLists.txt ++++ b/components/pthread/CMakeLists.txt +@@ -4,7 +4,7 @@ idf_component_register(SRCS "pthread.c" + INCLUDE_DIRS include) + + set(extra_link_flags "-u pthread_include_pthread_impl") +-list(APPEND extra_link_flags "-u pthread_include_pthread_cond_impl") ++list(APPEND extra_link_flags "-u pthread_include_pthread_cond_var_impl") + list(APPEND extra_link_flags "-u pthread_include_pthread_local_storage_impl") + + if(CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP) +diff --git a/components/pthread/component.mk b/components/pthread/component.mk +index c5793fded60c4e43f583121fc2a0b414eb7ef8f7..0e1cd8a32c26a54c18b319d06827883b24f4586d 100644 +--- a/components/pthread/component.mk ++++ b/components/pthread/component.mk +@@ -16,6 +16,6 @@ ifeq ($(GCC_NOT_5_2_0), 1) + # Forces the linker to include pthread implementation from this component, + # instead of the weak implementations provided by libgcc. + COMPONENT_ADD_LDFLAGS += -u pthread_include_pthread_impl +-COMPONENT_ADD_LDFLAGS += -u pthread_include_pthread_cond_impl ++COMPONENT_ADD_LDFLAGS += -u pthread_include_pthread_cond_var_impl + COMPONENT_ADD_LDFLAGS += -u pthread_include_pthread_local_storage_impl + endif # GCC_NOT_5_2_0 +diff --git a/export.sh b/export.sh +index 38a0b828e5d40e943719dffbe49e6769aeafad35..32b3291d17460a6284a213890bc7aaa81347cd86 100755 +--- a/export.sh ++++ b/export.sh +@@ -45,11 +45,11 @@ function idf_export_main() { + # Call idf_tools.py to export tool paths + export IDF_TOOLS_EXPORT_CMD=${IDF_PATH}/export.sh + export IDF_TOOLS_INSTALL_CMD=${IDF_PATH}/install.sh +- idf_exports=$(${IDF_PATH}/tools/idf_tools.py export) || return 1 ++ idf_exports=$(python2 ${IDF_PATH}/tools/idf_tools.py export) || return 1 + eval "${idf_exports}" + + echo "Checking if Python packages are up to date..." +- python ${IDF_PATH}/tools/check_python_dependencies.py || return 1 ++ python2 ${IDF_PATH}/tools/check_python_dependencies.py || return 1 + + + # Allow calling some IDF python tools without specifying the full path +diff --git a/install.sh b/install.sh +index d026e3c931672e00ec45277ee896b85762879385..acbce000124b4c54ec0aaab9aad5c2b61b931051 100755 +--- a/install.sh ++++ b/install.sh +@@ -6,10 +6,10 @@ set -u + export IDF_PATH=$(cd $(dirname $0); pwd) + + echo "Installing ESP-IDF tools" +-${IDF_PATH}/tools/idf_tools.py install ++python2 ${IDF_PATH}/tools/idf_tools.py install + + echo "Installing Python environment and packages" +-${IDF_PATH}/tools/idf_tools.py install-python-env ++python2 ${IDF_PATH}/tools/idf_tools.py install-python-env + + basedir="$(dirname $0)" + echo "All done! You can now run:" +diff --git a/requirements.txt b/requirements.txt +index 6a97933042f3c05b189c45769fe4ecd9ff3c2345..e04e05c1e0bbb0df917dbf08f50b31b6e77bb925 100644 +--- a/requirements.txt ++++ b/requirements.txt +@@ -10,4 +10,4 @@ pyserial>=3.0 + future>=0.15.2 + cryptography>=2.1.4,<35 + pyparsing>=2.0.3,<2.4.0 +-pyelftools>=0.22 ++pyelftools>=0.22,<0.28 +diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake +index 566ff8e984635b7b6d4accc254fa4e7045a758a5..2713df4f55eaaf2b3a57ddc72ab83aa1de1378df 100644 +--- a/tools/cmake/build.cmake ++++ b/tools/cmake/build.cmake +@@ -451,6 +451,10 @@ endmacro() + # files used for linking, targets which should execute before creating the specified executable, + # generating additional binary files, generating files related to flashing, etc.) + function(idf_build_executable elf) ++ # Set additional link flags for the executable ++ idf_build_get_property(link_options LINK_OPTIONS) ++ set_property(TARGET ${elf} APPEND PROPERTY LINK_OPTIONS "${link_options}") ++ + # Propagate link dependencies from component library targets to the executable + idf_build_get_property(link_depends __LINK_DEPENDS) + set_property(TARGET ${elf} APPEND PROPERTY LINK_DEPENDS "${link_depends}") +diff --git a/tools/cmake/component.cmake b/tools/cmake/component.cmake +index cbd6406d73e74d71c10d604f3f939cf0d0f8091f..dd4466face0004637319e0d3235a929de7e75dc4 100644 +--- a/tools/cmake/component.cmake ++++ b/tools/cmake/component.cmake +@@ -93,6 +93,7 @@ macro(__component_set_properties) + __component_set_property(${component_target} EMBED_FILES "${__EMBED_FILES}") + __component_set_property(${component_target} EMBED_TXTFILES "${__EMBED_TXTFILES}") + __component_set_property(${component_target} REQUIRED_IDF_TARGETS "${__REQUIRED_IDF_TARGETS}") ++ __component_set_property(${component_target} WHOLE_ARCHIVE ${__WHOLE_ARCHIVE}) + endmacro() + + # +@@ -386,8 +387,9 @@ endfunction() + # @param[in, optional] REQUIRED_IDF_TARGETS (multivalue) the list of IDF build targets that the component only supports + # @param[in, optional] EMBED_FILES (multivalue) list of binary files to embed with the component + # @param[in, optional] EMBED_TXTFILES (multivalue) list of text files to embed with the component ++# @param[in, optional] WHOLE_ARCHIVE (option) link the component as --whole-archive + function(idf_component_register) +- set(options) ++ set(options WHOLE_ARCHIVE) + set(single_value) + set(multi_value SRCS SRC_DIRS EXCLUDE_SRCS + INCLUDE_DIRS PRIV_INCLUDE_DIRS LDFRAGMENTS REQUIRES +diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake +index e64080e69ea7ed866886193a402ae5d0da0dd79b..f40ff335f29628016d41dc50e8a351f5bccbb5a5 100644 +--- a/tools/cmake/project.cmake ++++ b/tools/cmake/project.cmake +@@ -358,6 +358,7 @@ macro(project project_name) + __component_get_target(main_target idf::main) + __component_get_property(reqs ${main_target} REQUIRES) + __component_get_property(priv_reqs ${main_target} PRIV_REQUIRES) ++ __component_set_property(${main_target} WHOLE_ARCHIVE true) + idf_build_get_property(common_reqs __COMPONENT_REQUIRES_COMMON) + if(reqs STREQUAL common_reqs AND NOT priv_reqs) #if user has not set any requirements + list(REMOVE_ITEM build_components idf::main) +@@ -396,7 +397,19 @@ macro(project project_name) + if(test_components) + list(REMOVE_ITEM build_components ${test_components}) + endif() +- target_link_libraries(${project_elf} ${build_components}) ++ ++ foreach(build_component ${build_components}) ++ __component_get_target(build_component_target ${build_component}) ++ __component_get_property(whole_archive ${build_component_target} WHOLE_ARCHIVE) ++ if(whole_archive) ++ message(STATUS "Component ${build_component} will be linked with -Wl,--whole-archive") ++ target_link_libraries(${project_elf} "-Wl,--whole-archive" ${build_component} "-Wl,--no-whole-archive") ++ else() ++ target_link_libraries(${project_elf} ${build_component}) ++ message(STATUS "Component ${build_component} will not be linked with -Wl,--whole-archive") ++ #target_link_libraries(${project_elf} "-Wl,--whole-archive" ${build_component} "-Wl,--no-whole-archive") ++ endif() ++ endforeach() + + set(mapfile "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.map") + target_link_libraries(${project_elf} "-Wl,--cref -Wl,--Map=${mapfile} -Wl,--start-group") +diff --git a/tools/cmake/scripts/component_get_requirements.cmake b/tools/cmake/scripts/component_get_requirements.cmake +index 24637008bde86ead61a709c0a40c0be0274a7c46..15df499212d785d5763833fa77a69ddd3766df56 100644 +--- a/tools/cmake/scripts/component_get_requirements.cmake ++++ b/tools/cmake/scripts/component_get_requirements.cmake +@@ -22,7 +22,7 @@ macro(require_idf_targets) + endmacro() + + macro(idf_component_register) +- set(options) ++ set(options WHOLE_ARCHIVE) + set(single_value) + set(multi_value SRCS SRC_DIRS EXCLUDE_SRCS + INCLUDE_DIRS PRIV_INCLUDE_DIRS LDFRAGMENTS REQUIRES +diff --git a/tools/idf.py b/tools/idf.py +index 7d6a3f49f64fcf41268adea041d19f6a48857c12..269b828ed98581464b0e08beb4464ab9089bd956 100755 +--- a/tools/idf.py ++++ b/tools/idf.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python2 + # + # 'idf.py' is a top-level config/build command line tool for ESP-IDF + # diff --git a/platforms/ESP8266/sdkconfig.defaults b/platforms/ESP8266/sdkconfig.defaults new file mode 100644 index 000000000..b4b2839d7 --- /dev/null +++ b/platforms/ESP8266/sdkconfig.defaults @@ -0,0 +1,43 @@ +CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION=n +CONFIG_LWIP_IPV6=n +CONFIG_LWIP_IPV6_AUTOCONFIG=n +CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=n +CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=n +CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=n +CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_NEWLIB_NANO_FORMAT=y +CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE=y +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3072 +CONFIG_ESP_TIMER_TASK_STACK_SIZE=2560 +CONFIG_VFS_SUPPORT_IO=n +CONFIG_MBEDTLS_SHA512_C=n +CONFIG_MBEDTLS_TLS_CLIENT_ONLY=y +CONFIG_HAL_LOG_LEVEL_ERROR=y + +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=n +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=n + +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_LWIP_TCP_MSL=1000 +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_ESPTOOLPY_FLASHSIZE="16MB" +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_LWIP_ESP_LWIP_ASSERT=n +CONFIG_MBEDTLS_SSL_PROTO_TLS1=n +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=n + +CONFIG_LWIP_MAX_ACTIVE_TCP=8 +CONFIG_LWIP_MAX_LISTENING_TCP=3 +CONFIG_LWIP_MAX_UDP_PCBS=2 +CONFIG_LWIP_MAX_RAW_PCBS=2 +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=1024 +CONFIG_LWIP_IP4_FRAG=n +CONFIG_LWIP_IP6_FRAG=n +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=2048 +CONFIG_WIFI_PPT_TASKSTACK_SIZE=4096 + +CONFIG_ESP8266_WIFI_RX_BUFFER_NUM=6 +CONFIG_ESP8266_WIFI_LEFT_CONTINUOUS_RX_BUFFER_NUM=6 +CONFIG_SUPPORT_TERMIOS=n diff --git a/sdk/ESP8266_RTOS_SDK b/sdk/ESP8266_RTOS_SDK new file mode 160000 index 000000000..c965e03d2 --- /dev/null +++ b/sdk/ESP8266_RTOS_SDK @@ -0,0 +1 @@ +Subproject commit c965e03d2b7418b085c394dc98c6a0d3371c2abd diff --git a/sdk/esp-idf b/sdk/esp-idf index c8fc5f643..cbe9388f4 160000 --- a/sdk/esp-idf +++ b/sdk/esp-idf @@ -1 +1 @@ -Subproject commit c8fc5f643b7a7b0d3b182d3df610844e3dc9bd74 +Subproject commit cbe9388f45dd8f33fc560c9727d429e8e107d476 diff --git a/src/cmnds/cmd_main.c b/src/cmnds/cmd_main.c index f87e4401b..8919697d6 100644 --- a/src/cmnds/cmd_main.c +++ b/src/cmnds/cmd_main.c @@ -26,14 +26,16 @@ int cmd_uartInitIndex = 0; #elif PLATFORM_LN882H #include #include -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 #include "esp_wifi.h" -#include "esp_pm.h" #include "esp_sleep.h" -#include "driver/rtc_io.h" #include "driver/gpio.h" #include "driver/ledc.h" +#if !PLATFORM_ESP8266 +#include "esp_pm.h" +#include "driver/rtc_io.h" #include "esp_check.h" +#endif #elif PLATFORM_REALTEK #if PLATFORM_RTL8710B #include "wlan_intf.h" @@ -166,7 +168,7 @@ static commandResult_t CMD_PowerSave(const void* context, const char* cmd, const g_ln882h_pendingPowerSaveCommand = bOn; } else LN882H_ApplyPowerSave(bOn); -#elif defined(PLATFORM_ESPIDF) +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 switch(bOn) { case 1: @@ -182,6 +184,7 @@ static commandResult_t CMD_PowerSave(const void* context, const char* cmd, const esp_wifi_set_ps(WIFI_PS_NONE); break; } +#if PLATFORM_ESPIDF if(Tokenizer_GetArgsCount() > 1) { int tx = Tokenizer_GetArgInteger(1); @@ -208,6 +211,7 @@ static commandResult_t CMD_PowerSave(const void* context, const char* cmd, const esp_pm_configure(&pm_config); ADDLOG_INFO(LOG_FEATURE_CMD, "PowerSave freq scaling, min: %iMhz, max: %iMhz", minfreq, maxfreq); } +#endif #elif PLATFORM_REALTEK if(!wifi_is_up(RTW_STA_INTERFACE)) { @@ -325,12 +329,15 @@ static commandResult_t CMD_DeepSleep(const void* context, const char* cmd, const bk_enter_deep_sleep_mode(¶ms); return CMD_RES_OK; #elif defined(PLATFORM_W600) -#elif defined(PLATFORM_ESPIDF) - esp_sleep_enable_timer_wakeup(timeMS * 1000000); +#elif PLATFORM_ESPIDF + esp_sleep_enable_timer_wakeup(timeMS * 1000); #if CONFIG_IDF_TARGET_ESP32 rtc_gpio_isolate(GPIO_NUM_12); #endif esp_deep_sleep_start(); +#elif PLATFORM_ESP8266 + esp_wifi_stop(); + esp_deep_sleep(timeMS * 1000); #elif PLATFORM_XRADIO HAL_Wakeup_SetTimer_mS(timeMS * DS_MS_TO_S); pm_enter_mode(DEEP_SLEEP); @@ -1069,8 +1076,8 @@ void CMD_Init_Delayed() { CMD_StartTCPCommandLine(); } #endif -#if defined(PLATFORM_BEKEN) || defined(WINDOWS) || defined(PLATFORM_BL602) || defined(PLATFORM_ESPIDF) \ - || defined(PLATFORM_REALTEK) || defined(PLATFORM_ECR6600) || defined(PLATFORM_XRADIO) +#if PLATFORM_BEKEN || WINDOWS || PLATFORM_BL602 || PLATFORM_ESPIDF || PLATFORM_ESP8266 \ + || PLATFORM_REALTEK || PLATFORM_ECR6600 || PLATFORM_XRADIO UART_AddCommands(); #endif #if ENABLE_BL_TWIN diff --git a/src/cmnds/cmd_tokenizer.c b/src/cmnds/cmd_tokenizer.c index c0361635a..b3eca9db5 100644 --- a/src/cmnds/cmd_tokenizer.c +++ b/src/cmnds/cmd_tokenizer.c @@ -352,7 +352,7 @@ void Tokenizer_TokenizeString(const char *s, int flags) { g_argsFrom[g_numArgs] = g_buffer; // some hack, but we fored to have only have one arg, so we can extend the string over array bondaries. // probably better: introducing an union containing g_argsExpanded[][] and one sole string in the same memory area ... - CMD_ExpandConstantsWithinString(g_buffer,g_argsExpanded,sizeof(g_argsExpanded)-1); + CMD_ExpandConstantsWithinString(g_buffer,(char*)g_argsExpanded,sizeof(g_argsExpanded)-1); g_numArgs = 1; return; } diff --git a/src/driver/drv_bl0937.c b/src/driver/drv_bl0937.c index 29afc6ff8..f7fd7a7cc 100644 --- a/src/driver/drv_bl0937.c +++ b/src/driver/drv_bl0937.c @@ -57,6 +57,12 @@ extern void HAL_XR_ConfigurePin(GPIO_Port port, GPIO_Pin pin, GPIO_WorkMode mode xrpin_t* xr_cf; xrpin_t* xr_cf1; +#elif PLATFORM_ESP8266 || PLATFORM_ESPIDF + +#include "../hal/espidf/hal_pinmap_espidf.h" +espPinMapping_t* esp_cf; +espPinMapping_t* esp_cf1; + #else @@ -183,7 +189,7 @@ void cf1_irq_handler(uint32_t id, gpio_irq_event event) g_vc_pulses++; } -#elif PLATFORM_XRADIO +#elif PLATFORM_XRADIO || PLATFORM_ESPIDF || PLATFORM_ESP8266 static void HlwCf1Interrupt(void* arg) { @@ -268,6 +274,12 @@ void BL0937_Shutdown_Pins() HAL_GPIO_DeInit(xr_cf1->port, xr_cf1->pin); HAL_GPIO_DisableIRQ(xr_cf1->port, xr_cf1->pin); +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 + + gpio_isr_handler_remove(esp_cf->pin); + gpio_isr_handler_remove(esp_cf1->pin); + gpio_uninstall_isr_service(); + #endif } @@ -325,6 +337,12 @@ void BL0937_Init_Pins() xr_cf = g_pins + GPIO_HLW_CF; xr_cf1 = g_pins + GPIO_HLW_CF1; +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 + + esp_cf = g_pins + GPIO_HLW_CF; + esp_cf1 = g_pins + GPIO_HLW_CF1; + gpio_install_isr_service(0); + #endif BL0937_PMAX = CFG_GetPowerMeasurementCalibrationFloat(CFG_OBK_POWER_MAX, BL0937_PMAX); @@ -380,6 +398,11 @@ void BL0937_Init_Pins() cf1param.arg = (void*)0; HAL_GPIO_EnableIRQ(xr_cf1->port, xr_cf1->pin, &cf1param); +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 + + ESP_ConfigurePin(esp_cf1->pin, GPIO_MODE_INPUT, true, false, GPIO_INTR_NEGEDGE); + gpio_isr_handler_add((1ULL << (uint32_t)esp_cf1->pin), HlwCf1Interrupt, NULL); + #endif HAL_PIN_Setup_Input_Pullup(GPIO_HLW_CF); @@ -430,6 +453,11 @@ void BL0937_Init_Pins() cfparam.arg = (void*)0; HAL_GPIO_EnableIRQ(xr_cf->port, xr_cf->pin, &cfparam); +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 + + ESP_ConfigurePin(esp_cf->pin, GPIO_MODE_INPUT, true, false, GPIO_INTR_NEGEDGE); + gpio_isr_handler_add((1ULL << (uint32_t)esp_cf->pin), HlwCfInterrupt, NULL); + #endif g_vc_pulses = 0; diff --git a/src/driver/drv_soft_i2c.c b/src/driver/drv_soft_i2c.c index 5349995e7..146190666 100644 --- a/src/driver/drv_soft_i2c.c +++ b/src/driver/drv_soft_i2c.c @@ -10,7 +10,7 @@ #include "../httpserver/new_http.h" #include "../hal/hal_pins.h" -#if !defined(PLATFORM_ESPIDF) && !defined(PLATFORM_XR806) && !defined(PLATFORM_XR872) +#if !defined(PLATFORM_ESPIDF) && !defined(PLATFORM_XR806) && !defined(PLATFORM_XR872) && !defined(PLATFORM_ESP8266) void usleep(int r) //delay function do 10*r nops, because rtos_delay_milliseconds is too much { #ifdef WIN32 diff --git a/src/driver/drv_tuyaMCU.c b/src/driver/drv_tuyaMCU.c index 8d3a59b83..15fb86f4a 100644 --- a/src/driver/drv_tuyaMCU.c +++ b/src/driver/drv_tuyaMCU.c @@ -449,7 +449,7 @@ void TuyaMCU_SendCommandWithData(byte cmdType, byte* data, int payload_len) { byte check_sum = (0xFF + cmdType + (payload_len >> 8) + (payload_len & 0xFF)); - UART_InitUART(g_baudRate, 0, false); + //UART_InitUART(g_baudRate, 0, false); if (CFG_HasFlag(OBK_FLAG_TUYAMCU_USE_QUEUE)) { tuyaMCUPacket_t *p = TUYAMCU_AddToQueue(payload_len + 4); p->data[0] = cmdType; diff --git a/src/hal/espidf/hal_adc_espidf.c b/src/hal/espidf/hal_adc_espidf.c index 4fc277b4d..a395d01a4 100644 --- a/src/hal/espidf/hal_adc_espidf.c +++ b/src/hal/espidf/hal_adc_espidf.c @@ -5,7 +5,7 @@ #include "esp_adc/adc_oneshot.h" #include "esp_adc/adc_cali.h" #include "esp_adc/adc_cali_scheme.h" -#include "hal_generic_espidf.h" +#include "hal_pinmap_espidf.h" extern espPinMapping_t g_pins[]; extern int g_numPins; diff --git a/src/hal/espidf/hal_flashConfig_espidf.c b/src/hal/espidf/hal_flashConfig_espidf.c index 7c590f8b7..74cd3f656 100644 --- a/src/hal/espidf/hal_flashConfig_espidf.c +++ b/src/hal/espidf/hal_flashConfig_espidf.c @@ -1,4 +1,4 @@ -#ifdef PLATFORM_ESPIDF +#if PLATFORM_ESPIDF || PLATFORM_ESP8266 #include "../hal_flashConfig.h" #include "nvs_flash.h" diff --git a/src/hal/espidf/hal_flashVars_espidf.c b/src/hal/espidf/hal_flashVars_espidf.c index b7403ae85..58f581f00 100644 --- a/src/hal/espidf/hal_flashVars_espidf.c +++ b/src/hal/espidf/hal_flashVars_espidf.c @@ -1,4 +1,4 @@ -#ifdef PLATFORM_ESPIDF +#if PLATFORM_ESPIDF|| PLATFORM_ESP8266 #include "../../new_cfg.h" #include "../../logging/logging.h" diff --git a/src/hal/espidf/hal_generic_espidf.c b/src/hal/espidf/hal_generic_espidf.c index 5925b98c1..e487b882c 100644 --- a/src/hal/espidf/hal_generic_espidf.c +++ b/src/hal/espidf/hal_generic_espidf.c @@ -1,4 +1,4 @@ -#ifdef PLATFORM_ESPIDF +#if PLATFORM_ESPIDF || PLATFORM_ESP8266 #include #include "../hal_generic.h" @@ -6,6 +6,9 @@ #include "nvs_flash.h" #include "nvs.h" #include "freertos/FreeRTOS.h" +#if PLATFORM_ESPIDF +#include "hal/wdt_hal.h" +#endif static int bFlashReady = 0; @@ -22,7 +25,6 @@ void InitFlashIfNeeded() } bFlashReady = 1; - } void HAL_RebootModule() @@ -35,4 +37,14 @@ void HAL_Delay_us(int delay) usleep(delay); } +void HAL_Run_WDT() +{ +#if PLATFORM_ESPIDF + wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT(); + wdt_hal_write_protect_disable(&rtc_wdt_ctx); + wdt_hal_feed(&rtc_wdt_ctx); + wdt_hal_write_protect_enable(&rtc_wdt_ctx); +#endif +} + #endif // PLATFORM_ESPIDF diff --git a/src/hal/espidf/hal_generic_espidf.h b/src/hal/espidf/hal_generic_espidf.h deleted file mode 100644 index b67dfa5bb..000000000 --- a/src/hal/espidf/hal_generic_espidf.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef PLATFORM_ESPIDF - -#include "driver/gpio.h" - -typedef struct espPinMapping_s -{ - const char* name; - gpio_num_t pin; - bool isConfigured; -} espPinMapping_t; - -#endif // PLATFORM_ESPIDF diff --git a/src/hal/espidf/hal_main_espidf.c b/src/hal/espidf/hal_main_espidf.c index 48f83c437..e02842839 100644 --- a/src/hal/espidf/hal_main_espidf.c +++ b/src/hal/espidf/hal_main_espidf.c @@ -1,7 +1,68 @@ -#ifdef PLATFORM_ESPIDF +#if PLATFORM_ESPIDF || PLATFORM_ESP8266 #include "../../new_common.h" #include "../../logging/logging.h" #include "../../quicktick.h" +#include +#include "esp_wifi.h" +#include "esp_sleep.h" +#if PLATFORM_ESP8266 +#include "esp_netif.h" +#endif +void app_main(void); + +void Main_Init(); +void Main_OnEverySecond(); +float g_wifi_temperature = 0; + +#if !CONFIG_IDF_TARGET_ESP32 && !PLATFORM_ESP8266 + +#include "driver/temperature_sensor.h" + +#define TEMP_STACK_SIZE 1024 + +temperature_sensor_handle_t temp_handle = NULL; + +void temp_func(void* pvParameters) +{ + for(;;) + { + temperature_sensor_enable(temp_handle); + temperature_sensor_get_celsius(temp_handle, &g_wifi_temperature); + temperature_sensor_disable(temp_handle); + sys_delay_ms(10000); + } +} + +#endif + +void app_main(void) +{ + esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); + esp_netif_init(); + esp_event_loop_create_default(); +#if !CONFIG_IDF_TARGET_ESP32 && !PLATFORM_ESP8266 + temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80); + temperature_sensor_install(&temp_sensor_config, &temp_handle); + xTaskCreate(temp_func, "IntTemp", TEMP_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL); +#endif + +#if PLATFORM_ESP8266 + uint8_t mac[6]; + if(esp_base_mac_addr_get((unsigned char*)&mac) != ESP_OK) + { + esp_read_mac(mac, ESP_MAC_WIFI_STA); + esp_base_mac_addr_set((unsigned char*)&mac); + } +#endif + + Main_Init(); + + while(1) + { + sys_delay_ms(1000); + Main_OnEverySecond(); + } +} #endif // PLATFORM_ESPIDF diff --git a/src/hal/espidf/hal_pinmap_espidf.h b/src/hal/espidf/hal_pinmap_espidf.h new file mode 100644 index 000000000..a41127c1f --- /dev/null +++ b/src/hal/espidf/hal_pinmap_espidf.h @@ -0,0 +1,20 @@ +#if PLATFORM_ESPIDF || PLATFORM_ESP8266 + +#include "driver/gpio.h" +#if PLATFORM_ESP8266 +#define GPIO_NUM_NC -1 +#endif + +typedef struct +{ + const char* name; + gpio_num_t pin; + bool isConfigured; +} espPinMapping_t; + +extern espPinMapping_t g_pins[]; +extern int g_numPins; + +extern void ESP_ConfigurePin(gpio_num_t pin, gpio_mode_t mode, bool pup, bool pdown, gpio_int_type_t intr); + +#endif // PLATFORM_ESPIDF diff --git a/src/hal/espidf/hal_pins_espidf.c b/src/hal/espidf/hal_pins_espidf.c index 836aefbd1..fe30f8ef3 100644 --- a/src/hal/espidf/hal_pins_espidf.c +++ b/src/hal/espidf/hal_pins_espidf.c @@ -1,14 +1,11 @@ -#ifdef PLATFORM_ESPIDF +#if PLATFORM_ESPIDF || PLATFORM_ESP8266 #include "../../new_common.h" #include "../../logging/logging.h" #include "../../new_cfg.h" #include "../../new_pins.h" -#include "driver/gpio.h" +#include "hal_pinmap_espidf.h" #include "driver/ledc.h" -#include "hal_generic_espidf.h" - -#define LEDC_MAX_CH 6 #ifdef CONFIG_IDF_TARGET_ESP32C3 @@ -251,15 +248,203 @@ espPinMapping_t g_pins[] = { { "IO39", GPIO_NUM_39, false }, }; +#elif CONFIG_IDF_TARGET_ESP32C5 + +espPinMapping_t g_pins[] = { + { "IO0", GPIO_NUM_0, false }, + { "IO1", GPIO_NUM_1, false }, + { "IO2", GPIO_NUM_2, false }, + { "IO3", GPIO_NUM_3, false }, + { "IO4", GPIO_NUM_4, false }, + { "IO5", GPIO_NUM_5, false }, + { "IO6", GPIO_NUM_6, false }, + { "IO7", GPIO_NUM_7, false }, + { "IO8", GPIO_NUM_8, false }, + { "IO9", GPIO_NUM_9, false }, + { "IO10", GPIO_NUM_10, false }, + { "IO11", GPIO_NUM_11, false }, + { "IO12", GPIO_NUM_12, false }, + { "IO13", GPIO_NUM_13, false }, + { "IO14", GPIO_NUM_14, false }, + { "IO15", GPIO_NUM_15, false }, + { "IO16", GPIO_NUM_16, false }, + { "IO17", GPIO_NUM_17, false }, + { "IO18", GPIO_NUM_18, false }, + { "IO19", GPIO_NUM_19, false }, + { "IO20", GPIO_NUM_20, false }, + { "IO21", GPIO_NUM_21, false }, + { "IO22", GPIO_NUM_22, false }, + { "IO23", GPIO_NUM_23, false }, + { "IO24", GPIO_NUM_24, false }, + { "IO25", GPIO_NUM_25, false }, + { "IO26", GPIO_NUM_26, false }, + { "IO27", GPIO_NUM_27, false }, + { "IO28", GPIO_NUM_28, false }, +}; + +#elif CONFIG_IDF_TARGET_ESP32C61 + +espPinMapping_t g_pins[] = { + { "IO0", GPIO_NUM_0, false }, + { "IO1", GPIO_NUM_1, false }, + { "IO2", GPIO_NUM_2, false }, + { "IO3", GPIO_NUM_3, false }, + { "IO4", GPIO_NUM_4, false }, + { "IO5", GPIO_NUM_5, false }, + { "IO6", GPIO_NUM_6, false }, + { "IO7", GPIO_NUM_7, false }, + { "IO8", GPIO_NUM_8, false }, + { "IO9", GPIO_NUM_9, false }, + { "IO10", GPIO_NUM_10, false }, + { "IO11", GPIO_NUM_11, false }, + { "IO12", GPIO_NUM_12, false }, + { "IO13", GPIO_NUM_13, false }, + { "IO14", GPIO_NUM_14, false }, + { "IO15", GPIO_NUM_15, false }, + { "IO16", GPIO_NUM_16, false }, + { "IO17", GPIO_NUM_17, false }, + { "IO18", GPIO_NUM_18, false }, + { "IO19", GPIO_NUM_19, false }, + { "IO20", GPIO_NUM_20, false }, + { "IO21", GPIO_NUM_21, false }, +}; + +#elif PLATFORM_ESP8266 + +espPinMapping_t g_pins[] = { + { "IO0", GPIO_NUM_0, false }, + { "IO1", GPIO_NUM_1, false }, + { "IO2", GPIO_NUM_2, false }, + { "IO3", GPIO_NUM_3, false }, + { "IO4", GPIO_NUM_4, false }, + { "IO5", GPIO_NUM_5, false }, + { "IO12", GPIO_NUM_12, false }, + { "IO13", GPIO_NUM_13, false }, + { "IO14", GPIO_NUM_14, false }, + { "IO15", GPIO_NUM_15, false }, +}; + #else espPinMapping_t g_pins[] = { }; #endif +#if PLATFORM_ESP8266 +#include "driver/pwm.h" +#define gpio_reset_pin(x) //ESP_ConfigurePin(x, GPIO_MODE_INPUT, false, false, GPIO_INTR_DISABLE) +#define LEDC_MAX_CH 8 +#else +#define LEDC_MAX_CH 6 +#endif + int g_numPins = sizeof(g_pins) / sizeof(g_pins[0]); +const char* HAL_PIN_GetPinNameAlias(int index) +{ + if(index >= g_numPins) + return "error"; + return g_pins[index].name; +} + +void HAL_PIN_SetOutputValue(int index, int iVal) +{ + if(index >= g_numPins) + return; + espPinMapping_t* pin = g_pins + index; + if(pin->pin == GPIO_NUM_NC) return; + gpio_set_level(pin->pin, iVal ? 1 : 0); +} + +int HAL_PIN_ReadDigitalInput(int index) +{ + if(index >= g_numPins) + return 0; + espPinMapping_t* pin = g_pins + index; + if(pin->pin == GPIO_NUM_NC) return 0; + return gpio_get_level(pin->pin); +} + +void ESP_ConfigurePin(gpio_num_t pin, gpio_mode_t mode, bool pup, bool pdown, gpio_int_type_t intr) +{ + gpio_config_t conf = {}; + conf.pin_bit_mask = 1ULL << (uint32_t)pin; + conf.mode = mode; + conf.pull_up_en = pup ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE; + conf.pull_down_en = pdown ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE; + conf.intr_type = intr; + gpio_config(&conf); +} + +void HAL_PIN_Setup_Input_Pullup(int index) +{ + if(index >= g_numPins) + return; + espPinMapping_t* pin = g_pins + index; + if(pin->pin == GPIO_NUM_NC) return; + if(!pin->isConfigured) + { + pin->isConfigured = true; + ESP_ConfigurePin(pin->pin, GPIO_MODE_INPUT, true, false, GPIO_INTR_DISABLE); + return; + } + gpio_set_direction(pin->pin, GPIO_MODE_INPUT); + gpio_set_pull_mode(pin->pin, GPIO_PULLUP_ONLY); +} + +void HAL_PIN_Setup_Input_Pulldown(int index) +{ + if(index >= g_numPins) + return; + espPinMapping_t* pin = g_pins + index; + if(pin->pin == GPIO_NUM_NC) return; + if(!pin->isConfigured) + { + pin->isConfigured = true; + ESP_ConfigurePin(pin->pin, GPIO_MODE_INPUT, false, true, GPIO_INTR_DISABLE); + return; + } + gpio_set_direction(pin->pin, GPIO_MODE_INPUT); + gpio_set_pull_mode(pin->pin, GPIO_PULLDOWN_ONLY); +} + +void HAL_PIN_Setup_Input(int index) +{ + if(index >= g_numPins) + return; + espPinMapping_t* pin = g_pins + index; + if(pin->pin == GPIO_NUM_NC) return; + if(!pin->isConfigured) + { + pin->isConfigured = true; + ESP_ConfigurePin(pin->pin, GPIO_MODE_INPUT, false, false, GPIO_INTR_DISABLE); + return; + } + gpio_set_direction(pin->pin, GPIO_MODE_INPUT); + gpio_set_pull_mode(pin->pin, GPIO_FLOATING); +} + +void HAL_PIN_Setup_Output(int index) +{ + if(index >= g_numPins) + return; + espPinMapping_t* pin = g_pins + index; + if(pin->pin == GPIO_NUM_NC) return; + if(!pin->isConfigured) + { + pin->isConfigured = true; + ESP_ConfigurePin(pin->pin, GPIO_MODE_OUTPUT, true, false, GPIO_INTR_DISABLE); + return; + } + gpio_set_direction(pin->pin, GPIO_MODE_OUTPUT); + gpio_set_pull_mode(pin->pin, GPIO_PULLUP_ONLY); + gpio_set_level(pin->pin, 0); +} + +#if PLATFORM_ESPIDF || PLATFORM_ESP8266 + static ledc_channel_config_t ledc_channel[LEDC_MAX_CH]; +static float obk_ch_value[LEDC_MAX_CH]; static bool g_ledc_init = false; void InitLEDC() @@ -272,7 +457,9 @@ void InitLEDC() .freq_hz = 1000, .speed_mode = LEDC_LOW_SPEED_MODE, .timer_num = LEDC_TIMER_0, +#if PLATFORM_ESPIDF .clk_cfg = SOC_MOD_CLK_RC_FAST, +#endif }; ledc_timer_config(&ledc_timer); for(int i = 0; i < LEDC_MAX_CH; i++) @@ -326,116 +513,19 @@ int PIN_GetPWMIndexForPinIndex(int index) return -1; } -const char* HAL_PIN_GetPinNameAlias(int index) -{ - if(index >= g_numPins) - return "error"; - return g_pins[index].name; -} - int HAL_PIN_CanThisPinBePWM(int index) { if(index >= g_numPins) return 0; espPinMapping_t* pin = g_pins + index; +#if PLATFORM_ESP8266 + // it can be used, but will result in bootloop on reset + if(pin->pin == GPIO_NUM_0) return 0; +#endif if(pin->pin != GPIO_NUM_NC) return 1; else return 0; } -void HAL_PIN_SetOutputValue(int index, int iVal) -{ - if(index >= g_numPins) - return; - espPinMapping_t* pin = g_pins + index; - if(pin->pin == GPIO_NUM_NC) return; - gpio_set_level(pin->pin, iVal ? 1 : 0); -} - -int HAL_PIN_ReadDigitalInput(int index) -{ - if(index >= g_numPins) - return 0; - espPinMapping_t* pin = g_pins + index; - if(pin->pin == GPIO_NUM_NC) return 0; - return gpio_get_level(pin->pin); -} - -void ESP_ConfigurePin(gpio_num_t pin, gpio_mode_t mode, bool pup, bool pdown) -{ - gpio_config_t conf = {}; - conf.pin_bit_mask = 1ULL << (uint32_t)pin; - conf.mode = mode; - conf.pull_up_en = pup ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE; - conf.pull_down_en = pdown ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE; - conf.intr_type = GPIO_INTR_DISABLE; - gpio_config(&conf); -} - -void HAL_PIN_Setup_Input_Pullup(int index) -{ - if(index >= g_numPins) - return; - espPinMapping_t* pin = g_pins + index; - if(pin->pin == GPIO_NUM_NC) return; - if(!pin->isConfigured) - { - pin->isConfigured = true; - ESP_ConfigurePin(pin->pin, GPIO_MODE_INPUT, true, false); - return; - } - gpio_set_direction(pin->pin, GPIO_MODE_INPUT); - gpio_set_pull_mode(pin->pin, GPIO_PULLUP_ONLY); -} - -void HAL_PIN_Setup_Input_Pulldown(int index) -{ - if(index >= g_numPins) - return; - espPinMapping_t* pin = g_pins + index; - if(pin->pin == GPIO_NUM_NC) return; - if(!pin->isConfigured) - { - pin->isConfigured = true; - ESP_ConfigurePin(pin->pin, GPIO_MODE_INPUT, false, true); - return; - } - gpio_set_direction(pin->pin, GPIO_MODE_INPUT); - gpio_set_pull_mode(pin->pin, GPIO_PULLDOWN_ONLY); -} - -void HAL_PIN_Setup_Input(int index) -{ - if(index >= g_numPins) - return; - espPinMapping_t* pin = g_pins + index; - if(pin->pin == GPIO_NUM_NC) return; - if(!pin->isConfigured) - { - pin->isConfigured = true; - ESP_ConfigurePin(pin->pin, GPIO_MODE_INPUT, false, false); - return; - } - gpio_set_direction(pin->pin, GPIO_MODE_INPUT); - gpio_set_pull_mode(pin->pin, GPIO_FLOATING); -} - -void HAL_PIN_Setup_Output(int index) -{ - if(index >= g_numPins) - return; - espPinMapping_t* pin = g_pins + index; - if(pin->pin == GPIO_NUM_NC) return; - if(!pin->isConfigured) - { - pin->isConfigured = true; - ESP_ConfigurePin(pin->pin, GPIO_MODE_OUTPUT, true, false); - return; - } - gpio_set_direction(pin->pin, GPIO_MODE_OUTPUT); - gpio_set_pull_mode(pin->pin, GPIO_PULLUP_ONLY); - gpio_set_level(pin->pin, 0); -} - void HAL_PIN_PWM_Stop(int index) { if(index >= g_numPins) @@ -462,6 +552,12 @@ void HAL_PIN_PWM_Start(int index, int freq) { ledc_channel[freecha].gpio_num = pin->pin; ledc_channel_config(&ledc_channel[freecha]); +#if PLATFORM_ESP8266 + // will bootloop without delay + delay_ms(100); + pwm_deinit(); + ledc_fade_func_install(0); +#endif ADDLOG_INFO(LOG_FEATURE_PINS, "init ledc ch %i pin %i\n", freecha, pin->pin); } else @@ -478,11 +574,15 @@ void HAL_PIN_PWM_Update(int index, float value) int ch = GetLedcChannelForPin(pin->pin); if(ch >= 0) { - uint32_t curduty = ledc_get_duty(LEDC_LOW_SPEED_MODE, ch); +#if PLATFORM_ESPIDF uint32_t propduty = value * 81.91; - if(propduty != curduty) - { - ledc_set_duty(LEDC_LOW_SPEED_MODE, ch, value * 81.91); +#else + uint32_t propduty = value * 81.96; +#endif + if(value != obk_ch_value[ch]) + { + obk_ch_value[ch] = value; + ledc_set_duty(LEDC_LOW_SPEED_MODE, ch, propduty); ledc_update_duty(LEDC_LOW_SPEED_MODE, ch); if(value == 100.0f) { @@ -496,6 +596,8 @@ void HAL_PIN_PWM_Update(int index, float value) } } +#endif + unsigned int HAL_GetGPIOPin(int index) { return index; diff --git a/src/hal/espidf/hal_uart_espidf.c b/src/hal/espidf/hal_uart_espidf.c index 4d3cba75e..58b3521fd 100644 --- a/src/hal/espidf/hal_uart_espidf.c +++ b/src/hal/espidf/hal_uart_espidf.c @@ -1,4 +1,4 @@ -#ifdef PLATFORM_ESPIDF +#if PLATFORM_ESPIDF || PLATFORM_ESP8266 #include "../hal_uart.h" #include "../../new_pins.h" @@ -21,6 +21,9 @@ #endif uart_port_t uartnum = UART_NUM_0; + +#if 0//PLATFORM_ESPIDF + static QueueHandle_t uart_queue; uint8_t* data = NULL; @@ -48,6 +51,7 @@ static void uart_event_task(void* pvParameters) xQueueReset(uart_queue); break; default: + addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "uart event type: %d", event.type); break; } } @@ -57,6 +61,43 @@ static void uart_event_task(void* pvParameters) vTaskDelete(NULL); } +#else + +//#include "esp8266/uart_register.h" +//#include "esp8266/uart_struct.h" +//static DRAM_ATTR uart_dev_t* const UART[UART_NUM_MAX] = { &uart0, &uart1 }; +// +//static void IRAM_ATTR uart_intr_handle(void* arg) +//{ +// uart_port_t uartn = *((uart_port_t*)arg); +// uint16_t status = UART[uartn]->int_st.val; +// uint16_t rx_fifo_len = UART[uartn]->status.rxfifo_cnt; +// while(rx_fifo_len) +// { +// UART_AppendByteToReceiveRingBuffer(UART[uartn]->fifo.rw_byte); +// rx_fifo_len--; +// } +// uart_clear_intr_status(uartnum, UART_RXFIFO_FULL_INT_CLR | UART_RXFIFO_TOUT_INT_CLR); +//} + +#endif + +static void uart_event_task(void* pvParameters) +{ + uint8_t* data = (uint8_t*)malloc(512); + while(1) + { + int len = uart_read_bytes(uartnum, data, 512, 20 / portTICK_RATE_MS); + if(len) + { + for(int i = 0; i < len; i++) + { + UART_AppendByteToReceiveRingBuffer(data[i]); + } + } + } +} + void HAL_UART_SendByte(byte b) { uart_write_bytes(uartnum, &b, 1); @@ -85,11 +126,15 @@ int HAL_UART_Init(int baud, int parity, bool hwflowc) .data_bits = UART_DATA_8_BITS, .parity = parity > 0 ? parity + 1 : parity, .stop_bits = UART_STOP_BITS_1, - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .flow_ctrl = hwflowc == false ? UART_HW_FLOWCTRL_DISABLE : UART_HW_FLOWCTRL_CTS_RTS, +#if PLATFORM_ESPIDF .source_clk = UART_SCLK_DEFAULT, +#endif }; - uart_driver_install(uartnum, 512, 0, 20, &uart_queue, 0); uart_param_config(uartnum, &uart_config); + uart_driver_install(uartnum, 512, 0, 0, NULL, 0); + uart_enable_rx_intr(uartnum); +#if 0//PLATFORM_ESPIDF if(uartnum == UART_NUM_0) { uart_set_pin(uartnum, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); @@ -100,10 +145,13 @@ int HAL_UART_Init(int baud, int parity, bool hwflowc) } if(data == NULL) { - data = (uint8_t*)malloc(512); + //data = (uint8_t*)malloc(512); xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 16, NULL); - uart_enable_rx_intr(uartnum); } +#else + //uart_isr_register(uartnum, uart_intr_handle, &uartnum); +#endif + xTaskCreate(uart_event_task, "uart_event_task", 1024, NULL, 16, NULL); return 1; } diff --git a/src/hal/espidf/hal_wifi_espidf.c b/src/hal/espidf/hal_wifi_espidf.c index 80f0bcc8a..7f0361ca3 100644 --- a/src/hal/espidf/hal_wifi_espidf.c +++ b/src/hal/espidf/hal_wifi_espidf.c @@ -1,4 +1,4 @@ -#ifdef PLATFORM_ESPIDF +#if PLATFORM_ESPIDF || PLATFORM_ESP8266 #include "../../new_cfg.h" #include "../../logging/logging.h" @@ -10,48 +10,66 @@ #include "esp_system.h" #include "esp_wifi.h" #include "esp_event.h" -#include "esp_mac.h" #include "esp_log.h" #include "esp_netif.h" -#include "esp_netif_net_stack.h" #include "lwip/err.h" #include "lwip/sys.h" +#include "dhcpserver/dhcpserver.h" + +#if PLATFORM_ESPIDF +#include "esp_mac.h" +#include "esp_netif_net_stack.h" +static esp_netif_t* sta_netif = NULL; +static esp_netif_t* ap_netif = NULL; +#else +#include "tcpip_adapter.h" +#define ESP_MAC_BASE ESP_MAC_WIFI_STA +#define esp_netif_ip_info_t tcpip_adapter_ip_info_t +#define esp_event_handler_instance_t esp_event_handler_t +#define esp_event_handler_instance_register(a,b,c,d,e) esp_event_handler_register(a,b,c,e) +#define esp_netif_t tcpip_adapter_if_t +#define esp_netif_set_hostname tcpip_adapter_set_hostname +#define esp_netif_get_ip_info tcpip_adapter_get_ip_info +#define esp_netif_create_default_wifi_ap() TCPIP_ADAPTER_IF_AP +#define esp_netif_create_default_wifi_sta() TCPIP_ADAPTER_IF_STA +#define esp_netif_destroy(...) +static tcpip_adapter_if_t sta_netif = TCPIP_ADAPTER_IF_STA; +static tcpip_adapter_if_t ap_netif = TCPIP_ADAPTER_IF_AP; +#endif static void (*g_wifiStatusCallback)(int code); static int g_bOpenAccessPointMode = 0; static esp_netif_ip_info_t g_ip_info; -static esp_netif_t* sta_netif = NULL; -static esp_netif_t* ap_netif = NULL; -static char g_ip[16]; -static char g_gw[16]; -static char g_ms[16]; +esp_event_handler_instance_t instance_any_id, instance_got_ip; +bool handlers_registered = false; // This must return correct IP for both SOFT_AP and STATION modes, // because, for example, javascript control panel requires it const char* HAL_GetMyIPString() { - sprintf(g_ip, IPSTR, IP2STR(&g_ip_info.ip)); - return g_ip; + return ipaddr_ntoa((ip4_addr_t*)&g_ip_info.ip); } const char* HAL_GetMyGatewayString() { - sprintf(g_gw, IPSTR, IP2STR(&g_ip_info.gw)); - return g_gw; + return ipaddr_ntoa((ip4_addr_t*)&g_ip_info.gw); } const char* HAL_GetMyDNSString() { +#if PLATFORM_ESP8266 + ip4_addr_t dns = dhcps_dns_getserver(); + return ipaddr_ntoa(&dns); +#else return "error"; +#endif } const char* HAL_GetMyMaskString() { - sprintf(g_ms, IPSTR, IP2STR(&g_ip_info.netmask)); - return g_ms; + return ipaddr_ntoa((ip4_addr_t*)&g_ip_info.netmask); } - int WiFI_SetMacAddress(char* mac) { return 0; @@ -73,13 +91,14 @@ const char* HAL_GetMACStr(char* macstr) void HAL_PrintNetworkInfo() { uint8_t mac[6]; - esp_read_mac(mac, ESP_MAC_BASE); + WiFI_GetMacAddress((char*)&mac); bk_printf("+--------------- net device info ------------+\r\n"); bk_printf("|netif type : %-16s |\r\n", g_bOpenAccessPointMode == 0 ? "STA" : "AP"); + bk_printf("|netif rssi = %-16i |\r\n", HAL_GetWifiStrength()); bk_printf("|netif ip = %-16s |\r\n", HAL_GetMyIPString()); bk_printf("|netif mask = %-16s |\r\n", HAL_GetMyMaskString()); bk_printf("|netif gateway = %-16s |\r\n", HAL_GetMyGatewayString()); - bk_printf("|netif mac : [%02X:%02X:%02X:%02X:%02X:%02X] %-7s |\r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ""); + bk_printf("|netif mac : ["MACSTR"] %-6s |\r\n", MAC2STR(mac), ""); bk_printf("+--------------------------------------------+\r\n"); } @@ -135,17 +154,20 @@ void event_handler(void* arg, esp_event_base_t event_base, void HAL_ConnectToWiFi(const char* oob_ssid, const char* connect_key, obkStaticIP_t* ip) { +#if PLATFORM_ESPIDF if(sta_netif != NULL) +#else + if(1) +#endif { esp_wifi_stop(); esp_netif_destroy(sta_netif); esp_wifi_deinit(); - delay_ms(10); + delay_ms(50); } - else - { - esp_event_handler_instance_t instance_any_id, instance_got_ip; + if(!handlers_registered) + { esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, @@ -156,6 +178,7 @@ void HAL_ConnectToWiFi(const char* oob_ssid, const char* connect_key, obkStaticI &event_handler, NULL, &instance_got_ip); + handlers_registered = true; } sta_netif = esp_netif_create_default_wifi_sta(); @@ -168,17 +191,17 @@ void HAL_ConnectToWiFi(const char* oob_ssid, const char* connect_key, obkStaticI { ADDLOG_ERROR(LOG_FEATURE_MAIN, "WiFi saved ssid/pass != current, resetting"); memset(&wifi_config.sta, 0, sizeof(wifi_sta_config_t)); - wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + //wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; strncpy((char*)wifi_config.sta.ssid, (char*)oob_ssid, 32); strncpy((char*)wifi_config.sta.password, (char*)connect_key, 64); } - esp_netif_set_hostname(sta_netif, CFG_GetDeviceName()); - - esp_wifi_set_config(WIFI_IF_STA, &wifi_config); esp_wifi_set_mode(WIFI_MODE_STA); + esp_wifi_set_config(WIFI_IF_STA, &wifi_config); esp_wifi_start(); + + esp_netif_set_hostname(sta_netif, CFG_GetDeviceName()); } void HAL_DisconnectFromWifi() @@ -190,13 +213,11 @@ int HAL_SetupWiFiOpenAccessPoint(const char* ssid) { g_bOpenAccessPointMode = 1; ap_netif = esp_netif_create_default_wifi_ap(); - esp_netif_create_default_wifi_sta(); + sta_netif = esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); cfg.nvs_enable = false; esp_wifi_init(&cfg); - esp_event_handler_instance_t instance_any_id; - esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, @@ -211,10 +232,12 @@ int HAL_SetupWiFiOpenAccessPoint(const char* ssid) .channel = 1, .max_connection = 1, .authmode = WIFI_AUTH_OPEN, +#if !PLATFORM_ESP8266 .pmf_cfg = { .required = false, }, +#endif }, }; diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c index c6d1016bb..fb02b0714 100644 --- a/src/httpserver/http_fns.c +++ b/src/httpserver/http_fns.c @@ -53,7 +53,7 @@ extern hal_reset_reason_t reset_reason; #endif SemaphoreHandle_t scan_hdl; -#elif defined(PLATFORM_ESPIDF) +#elif defined(PLATFORM_ESPIDF) || PLATFORM_ESP8266 #include "esp_wifi.h" #include "esp_system.h" #elif defined(PLATFORM_BK7231T) @@ -1398,7 +1398,7 @@ int http_fn_cfg_wifi(http_request_t* request) { hprintf255(request, "[%i/%i] SSID: %s, Channel: %i, Signal %i
", i + 1, (int)num, ar[i].ssid, ar[i].channel, ar[i].rssi); } tuya_os_adapt_wifi_release_ap(ar); -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 // doesn't work in ap mode, only sta/apsta uint16_t ap_count = 0, number = 30; wifi_ap_record_t ap_info[number]; @@ -3178,7 +3178,7 @@ void OTA_RequestDownloadFromHTTP(const char* s) { #elif PLATFORM_LN882H -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 #elif PLATFORM_TR6260 #elif PLATFORM_REALTEK #elif PLATFORM_ECR6600 diff --git a/src/httpserver/new_tcp_server.c b/src/httpserver/new_tcp_server.c index d99b283e8..8f13edea5 100644 --- a/src/httpserver/new_tcp_server.c +++ b/src/httpserver/new_tcp_server.c @@ -8,7 +8,12 @@ #include "lwip/inet.h" #include "../logging/logging.h" #include "new_http.h" - +#if PLATFORM_ESP8266 +#define MAX_SOCKETS_TCP 2 +#define REPLY_BUFFER_SIZE 1024 +#define INCOMING_BUFFER_SIZE 1024 +#define HTTP_CLIENT_STACK_SIZE 4096 +#endif #ifndef MAX_SOCKETS_TCP #define MAX_SOCKETS_TCP MEMP_NUM_TCP_PCB #endif @@ -16,11 +21,17 @@ void HTTPServer_Start(); #define HTTP_SERVER_PORT 80 -#define REPLY_BUFFER_SIZE 2048 -#define INCOMING_BUFFER_SIZE 2048 #define INVALID_SOCK -1 -#define HTTP_CLIENT_STACK_SIZE 8192 +#ifndef REPLY_BUFFER_SIZE +#define REPLY_BUFFER_SIZE 2048 +#endif +#ifndef INCOMING_BUFFER_SIZE +#define INCOMING_BUFFER_SIZE 2048 +#endif +#ifndef HTTP_CLIENT_STACK_SIZE +#define HTTP_CLIENT_STACK_SIZE 8192 +#endif typedef struct { int fd; diff --git a/src/httpserver/rest_interface.c b/src/httpserver/rest_interface.c index 01ed4390d..12efafc94 100644 --- a/src/httpserver/rest_interface.c +++ b/src/httpserver/rest_interface.c @@ -38,7 +38,7 @@ uint32_t flash_read(uint32_t flash, uint32_t addr, void* buf, uint32_t size); #include "hal/hal_flash.h" #include "flash_partition_table.h" -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 #include "esp_system.h" #include "esp_ota_ops.h" @@ -48,8 +48,16 @@ uint32_t flash_read(uint32_t flash, uint32_t addr, void* buf, uint32_t size); #include "nvs.h" #include "nvs_flash.h" #include "esp_wifi.h" +#if PLATFORM_ESPIDF +#include "esp_flash.h" #include "esp_pm.h" -#include "esp_flash_spi_init.h" +#else +#include "esp_image_format.h" +#include "spi_flash.h" +#define esp_flash_read(a,b,c,d) spi_flash_read(c,b,d) +#define OTA_WITH_SEQUENTIAL_WRITES OTA_SIZE_UNKNOWN +#define esp_ota_abort esp_ota_end +#endif #elif PLATFORM_REALTEK @@ -309,7 +317,7 @@ static int http_rest_post(http_request_t* request) { return http_rest_post_flash(request, -1, -1); #elif PLATFORM_LN882H return http_rest_post_flash(request, -1, -1); -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 return http_rest_post_flash(request, -1, -1); #elif PLATFORM_REALTEK return http_rest_post_flash(request, 0, -1); @@ -1603,7 +1611,6 @@ static int http_rest_post_flash(http_request_t* request, int startaddr, int maxa int towrite = request->bodylen; char* writebuf = request->bodystart; int writelen = request->bodylen; - int fsize = 0; ADDLOG_DEBUG(LOG_FEATURE_OTA, "OTA post len %d", request->contentLength); @@ -2141,7 +2148,7 @@ static int http_rest_post_flash(http_request_t* request, int startaddr, int maxa } -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 ADDLOG_DEBUG(LOG_FEATURE_OTA, "Ota start!\r\n"); esp_err_t err; @@ -2151,7 +2158,7 @@ static int http_rest_post_flash(http_request_t* request, int startaddr, int maxa update_partition = esp_ota_get_next_update_partition(NULL); if(request->contentLength >= 0) { - fsize = towrite = request->contentLength; + towrite = request->contentLength; } esp_wifi_set_ps(WIFI_PS_NONE); @@ -2197,7 +2204,7 @@ static int http_rest_post_flash(http_request_t* request, int startaddr, int maxa return -1; } - ADDLOG_DEBUG(LOG_FEATURE_OTA, "OTA in progress: %.1f%%", (100 - ((float)towrite / fsize) * 100)); + ADDLOG_DEBUG(LOG_FEATURE_OTA, "Writelen %i at %i", writelen, total); total += writelen; startaddr += writelen; towrite -= writelen; @@ -3289,7 +3296,7 @@ static int http_rest_get_flash(http_request_t* request, int startaddr, int len) res = tls_fls_read(startaddr, (uint8_t*)buffer, readlen); #elif PLATFORM_LN882H res = hal_flash_read(startaddr, readlen, (uint8_t *)buffer); -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 res = esp_flash_read(NULL, (void*)buffer, startaddr, readlen); #elif PLATFORM_TR6260 res = hal_spiflash_read(startaddr, (uint8_t*)buffer, readlen); diff --git a/src/littlefs/lfs_util.h b/src/littlefs/lfs_util.h index 691344aee..bf862e27c 100644 --- a/src/littlefs/lfs_util.h +++ b/src/littlefs/lfs_util.h @@ -40,7 +40,7 @@ #if PLATFORM_BEKEN #include "mem_pub.h" -#elif PLATFORM_BL602 || PLATFORM_LN882H || PLATFORM_ESPIDF || PLATFORM_XRADIO +#elif PLATFORM_BL602 || PLATFORM_LN882H || PLATFORM_ESPIDF || PLATFORM_XRADIO || PLATFORM_ESP8266 #define os_free free #define os_malloc malloc #elif PLATFORM_REALTEK || PLATFORM_W800 || PLATFORM_W600 diff --git a/src/littlefs/our_lfs.c b/src/littlefs/our_lfs.c index 240b9cdc9..9babea298 100644 --- a/src/littlefs/our_lfs.c +++ b/src/littlefs/our_lfs.c @@ -34,7 +34,7 @@ bool lfs_init = false; #include "hal/hal_flash.h" #include "flash_partition_table.h" -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 #include "esp_partition.h" esp_partition_t* esplfs = NULL; @@ -139,7 +139,7 @@ static commandResult_t CMD_LFS_Size(const void *context, const char *cmd, const return CMD_RES_OK; } -#if PLATFORM_ESPIDF || PLATFORM_RTL8720D || PLATFORM_BL602 +#if PLATFORM_ESPIDF || PLATFORM_RTL8720D || PLATFORM_BL602 || PLATFORM_ESP8266 ADDLOG_ERROR(LOG_FEATURE_CMD, PLATFORM_MCU_NAME" doesn't support changing LFS size"); return CMD_RES_ERROR; #endif @@ -253,7 +253,7 @@ static commandResult_t CMD_LFS_Format(const void *context, const char *cmd, cons break; } -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 if(esplfs == NULL) { @@ -502,7 +502,7 @@ void init_lfs(int create){ newsize = lfs_info.size; CFG_SetLFS_Size(lfs_info.size); -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 if(esplfs == NULL) { @@ -749,7 +749,7 @@ static int lfs_erase(const struct lfs_config *c, lfs_block_t block){ return res; } -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 static int lfs_read(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size) diff --git a/src/littlefs/our_lfs.h b/src/littlefs/our_lfs.h index bc8db182b..76a40e6c6 100644 --- a/src/littlefs/our_lfs.h +++ b/src/littlefs/our_lfs.h @@ -63,7 +63,7 @@ // end media partition #define LFS_BLOCKS_END 0x001DD000 -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 #define LFS_BLOCKS_START 0x0 #define LFS_BLOCKS_START_MIN 0x0 diff --git a/src/mqtt/new_mqtt.c b/src/mqtt/new_mqtt.c index b881f8b5c..8465160c0 100644 --- a/src/mqtt/new_mqtt.c +++ b/src/mqtt/new_mqtt.c @@ -1756,7 +1756,7 @@ static BENCHMARK_TEST_INFO* info = NULL; #if WINDOWS #elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_ESPIDF || PLATFORM_TR6260 \ - || PLATFORM_REALTEK || PLATFORM_ECR6600 + || PLATFORM_REALTEK || PLATFORM_ECR6600 || PLATFORM_ESP8266 static void mqtt_timer_thread(void* param) { while (1) @@ -1797,7 +1797,7 @@ commandResult_t MQTT_StartMQTTTestThread(const void* context, const char* cmd, c #if WINDOWS #elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_ESPIDF || PLATFORM_TR6260 \ - || PLATFORM_REALTEK || PLATFORM_ECR6600 + || PLATFORM_REALTEK || PLATFORM_ECR6600 || PLATFORM_ESP8266 xTaskCreate(mqtt_timer_thread, "mqtt", 1024, (void*)info, 15, NULL); #elif PLATFORM_XRADIO || PLATFORM_LN882H OS_TimerSetInvalid(&timer); diff --git a/src/new_common.h b/src/new_common.h index dd9fae099..d908911d4 100644 --- a/src/new_common.h +++ b/src/new_common.h @@ -129,6 +129,10 @@ typedef long BaseType_t; #define PLATFORM_MCU_NAME "ESP32S2" #elif CONFIG_IDF_TARGET_ESP32S3 #define PLATFORM_MCU_NAME "ESP32S3" +#elif CONFIG_IDF_TARGET_ESP32C5 +#define PLATFORM_MCU_NAME "ESP32C5" +#elif CONFIG_IDF_TARGET_ESP32C61 +#define PLATFORM_MCU_NAME "ESP32C61" #else #define PLATFORM_MCU_NAME MANUFACTURER #endif @@ -163,6 +167,11 @@ typedef long BaseType_t; #define DEVICENAME_PREFIX_SHORT "ecr6600" #define PLATFORM_MCU_NAME "ECR6600" #define MANUFACTURER "ESWIN" +#elif PLATFORM_ESP8266 +#define DEVICENAME_PREFIX_FULL "OpenESP8266" +#define DEVICENAME_PREFIX_SHORT "esp8266" +#define PLATFORM_MCU_NAME "ESP8266" +#define MANUFACTURER "Espressif" #else #error "You must define a platform.." This platform is not supported, error! @@ -214,6 +223,8 @@ This platform is not supported, error! #define USER_SW_VER "BK7252N_Test" #elif PLATFORM_ECR6600 #define USER_SW_VER "ECR6600_Test" +#elif PLATFORM_ESP8266 +#define USER_SW_VER "ESP8266_Test" #else #warning "USER_SW_VER undefined" #define USER_SW_VER "unknown" @@ -515,7 +526,7 @@ OSStatus rtos_suspend_thread(beken_thread_t* thread); #define OBK_OTA_EXTENSION ".bin" #define OBK_OTA_NAME_EXTENSION "_OTA" -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 #include #include "esp_timer.h" @@ -526,9 +537,9 @@ OSStatus rtos_suspend_thread(beken_thread_t* thread); #define os_free free #define os_malloc malloc -//#define bk_printf printf +#define bk_printf printf -#define bk_printf(...) ESP_LOGI("OpenBeken", __VA_ARGS__); +//#define bk_printf(...) ESP_LOGI("OpenBeken", __VA_ARGS__); #define kNoErr 0 //! No error occurred. #define rtos_delay_milliseconds sys_delay_ms @@ -558,6 +569,10 @@ OSStatus rtos_suspend_thread(beken_thread_t* thread); #define OBK_OTA_EXTENSION ".img" +#if PLATFORM_ESP8266 +#define xPortGetFreeHeapSize() esp_get_free_heap_size() +#endif + #elif PLATFORM_TR6260 #include "FreeRTOS.h" @@ -831,7 +846,8 @@ int strcpy_safe_checkForChanges(char *tg, const char *src, int tgMaxLen); void urldecode2_safe(char *dst, const char *srcin, int maxDstLen); int strIsInteger(const char *s); -#if !defined(PLATFORM_ESPIDF) && !defined(PLATFORM_TR6260) && !defined(PLATFORM_ECR6600) && !defined(PLATFORM_BL602) +#if !defined(PLATFORM_ESPIDF) && !defined(PLATFORM_TR6260) && !defined(PLATFORM_ECR6600) && !defined(PLATFORM_BL602) && \ + !defined(PLATFORM_ESP8266) const char* strcasestr(const char* str1, const char* str2); #endif @@ -865,7 +881,7 @@ int LWIP_GetMaxSockets(); int LWIP_GetActiveSockets(); #ifndef LINUX -#ifndef PLATFORM_ESPIDF +#if !PLATFORM_ESPIDF && !PLATFORM_ESP8266 //delay function do 10*r nops, because rtos_delay_milliseconds is too much void usleep(int r); #endif diff --git a/src/new_pins.c b/src/new_pins.c index 1cdbafa0b..c18859d00 100644 --- a/src/new_pins.c +++ b/src/new_pins.c @@ -20,8 +20,10 @@ #ifdef PLATFORM_BEKEN #include #include "driver/drv_ir.h" -#elif PLATFORM_ESPIDF +#elif PLATFORM_ESPIDF || PLATFORM_ESP8266 +#include "hal/espidf/hal_pinmap_espidf.h" #include "esp_sleep.h" +#include "esp_wifi.h" #elif PLATFORM_XRADIO #undef HAL_ADC_Init #include "hal/xradio/hal_pinmap_xradio.h" diff --git a/src/new_pins.h b/src/new_pins.h index 47d181bf7..ef3eca8e8 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -1041,9 +1041,15 @@ typedef enum channelType_e { #define PLATFORM_GPIO_MAX 31 #elif CONFIG_IDF_TARGET_ESP32 #define PLATFORM_GPIO_MAX 40 +#elif CONFIG_IDF_TARGET_ESP32C5 +#define PLATFORM_GPIO_MAX 29 +#elif CONFIG_IDF_TARGET_ESP32C61 +#define PLATFORM_GPIO_MAX 22 #else #define PLATFORM_GPIO_MAX 0 #endif +#elif PLATFORM_ESP8266 +#define PLATFORM_GPIO_MAX 10 #elif PLATFORM_TR6260 #define PLATFORM_GPIO_MAX 25 #elif PLATFORM_RTL87X0C diff --git a/src/obk_config.h b/src/obk_config.h index a75cf31a6..d37981f94 100644 --- a/src/obk_config.h +++ b/src/obk_config.h @@ -116,7 +116,6 @@ #endif - #define ENABLE_DRIVER_TCL 1 #define ENABLE_DRIVER_PIR 1 #define ENABLE_HA_DISCOVERY 1 @@ -177,7 +176,6 @@ #elif PLATFORM_BL602 - //#define ENABLE_SEND_POSTANDGET 1 #define ENABLE_HA_DISCOVERY 1 // I have enabled drivers on BL602 @@ -326,7 +324,6 @@ #elif PLATFORM_LN882H - //#define ENABLE_SEND_POSTANDGET 1 #define ENABLE_HA_DISCOVERY 1 #define ENABLE_MQTT 1 @@ -352,9 +349,7 @@ #elif PLATFORM_ESPIDF - - -#define ENABLE_SEND_POSTANDGET 1 +#define ENABLE_SEND_POSTANDGET 1 #define ENABLE_HA_DISCOVERY 1 #define ENABLE_MQTT 1 #define ENABLE_I2C 1 @@ -389,7 +384,6 @@ #elif PLATFORM_TR6260 - //#define ENABLE_SEND_POSTANDGET 1 #define ENABLE_HA_DISCOVERY 1 #define ENABLE_MQTT 1 @@ -410,7 +404,7 @@ #elif PLATFORM_REALTEK -#define ENABLE_SEND_POSTANDGET 1 +#define ENABLE_SEND_POSTANDGET 1 #define ENABLE_HA_DISCOVERY 1 #define ENABLE_MQTT 1 #define NO_CHIP_TEMPERATURE 1 @@ -461,7 +455,6 @@ #define ENABLE_DRIVER_SSDP 1 #define ENABLE_OBK_SCRIPTING 1 #define ENABLE_ADVANCED_CHANNELTYPES_DISCOVERY 1 -#define ENABLE_DRIVER_SSDP 1 #define ENABLE_TASMOTA_JSON 1 #define ENABLE_TASMOTADEVICEGROUPS 1 #define ENABLE_NTP 1 @@ -471,6 +464,33 @@ #define ENABLE_DRIVER_BL0937 1 #define ENABLE_OBK_BERRY 1 +#elif PLATFORM_ESP8266 + +#define ENABLE_SEND_POSTANDGET 1 +#define NO_CHIP_TEMPERATURE 1 +#define ENABLE_HA_DISCOVERY 1 +#define ENABLE_MQTT 1 +#define ENABLE_LITTLEFS 1 +#define NEW_TCP_SERVER 1 +#define ENABLE_EXPAND_CONSTANT 1 +#define ENABLE_ADVANCED_CHANNELTYPES_DISCOVERY 1 +#define ENABLE_OBK_SCRIPTING 1 +//#define ENABLE_DRIVER_BL0942 1 +#define ENABLE_DRIVER_BL0937 1 +#define ENABLE_TASMOTA_JSON 1 +#define ENABLE_TASMOTADEVICEGROUPS 1 +#define ENABLE_I2C 1 +#define ENABLE_DRIVER_AHT2X 1 +#define ENABLE_NTP 1 +#define ENABLE_DRIVER_LED 1 +#define ENABLE_DRIVER_WEMO 1 +#define ENABLE_DRIVER_SSDP 1 +#define ENABLE_DRIVER_TUYAMCU 1 +#define ENABLE_DRIVER_DS1820 1 +#define ENABLE_DRIVER_BMPI2C 1 + +//#define ENABLE_OBK_BERRY 1 + #else //#error "Platform not defined" diff --git a/src/user_main.c b/src/user_main.c index e6a7b7b88..097a71b6a 100644 --- a/src/user_main.c +++ b/src/user_main.c @@ -160,7 +160,7 @@ void extended_app_waiting_for_launch2(void) { #endif -#if defined(PLATFORM_LN882H) || defined(PLATFORM_ESPIDF) +#if defined(PLATFORM_LN882H) || defined(PLATFORM_ESPIDF) || defined(PLATFORM_ESP8266) int LWIP_GetMaxSockets() { return 0; @@ -172,7 +172,7 @@ int LWIP_GetActiveSockets() { #if PLATFORM_BL602 || PLATFORM_W800 || PLATFORM_W600 || PLATFORM_LN882H \ || PLATFORM_ESPIDF || PLATFORM_TR6260 || PLATFORM_REALTEK || PLATFORM_ECR6600 \ - || PLATFORM_XRADIO + || PLATFORM_XRADIO || PLATFORM_ESP8266 OSStatus rtos_create_thread(beken_thread_t* thread, uint8_t priority, const char* name, @@ -530,7 +530,7 @@ bool Main_HasFastConnect() { } return false; } -#if PLATFORM_LN882H || PLATFORM_ESPIDF +#if PLATFORM_LN882H || PLATFORM_ESPIDF || PLATFORM_ESP8266 // Quick hack to display LN-only temperature, // we may improve it in the future extern float g_wifi_temperature; @@ -614,7 +614,7 @@ void Main_OnEverySecond() #ifndef OBK_DISABLE_ALL_DRIVERS DRV_OnEverySecond(); #if defined(PLATFORM_BEKEN) || defined(WINDOWS) || defined(PLATFORM_BL602) || defined(PLATFORM_ESPIDF) \ - || defined (PLATFORM_RTL87X0C) + || defined (PLATFORM_RTL87X0C) || PLATFORM_ESP8266 UART_RunEverySecond(); #endif #endif @@ -927,7 +927,7 @@ void QuickTick(void* param) #if defined(PLATFORM_BEKEN) || defined(WINDOWS) g_timeMs = rtos_get_time(); -#elif defined (PLATFORM_ESPIDF) +#elif defined(PLATFORM_ESPIDF) //|| defined(PLATFORM_ESP8266) g_timeMs = esp_timer_get_time() / 1000; #else g_timeMs += QUICK_TMR_DURATION; @@ -992,13 +992,18 @@ void QuickTick(void* param) } - +#if PLATFORM_ESP8266 || PLATFORM_ESPIDF +#define QT_STACK_SIZE 2048 +#else +#define QT_STACK_SIZE 1024 +#endif //////////////////////////////////////////////////////// // this is the bit which runs the quick tick timer #if WINDOWS -#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_TR6260 || defined(PLATFORM_REALTEK) || PLATFORM_ECR6600 +#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_TR6260 || defined(PLATFORM_REALTEK) || PLATFORM_ECR6600 \ + || PLATFORM_ESP8266 || PLATFORM_ESPIDF void quick_timer_thread(void* param) { while (1) { @@ -1006,8 +1011,6 @@ void quick_timer_thread(void* param) QuickTick(0); } } -#elif PLATFORM_ESPIDF -esp_timer_handle_t g_quick_timer; #elif PLATFORM_XRADIO || PLATFORM_LN882H OS_Timer_t g_quick_timer; #else @@ -1017,17 +1020,9 @@ void QuickTick_StartThread(void) { #if WINDOWS -#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_TR6260 || defined(PLATFORM_REALTEK) || PLATFORM_ECR6600 - xTaskCreate(quick_timer_thread, "quick", 1024, NULL, 15, NULL); -#elif PLATFORM_ESPIDF - const esp_timer_create_args_t g_quick_timer_args = - { - .callback = &QuickTick, - .name = "quick" - }; - - esp_timer_create(&g_quick_timer_args, &g_quick_timer); - esp_timer_start_periodic(g_quick_timer, QUICK_TMR_DURATION * 1000); +#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_TR6260 || defined(PLATFORM_REALTEK) || PLATFORM_ECR6600 \ + || PLATFORM_ESP8266 || PLATFORM_ESPIDF + xTaskCreate(quick_timer_thread, "quick", QT_STACK_SIZE, NULL, 15, NULL); #elif PLATFORM_XRADIO || PLATFORM_LN882H OS_TimerSetInvalid(&g_quick_timer);