#include <WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <HTTPClient.h>
// --- Pin Definitions ---
#define DHTPIN 4
#define DHTTYPE DHT22
#define BUTTON_ARRIVAL 25
#define BUTTON_DISPATCH 26
// --- Hardware ---
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);
// --- Network Credentials ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
const char* firebaseHost = "https://medisupply-dd526-default-rtdb.firebaseio.com/";
// --- MQTT Client ---
WiFiClient espClient;
PubSubClient client(espClient);
// --- Timing ---
unsigned long lastSensorSend = 0;
unsigned long lastEventSend = 0;
const unsigned long sensorInterval = 10000; // 10 seconds
const unsigned long eventInterval = 20000; // 20 seconds
// --- Counters ---
int dispatchedCount = 0;
int receivedCount = 0;
// --- Button Lockouts ---
bool arrivalSent = false;
bool dispatchSent = false;
// --- WiFi Setup ---
void setup_wifi() {
Serial.print("š Connecting to WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nā
WiFi connected");
}
// --- Firebase Send ---
void sendToFirebase(const String& path, const String& jsonPayload) {
HTTPClient http;
String url = String(firebaseHost) + path;
http.begin(url);
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(jsonPayload);
if (httpCode > 0) {
String response = http.getString();
Serial.println("ā
Firebase Response: " + response);
} else {
Serial.println("ā Firebase Error: " + String(httpCode));
}
http.end();
}
// --- MQTT Callback (not used, but logged) ---
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("š„ MQTT Msg [");
Serial.print(topic);
Serial.print("]: ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
// --- MQTT Reconnect ---
void reconnect() {
while (!client.connected()) {
Serial.print("š Reconnecting to MQTT...");
if (client.connect("ESP32Client")) {
Serial.println("ā
Connected to MQTT broker");
client.subscribe("medical/supply/command");
} else {
Serial.print("ā Failed (");
Serial.print(client.state());
Serial.println(") ā retrying in 2s");
delay(2000);
}
}
}
void setup() {
Serial.begin(115200);
dht.begin();
lcd.init();
lcd.backlight();
pinMode(BUTTON_ARRIVAL, INPUT_PULLUP);
pinMode(BUTTON_DISPATCH, INPUT_PULLUP);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
lcd.setCursor(0, 0);
lcd.print("System Ready...");
delay(1500);
lcd.clear();
}
void loop() {
if (!client.connected()) reconnect();
client.loop();
unsigned long now = millis();
// --- Handle Arrival ---
if (digitalRead(BUTTON_ARRIVAL) == LOW && !arrivalSent) {
arrivalSent = true;
receivedCount++;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Item Received");
Serial.println("š¦ Item Received");
String payload = "{\"event\":\"arrival\",\"timestamp\":" + String(now) + "}";
client.publish("medical/supply/event", payload.c_str(), true);
sendToFirebase("/events.json", payload);
Serial.println("š¤ Sent to MQTT: " + payload);
delay(500);
}
if (digitalRead(BUTTON_ARRIVAL) == HIGH) arrivalSent = false;
// --- Handle Dispatch ---
if (digitalRead(BUTTON_DISPATCH) == LOW && !dispatchSent) {
dispatchSent = true;
dispatchedCount++;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Item Dispatched");
Serial.println("š Item Dispatched");
String payload = "{\"event\":\"dispatch\",\"timestamp\":" + String(now) + "}";
client.publish("medical/supply/event", payload.c_str(), true);
sendToFirebase("/events.json", payload);
Serial.println("š¤ Sent to MQTT: " + payload);
delay(500);
}
if (digitalRead(BUTTON_DISPATCH) == HIGH) dispatchSent = false;
// --- Send Temp & Humidity ---
if (now - lastSensorSend > sensorInterval) {
lastSensorSend = now;
float h = dht.readHumidity();
float t = dht.readTemperature();
if (!isnan(h) && !isnan(t)) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(t, 1);
lcd.print("C");
lcd.setCursor(0, 1);
lcd.print("Hum: ");
lcd.print(h, 1);
lcd.print("%");
String payload = "{\"temperature\":" + String(t, 1) + ",\"humidity\":" + String(h, 1) + "}";
client.publish("medical/supply/monitor", payload.c_str(), true);
sendToFirebase("/monitor.json", payload);
Serial.println("š”ļø Sent to MQTT: " + payload);
} else {
Serial.println("ā ļø DHT read failed");
}
}
// --- Send Summary Counts ---
if (now - lastEventSend > eventInterval) {
lastEventSend = now;
String payload = "{\"summary\":{\"dispatched\":" + String(dispatchedCount) +
",\"received\":" + String(receivedCount) + "}}";
client.publish("medical/supply/summary", payload.c_str(), true);
sendToFirebase("/summary.json", payload);
Serial.println("š Sent summary to MQTT: " + payload);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Total Sent: ");
lcd.print(dispatchedCount);
lcd.setCursor(0, 1);
lcd.print("Total Recv: ");
lcd.print(receivedCount);
}
}