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

5 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++ )