#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <LiquidCrystal_I2C.h>
const String SSID = "Wokwi-GUEST";
const String PW = "";
const String BROKER = "mqtt.beebotte.com";
const uint16_t PORT = 1883;
const String CHANNEL = "";
const String TOKEN = "";
const String TEMP_FIELD = "Temperature";
const String HUMIDITY_FIELD = "Humidity";
const String DISTANCE_FIELD = "Distance";
const String LED_FIELD = "Led";
const uint16_t LED_PIN = 32;
const uint16_t TRIG_PIN = 14;
const uint16_t ECHO_PIN = 35;
// Automatically generated from other variables
const String USERNAME = "token:" + TOKEN;
const String TEMP_TOPIC = CHANNEL + "/" + TEMP_FIELD;
const String HUMIDITY_TOPIC = CHANNEL + "/" + HUMIDITY_FIELD;
const String DISTANCE_TOPIC = CHANNEL + "/" + DISTANCE_FIELD;
const String LED_TOPIC = CHANNEL + "/" + LED_FIELD;
WiFiClient wifi;
PubSubClient mqtt;
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);
StaticJsonDocument<64> receiveDoc;
StaticJsonDocument<128> sendDoc;
float measureDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH);
return duration * 0.034 / 2;
}
void callback(const char* topic, byte* payload, unsigned int length) {
Serial.println();
char termPayload[length + 1];
strncpy(termPayload, (char*)payload, length);
termPayload[length] = '\0';
Serial.println("Received " + String(termPayload) + " on topic " + String(topic) + ".");
if (deserializeJson(receiveDoc, termPayload) != DeserializationError::Ok) {
Serial.println("Error parsing JSON.");
} else if (String(topic) == TEMP_TOPIC) {
float data = receiveDoc["data"];
lcd.setCursor(13, 0);
lcd.print(data);
} else if (String(topic) == HUMIDITY_TOPIC) {
float data = receiveDoc["data"];
lcd.setCursor(10, 1);
lcd.print(data);
} else if (String(topic) == LED_TOPIC) {
boolean data = receiveDoc["data"];
digitalWrite(LED_PIN, data ? HIGH : LOW);
publish();
} else {
Serial.println("Unrecognized topic " + String(topic));
}
}
void publish() {
float distance = measureDistance();
lcd.setCursor(10, 2);
lcd.print(distance);
sendDoc["data"] = distance;
String payload;
serializeJson(sendDoc, payload);
Serial.println("Publishing " + payload + " to " + DISTANCE_TOPIC);
if (mqtt.publish(DISTANCE_TOPIC.c_str(), payload.c_str())) {
Serial.println("Distance published.");
} else {
Serial.println("Error publishing distance.");
}
}
void setup() {
Serial.begin(115200);
while (!Serial) continue;
Serial.println();
Serial.print("Started.\nConnecting to wifi \"" + SSID + "\" with password \"" + PW + "\" ...");
WiFi.begin(SSID.c_str(), PW.c_str());
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.print(" Connected to Wifi. \nFinishing setup... ");
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
lcd.init();
lcd.setCursor(0, 0);
lcd.print("Temperature: C");
lcd.setCursor(0, 1);
lcd.print("Humidity: %");
lcd.setCursor(0, 2);
lcd.print("Distance: cm");
sendDoc["channel"] = CHANNEL;
sendDoc["write"] = false;
sendDoc["resource"] = DISTANCE_FIELD;
mqtt.setServer(BROKER.c_str(), PORT);
mqtt.setClient(wifi);
mqtt.setCallback(callback);
Serial.println("Ready.");
}
void loop() {
if (!mqtt.connected()) {
Serial.println("\nMQTT not connected. Connecting to broker " + BROKER + " on port " + String(PORT) + " with username=\"" + USERNAME + "\" and no password.");
if (!mqtt.connect(String(random(4294967295)).c_str(), USERNAME.c_str(), NULL)) {
return;
}
Serial.println("Connected to broker. Subbing.");
if (mqtt.subscribe(TEMP_TOPIC.c_str())) {
Serial.println("Subbed to " + TEMP_TOPIC + ".");
}
if (mqtt.subscribe(HUMIDITY_TOPIC.c_str())) {
Serial.println("Subbed to " + HUMIDITY_TOPIC + ".");
}
if (mqtt.subscribe(LED_TOPIC.c_str())) {
Serial.println("Subbed to " + LED_TOPIC + ".");
}
return;
}
mqtt.loop();
delay(200);
}