require("dotenv").config(); const mqtt = require("mqtt"); const express = require("express"); const db = require("./db"); const { Armed, Disarmed, Triggered, Arming, Disarming } = require("./state"); const app = express(); app.use(require("./routes")) app.use(express.static("public")); app.listen(process.env.PORT || 8080, () => { console.log(`Listening on port ${process.env.PORT || 8080}`); }); const mqttClient = mqtt.connect(process.env.MQTT, { clean: true, }); mqttClient.on("connect", (a) => { console.log(`Connected to ${process.env.MQTT}`); // mqttClient.publish("door/lock", JSON.stringify({ deviceId: 2, lock: true })); // setTimeout(() => { // mqttClient.publish("door/lock", JSON.stringify({ deviceId: 2, lock: false })); // }, 3000); mqttClient.publish("alarm/state", JSON.stringify({ status: alarmStatus })); // mqttClient.publish("alarm/state", JSON.stringify({ status: "Triggered" })); // setTimeout(() => { // mqttClient.publish("alarm/state", JSON.stringify({ status: "Arming" })); // }, 5000); }); mqttClient.subscribe("motion"); // mqttClient.subscribe("sound"); mqttClient.subscribe("temperature"); mqttClient.subscribe("light"); mqttClient.subscribe("door/status"); mqttClient.subscribe("display/arm"); mqttClient.subscribe("display/disarm"); function insertEvent(deviceId, eventType) { db.query(` INSERT INTO events (deviceId, type) VALUES ($1, $2) `, [ deviceId, eventType ]); } function triggerAlarm(deviceId) { mqttClient.publish("alarm/state", JSON.stringify({ status: Triggered })); alarmStatus = Triggered; console.log("Alarm has been triggered"); insertEvent(deviceId, Triggered); } function disarmingAlarm(deviceId) { mqttClient.publish("alarm/state", JSON.stringify({ status: Disarming })); alarmStatus = Disarming; console.log("Alarm has been set to Disarming"); timer = setTimeout(disarmingTimerRunout, 30, deviceId); insertEvent(deviceId, Disarming); } function disarmingTimerRunout(deviceId) { if (alarmStatus === Disarming) { triggerAlarm(deviceId); } } function armAlarm(deviceId) { mqttClient.publish("alarm/state", JSON.stringify({ status: Arming })); alarmStatus = Arming; console.log("Alarm has been set to Arming"); timer = setTimeout(armingTimerRunout, 30, deviceId); insertEvent(deviceId, Arming); } function armingTimerRunout(deviceId) { if (alarmStatus === Arming) { mqttClient.publish("alarm/state", JSON.stringify({ status: Armed })); mqttClient.publish("door/lock", JSON.stringify({ deviceId: 2, lock: true })); alarmStatus = Armed; console.log("Alarm has been set to Armed"); insertEvent(deviceId, Armed); } } function disarmAlarm(deviceId) { mqttClient.publish("alarm/state", JSON.stringify({ status: Disarmed })); mqttClient.publish("door/lock", JSON.stringify({ deviceId: 2, lock: false })); alarmStatus = Disarmed; clearTimeout(timer); console.log("Alarm has been set to Disarmed"); insertEvent(deviceId, Disarmed); } let timer; let alarmStatus = Armed; mqttClient.on("message", (topic, message) => { // console.log(topic, message.toString()); switch (topic) { case "motion": { const data = JSON.parse(message); if ((alarmStatus === Armed || alarmStatus === Triggered) && data.value === true) { console.log("motion"); triggerAlarm(data.deviceId); } break; } case "sound": { const data = JSON.parse(message); if (alarmStatus === Armed || alarmStatus === Triggered) { console.log("sound", data.value); triggerAlarm(data.deviceId); } break; } case "door/status": { const data = JSON.parse(message); console.log(data); if ((alarmStatus === Armed || alarmStatus === Triggered) && data.open === true) { console.log("door sensor"); disarmingAlarm(data.deviceId); } break; } case "arm": { const data = JSON.parse(message); armAlarm(data.deviceId); break; } case "disarm": { const data = JSON.parse(message); disarmAlarm(data.deviceId); break; } case "light": { const data = JSON.parse(message); db.query(` INSERT INTO light_measurements (deviceId, value) VALUES ($1, $2) `, [ data.deviceId, data.value ]); break; } case "temperature": { const data = JSON.parse(message); db.query(` INSERT INTO temperature_measurements (deviceId, value) VALUES ($1, $2) `, [ data.deviceId, data.value ]); break; } default: console.log("Unsupported topic received: " + topic); break; } });