Secure MQTT in arduino uno + esp 8266

Hi everyone,

I am building an IoT project to send some sensor data to a server. Presently I am using a DHT11 for temperature data. I'll expand later to include more sensors. So for this project, I have got my hands on an arduino UNO, a DHT11 and an esp8266 module.

I want to send this data to the server using mqtt protocol with SSL.

Presently I am using my uno to read data from DHT and print it on serial. Here's the code for that

#include <dht.h>        // Include library
#define outPin 8        // Defines pin number to which the sensor is connected

dht DHT;                // Creates a DHT object

void setup() {
	Serial.begin(9600);
}

void loop() {
	int readData = DHT.read11(outPin);

	float t = DHT.temperature;        // Read temperature
	float h = DHT.humidity;           // Read humidity

	Serial.println(t);
	
	delay(2000); // wait two seconds
}

and I have made a python code to read data from the serial and write send it through mqtt. here's the code:

import random
from paho.mqtt import client as mqtt_client
import json
import serial
from time import sleep

broker = 'something.something.com'
port = 8883
topic = 'dataset'
client_id = f'python-mqtt-{random.randint(0, 1000)}'
username = 'username'
password = 'password'


def connect_mqtt():
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
        else:
            print("Failed to connect, return code %d\n", rc)
    # Set Connecting Client ID
    client = mqtt_client.Client(client_id)
    # Set CA certificate
    client.tls_set(ca_certs='certificate.crt')
    client.username_pw_set(username, password)
    client.on_connect = on_connect
    client.connect(broker, port)
    return client


def publish(client):
    arduino = serial.Serial('COM4', 9800, timeout=1)
    sleep(2)
    while True:
        data=arduino.readline()
        if data:
            data=data.decode().strip()
            #print(data)
            dict={"sensor_id": 52647892, #some random int for now
                    "data": {"temp":float(data)},
                    "time": "14:30",
                    "month": f"2023-06-22"}
            print(dict)
            json_data=json.dumps(dict)
            result = client.publish(topic, json_data)
            if result[0] == 0:
                print(f"published")
            else:
                print(f"Failed to send message to topic {topic}")


def run():
    client = connect_mqtt()
    client.loop_start()
    publish(client)


if __name__ == '__main__':
    run()

I have a file that contains the SSL certificate that this code is using. This thing works perfectly, the data is going to the server properly. I came up with this methodology (of sending data through serial and then through python) as the esp was still on its way. now the esp has been delivered.

I want to wire my esp8266 module to my arduino uno and then send data through it to my mqtt server using SSL certificate. I have to have use this sever only and it will not work without this SSL certificate. I searched on the internet but couldn't find anything. I saw tutorials using nodemcu directly but I have already ordered these and even if I order the nodemcu it will take some time to arrive (I am short on time). Can anyone help on how can I do this with the UNO and esp8266 module that I currently have?

Thanks for the help

one option. put Jiri Bilek's 'fake' AT firmware in the esp8266. it allows to add your own certificate.
use my WiFiEspAT library with PubSubClient in the Uno

Is there any other way than this?
Is there any method (or library) where i won't have to modify esp8266 firmware?

and what version of AT firmware is in your esp8266?

@Juraj
Running AT+GMR returned this

AT version:1.2.0.0(Jul 1 2016 20:04:45)
SDK version:1.5.4.1(39cb9a32)
v1.0.0
Mar 11 2018 18:27:31

thanks

the old WiFiEsp library should work with that old AT firmware

Do you mean this https://github.com/bportaluri/WiFiEsp?

How can I establish an SSL connection using this library and my certificate?

there is no way to use your certificate (not signed by a well known CA) without programming the esp8266

So finally, I got my hands on a NodeMCU for my project and created the below code for nodemcu.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>

// Wi-Fi settings
const char* ssid = "ssid";
const char* password = "pass";

// MQTT broker settings
const char* mqttServer = "mqtt.myserver.com";
const int mqttPort = 8883;  // MQTT over SSL/TLS default port

// MQTT authentication
const char* mqttUsername = "guest";
const char* mqttPassword = "guest";

// Sensor pin
const int sensorPin = A0;

// Create an instance of WiFiClientSecure
WiFiClientSecure wifiClient;

// Create an instance of PubSubClient
PubSubClient mqttClient(wifiClient);

// Root CA certificate
const char* rootCACertificate = R"(
-----BEGIN CERTIFICATE-----
My certificate goes here
-----END CERTIFICATE-----
)";

void setup() {
  Serial.begin(9600);
  delay(10);

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi!");

  // Configure MQTT server and set SSL/TLS options
  mqttClient.setServer(mqttServer, mqttPort);
  mqttClient.setCallback(callback);

  // Load root CA certificate into WiFiClientSecure object
  wifiClient.setTrustAnchors(new BearSSL::X509List(rootCACertificate));
  
  // Connect to MQTT broker
  connectToMqtt();
}

void loop() {
  if (!mqttClient.connected()) {
    // If MQTT connection is lost, try to reconnect
    reconnect();
  }

  // Read sensor data
  int sensorValue = 22;

  // Convert sensor value to a string
  String payload = String(sensorValue);

  // Publish the sensor data to the MQTT topic
  mqttClient.publish("sensor_data_topic", payload.c_str());

  // Wait for some time before publishing the next sensor data
  delay(5000);
}

void connectToMqtt() {
  // Loop until connected to MQTT broker
  while (!mqttClient.connected()) {
    Serial.println("Connecting to MQTT server...");
    if (mqttClient.connect("ESP8266Client", mqttUsername, mqttPassword)) {
      Serial.println("Connected to MQTT server!");
      // Subscribe to MQTT topics, if needed
      // mqttClient.subscribe("topic_name");
    } else {
      Serial.print("Failed to connect to MQTT server. Retrying in 5 seconds...");
      delay(5000);
    }
  }
}

void reconnect() {
  // Disconnect if already connected
  if (mqttClient.connected()) {
    mqttClient.disconnect();
  }

  // Attempt to reconnect
  connectToMqtt();
}

void callback(char* topic, byte* payload, unsigned int length) {
  // Handle MQTT subscription messages, if needed
  // ...
}

but I am not able to connect to my server through this server even though my code in the first post is able to connect and send data properly.

I tried using a public mqtt server that does not use SSL and was able to connect my nodemcu to it and send the data properly.

Am I making any mistake in adding my certificate? or is it something else?

Please help
Thanks

I also tried this example: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino

But got "Connection failed"

Please help
Thanks

for a test try to set wifiClient.setInsecure()

1 Like

I used

and both the example and my code work now. Thank you so much @Juraj .

But does including this line make my data transmission insecure? can you please help me understand what did this line of code do?

Thanks

setInsecure skips checking validity of the servers certificate. it is good to test if the problem is with the connection or with the certificate evaluation.
so now you know that the problem is with the certificates. but I have no experience with this part.

Can you please elaborate which certificate are you talking about? is it my rootCACertificate? But python code in the first post is sending data properly (and now the nodemcu is also able to send it properly)

Thanks

I don't know.
maybe create a new topic for this problem so more people see it

OK.

We don't really need duplicate topics that need to be merged again....

it is not duplicate. the topic shifted from Uno to esp8266 Arduino and from possibility to provide own CA certificate for Uno+esp8266 to solve certificate validation in esp8266 Arduino

Righto....Start a new topic then if that will get the necessary help, I guess if there are any problems you can point to the end of this thread. :slightly_smiling_face:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.