diff --git a/.travis.yml b/.travis.yml index 6410b55..0b8a459 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ addons: before_install: # Save path to the git respository - PROJECT_PATH=$(pwd) + - CI_COMMIT_SHA=$(git rev-parse HEAD) install: # Install ESP32 toochain following steps as desribed @@ -24,31 +25,35 @@ install: - mkdir -p ~/esp - cd ~/esp # Download binary toolchain for the ESP32 - - wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-61-gab8375a-5.2.0.tar.gz - - tar -xzf xtensa-esp32-elf-linux64-1.22.0-61-gab8375a-5.2.0.tar.gz - # Make xtensa-esp32-elf available for all terminal sessions - - export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin + - wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz + - tar -xzf xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz # Get ESP-IDF from github - git clone --recursive https://github.com/espressif/esp-idf.git # Set the path to ESP-IDF directory - export IDF_PATH=~/esp/esp-idf + - python -m pip install --user -r $IDF_PATH/requirements.txt + # Setup build tool: xtensa-esp32-elf and idf.py + - export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin:$IDF_PATH/tools script: - # Go back to the git repository - - cd $PROJECT_PATH/examples/mqtt_tcp - # Update configuration so that kconfig doesn't start interactive mode - - make defconfig - # Build project from the git repository - - make -j4 - - cd $PROJECT_PATH/examples/mqtt_ssl - - make defconfig - - make -j4 - - cd $PROJECT_PATH/examples/mqtt_ws - - make defconfig - - make -j4 - - cd $PROJECT_PATH/examples/mqtt_wss - - make defconfig - - make -j4 - - cd $PROJECT_PATH/examples/emitter-client + # Legacy build with IDF < 3.2 + - cd $IDF_PATH && git checkout --recurse-submodules v3.1 + - cd $PROJECT_PATH + - ./modify_for_legacy_idf.sh || true + - cd $PROJECT_PATH/examples/tcp - make defconfig - make -j4 + # Master build with latest IDF + - cd $IDF_PATH && git checkout --recurse-submodules master + - cd $IDF_PATH/components/mqtt/esp-mqtt + - git remote add local $PROJECT_PATH/.git + - git fetch local + - git checkout $CI_COMMIT_SHA + - cd $IDF_PATH/examples/protocols/mqtt/tcp + - idf.py build + - cd $IDF_PATH/examples/protocols/mqtt/ssl + - idf.py build + - cd $IDF_PATH/examples/protocols/mqtt/ws + - idf.py build + - cd $IDF_PATH/examples/protocols/mqtt/wss + - idf.py build \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 7ae4f9b..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(COMPONENT_ADD_INCLUDEDIRS "include") -set(COMPONENT_PRIV_INCLUDEDIRS "lib/include") -set(COMPONENT_SRCDIRS ". lib") - -set(COMPONENT_REQUIRES lwip nghttp mbedtls) - -register_component() - diff --git a/README.md b/README.md index f083ab0..abe4822 100644 --- a/README.md +++ b/README.md @@ -15,158 +15,11 @@ ## How to use -Clone this component to [ESP-IDF](https://github.com/espressif/esp-idf) project (as submodule): -``` -git submodule add https://github.com/tuanpmt/espmqtt.git components/espmqtt -``` - -Or run a sample (make sure you have installed the [toolchain](http://esp-idf.readthedocs.io/en/latest/get-started/index.html#setup-toolchain)): - -``` -git clone https://github.com/tuanpmt/espmqtt.git -cd espmqtt/examples/mqtt_tcp -make menuconfig -make flash monitor -``` +[ESP-MQTT](https://github.com/espressif/esp-mqtt) is a standard [ESP-IDF](https://github.com/espressif/esp-idf) component. +Please refer to instructions in [ESP-IDF](https://github.com/espressif/esp-idf) ## Documentation -### URI - -- Curently support `mqtt`, `mqtts`, `ws`, `wss` schemes -- MQTT over TCP samples: - + `mqtt://iot.eclipse.org`: MQTT over TCP, default port 1883: - + `mqtt://iot.eclipse.org:1884` MQTT over TCP, port 1884: - + `mqtt://username:password@iot.eclipse.org:1884` MQTT over TCP, port 1884, with username and password -- MQTT over SSL samples: - + `mqtts://iot.eclipse.org`: MQTT over SSL, port 8883 - + `mqtts://iot.eclipse.org:8884`: MQTT over SSL, port 8884 -- MQTT over Websocket samples: - + `ws://iot.eclipse.org:80/ws` -- MQTT over Websocket Secure samples: - + `wss://iot.eclipse.org:443/ws` -- Minimal configurations: - -```c -const esp_mqtt_client_config_t mqtt_cfg = { - .uri = "mqtt://iot.eclipse.org", - .event_handle = mqtt_event_handler, - // .user_context = (void *)your_context -}; -``` - -- If there are any options related to the URI in `esp_mqtt_client_config_t`, the option defined by the URI will be overridden. Sample: - -```c -const esp_mqtt_client_config_t mqtt_cfg = { - .uri = "mqtt://iot.eclipse.org:1234", - .event_handle = mqtt_event_handler, - .port = 4567, -}; -//MQTT client will connect to iot.eclipse.org using port 4567 -``` - -### SSL - -- Get Certification from server, example: `iot.eclipse.org` `openssl s_client -showcerts -connect iot.eclipse.org:8883 /dev/null|openssl x509 -outform PEM >iot_eclipse_org.pem` -- Check the sample application: `examples/mqtt_ssl` -- Configuration: - -```cpp -const esp_mqtt_client_config_t mqtt_cfg = { - .uri = "mqtts://iot.eclipse.org:8883", - .event_handle = mqtt_event_handler, - .cert_pem = (const char *)iot_eclipse_org_pem_start, -}; -``` - - -### More options for `esp_mqtt_client_config_t` - -- `event_handle` for MQTT events -- `host`: MQTT server domain (ipv4 as string) -- `port`: MQTT server port -- `client_id`: default client id is `ESP32_%CHIPID%` -- `username`: MQTT username -- `password`: MQTT password -- `lwt_topic, lwt_msg, lwt_qos, lwt_retain, lwt_msg_len`: are mqtt lwt options, default NULL -- `disable_clean_session`: mqtt clean session, default clean_session is true -- `keepalive`: (value in seconds) mqtt keepalive, default is 120 seconds -- `disable_auto_reconnect`: this mqtt client will reconnect to server (when errors/disconnect). Set `disable_auto_reconnect=true` to disable -- `user_context` pass user context to this option, then can receive that context in `event->user_context` -- `task_prio, task_stack` for MQTT task, default priority is 5, and task_stack = 6144 bytes (or default task stack can be set via `make menucofig`). -- `buffer_size` for MQTT send/receive buffer, default is 1024 -- `cert_pem` pointer to CERT file for server verify (with SSL), default is NULL, not required to verify the server -- `transport`: override URI transport - + `MQTT_TRANSPORT_OVER_TCP`: MQTT over TCP, using scheme: `mqtt` - + `MQTT_TRANSPORT_OVER_SSL`: MQTT over SSL, using scheme: `mqtts` - + `MQTT_TRANSPORT_OVER_WS`: MQTT over Websocket, using scheme: `ws` - + `MQTT_TRANSPORT_OVER_WSS`: MQTT over Websocket Secure, using scheme: `wss` - -### Change settings in `menuconfig` - -``` -make menuconfig --> Component config -> ESPMQTT Configuration -``` - -## Example - -Check `examples/mqtt_tcp` and `examples/mqtt_ssl` project. In Short: - -```cpp - -static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) -{ - esp_mqtt_client_handle_t client = event->client; - int msg_id; - // your_context_t *context = event->context; - switch (event->event_id) { - case MQTT_EVENT_CONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); - ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); - break; - - case MQTT_EVENT_SUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); - msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_UNSUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_PUBLISHED: - ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); - break; - case MQTT_EVENT_ERROR: - ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - break; - } - return ESP_OK; -} -const esp_mqtt_client_config_t mqtt_cfg = { - .uri = "mqtt://iot.eclipse.org", - .event_handle = mqtt_event_handler, - // .user_context = (void *)your_context -}; - -esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); -esp_mqtt_client_start(client); -``` +Please refer to the standard [ESP-IDF](https://github.com/espressif/esp-idf) documentation here https://github.com/espressif/esp-idf/blob/master/docs/en/api-reference/protocols/mqtt.rst ## License - MQTT Package - [Stephen Robinson - contiki-mqtt](https://github.com/esar/contiki-mqtt) diff --git a/component.mk b/component.mk deleted file mode 100644 index 79bcc62..0000000 --- a/component.mk +++ /dev/null @@ -1,10 +0,0 @@ -# -# Component Makefile -# -# This Makefile should, at the very least, just include $(SDK_PATH)/make/component.mk. By default, -# this will take the sources in this directory, compile them and link them into -# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, -# please read the SDK documents if you need to do this. -# -COMPONENT_SRCDIRS := . lib -COMPONENT_PRIV_INCLUDEDIRS := lib/include diff --git a/modify_for_legacy_idf.sh b/modify_for_legacy_idf.sh new file mode 100755 index 0000000..6c43074 --- /dev/null +++ b/modify_for_legacy_idf.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# This snipped prepares environment for using esp-mqtt repository separately from idf -- legacy use before IDFv3.2 +# +esp_mqtt_path=`pwd` +mkdir -p ${esp_mqtt_path}/examples +pushd +cd $IDF_PATH +former_commit_id=`git rev-parse HEAD` +git checkout master + +for example in tcp; do + cp -r $IDF_PATH/examples/protocols/mqtt/${example} ${esp_mqtt_path}/examples + echo 'EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/../../../' > ${esp_mqtt_path}/examples/${example}/Makefile + cat $IDF_PATH/examples/protocols/mqtt/${example}/Makefile >> ${esp_mqtt_path}/examples/${example}/Makefile + echo "CONFIG_MQTT_TRANSPORT_SSL=" >> ${esp_mqtt_path}/examples/${example}/sdkconfig.defaults + echo "CONFIG_MQTT_TRANSPORT_WEBSOCKET=" >> ${esp_mqtt_path}/examples/${example}/sdkconfig.defaults +done + +cp -r $IDF_PATH/components/tcp_transport ${esp_mqtt_path}/.. +rm ${esp_mqtt_path}/../tcp_transport/transport_ssl.c +echo -e "#include \"esp_transport.h\"\nvoid esp_transport_ws_set_path(esp_transport_handle_t t, const char *path) {}" > ${esp_mqtt_path}/../tcp_transport/transport_ws.c + +cp $IDF_PATH/components/mqtt/Kconfig ${esp_mqtt_path} +sed 's/esp-mqtt/\./g' $IDF_PATH/components/mqtt/component.mk > ${esp_mqtt_path}/component.mk +git checkout $former_commit_id +popd \ No newline at end of file diff --git a/mqtt_client.c b/mqtt_client.c index 253b137..a433f4e 100644 --- a/mqtt_client.c +++ b/mqtt_client.c @@ -761,28 +761,32 @@ esp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client) return ESP_FAIL; } #if MQTT_CORE_SELECTION_ENABLED - ESP_LOGD(TAG, "Core selection enabled on %u", MQTT_TASK_CORE); - if (xTaskCreatePinnedToCore(esp_mqtt_task, "mqtt_task", client->config->task_stack, client, client->config->task_prio, NULL, MQTT_TASK_CORE) != pdTRUE) { - ESP_LOGE(TAG, "Error create mqtt task"); - return ESP_FAIL; - } + ESP_LOGD(TAG, "Core selection enabled on %u", MQTT_TASK_CORE); + if (xTaskCreatePinnedToCore(esp_mqtt_task, "mqtt_task", client->config->task_stack, client, client->config->task_prio, NULL, MQTT_TASK_CORE) != pdTRUE) { + ESP_LOGE(TAG, "Error create mqtt task"); + return ESP_FAIL; + } #else - ESP_LOGD(TAG, "Core selection disabled"); - if (xTaskCreate(esp_mqtt_task, "mqtt_task", client->config->task_stack, client, client->config->task_prio, NULL) != pdTRUE) { - ESP_LOGE(TAG, "Error create mqtt task") ; - return ESP_FAIL; - } + ESP_LOGD(TAG, "Core selection disabled"); + if (xTaskCreate(esp_mqtt_task, "mqtt_task", client->config->task_stack, client, client->config->task_prio, NULL) != pdTRUE) { + ESP_LOGE(TAG, "Error create mqtt task"); + return ESP_FAIL; + } #endif return ESP_OK; } - esp_err_t esp_mqtt_client_stop(esp_mqtt_client_handle_t client) { - client->run = false; - xEventGroupWaitBits(client->status_bits, STOPPED_BIT, false, true, portMAX_DELAY); - client->state = MQTT_STATE_UNKNOWN; - return ESP_OK; + if (client->run) { + client->run = false; + xEventGroupWaitBits(client->status_bits, STOPPED_BIT, false, true, portMAX_DELAY); + client->state = MQTT_STATE_UNKNOWN; + return ESP_OK; + } else { + ESP_LOGW(TAG, "Client asked to stop, but was not started"); + return ESP_FAIL; + } } static esp_err_t esp_mqtt_client_ping(esp_mqtt_client_handle_t client)