diff --git a/main.js b/main.js deleted file mode 100644 index 0e340f03ad445f15d684ef5ba8455a085a80dc3f..0000000000000000000000000000000000000000 --- a/main.js +++ /dev/null @@ -1,338 +0,0 @@ -// added 2025-05-24 [ROY] for fixing error-state npm program -require('dotenv').config() -const mqtt = require('mqtt'); -const http = require('http'); -const fs = require('node:fs'); -const crypto = require("crypto"); - -// Prepend timestamp and severity to all console messages -require('console-stamp')(console); - -class DoorInfo { - state = null; - opener = null; - lastChange = null; - history = []; - historyEnabled = false; -} - -const web_host = process.env.HTTP_BIND; -const web_port = process.env.HTTP_PORT; - -const mqtt_host = process.env.MQTT_HOST; -const mqtt_port = process.env.MQTT_PORT; - -// Use a randomized client ID to avoid collisions, as we don't need any kind -// of session resumption -const clientId = crypto.randomUUID(); - -// Create an MQTT client instance -const options = { - clean: true, - connectTimeout: 5000, - clientId: clientId, - username: process.env.MQTT_USER, - password: process.env.MQTT_PASS, -}; - -const client = mqtt.connect(`mqtt://${mqtt_host}:${mqtt_port}`, options); - -client.on('connect', () => { - console.log(`Connected to MQTT broker ${mqtt_host}!`); - client.subscribe('door/#', () => {}); -}); - -let doors = { - 'ucc-door': new DoorInfo(), - 'unisfa-door': new DoorInfo(), - 'uwaes-door': new DoorInfo(), -}; - -doors['ucc-door'].historyEnabled = true; -doors['uwaes-door'].historyEnabled = false; -doors['unisfa-door'].historyEnabled = false; - -// Load history from file if it exists -const loadHistory = () => { - try { - const history = JSON.parse(fs.readFileSync(`${__dirname}/door_history.json`, 'utf8')); - for (const [door, info] of Object.entries(history)) { - if (!doors[door]) continue; - doors[door].history = info.history || []; - } - console.log('Loaded door history from file'); - } catch (err) { - console.log('No history file found, starting fresh'); - } -}; - -// Save history to file -const saveHistory = () => { - const history = {}; - for (const [door, info] of Object.entries(doors)) { - history[door] = { - history: info.history - }; - } - fs.writeFileSync(`${__dirname}/door_history.json`, JSON.stringify(history, null, 2)); - console.log('Saved door history to file'); -}; - -const update_door_state = (door, state) => { - if (doors[door] === undefined) { - console.log(`Tried to update state for unknown door ${door}`); - return; - } - - const oldState = doors[door].state; - - switch (state) { - case "ON": - console.log(`Door ${door} opened!`); - doors[door].state = true; - break; - - case "OFF": - console.log(`Door ${door} closed!`); - doors[door].state = false; - break; - - default: - console.log(`Unknown message received for door ${door}`); - return; - } - - // Only update lastChange if the state actually changed - if (oldState !== doors[door].state) { - const timestamp = new Date().toISOString(); - doors[door].lastChange = timestamp; - - // Add to history - doors[door].history.unshift({ - timestamp, - state: doors[door].state, - opener: doors[door].opener - }); - - // Keep only last 1000 changes - if (doors[door].history.length > 1000) { - doors[door].history = doors[door].history.slice(0, 1000); - } - - // Save history to file - saveHistory(); - } -}; - -const update_door_opener = (door, opener) => { - if (doors[door] === undefined) { - console.log(`Tried to update opener for unknown door ${door}`); - return; - } - - if (opener) { - console.log(`Marked door ${door} as opened by ${opener}`); - doors[door].opener = opener; - - if (doors[door].state && doors[door].history.length > 0) { - doors[door].history[0].timestamp = new Date().toISOString(); - doors[door].history[0].opener = opener; - saveHistory(); - } - } -}; - -// Receive messages -client.on('message', (topic, message) => { - console.log(`Received message on topic ${topic}`); - - const topicparts = topic.split('/'); - if (topicparts.length != 3) { - console.log(`Unknown topic ${topic} received`); - return; - } - - if (topicparts[0] === 'door' && topicparts[2] === 'state') { - update_door_state(topicparts[1], message.toString()); - } - else if (topicparts[0] === 'door' && topicparts[2] === 'opener') { - update_door_opener(topicparts[1], message.toString()); - } - else { - console.log(`Unknown topic ${topic} received`); - - } -}); - -const send_error = (res, code) => { - res.writeHead(code); - res.end(); -}; - -const send_redirect = (res, code, loc) => { - res.writeHead(code, {'Location': loc}); - res.end(); -}; - -const send_json = (res, code, data) => { - res.writeHead(code, {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'}); - res.end(JSON.stringify(data)); -}; - -const send_file = (res, code, fname, ctype) => { - const data = fs.readFileSync(fname); - - res.writeHead(code, {'Content-Type': ctype}); - res.end(data); -}; - -const handleHistoryRequest = (req, res, door) => { - const n = parseInt(req.url.split('/').pop()); - if (isNaN(n) || n <= 0) { - return send_json(res, 400, { error: 'Invalid number of changes requested' }); - } - - const history = doors[door].history.slice(0, n); - return send_json(res, 200, history); -}; - -const handleLastChangeRequest = (res, door) => { - if (doors[door].lastChange === null) { - return send_json(res, 500, null); - } - - return send_json(res, 200, { - lastChange: doors[door].lastChange, - state: doors[door].state - }); -}; - -const handleStateRequest = (req, res) => { - const parts = req.url.split('/').filter(Boolean); - if (parts.length < 2) return send_error(res, 404); - - const door = parts[1]; - const doorId = `${door}-door`; - - if (!doors[doorId]) { - return send_error(res, 404); - } - - if (parts.length === 2) { - // handle /state/{door} - if (doors[doorId].state === null) { - return send_json(res, 500, null); - } - return send_json(res, 200, doors[doorId].state); - } - - if (parts[2] === 'lastchange') { - return handleLastChangeRequest(res, doorId); - } - - if (parts[2] === 'history') { - if (!doors[doorId].historyEnabled) { - return send_error(res, 404); - } - if (parts.length !== 4) return send_error(res, 404); - return handleHistoryRequest(req, res, doorId); - } - - return send_error(res, 404); -}; - -// Serve state on http -const server = http.createServer((req, res) => { - console.log(`Serving request for ${req.url}`); - - if (req.method !== 'GET') { - return send_error(res, 400); - } - - if (req.url === '/') { - return send_redirect(res, 307, '/ucc'); - } - - if (req.url === '/ucc') { - if (doors['ucc-door'].state === null) { - return send_file(res, 500, './pages/ucc_door_unavail.html', 'text/html'); - } - - const fname = doors['ucc-door'].state ? './pages/ucc_door_open.html' : './pages/ucc_door_closed.html'; - return send_file(res, 200, fname, 'text/html'); - } - - if (req.url === '/unisfa') { - if (doors['unisfa-door'].state === null) { - return send_file(res, 500, './pages/unisfa_door_unavail.html', 'text/html'); - } - - const fname = doors['unisfa-door'].state ? './pages/unisfa_door_open.html' : './pages/unisfa_door_closed.html'; - return send_file(res, 200, fname, 'text/html'); - } - - if (req.url === '/uwaes') { - if (doors['uwaes-door'].state === null) { - return send_file(res, 500, './pages/uwaes_door_unavail.html', 'text/html'); - } - - const fname = doors['uwaes-door'].state ? './pages/uwaes_door_open.html' : './pages/uwaes_door_closed.html'; - return send_file(res, 200, fname, 'text/html'); - } - - if (req.url.startsWith('/state/')) { - return handleStateRequest(req, res); - } - - if (req.url === '/opener/ucc') { - if (doors['ucc-door'].opener === null) { - return send_json(res, 500, null); - } - - return send_json(res, 200, doors['ucc-door'].state ? doors['ucc-door'].opener : null); - } - - if (req.url === '/static/door_ucc_open.jpg') { - return send_file(res, 200, './static/door_ucc_open.jpg', 'image/jpeg'); - } - - if (req.url === '/static/door_ucc_closed.jpg') { - return send_file(res, 200, './static/door_ucc_closed.jpg', 'image/jpeg'); - } - - if (req.url === '/static/door_unisfa_open.jpg') { - return send_file(res, 200, './static/door_unisfa_open.jpg', 'image/jpeg'); - } - - if (req.url === '/static/door_unisfa_closed.jpg') { - return send_file(res, 200, './static/door_unisfa_closed.jpg', 'image/jpeg'); - } - - if (req.url === '/static/door_uwaes_open.jpg') { - return send_file(res, 200, './static/door_uwaes_open.jpg', 'image/jpeg'); - } - - if (req.url === '/static/door_uwaes_closed.jpg') { - return send_file(res, 200, './static/door_uwaes_closed.jpg', 'image/jpeg'); - } - - if (req.url === '/static/style.css') { - return send_file(res, 200, './static/style.css', 'text/css'); - } - - if (req.url === '/static/darkmode.js') { - return send_file(res, 200, './static/darkmode.js', 'text/javascript'); - } - - return send_error(res, 404); -}); - -// Load history when server starts -loadHistory(); - -// Run the server -server.listen(web_port, web_host, () => { - console.log(`HTTP server started on http://${web_host}:${web_port}`); -}); - -// vim: set ts=2 sts=2 sw=2 et: diff --git a/package.json b/package.json deleted file mode 100644 index 6b491a0c97ad01995df46070d2e5645ae22956df..0000000000000000000000000000000000000000 --- a/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "@ucc/doorsense", - "private": true, - "dependencies": { - "console-stamp": "^3.1.2", - "dotenv": "^16.5.0", - "mqtt": "^5.10.1", - "package.json": "^2.0.1" - }, - "scripts": { - "start": "node main.js" - } -} diff --git a/pages/ucc_door_closed.html b/pages/ucc_door_closed.html deleted file mode 100644 index f97bb8c0c70207b3e1f3fd03324a08b54bb4c4e8..0000000000000000000000000000000000000000 --- a/pages/ucc_door_closed.html +++ /dev/null @@ -1,23 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <title>UCC Door Status</title> - <link rel="stylesheet" href="/static/style.css"> - </head> - <body> - <p><a href="#light">lightmode</a> <a href="#dark">darkmode</a></p> - <h1>UCC Door Status</h1> - <p>The door is currently closed.</p> - <img - src="/static/door_ucc_closed.jpg" - width="574" - height="1020" - alt="A plain image of the UCC door. Surely nothing sinister lies within..." - title="A plain image of the UCC door. Surely nothing sinister lies within..." - > - <script src="/static/darkmode.js"></script> - </body> -</html> - -<!-- vim: set ts=2 sts=2 sw=2 et: --> diff --git a/pages/ucc_door_open.html b/pages/ucc_door_open.html deleted file mode 100644 index b8dc468d709d6960313277abb78eeb70f8003ef4..0000000000000000000000000000000000000000 --- a/pages/ucc_door_open.html +++ /dev/null @@ -1,33 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <title>UCC Door Status</title> - <link rel="stylesheet" href="/static/style.css"> - </head> - <body> - <p><a href="#light">lightmode</a> <a href="#dark">darkmode</a></p> - <h1>UCC Door Status</h1> - <p>The door is currently open!</p> - <p>Opened by: <span id="opener"></span></p> - <img - src="/static/door_ucc_open.jpg" - width="574" - height="1020" - alt="A wild Gary lurking in the open doorway to the UCC clubroom." - title="A wild Gary lurking in the open doorway to the UCC clubroom." - > - <script> - fetch('/opener/ucc').then(response => { - response.json().then(opener => { - if (opener) { - document.getElementById('opener').innerText = opener; - } - }); - }); - </script> - <script src="/static/darkmode.js"></script> - </body> -</html> - -<!-- vim: set ts=2 sts=2 sw=2 et: --> diff --git a/pages/ucc_door_unavail.html b/pages/ucc_door_unavail.html deleted file mode 100644 index 8ea943d9a0969e9cf088db9d363c209609a733fd..0000000000000000000000000000000000000000 --- a/pages/ucc_door_unavail.html +++ /dev/null @@ -1,16 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <title>UCC Door Status</title> - <link rel="stylesheet" href="/static/style.css"> - </head> - <body> - <p><a href="#light">lightmode</a> <a href="#dark">darkmode</a></p> - <h1>UCC Door Status</h1> - <p>The door sensor is currently unavailable. Sorry :-(</p> - <script src="/static/darkmode.js"></script> - </body> -</html> - -<!-- vim: set ts=2 sts=2 sw=2 et: --> diff --git a/pages/unisfa_door_closed.html b/pages/unisfa_door_closed.html deleted file mode 100644 index 28b29de1c196b4c66f393f5fe1c654aab2e9aa76..0000000000000000000000000000000000000000 --- a/pages/unisfa_door_closed.html +++ /dev/null @@ -1,23 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <title>Unisfa Door Status</title> - <link rel="stylesheet" href="/static/style.css"> - </head> - <body> - <p><a href="#light">lightmode</a> <a href="#dark">darkmode</a></p> - <h1>Unisfa Door Status</h1> - <p>The door is currently closed.</p> - <img - src="/static/door_unisfa_closed.jpg" - width="756" - height="1008" - alt="A plain image of the Unisfa door. There are some posters stuck upon it." - title="A plain image of the Unisfa door. There are some posters stuck upon it." - > - <script src="/static/darkmode.js"></script> - </body> -</html> - -<!-- vim: set ts=2 sts=2 sw=2 et: --> diff --git a/pages/unisfa_door_open.html b/pages/unisfa_door_open.html deleted file mode 100644 index 0bb2161c7a529d7a45b59b3ef3247f2eb12b258d..0000000000000000000000000000000000000000 --- a/pages/unisfa_door_open.html +++ /dev/null @@ -1,23 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <title>Unisfa Door Status</title> - <link rel="stylesheet" href="/static/style.css"> - </head> - <body> - <p><a href="#light">lightmode</a> <a href="#dark">darkmode</a></p> - <h1>Unisfa Door Status</h1> - <p>The door is currently open!</p> - <img - src="/static/door_unisfa_open.jpg" - width="756" - height="1008" - alt="The door is open, however the Guardian of the Books blocks your path. Tread carefully..." - title="The door is open, however the Guardian of the Books blocks your path. Tread carefully..." - > - <script src="/static/darkmode.js"></script> - </body> -</html> - -<!-- vim: set ts=2 sts=2 sw=2 et: --> diff --git a/pages/unisfa_door_unavail.html b/pages/unisfa_door_unavail.html deleted file mode 100644 index a445da55c8726a3d7c2796b7a7f5144509132fd5..0000000000000000000000000000000000000000 --- a/pages/unisfa_door_unavail.html +++ /dev/null @@ -1,16 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <title>Unisfa Door Status</title> - <link rel="stylesheet" href="/static/style.css"> - </head> - <body> - <p><a href="#light">lightmode</a> <a href="#dark">darkmode</a></p> - <h1>Unisfa Door Status</h1> - <p>The door sensor is currently unavailable. Sorry :-(</p> - <script src="/static/darkmode.js"></script> - </body> -</html> - -<!-- vim: set ts=2 sts=2 sw=2 et: --> diff --git a/pages/uwaes_door_closed.html b/pages/uwaes_door_closed.html deleted file mode 100644 index a4424a64e6ab24a71f3c48a7d7d0c92fef2d4635..0000000000000000000000000000000000000000 --- a/pages/uwaes_door_closed.html +++ /dev/null @@ -1,23 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <title>UWA Esports Door Status</title> - <link rel="stylesheet" href="/static/style.css"> - </head> - <body> - <p><a href="#light">lightmode</a> <a href="#dark">darkmode</a></p> - <h1>UWA Esports Door Status</h1> - <p>The door is currently closed.</p> - <img - src="/static/door_uwaes_closed.jpg" - width="756" - height="1008" - alt="Who is it that lies in wait behind the door?" - title="Who is it that lies in wait behind the door?" - > - <script src="/static/darkmode.js"></script> - </body> -</html> - -<!-- vim: set ts=2 sts=2 sw=2 et: --> diff --git a/pages/uwaes_door_open.html b/pages/uwaes_door_open.html deleted file mode 100644 index 0fd400eea8e1990d8406546ad30a07dbd2080ba6..0000000000000000000000000000000000000000 --- a/pages/uwaes_door_open.html +++ /dev/null @@ -1,23 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <title>UWA Esports Door Status</title> - <link rel="stylesheet" href="/static/style.css"> - </head> - <body> - <p><a href="#light">lightmode</a> <a href="#dark">darkmode</a></p> - <h1>UWA Esports Door Status</h1> - <p>The door is currently open!</p> - <img - src="/static/door_uwaes_open.jpg" - width="756" - height="1008" - alt="It is he, wearer of many hats. Beware!" - title="It is he, wearer of many hats. Beware!" - > - <script src="/static/darkmode.js"></script> - </body> -</html> - -<!-- vim: set ts=2 sts=2 sw=2 et: --> diff --git a/pages/uwaes_door_unavail.html b/pages/uwaes_door_unavail.html deleted file mode 100644 index 92c30ab9923aa308b68f165bd838b4fbaad40686..0000000000000000000000000000000000000000 --- a/pages/uwaes_door_unavail.html +++ /dev/null @@ -1,16 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <title>UWA Esports Door Status</title> - <link rel="stylesheet" href="/static/style.css"> - </head> - <body> - <p><a href="#light">lightmode</a> <a href="#dark">darkmode</a></p> - <h1>UWA Esports Door Status</h1> - <p>The door sensor is currently unavailable. Sorry :-(</p> - <script src="/static/darkmode.js"></script> - </body> -</html> - -<!-- vim: set ts=2 sts=2 sw=2 et: --> diff --git a/src/dispense_door_opener_lookup.sh b/src/dispense_door_opener_lookup.sh index 1efd061db1ff6aff44c547cb3e6f75c6b0e1d234..995e674ad635d042f5b11e2992857045e34bbd0c 100755 --- a/src/dispense_door_opener_lookup.sh +++ b/src/dispense_door_opener_lookup.sh @@ -33,6 +33,6 @@ inotifywait -m -e close_write "$COKELOGFILE" | while read -r filename event even done <<<"$lines" offset+=10 done - mosquitto_pub -h "$MQTT_HOST" -p "$MQTT_PORT" --username "$MQTT_USER" --pw "$MQTT_PASS" -t "door/ucc-door/opener" -m "$opener" + mosquitto_pub -h "$MQTT_HOST" -p "$MQTT_PORT" --username "$MQTT_USER" --pw "$MQTT_PASS" -t "door/ucc-door/openedby" -m "$opener" done diff --git a/src/main.js b/src/main.js index ff2ab3007ec3c6afee0e3e2ff98e24da746974da..74708554df739ec19db7b8c7d12d2a5dd06c3c41 100644 --- a/src/main.js +++ b/src/main.js @@ -155,7 +155,7 @@ client.on('message', (topic, message) => { if (topicparts[0] === 'door' && topicparts[2] === 'state') { update_door_state(topicparts[1], message.toString()); } - else if (topicparts[0] === 'door' && topicparts[2] === 'opener') { + else if (topicparts[0] === 'door' && topicparts[2] === 'openedby') { update_door_opener(topicparts[1], message.toString()); } else { diff --git a/static/darkmode.js b/static/darkmode.js deleted file mode 100644 index 619726da046679c7aca196ee4fa90375095b0936..0000000000000000000000000000000000000000 --- a/static/darkmode.js +++ /dev/null @@ -1,17 +0,0 @@ -const darkmode = () => { - const DARK_FRAG = "#dark"; - const DARK_CLASS = "dark"; - const rootClasses = document.documentElement.classList; - const hash = window.location.hash; - - if (hash === DARK_FRAG) { - rootClasses.add(DARK_CLASS); - } - else { - rootClasses.remove(DARK_CLASS); - } -}; - -window.onhashchange = darkmode; - -darkmode(); diff --git a/static/door_ucc_closed.jpg b/static/door_ucc_closed.jpg deleted file mode 100644 index b1a61e3659fa73af6455bb75e7c9c10cf95ea751..0000000000000000000000000000000000000000 Binary files a/static/door_ucc_closed.jpg and /dev/null differ diff --git a/static/door_ucc_open.jpg b/static/door_ucc_open.jpg deleted file mode 100644 index 2d66b46a1855a51e75f90cd643352ec57f396c27..0000000000000000000000000000000000000000 Binary files a/static/door_ucc_open.jpg and /dev/null differ diff --git a/static/door_unisfa_closed.jpg b/static/door_unisfa_closed.jpg deleted file mode 100644 index ad965cfb7d1f4a58a8b331eaad45123d77594db5..0000000000000000000000000000000000000000 Binary files a/static/door_unisfa_closed.jpg and /dev/null differ diff --git a/static/door_unisfa_open.jpg b/static/door_unisfa_open.jpg deleted file mode 100644 index efce08c24982abfd97b50994e79bd1c86fa6c451..0000000000000000000000000000000000000000 Binary files a/static/door_unisfa_open.jpg and /dev/null differ diff --git a/static/door_uwaes_closed.jpg b/static/door_uwaes_closed.jpg deleted file mode 100644 index 53cf3a7d06980354b2797ae30e2fd71554753ad7..0000000000000000000000000000000000000000 Binary files a/static/door_uwaes_closed.jpg and /dev/null differ diff --git a/static/door_uwaes_open.jpg b/static/door_uwaes_open.jpg deleted file mode 100644 index 3e6c8b8cbcdcfd302a4cee655d9f309ad18bb088..0000000000000000000000000000000000000000 Binary files a/static/door_uwaes_open.jpg and /dev/null differ diff --git a/static/style.css b/static/style.css deleted file mode 100644 index 2afcdecf7732f1ab7f4e714dbc030ac18dc6d9ff..0000000000000000000000000000000000000000 --- a/static/style.css +++ /dev/null @@ -1,13 +0,0 @@ -html { - background-color: white; -} - -/* FSCK CHROME FOR MAKING THIS HARDER THAN IT SHOULD BE */ -html.dark { - background-color: black; -} - -html.dark h1, -html.dark p { - color: white; -}