Saturday, August 26, 2017

Demo 30: How to use Arduino ESP32 MQTTS with MQTTS Mosquitto broker (TLS/SSL)

1. Introduction
Arduino-ESP32 SDK has been updated and new WiFiClientSecure library not working any more. In order to fix it, please using the old github commit or download the zip file here.
After downloading the old commit; extract it; go to the libraries folder; copy the
WiFiClientSecure folder; replace the current WiFiClientSecure folder (in Arduino/hardware/espressif/esp32/libraries or refer here) by the copied WiFiClientSecure folder.
- In this tutorial, I will show you how to use ESP32 MQTTS with MQTTS Mosquitto broker (TLS/SSL).
- In order to make this tutorial, please refer topics:
How to set up secure transportation for MQTT Mosquitto broker with SSL/TLS
Demo 29: How to use HTTPS in Arduino ESP32
Demo 14: How to use MQTT and Arduino ESP32 to build a simple Smart home system
- The requirement for this demo: ESP32 with a LED on it will turn On/Off when subscribing a topic "smarthome/room1/led" with values (0: off, 1: on).
2. Steps
- After doing the steps in this demo How to set up secure transportation for MQTT Mosquitto broker with SSL/TLS, you have to extract the content of ca.crt for SSL/TLS handshake phase by running the command:  
cat /etc/mosquitto/certs/ca.crt
 Figure: Extract content of ca.crt
- Get the IP address of machine that run MQTT mosquitto by running command: ifconfig or if you use MDNS for that machine you can follow this tutorial to get the IP directly from ESP32: How to get the IP address of a node by its mdns host name in Arduino ESP32.
- We will use WiFiClientSecure class for SSL/TLS handshake phase and PubSubClient library for ESP32 MQTT communication. Please see the topics that I mentioned above.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <ESPmDNS.h>

/* change it with your ssid-password */
const char* ssid = "dd-wrt";
const char* password = "0000000000";
/* this is the MDNS name of PC where you installed MQTT Server */
const char* serverHostname = "iotsharing";

const char* ca_cert = \ 
"-----BEGIN CERTIFICATE-----\n" \
"MIIDpzCCAo+gAwIBAgIJAOHc50EeJ6aeMA0GCSqGSIb3DQEBDQUAMGoxFzAVBgNV\n" \
"BAMMDkFuIE1RVFQgYnJva2VyMRYwFAYDVQQKDA1Pd25UcmFja3Mub3JnMRQwEgYD\n" \
"VQQLDAtnZW5lcmF0ZS1DQTEhMB8GCSqGSIb3DQEJARYSbm9ib2R5QGV4YW1wbGUu\n" \
"bmV0MB4XDTE3MDgyNzAyMDQwNFoXDTMyMDgyMzAyMDQwNFowajEXMBUGA1UEAwwO\n" \
"QW4gTVFUVCBicm9rZXIxFjAUBgNVBAoMDU93blRyYWNrcy5vcmcxFDASBgNVBAsM\n" \
"C2dlbmVyYXRlLUNBMSEwHwYJKoZIhvcNAQkBFhJub2JvZHlAZXhhbXBsZS5uZXQw\n" \
"ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8mQfR058k7LBV7Xt6RiZL\n" \
"BIpC5ewSweAnsaS6Ue+jx6uruJsccnIJbiHJVjOcSYV3JLMt3un7d0JTottW6Zx/\n" \
"VleYC4CUzf3bcHLe7Qhl0veP9QAdZceblMCbEqAM9227EaXKQVzAYGwRnuxvfJM7\n" \
"P84iu2J/zB4o+AEWUJDIW38SO4b+0i1FYHmKKxEx7dztDyCJvTsn35wX3oKlJ5e+\n" \
"na/6csD+Ngh9QQ+wDd02TBqXKB7UXyRT5ECesu19U6CTE7Wr9xECbDO262aD6GtC\n" \
"HpeSAWqa6HKbKjZ20pL5V5ceS85TdWbvPdVrFUDWMIhK9dNuwhIK0s6VyRcJkbe5\n" \
"AgMBAAGjUDBOMB0GA1UdDgQWBBQPZ0u1jIg65jT3Th42VGMnya6VDDAfBgNVHSME\n" \
"GDAWgBQPZ0u1jIg65jT3Th42VGMnya6VDDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3\n" \
"DQEBDQUAA4IBAQB8JrNsV32aXBOLSX8WqoHuU2NOJH+1fTdGDLYLEAPe/x3YxkNC\n" \
"MJDx8TGLSQsz4L0kCsLEQ/qsnkuPJUt3x7eNIMOrvS+zDv9wXqnGwMgeAOtEkG5n\n" \
"NbPezM50ovgZAuEZMphp2s/Zl0EROydnqpkweWa5bxYRkiQBlp0nUkCtec3PZ6iO\n" \
"QVPj/bHHi4T3jkbL0+oLNShv9Zw9hr6BkKCVqeHe9prlOMVuEJOVrEKzkhhAY90p\n" \
"Wwrj+OQYCLllJVD9VQhLVOXLg1bSuqkld3PCQBFNvrvk4Up61wuu/Oj5c5g8vwYd\n" \
"0ul29sU3heTw4ZXifpbMXRM36LFNH5uLrSba\n" \
"-----END CERTIFICATE-----\n";

/* create an instance of WiFiClientSecure */
WiFiClientSecure espClient;
PubSubClient client(espClient);

/*LED GPIO pin*/
const char led = 4;

/* topics */
#define COUNTER_TOPIC    "smarthome/room1/counter"
#define LED_TOPIC     "smarthome/room1/led" /* 1=on, 0=off */

long lastMsg = 0;
char msg[20];
int counter = 0;

void receivedCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message received: ");
  Serial.println(topic);

  Serial.print("payload: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  /* we got '1' -> on */
  if ((char)payload[0] == '1') {
    digitalWrite(led, HIGH); 
  } else {
    /* we got '0' -> on */
    digitalWrite(led, LOW);
  }

}

void mqttconnect() {
  /* Loop until reconnected */
  while (!client.connected()) {
    Serial.print("MQTT connecting ...");
    /* client ID */
    String clientId = "ESP32Client";
    /* connect now */
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      /* subscribe topic */
      client.subscribe(LED_TOPIC);
    } else {
      Serial.print("failed, status code =");
      Serial.print(client.state());
      Serial.println("try again in 5 seconds");
      /* Wait 5 seconds before retrying */
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  /* set led as output to control led on-off */
  pinMode(led, OUTPUT);

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  /*setup MDNS for ESP32 */
  if (!MDNS.begin("esp32")) {
      Serial.println("Error setting up MDNS responder!");
      while(1) {
          delay(1000);
      }
  }
  /* get the IP address of server by MDNS name */
  Serial.println("mDNS responder started");
  IPAddress serverIp = MDNS.queryHost(serverHostname);
  Serial.print("IP address of server: ");
  Serial.println(serverIp.toString());
  /* set SSL/TLS certificate */
  espClient.setCACert(ca_cert);
  /* configure the MQTT server with IPaddress and port */
  client.setServer(serverIp, 8883);
  /* this receivedCallback function will be invoked 
  when client received subscribed topic */
  client.setCallback(receivedCallback);
  
}
void loop() {
  /* if client was disconnected then try to reconnect again */
  if (!client.connected()) {
    mqttconnect();
  }
  /* this function will listen for incomming 
  subscribed topic-process-invoke receivedCallback */
  client.loop();
  /* we increase counter every 3 secs
  we count until 3 secs reached to avoid blocking program if using delay()*/
  long now = millis();
  if (now - lastMsg > 3000) {
    lastMsg = now;
    if (counter < 100) {
      counter++;
      snprintf (msg, 20, "%d", counter);
      /* publish the message */
      client.publish(COUNTER_TOPIC, msg);
    }else {
      counter = 0;  
    }
  }
}
3. Result

8 comments:

Anonymous said...

I keep getting the following error in my broker's logs:

New connection from xxx.yyy.zzz.ddd on port 8883.
1513416718: OpenSSL Error: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate
1513416718: OpenSSL Error: error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure
1513416718: Socket error on client , disconnecting.

I followed the procedure exactly as stated. The only real difference is that my device connects from an external location to my home MQTT broker (I opened port 8883 and forwarded it to the broker). I can see the connection attempts, but the SSL handshake fails every time... is there a known solution for that?

iotsharing dotcom said...

1. are you able to connect it from local?
2. If yes, Are you able to ping it from external?

Bernardo Carvalho said...

I'm also having problems connecting to my Mosquito server.
My broker's log gets
1513549085: New connection from 46.189.241.12 on port 8883.
1513549085: OpenSSL Error: error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure
1513549085: Socket error on client (null), disconnecting.

I also tried the test.mosquitto.org broker with their own certificate test.mosquitto.org/ssl/mosquitto.org.crt but always get
the same message on the Serial console:

Attempting MQTT connection...failed, rc=-2 try again in 5 seconds

iotsharing dotcom said...

Hi all,

Arduino-ESP32 SDK has been updated and new WiFiClientSecure library not working any more. In order to fix it, please using the old github commit or download the zip file here.

After downloading the old commit; extract it; go to the libraries folder; copy the
WiFiClientSecure folder; replace the current WiFiClientSecure folder (in Arduino/hardware/espressif/esp32/libraries or refer here) by the copied WiFiClientSecure folder.

Constan said...

Excelent article.

Im trying connect to Sap Leonardo (mqtt-tls) , it requiere 3 certs (root ca, cert, key). The problem is: connect, publish but "not publish" in sap leonardo cockpit dashboard ... in Python paho use similar code and work fine. Mqtt for arduino esp32 have some debug or message code error or logging for diagnostic some error and outcomming message?

(in arduino esp32 work with 3 certs and 2 too, maybe I must test with idf-c++ )

Vinicius said...

Thank you so much!
I was looking for resolving a name with the ESP32 to conecta to my mosquitto server.

YASHASWI said...

I tried using the above code with the necessary steps and tried connecting to "test.mosquitto.org" my esp32 is constantly rebooting while trying to connect to mqtt server i am sharing the serial prints below :

---------------------Serial monitor-------------------------------------------------

Connecting to Hocket
..
WiFi connected
IP address:
192.168.0.105
mDNS responder started
IP address of server: 0.0.0.0
MQTT connecting ...Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400f4744 PS : 0x00060030 A0 : 0x800feca5 A1 : 0x3ffb1e20
A2 : 0x3ffbaa70 A3 : 0x00000190 A4 : 0x8008e98c A5 : 0x3ffb1af0
A6 : 0x00000000 A7 : 0x3ffb0060 A8 : 0xfefefefe A9 : 0x3ffb1e10
A10 : 0x3ffba820 A11 : 0x00000000 A12 : 0x00000190 A13 : 0x3ffba9b0
A14 : 0x00000020 A15 : 0x00000019 SAR : 0x00000018 EXCCAUSE: 0x0000001c
EXCVADDR: 0xfefeff26 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000

Backtrace: 0x400f4744:0x3ffb1e20 0x400feca2:0x3ffb1e40 0x400d2ba2:0x3ffb1e60 0x400d297d:0x3ffb1e80 0x400d2a7f:0x3ffb1ea0 0x400d2aa9:0x3ffb1ec0 0x400d31aa:0x3ffb1ef0 0x400d3382:0x3ffb1f30 0x400d1b49:0x3ffb1f60 0x400d1d9b:0x3ffb1f90 0x400d3e0d:0x3ffb1fb0 0x4008e779:0x3ffb1fd0

Rebooting...
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1100
load:0x40078000,len:10088
load:0x40080400,len:6380
entry 0x400806a4

ishan said...

I'm also trying to use the above code with the necessary steps and tried connecting to "test.mosquitto.org" my ESP32 is constantly rebooting while trying to connect to MQTT server

-------Serial output ---------

MQTT connecting ...Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400f4b44 PS : 0x00060230 A0 : 0x800ff0a5 A1 : 0x3ffb1e00
A2 : 0x3ffbaa70 A3 : 0x00000190 A4 : 0x8008f13c A5 : 0x3ffb1ad0
A6 : 0x00000000 A7 : 0x3ffb0060 A8 : 0xfefefefe A9 : 0x3ffb1df0
A10 : 0x3ffba820 A11 : 0x00000000 A12 : 0x00000190 A13 : 0x3ffba9b0
A14 : 0x00000020 A15 : 0x00000019 SAR : 0x00000018 EXCCAUSE: 0x0000001c
EXCVADDR: 0xfefeff26 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000

Any help would be highly appreciated.