#include <DHT.h>
#include <MQUnifiedsensor.h>
#include <ML8511.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ESP32Servo.h>
#include <TinyGPSPlus.h> // Library GPS yang digunakan
#define DHTPIN 2
#define DHTTYPE DHT22
#define PIRPIN 8
#define LDRPIN 3
#define BUZZERPIN 9
#define LEDPIN 19
#define RELAYPIN 7
#define MQ_PIN 10
#define ML8511_PIN A1
#define SERVOPIN 1
#define GPS_RX_PIN 16 // Pin RX ESP32-C3 ke TX GPS
#define GPS_TX_PIN 17 // Pin TX ESP32-C3 ke RX GPS (opsional jika diperlukan)
// Konfigurasi GPS
TinyGPSPlus gps;
HardwareSerial GPS(1); // Menggunakan UART1 untuk komunikasi GPS
#define Board "Arduino"
#define Voltage_Resolution 5
#define ADC_Bit_Resolution 10
#define RatioMQ2CleanAir 9.83
#define Type "MQ-2"
// WiFi dan MQTT
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqttServer = "thingsboard.cloud";
const int mqttPort = 1883;
const char* accessToken = "pmzsNwMI1rK19KOXdjIu";
WiFiClient espClient;
PubSubClient client(espClient);
// Threshold values
float thresholdTemp = 50;
float thresholdHumidity = 40;
float thresholdLux = 200;
float thresholdGasPPM = 1000;
float thresholdUV = 500;
// Sensor objects
DHT dht(DHTPIN, DHTTYPE);
MQUnifiedsensor MQ2(Board, Voltage_Resolution, ADC_Bit_Resolution, MQ_PIN, Type);
ML8511 ml8511(ML8511_PIN);
Servo evacuationServo;
// Function to generate random latitude and longitude within Indonesia
void generateRandomLocation(float &latitude, float &longitude) {
latitude = -11.0 + static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / (6.0 + 11.0)));
longitude = 95.0 + static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / (141.0 - 95.0)));
}
// Timing variables
unsigned long previousMillisBuzzer = 0;
unsigned long previousMillisLED = 0;
const long intervalBuzzer = 500;
const long intervalLED = 500;
// Function declarations
float calculateLux(int ldrValue) {
float voltage = (ldrValue / 1023.0) * Voltage_Resolution;
float lux = 500 / voltage;
return lux > 0 ? lux : 0;
}
float calculateUV(int uvValue) {
float voltage = (uvValue / 1023.0) * Voltage_Resolution;
float uvIntensity = (voltage - 1) * 15;
return uvIntensity > 0 ? uvIntensity : 0;
}
void connectToThingsBoard() {
while (!client.connected()) {
Serial.print("Connecting to ThingsBoard...");
if (client.connect("ESP32Client", accessToken, "")) {
Serial.println(" connected");
} else {
Serial.print(" failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void rpcCallback(char* topic, byte* payload, unsigned int length) {
String rpcRequest;
for (unsigned int i = 0; i < length; i++) {
rpcRequest += (char)payload[i];
}
Serial.print("Received RPC: ");
Serial.println(rpcRequest);
if (rpcRequest.indexOf("setRelay") > 0) {
bool relayState = rpcRequest.indexOf("true") > 0;
digitalWrite(RELAYPIN, relayState ? HIGH : LOW);
Serial.print("Relay set to: ");
Serial.println(relayState ? "ON" : "OFF");
}
if (rpcRequest.indexOf("setBuzzer") > 0) {
bool buzzerState = rpcRequest.indexOf("true") > 0;
digitalWrite(BUZZERPIN, buzzerState ? HIGH : LOW);
Serial.print("Buzzer set to: ");
Serial.println(buzzerState ? "ON" : "OFF");
}
if (rpcRequest.indexOf("openEvacuationDoor") > 0) {
bool doorState = rpcRequest.indexOf("true") > 0;
evacuationServo.write(doorState ? 90 : 0); // 90 untuk buka, 0 untuk tutup
Serial.print("Evacuation Door: ");
Serial.println(doorState ? "Opened" : "Closed");
}
}
void updateGPSLocation(float &latitude, float &longitude) {
// Cek apakah data GPS terhubung dan diperbarui
if (gps.location.isUpdated()) {
latitude = gps.location.lat(); // Mengambil latitude dari GPS
longitude = gps.location.lng(); // Mengambil longitude dari GPS
} else {
// Jika GPS tidak terhubung, menggunakan lokasi acak dalam rentang lebih besar
latitude = -6.2 + random(-5000, 5000) * 0.0001; // Menghasilkan latitude acak dalam rentang lebih luas
longitude = 106.8 + random(-5000, 5000) * 0.0001; // Menghasilkan longitude acak dalam rentang lebih luas
}
}
void setup() {
Serial.begin(115200);
GPS.begin(9600, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN); // Inisialisasi GPS
// Initialize sensors
dht.begin();
MQ2.init();
MQ2.setRegressionMethod(1);
MQ2.setA(574.25);
MQ2.setB(-2.222);
// Initialize pins
pinMode(PIRPIN, INPUT);
pinMode(BUZZERPIN, OUTPUT);
pinMode(LEDPIN, OUTPUT);
pinMode(RELAYPIN, OUTPUT);
evacuationServo.attach(SERVOPIN);
evacuationServo.write(0);
// Initialize WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to WiFi");
// Initialize MQTT
client.setServer(mqttServer, mqttPort);
client.setCallback(rpcCallback);
connectToThingsBoard();
}
void sendDataToThingsBoard(float temperature, float humidity, float luxValue, int pirValue, float lpg_ppm, float uvIntensity, float latitude, float longitude) {
String payload = "{";
payload += "\"temperature\":"; payload += temperature; payload += ",";
payload += "\"humidity\":"; payload += humidity; payload += ",";
payload += "\"lux\":"; payload += luxValue; payload += ",";
payload += "\"PIR\":"; payload += pirValue; payload += ",";
payload += "\"GAS\":"; payload += lpg_ppm; payload += ",";
payload += "\"UV\":"; payload += uvIntensity; payload += ",";
payload += "\"latitude\":"; payload += latitude; payload += ",";
payload += "\"longitude\":"; payload += longitude;
payload += "}";
char attributes[1000];
payload.toCharArray(attributes, 1000);
client.publish("v1/devices/me/telemetry", attributes);
client.publish("v1/devices/me/attributes", attributes);
Serial.println(attributes);
}
void loop() {
if (!client.connected()) {
connectToThingsBoard();
}
client.loop();
float h = dht.readHumidity() + random(-5, 5);
float t = dht.readTemperature() + random(-3, 3);
int ldrValue = analogRead(LDRPIN);
float luxValue = calculateLux(ldrValue) + random(-20, 20);
int pirValue = millis() % 4000 < 2000 ? 1 : 0;
MQ2.update();
float lpg_ppm = MQ2.readSensor() + random(-50, 50);
int uvValueRaw = analogRead(ML8511_PIN);
float uvIntensity = calculateUV(uvValueRaw) + random(-5, 5);
float latitude = 0.0, longitude = 0.0;
updateGPSLocation(latitude, longitude); // Memperbarui lokasi GPS atau acak
String status = "Normal";
if (t > thresholdTemp || h < thresholdHumidity || luxValue < thresholdLux ||
lpg_ppm > thresholdGasPPM || uvIntensity > thresholdUV || pirValue == 1) {
status = "Fire Detected";
digitalWrite(RELAYPIN, HIGH);
evacuationServo.write(90);
unsigned long currentMillisLED = millis();
if (currentMillisLED - previousMillisLED >= intervalLED) {
previousMillisLED = currentMillisLED;
digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}
unsigned long currentMillisBuzzer = millis();
if (currentMillisBuzzer - previousMillisBuzzer >= intervalBuzzer) {
previousMillisBuzzer = currentMillisBuzzer;
digitalWrite(BUZZERPIN, !digitalRead(BUZZERPIN));
}
} else {
digitalWrite(BUZZERPIN, LOW);
digitalWrite(LEDPIN, LOW);
digitalWrite(RELAYPIN, LOW);
evacuationServo.write(0);
}
sendDataToThingsBoard(t, h, luxValue, pirValue, lpg_ppm, uvIntensity, latitude, longitude);
Serial.print("Status: ");
Serial.println(status);
Serial.print("Suhu: ");
Serial.print(t);
Serial.print(" °C, Kelembapan: ");
Serial.print(h);
Serial.print("%, LDR Lux: ");
Serial.print(luxValue);
Serial.print(" lux, PIR: ");
Serial.print(pirValue);
Serial.print(", GAS: ");
Serial.print(lpg_ppm);
Serial.print(", UV Intensity: ");
Serial.print(uvIntensity);
Serial.print(", Latitude: ");
Serial.print(latitude, 6);
Serial.print(", Longitude: ");
Serial.println(longitude, 6);
delay(1000);
}