mirror of
https://github.com/espressif/esp-mqtt.git
synced 2025-07-30 18:58:07 +02:00
Merge branch 'bugfix/client_stop_only_if_started' into 'idf'
client to stop only if started See merge request idf/esp-mqtt!7
This commit is contained in:
45
.travis.yml
45
.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
|
@ -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()
|
||||
|
153
README.md
153
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 2>/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)
|
||||
|
10
component.mk
10
component.mk
@ -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
|
27
modify_for_legacy_idf.sh
Executable file
27
modify_for_legacy_idf.sh
Executable file
@ -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
|
@ -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)
|
||||
|
Reference in New Issue
Block a user