#include struct Sensor { uint8_t pin; const char* id; int lastState; unsigned long lastChangeMs; }; Sensor sensors[] = { {2, "back_door", HIGH, 0}, {3, "gate", HIGH, 0}, {4, "garage", HIGH, 0}, {5, "front_door", HIGH, 0} }; const uint8_t SENSOR_COUNT = sizeof(sensors) / sizeof(sensors[0]); const unsigned long POLL_INTERVAL_MS = 200; // sampling rate const unsigned long DEBOUNCE_DELAY_MS = 200; const unsigned long HEARTBEAT_MS = 30000; unsigned long lastPollTime = 0; unsigned long lastHeartbeatMs = 0; void setup() { Serial.begin(9600); for (uint8_t i = 0; i < SENSOR_COUNT; i++) { pinMode(sensors[i].pin, INPUT_PULLUP); sensors[i].lastState = digitalRead(sensors[i].pin); sensors[i].lastChangeMs = millis(); // Emit baseline state on startup sendEvent(sensors[i].id, sensors[i].lastState); } } void loop() { unsigned long now = millis(); if (now - lastPollTime >= POLL_INTERVAL_MS) { lastPollTime = now; for (uint8_t i = 0; i < SENSOR_COUNT; i++) { int currentState = digitalRead(sensors[i].pin); if (currentState != sensors[i].lastState && now - sensors[i].lastChangeMs >= DEBOUNCE_DELAY_MS) { sensors[i].lastChangeMs = now; sensors[i].lastState = currentState; sendEvent(sensors[i].id, currentState); } } } // heartbeat (lets backend detect device death) if (now - lastHeartbeatMs >= HEARTBEAT_MS) { lastHeartbeatMs = now; sendHeartbeat(); } } void sendEvent(const char* sensorId, int state) { Serial.print("{\"type\":\"SENSOR\",\"sensorId\":\""); Serial.print(sensorId); Serial.print("\",\"state\":\""); Serial.print(state == LOW ? "CLOSED" : "OPEN"); Serial.print("\",\"ts\":"); Serial.print(millis()); Serial.println("}"); } void sendHeartbeat() { Serial.print("{\"type\":\"HEARTBEAT\",\"ts\":"); Serial.print(millis()); Serial.println("}"); }