Skip to content

Commit eae96cc

Browse files
committed
added examples mqtt and ota
1 parent d889441 commit eae96cc

18 files changed

+620
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.projbuild

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,11 @@ ESP32 projects reference based on the official ESP-IDF taking advantage of OTA M
44
# Requirements
55
* the [official esp-idf SDK](https://github.com/espressif/esp-idf)
66

7+
cd ~/esp-idf
8+
git fetch
9+
git checkout cc8ad721f98ffbc7953ece70616c07422b58e06b
10+
11+
using esp-idf commit from Tue Aug 28 11:01:22
12+
713
# Used module
814
* ESP-WROOM-32

mqtt/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
build
2+
server_certs
3+
sdkconfig

mqtt/CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# The following four lines of boilerplate have to be in your project's CMakeLists
2+
# in this exact order for cmake to work correctly
3+
cmake_minimum_required(VERSION 3.5)
4+
5+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6+
7+
project(mqtt_tcp)

mqtt/Makefile

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#
2+
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
3+
# project subdirectory.
4+
#
5+
PROJECT_NAME := mqtt_tcp
6+
7+
include $(IDF_PATH)/make/project.mk

mqtt/README.md

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# ESP-MQTT sample application
2+
(See the README.md file in the upper level 'examples' directory for more information about examples.)
3+
4+
This example connects to the broker URI selected using `make menuconfig` (using mqtt tcp transport) and as a demonstration subscribes/unsubscribes and send a message on certain topic.
5+
Note: If the URI equals `FROM_STDIN` then the broker address is read from stdin upon application startup (used for testing)
6+
7+
It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker.
8+
9+
## How to use example
10+
11+
### Hardware Required
12+
13+
This example can be executed on any ESP32 board, the only required interface is WiFi and connection to internet.
14+
15+
### Configure the project
16+
17+
```
18+
make menuconfig
19+
```
20+
21+
* Set serial port under Serial Flasher Options.
22+
23+
* Set ssid and password for the board to connect to AP.
24+
25+
### Build and Flash
26+
27+
Build the project and flash it to the board, then run monitor tool to view serial output:
28+
29+
```
30+
make -j4 flash monitor
31+
```
32+
33+
(To exit the serial monitor, type ``Ctrl-]``.)
34+
35+
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
36+
37+
## Example Output
38+
39+
```
40+
I (3714) event: sta ip: 192.168.0.139, mask: 255.255.255.0, gw: 192.168.0.2
41+
I (3714) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
42+
I (3964) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000
43+
I (4164) MQTT_EXAMPLE: MQTT_EVENT_CONNECTED
44+
I (4174) MQTT_EXAMPLE: sent publish successful, msg_id=41464
45+
I (4174) MQTT_EXAMPLE: sent subscribe successful, msg_id=17886
46+
I (4174) MQTT_EXAMPLE: sent subscribe successful, msg_id=42970
47+
I (4184) MQTT_EXAMPLE: sent unsubscribe successful, msg_id=50241
48+
I (4314) MQTT_EXAMPLE: MQTT_EVENT_PUBLISHED, msg_id=41464
49+
I (4484) MQTT_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=17886
50+
I (4484) MQTT_EXAMPLE: sent publish successful, msg_id=0
51+
I (4684) MQTT_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=42970
52+
I (4684) MQTT_EXAMPLE: sent publish successful, msg_id=0
53+
I (4884) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19
54+
I (4884) MQTT_EXAMPLE: MQTT_EVENT_DATA
55+
TOPIC=/topic/qos0
56+
DATA=data
57+
I (5194) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19
58+
I (5194) MQTT_EXAMPLE: MQTT_EVENT_DATA
59+
TOPIC=/topic/qos0
60+
DATA=data
61+
```

mqtt/main/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
set(COMPONENT_SRCS "app_main.c")
2+
set(COMPONENT_ADD_INCLUDEDIRS ".")
3+
4+
register_component()

mqtt/main/app_main.c

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#include <stdio.h>
2+
#include <stdint.h>
3+
#include <stddef.h>
4+
#include <string.h>
5+
#include "esp_wifi.h"
6+
#include "esp_system.h"
7+
#include "nvs_flash.h"
8+
#include "esp_event_loop.h"
9+
10+
#include "freertos/FreeRTOS.h"
11+
#include "freertos/task.h"
12+
#include "freertos/semphr.h"
13+
#include "freertos/queue.h"
14+
#include "freertos/event_groups.h"
15+
16+
#include "lwip/sockets.h"
17+
#include "lwip/dns.h"
18+
#include "lwip/netdb.h"
19+
20+
#include "esp_log.h"
21+
#include "mqtt_client.h"
22+
23+
static const char *TAG = "MQTT_EXAMPLE";
24+
25+
static EventGroupHandle_t wifi_event_group;
26+
const static int CONNECTED_BIT = BIT0;
27+
28+
29+
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
30+
{
31+
esp_mqtt_client_handle_t client = event->client;
32+
int msg_id;
33+
// your_context_t *context = event->context;
34+
switch (event->event_id) {
35+
case MQTT_EVENT_CONNECTED:
36+
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
37+
msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
38+
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
39+
40+
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
41+
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
42+
43+
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
44+
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
45+
46+
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
47+
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
48+
break;
49+
case MQTT_EVENT_DISCONNECTED:
50+
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
51+
break;
52+
53+
case MQTT_EVENT_SUBSCRIBED:
54+
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
55+
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
56+
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
57+
break;
58+
case MQTT_EVENT_UNSUBSCRIBED:
59+
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
60+
break;
61+
case MQTT_EVENT_PUBLISHED:
62+
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
63+
break;
64+
case MQTT_EVENT_DATA:
65+
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
66+
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
67+
printf("DATA=%.*s\r\n", event->data_len, event->data);
68+
break;
69+
case MQTT_EVENT_ERROR:
70+
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
71+
break;
72+
}
73+
return ESP_OK;
74+
}
75+
76+
static esp_err_t wifi_event_handler(void *ctx, system_event_t *event)
77+
{
78+
switch (event->event_id) {
79+
case SYSTEM_EVENT_STA_START:
80+
esp_wifi_connect();
81+
break;
82+
case SYSTEM_EVENT_STA_GOT_IP:
83+
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
84+
85+
break;
86+
case SYSTEM_EVENT_STA_DISCONNECTED:
87+
esp_wifi_connect();
88+
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
89+
break;
90+
default:
91+
break;
92+
}
93+
return ESP_OK;
94+
}
95+
96+
static void wifi_init(void)
97+
{
98+
tcpip_adapter_init();
99+
wifi_event_group = xEventGroupCreate();
100+
ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL));
101+
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
102+
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
103+
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
104+
wifi_config_t wifi_config = {
105+
.sta = {
106+
.ssid = CONFIG_WIFI_SSID,
107+
.password = CONFIG_WIFI_PASSWORD,
108+
},
109+
};
110+
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
111+
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
112+
ESP_LOGI(TAG, "start the WIFI SSID:[%s]", CONFIG_WIFI_SSID);
113+
ESP_ERROR_CHECK(esp_wifi_start());
114+
ESP_LOGI(TAG, "Waiting for wifi");
115+
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
116+
}
117+
118+
static void mqtt_app_start(void)
119+
{
120+
esp_mqtt_client_config_t mqtt_cfg = {
121+
.uri = CONFIG_BROKER_URL,
122+
.event_handle = mqtt_event_handler,
123+
// .user_context = (void *)your_context
124+
};
125+
126+
#if CONFIG_BROKER_URL_FROM_STDIN
127+
char line[128];
128+
129+
if (strcmp(mqtt_cfg.uri, "FROM_STDIN") == 0) {
130+
int count = 0;
131+
printf("Please enter url of mqtt broker\n");
132+
while (count < 128) {
133+
int c = fgetc(stdin);
134+
if (c == '\n') {
135+
line[count] = '\0';
136+
break;
137+
} else if (c > 0 && c < 127) {
138+
line[count] = c;
139+
++count;
140+
}
141+
vTaskDelay(10 / portTICK_PERIOD_MS);
142+
}
143+
mqtt_cfg.uri = line;
144+
printf("Broker url: %s\n", line);
145+
} else {
146+
ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
147+
abort();
148+
}
149+
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
150+
151+
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
152+
esp_mqtt_client_start(client);
153+
}
154+
155+
void app_main()
156+
{
157+
ESP_LOGI(TAG, "[APP] Startup..");
158+
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
159+
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
160+
161+
esp_log_level_set("*", ESP_LOG_INFO);
162+
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
163+
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
164+
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
165+
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
166+
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
167+
168+
nvs_flash_init();
169+
wifi_init();
170+
mqtt_app_start();
171+
}

mqtt/main/component.mk

Whitespace-only changes.

mqtt/mqtt_tcp_example_test.py

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import re
2+
import os
3+
import sys
4+
from socket import *
5+
from threading import Thread
6+
import time
7+
8+
global msgid
9+
10+
def get_my_ip():
11+
s1 = socket(AF_INET, SOCK_DGRAM)
12+
s1.connect(("8.8.8.8", 80))
13+
my_ip = s1.getsockname()[0]
14+
s1.close()
15+
return my_ip
16+
17+
def mqqt_server_sketch(my_ip, port):
18+
global msgid
19+
print("Starting the server on {}".format(my_ip))
20+
s=socket(AF_INET, SOCK_STREAM)
21+
s.settimeout(60)
22+
s.bind((my_ip, port))
23+
s.listen(1)
24+
q,addr=s.accept()
25+
q.settimeout(30)
26+
print("connection accepted")
27+
# q.send(g_msg_to_client)
28+
data = q.recv(1024)
29+
# check if received initial empty message
30+
print("received from client {}".format(data))
31+
data = bytearray([0x20, 0x02, 0x00, 0x00])
32+
q.send(data)
33+
# try to receive qos1
34+
data = q.recv(1024)
35+
msgid = ord(data[15])*256+ord(data[16])
36+
print("received from client {}, msgid: {}".format(data, msgid))
37+
data = bytearray([0x40, 0x02, data[15], data[16]])
38+
q.send(data)
39+
time.sleep(5)
40+
s.close()
41+
print("server closed")
42+
43+
# this is a test case write with tiny-test-fw.
44+
# to run test cases outside tiny-test-fw,
45+
# we need to set environment variable `TEST_FW_PATH`,
46+
# then get and insert `TEST_FW_PATH` to sys path before import FW module
47+
test_fw_path = os.getenv("TEST_FW_PATH")
48+
if test_fw_path and test_fw_path not in sys.path:
49+
sys.path.insert(0, test_fw_path)
50+
51+
import TinyFW
52+
import IDF
53+
54+
55+
56+
57+
@IDF.idf_example_test(env_tag="Example_WIFI")
58+
def test_examples_protocol_mqtt_qos1(env, extra_data):
59+
global msgid
60+
"""
61+
steps: (QoS1: Happy flow)
62+
1. start the broker broker (with correctly sending ACK)
63+
2. DUT client connects to a broker and publishes qos1 message
64+
3. Test evaluates that qos1 message is queued and removed from queued after ACK received
65+
4. Test the broker received the same message id evaluated in step 3
66+
"""
67+
dut1 = env.get_dut("mqtt_tcp", "examples/protocols/mqtt/tcp")
68+
# check and log bin size
69+
binary_file = os.path.join(dut1.app.binary_path, "mqtt_tcp.bin")
70+
bin_size = os.path.getsize(binary_file)
71+
IDF.log_performance("mqtt_tcp_bin_size", "{}KB".format(bin_size//1024))
72+
IDF.check_performance("mqtt_tcp_size", bin_size//1024)
73+
# 1. start mqtt broker sketch
74+
host_ip = get_my_ip()
75+
thread1 = Thread(target = mqqt_server_sketch, args = (host_ip,1883))
76+
thread1.start()
77+
# 2. start the dut test and wait till client gets IP address
78+
dut1.start_app()
79+
# waiting for getting the IP address
80+
data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)
81+
# time.sleep(15)
82+
print ("writing to device: {}".format("mqtt://" + host_ip + "\n"))
83+
dut1.write("mqtt://" + host_ip + "\n")
84+
thread1.join()
85+
print ("Message id received from server: {}".format(msgid))
86+
# 3. check the message id was enqueued and then deleted
87+
msgid_enqueued = dut1.expect(re.compile(r"OUTBOX: ENQUEUE msgid=([0-9]+)"), timeout=30)
88+
# expect_txt="OUTBOX: ENQUEUE msgid=" + str(msgid)
89+
# dut1.expect(re.compile(expect_txt), timeout=30)
90+
msgid_deleted = dut1.expect(re.compile(r"OUTBOX: DELETED msgid=([0-9]+)"), timeout=30)
91+
# expect_txt="OUTBOX: DELETED msgid=" + str(msgid)
92+
# dut1.expect(re.compile(expect_txt), timeout=30)
93+
# 4. check the msgid of received data are the same as that of enqueued and deleted from outbox
94+
if (msgid_enqueued[0] == str(msgid) and msgid_deleted[0] == str(msgid)):
95+
print("PASS: Received correct msg id")
96+
else:
97+
print("Failure!")
98+
raise ValueError('Mismatch of msgid: received: {}, enqueued {}, deleted {}'.format(msgid, msgid_enqueued, msgid_deleted))
99+
100+
if __name__ == '__main__':
101+
test_examples_protocol_mqtt_qos1()

mqtt/sdkconfig.defaults

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CONFIG_BROKER_URL="FROM_STDIN"
2+
CONFIG_LOG_DEFAULT_LEVEL_NONE=
3+
CONFIG_LOG_DEFAULT_LEVEL_ERROR=
4+
CONFIG_LOG_DEFAULT_LEVEL_WARN=
5+
CONFIG_LOG_DEFAULT_LEVEL_INFO=
6+
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
7+
CONFIG_LOG_DEFAULT_LEVEL_VERBOSE=

ota/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
build
2+
server_certs
3+
sdkconfig

ota/CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# The following lines of boilerplate have to be in your project's CMakeLists
2+
# in this exact order for cmake to work correctly
3+
cmake_minimum_required(VERSION 3.5)
4+
5+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6+
project(simple_ota)

0 commit comments

Comments
 (0)