#include <Arduino.h>
#include <MQTT.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <ESP32httpUpdate.h>
#include <EEPROM.h>
#define FIRMWARE_VERSION 1.1
#define UPDATE_URL "http://10.17.101.41/ewsWL-firmware/firmware.json"
#define EEPROM_SIZE 512
TaskHandle_t firmwareTask;
const char* mqtt_server = "10.17.101.41";
const int mqtt_port = 1883;
const char* mqtt_username = "ESP_RFID";
const char* mqtt_password = "RFIDRND";
//const char* mqtt_server = "devbroker.balitower.co.id";
//const int mqtt_port = 1883;
//const char* mqtt_username = "devims";
//const char* mqtt_password = "devims-c0b4";
// const char* mqtt_server = "broker.emqx.io";
// const int mqtt_port = 1883;
const char* topic_ews = "EWS/Bandung/WaterLevel";
const char* topic_ews_2 = "EWS/Bandung/SurfaceWater";
const char* topic_ews_log = "EWS/Bandung/log";
const char* topic_firmware_status = "EWS/Bandung/firmware";
// const char* wifi_ssid = "RND";
// const char* wifi_password = "fYsjCeNq7DnvP3";
const char* wifi_ssid = "Wokwi-GUEST";
const char* wifi_password = "";
//const char* wifi_ssid = "hardware";
//const char* wifi_password = "hw_balitower_01";
const byte RELAY_PIN = 33;
const byte BUZZER = 32;
const byte buttonPin = 12;
const int LED_GREEN = 26;
const int LED_BLUE = 27;
bool panicSent = false;
bool relayActive = false;
unsigned long relayOnTime = 0;
WiFiClient wifiClient;
WiFiClient mqttClient;
MQTTClient client;
bool isWiFiConnected = false;
bool isMQTTConnected = false;
uint64_t uid = ESP.getEfuseMac();
void setup() {
Serial.begin(115200);
pinMode(RELAY_PIN, OUTPUT);
pinMode(BUZZER, OUTPUT);
pinMode(buttonPin, INPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_BLUE, LOW);
EEPROM.begin(EEPROM_SIZE);
clearEEPROM();
connectWiFi();
client.setWill("EWS/Bandung/588DECA", "Disconnected", true, 1);
connectMQTT();
client.onMessage(messageReceived);
client.subscribe(topic_ews);
client.subscribe(topic_ews_2);
xTaskCreatePinnedToCore(firmwareUpdateTask, "Firmware Update", 10000, NULL, 1, &firmwareTask, 0);
}
void loop() {
if (!WiFi.isConnected()) {
reconnectWiFi();
}
client.loop();
if (isWiFiConnected && !client.connected()) {
reconnectMQTT();
}
if (relayActive && (millis() - relayOnTime >= 3000)) {
digitalWrite(RELAY_PIN, LOW);
noTone(BUZZER);
relayActive = false;
}
delay(10);
}
void connectWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(wifi_ssid, wifi_password);
int timeout = 0;
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED && timeout < 30) {
digitalWrite(LED_GREEN, LOW);
Serial.print(".");
delay(500);
timeout++;
}
if(WiFi.status() == WL_CONNECTED) {
Serial.println("");
Serial.println("Successfully connected to Wi-Fi");
digitalWrite(LED_GREEN, HIGH);
Serial.print("Connected to WiFi. IP: ");
Serial.println(WiFi.localIP());
isWiFiConnected = true;
} else {
Serial.println("");
Serial.println("Failed to Connect to WiFi");
}
}
void reconnectWiFi() {
digitalWrite(LED_GREEN, LOW);
isWiFiConnected = false;
connectWiFi();
}
void connectMQTT() {
client.begin(mqtt_server, mqtt_port, mqttClient);
client.setOptions(120, true, 1000);
int timeout = 0;
Serial.print("Connecting to Broker");
while (!client.connect("WokwiEWS", mqtt_username, mqtt_password)&& timeout < 30) {
digitalWrite(LED_BLUE, LOW);
Serial.print(".");
delay(500);
timeout++;
}
if(client.connected()) {
Serial.println("");
Serial.println("Successfully Connected to Broker");
digitalWrite(LED_BLUE, HIGH);
isMQTTConnected = true;
client.publish("EWS/Bandung/588DECA", "Connected", true, 1);
} else {
Serial.println("");
Serial.println("Failed to Connect to Broker");
}
}
void reconnectMQTT() {
digitalWrite(LED_BLUE, LOW);
isMQTTConnected = false;
connectMQTT();
}
void messageReceived(String &topic, String &payload) {
Serial.println("Message received:");
Serial.println("Topic: " + topic);
Serial.println("Payload: " + payload);
if (topic.equals(topic_ews) || topic.equals(topic_ews_2)) {
payload.replace("\"", "");
payload.trim();
payload.toLowerCase();
bool relay_state = (payload == "true");
if (relay_state == true) {
String message = "Data Diterima Oleh EWS System";
client.publish(topic_ews_log, message);
}
if (relay_state == true && relayActive == false) {
digitalWrite(RELAY_PIN, HIGH);
tone(BUZZER, 262);
relayOnTime = millis();
relayActive = true;
}
if (relay_state == false){
digitalWrite(RELAY_PIN, LOW);
noTone(BUZZER);
}
}
}
void firmwareUpdateTask(void* parameter) {
while (true) {
checkFirmwareUpdate();
delay(60000);
}
}
void checkFirmwareUpdate() {
Serial.println("Checking Update");
HTTPClient http;
String response;
String url = UPDATE_URL;
http.begin(url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
response = http.getString();
Serial.println(response);
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, response);
if (!error) {
JsonObject obj = doc.as<JsonObject>();
String version = obj["version"];
String url_update = obj["url"];
if (version.toDouble() > FIRMWARE_VERSION) {
Serial.println("Update Available");
if (updateFirmware(url_update) == HTTP_UPDATE_OK) {
Serial.println("\nUpdate Success");
String message = "\nUpdate Success, Firmware V : " + String(FIRMWARE_VERSION);
client.publish(topic_firmware_status, message);
ESP.restart();
} else {
Serial.println("\nUpdate Failed");
String message = "\nUpdate Failed, Firmware V : " + String(FIRMWARE_VERSION);
client.publish(topic_firmware_status, message);
}
} else {
Serial.println("\nNo Update Available");
String message = "\nNo Update Available, Firmware V : " + String(FIRMWARE_VERSION);
client.publish(topic_firmware_status, message);
}
} else {
Serial.print("\ndeserializeJson() failed: ");
Serial.println(error.c_str());
}
} else {
Serial.printf("HTTP GET failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
t_httpUpdate_return updateFirmware(String url_update) {
t_httpUpdate_return ret = HTTP_UPDATE_FAILED;
if (WiFi.status() == WL_CONNECTED) {
ret = ESPhttpUpdate.update(url_update);
switch (ret) {
case HTTP_UPDATE_OK:
Serial.println("\n[update] Update OK.");
break;
case HTTP_UPDATE_NO_UPDATES:
Serial.println("\n[update] No Update.");
break;
default:
Serial.printf("\n[update] Update Failed. Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
break;
}
} else {
Serial.println("\n[update] WiFi not connected.");
}
return ret;
}
void clearEEPROM() {
for (int i = 0; i < EEPROM_SIZE; i++) {
EEPROM.write(i, 0);
}
EEPROM.commit();
}