Skip to main content
Intro to IoT Class Docs
Tech TLH Discord Code and Coffee TLH GitHub Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Enabling MQTT

Handling Secure Connections

We’re using a secure connection, but can’t validate the SSL certificate from HiveMQ right now. This means we have to loosen restrictions a little bit by keeping the connection encrypted, but placing blind trust in the server on the other end. This would not be an optimal situation if some heavy industrial machinery was waiting for commands to run, but it’s not going to hurt us for a thermometer prototype.

This requires including another header and explicitly setting up a blind trust connection:

#include <WiFiClientSecure.h>

// in variables section
WiFiClientSecure net;

// in the connect() method
void connect() {
  net.setInsecure();
}

Connecting to MQTT

To get MQTT working, we need to include the client library and also give it a variable to store its state.

It also has its own section in both connect() and setup() to handle startup and reconnects, and looks vaguely familiar to code we already have.

#include <MQTT.h>

// in variables section
MQTTClient client;

// in the connect() method
void connect() {
  // after other Serial.print + while{} loops
  Serial.print("connecting to MQTT...");
  while (!client.connect(MQTT_NAME, MQTT_NAME, MQTT_PASS)) {
    Serial.print(".");
    delay(1000);
  }
}

// at startup in setup()
void setup() {
  // WiFi.begin(...);
  client.begin(MQTT_SERVER, MQTT_PORT, net);
}

In the main loop, it can also check if wifi has dropped between updates and make use of the connect() method to reconnect before sending another message.

void loop()
{
  // at the top of the loop
   client.loop();
  if (!client.connected()) {
    connect();
  } 
}

And the message can be published after creating the JSON document is serialized.

if(ok) {
  // serializeJson(doc, message);
  // Serial.println(message);
  client.publish(MQTT_TOPIC, message);
}

Notice a few of the #define macros from the Notepad document? They come into play here, too.

Here’s what it looks like assembled:

 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
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <MQTT.h>
#include <ezTime.h>
#include <ArduinoJson.h>
#include <AHT20.h>

#define WIFI_SSID "code"
#define WIFI_PASS "andcoffee"

// NOTE: replace with your own server URL!  The port stays the same.
#define MQTT_SERVER "0123456789abcdef.s1.eu.hivemq.cloud"
#define MQTT_PORT 8883

// Replace these with your own as well
#define MQTT_NAME "myesp32"
#define MQTT_PASS "password123"
#define MQTT_TOPIC "/code/coffee"

#define UPDATE_SECONDS 2

WiFiClientSecure net;
Timezone local;
MQTTClient client;
AHT20 AHT;

float humidity, temperature;
JsonDocument doc;
String message;

void connect() {
  Serial.print("connecting to wifi...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("done.");

  waitForSync();  // time

  Serial.print("getting time zone...");
  while (!local.setLocation("America/New_York")) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("done.");

  net.setInsecure();

  Serial.print("connecting to MQTT...");
  while (!client.connect(MQTT_NAME, MQTT_NAME, MQTT_PASS)) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("done.");
}

void setup()
{
  Serial.begin(115200);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  client.begin(MQTT_SERVER, MQTT_PORT, net);
  AHT.begin();

  connect();
}

void loop()
{
  client.loop();
  if (!client.connected()) {
    connect();
  }

  bool ok = AHT.getSensor(&humidity, &temperature);

  if(ok)
  {
    doc["time"] = local.dateTime(ISO8601);
    doc["humidity"] = humidity * 100;
    doc["temperature"] = temperature * 9 / 5 + 32;

    serializeJson(doc, message);

    Serial.println(message);
    client.publish(MQTT_TOPIC, message);

  }
  else
  {
    Serial.println("ERROR: no temp data");
  }

  delay(UPDATE_SECONDS * 1000);
}

Wait a Second!

If you just copied the above code block, don’t forget to change out #define statements with your own info!

Last Burn, Hopefully

With the board plugged in to USB, go ahead and upload it with mqtt info. The serial monitor will now show it connecting to HiveMQ, and we can watch the data stream on the server end.

Next Up: Verify MQTT