//curl -u esp32test:esp32test -d {\"device\":\"lamp1\",\"trigger\":\"on\"} mqtt://161.97.110.178:1883/topicName/led
//curl -u esp32test:esp32test -d {\"device\":\"lamp1\",\"trigger\":\"off\"} mqtt://161.97.110.178:1883/topicName/led
//curl -u esp32test:esp32test -d {\"device\":\"lamp1\",\"trigger\":\"pulse\",\"ontime\":3} mqtt://161.97.110.178:1883/topicName/led
//curl -u esp32test:esp32test -d {\"device\":\"all\",\"trigger\":\"status\"} mqtt://161.97.110.178:1883/topicName/led
//http://161.97.110.178:18083/#/login?to=/dashboard/overview
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#define NTP_SERVER "pool.ntp.org"
#define UTC_OFFSET 0
#define UTC_OFFSET_DST 0
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqttServer = "161.97.110.178";//"broker.emqx.io"
const char* mqttUser = "esp32test";
const char* mqttPassword = "esp32test";
const int port = 1883;
String stMac;
char mac[50];
char clientId[50];
uint32_t chipid = ESP.getEfuseMac();
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change:
const long interval = 1000; // interval at which to blink (milliseconds)
int lamp1cmd = 0; //0 = no 1 = on 2 = off 3 = pulseon
int lamp1pulseduratinsec = 1; //pulse the output dealy in seconds
int lamp2cmd = 0; //0 = no 1 = on 2 = off 3 = pulseon
int lamp2pulseduratinsec = 1; //pulse the output dealy in seconds
int lamp3cmd = 0; //0 = no 1 = on 2 = off 3 = pulseon
int lamp3pulseduratinsec = 1; //pulse the output dealy in seconds
int lamp4cmd = 0; //0 = no 1 = on 2 = off 3 = pulseon
int lamp4pulseduratinsec = 1; //pulse the output dealy in seconds
int lampallcmd = 0; //0= no 1 = send status of all 4 relays.
WiFiClient espClient;
PubSubClient client(mqttServer, port, espClient);
//const int ledPin = 2;
//for output
const int lamp1 = 2; //lamp for mqtt connected D2
const int lamp2 = 4; //lamp for start indicator D4
const int lamp3 = 5; //lamp for stop indicator D5
const int lamp4 = 18; //lamp for stop indicator D18
// Relay Identification
enum Relay
{
Relay_00 = 0,
Relay_01 = 1,
Relay_02 = 2,
Relay_03 = 3
};
// Relay Id to Pin
enum RelayPin
{
Relay_00_Pin = 2,
Relay_01_Pin = 4,
Relay_02_Pin = 5,
Relay_03_Pin = 18
};
void setup() {
Serial.begin(115200);
delay(10);
Serial.println("Inside Setup");
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
wifiConnect();
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println(WiFi.macAddress());
stMac = WiFi.macAddress();
stMac.replace(":", "_");
Serial.println(stMac);
client.setSocketTimeout(60);
client.setKeepAlive(5);
client.setServer(mqttServer, port);
client.setCallback(callback);
//setup pin output
//pinMode(lamp1, OUTPUT);
//pinMode(lamp2, OUTPUT);
//pinMode(lamp3, OUTPUT);
//pinMode(lamp4, OUTPUT);
//Reset lamp, turn off all
//digitalWrite(lamp1, LOW);
//digitalWrite(lamp2, LOW);
//digitalWrite(lamp3, LOW);
//digitalWrite(lamp4, LOW);
// Setup PIN Mode for Relay
pinMode(Relay_00_Pin, OUTPUT);
pinMode(Relay_01_Pin, OUTPUT);
pinMode(Relay_02_Pin, OUTPUT);
pinMode(Relay_03_Pin, OUTPUT);
// Init Relay
digitalWrite(Relay_00_Pin, LOW);
digitalWrite(Relay_01_Pin, LOW);
digitalWrite(Relay_02_Pin, LOW);
digitalWrite(Relay_03_Pin, LOW);
configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
}
void wifiConnect() {
Serial.println("Inside wifiConnect");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
}
void mqttReconnect() {
Serial.println("Inside mqttReconnect");
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
snprintf(clientId, 25, "ESP32-%08X", chipid);
if (client.connect(clientId, mqttUser, mqttPassword )) {
Serial.println(clientId);
Serial.println(" connected");
client.subscribe("topicName/led");
StaticJsonDocument<200> relayStatus;
relayStatus["clientId"] = clientId;
relayStatus["time"] = Get_Epoch_Time();
relayStatus["command"] = "Connection";
relayStatus["message"] = "Reconnecting";
char relayStatusAsJson[200];
serializeJson(relayStatus, relayStatusAsJson);
client.publish("topicName/ledstatus", relayStatusAsJson);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void callback(char* topic, byte* message, unsigned int length) {
Serial.println("Inside callback");
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String json_received;
for (int i = 0; i < length; i++) {
json_received += (char)message[i];
}
Serial.println(json_received);
//Parse json
StaticJsonDocument<256> doc;
deserializeJson(doc, message, length);
JsonObject documentRoot = doc.as<JsonObject>();
//get json parsed value
//sample of json: {"device":"lamp1","trigger":"on","ontime":2}
Serial.print("Command:");
String device = documentRoot["device"];
String trigger = documentRoot["trigger"];
int pulseonsec = documentRoot["ontime"];
Serial.println("Turn " + trigger + " " + device);
Serial.println("-----------------------");
if (device == "lamp1") {
//Lamp1***************************
if (trigger == "on")
{
lamp1cmd = 1;
} else if (trigger == "off")
{
lamp1cmd = 2;
} else if (trigger == "pulse")
{
lamp1cmd = 3;
lamp1pulseduratinsec = pulseonsec;
} else if (trigger == "status")
{
lamp1cmd = 5;
lamp1pulseduratinsec = pulseonsec;
}
}
if (device == "lamp2") {
//Lamp2***************************
if (trigger == "on")
{
lamp2cmd = 1;
} else if (trigger == "off")
{
lamp2cmd = 2;
} else if (trigger == "pulse")
{
lamp2cmd = 3;
lamp2pulseduratinsec = pulseonsec;
}
}
if (device == "lamp3") {
//Lamp3***************************
if (trigger == "on")
{
lamp3cmd = 1;
} else if (trigger == "off")
{
lamp3cmd = 2;
} else if (trigger == "pulse")
{
lamp3cmd = 3;
lamp3pulseduratinsec = pulseonsec;
}
}
if (device == "lamp4") {
//Lamp3***************************
if (trigger == "on")
{
lamp4cmd = 1;
} else if (trigger == "off")
{
lamp4cmd = 2;
} else if (trigger == "pulse")
{
lamp4cmd = 3;
lamp4pulseduratinsec = pulseonsec;
}
}
if (device == "all") {
//All***************************
if (trigger == "status")
{
lampallcmd = 1;
}
}
//Serial.println(lamp1cmd);
//Serial.println(lamp2cmd);
//Serial.println(lamp3cmd);
//Serial.println(lamp4cmd);
}
void swTick() {
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// Every second tick
previousMillis = currentMillis;
//process the commnads and io tasks
if (lamp1cmd == 4) {
lamp1pulseduratinsec--;
if (lamp1pulseduratinsec < 0) {
digitalWrite(Relay_00_Pin, LOW);
lamp1cmd = 0;
}
}
if (lamp2cmd == 4) {
lamp2pulseduratinsec--;
if (lamp2pulseduratinsec < 0) {
digitalWrite(Relay_01_Pin, LOW);
lamp2cmd = 0;
}
}
if (lamp3cmd == 4) {
lamp3pulseduratinsec--;
if (lamp3pulseduratinsec < 0) {
digitalWrite(Relay_02_Pin, LOW);
lamp3cmd = 0;
}
}
if (lamp4cmd == 4) {
lamp4pulseduratinsec--;
if (lamp4pulseduratinsec < 0) {
digitalWrite(Relay_03_Pin, LOW);
lamp4cmd = 0;
}
}
if ((WiFi.status() != WL_CONNECTED)) {
Serial.print(millis());
Serial.println("Reconnecting to WiFi...");
WiFi.disconnect();
WiFi.reconnect();
}
printLocalTime();
}
switch (lamp1cmd) {
case 1:
digitalWrite(Relay_00_Pin, HIGH);
lamp1cmd = 0;
break;
case 2:
digitalWrite(Relay_00_Pin, LOW);
lamp1cmd = 0;
break;
case 3:
digitalWrite(Relay_00_Pin, HIGH);
lamp1cmd = 4;
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
switch (lamp2cmd) {
case 1:
digitalWrite(Relay_01_Pin, HIGH);
lamp2cmd = 0;
break;
case 2:
digitalWrite(Relay_01_Pin, LOW);
lamp2cmd = 0;
break;
case 3:
digitalWrite(Relay_01_Pin, HIGH);
lamp2cmd = 4;
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
switch (lamp3cmd) {
case 1:
digitalWrite(Relay_02_Pin, HIGH);
lamp3cmd = 0;
break;
case 2:
digitalWrite(Relay_02_Pin, LOW);
lamp3cmd = 0;
break;
case 3:
digitalWrite(Relay_02_Pin, HIGH);
lamp3cmd = 4;
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
switch (lamp4cmd) {
case 1:
digitalWrite(Relay_03_Pin, HIGH);
lamp4cmd = 0;
break;
case 2:
digitalWrite(Relay_03_Pin, LOW);
lamp4cmd = 0;
break;
case 3:
digitalWrite(Relay_03_Pin, HIGH);
lamp4cmd = 4;
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
if (lampallcmd == 1) {
StaticJsonDocument<200> relayStatus;
relayStatus["clientId"] = clientId;
relayStatus["time"] = Get_Epoch_Time();
relayStatus["command"] = "Status";
//relayStatus["relayId"] = 1;
//relayStatus["status"] = digitalRead(Relay_01_Pin);
JsonArray relaysStatusJsonArray = relayStatus.createNestedArray("output");
int * relaysStatus = get_relays_status();
for (int i = 0; i <= 3; i++)
{
relaysStatusJsonArray.add(relaysStatus[i]);
}
char relayStatusAsJson[200];
serializeJson(relayStatus, relayStatusAsJson);
client.publish("topicName/ledstatus", relayStatusAsJson);
lampallcmd = 0;
}
}
/**
* Return the relays status
*/
int * get_relays_status()
{
static int relaysStatus[4];
digitalRead(Relay_00_Pin) == LOW ? relaysStatus[0] = LOW : relaysStatus[0] = HIGH;
digitalRead(Relay_01_Pin) == LOW ? relaysStatus[1] = LOW : relaysStatus[1] = HIGH;
digitalRead(Relay_02_Pin) == LOW ? relaysStatus[2] = LOW : relaysStatus[2] = HIGH;
digitalRead(Relay_03_Pin) == LOW ? relaysStatus[3] = LOW : relaysStatus[3] = HIGH;
return relaysStatus;
}
void printLocalTime() {
Serial.println("Inside printLocalTime");
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Connection Err");
return;
}
Serial.println(&timeinfo, "%d%m%Y%H%M%S%Z");
//Serial.println(&timeinfo, "%d/%m/%Y %Z");
//Serial.println(lamp1cmd);
//Serial.println(lamp2cmd);
//Serial.println(lamp3cmd);
//Serial.println(lamp4cmd);
//Serial.println(lampallcmd);
}
// Get_Epoch_Time() Function that gets current epoch time
unsigned long Get_Epoch_Time() {
time_t now;
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
//Serial.println("Failed to obtain time");
return (0);
}
time(&now);
return now;
}
void loop() {
//delay(10);
swTick();
if (!client.connected()) {
mqttReconnect();
}
client.loop();
}