import connection from './db.js' import { parse } from 'path' import wss from './websocket.js' import {port, parser} from './port.js' let status = null let history = null // If port is already open, fetch status from arduino, otherwise wait for port to open // the delay is to make sure the arduino is ready to receive data if(port.isOpen) { setTimeout(getStatusFromArduino, 3000) }else { port.on('open', () => {setTimeout(getStatusFromArduino, 3000)}) } // Fetch history from database on startup await upadteHistory() // Listen for data from arduino parser.on('data', function returnStatus(data) { const status = JSON.parse(data.toString()) updateStatus(status) wss.clients.forEach(client => { client.send(JSON.stringify({status: status})) }) }) // Listen for websocket connections const allowedMessages = ['lock', 'unlock', 'catEntered', 'catLeft', 'status'] wss.on('connection', async function connection(ws) { if(!status) await getStatusFromArduino() await upadteHistory() ws.send(JSON.stringify({status, history})) ws.on('message', async function incoming(buffer) { const message = buffer.toString('utf8').trim() console.log(`received: ${message}`) if(allowedMessages.includes(message)) { port.write(`${message}\n`) port.flush() }else if(message === 'history') { if(!history) await upadteHistory() ws.write(JSON.stringify(history)) } }); }) function getStatusFromArduino() { port.write('status\n') port.flush() } async function upadteHistory() { const [lockLog, catLog] = await Promise.all([ connection.query(`SELECT * FROM lock_log ORDER BY date DESC LIMIT 10`), connection.query(`SELECT * FROM cat_log ORDER BY date DESC LIMIT 10`) ]) const lockHistoryForWebsocket = lockLog.map(log => { return { date: new Date(log.date), event: log.action } }) const catHistoryForWebsocket = catLog.map(log => { return { date: new Date(log.date), event: log.action, catsInside: log.cats_inside } }) history = { lockLog: lockHistoryForWebsocket, catLog: catHistoryForWebsocket } } async function updateStatus(newStatus) { if(!status) return status = newStatus if(newStatus.locked === status.locked && newStatus.catsInside === status.catsInside) return if(newStatus.locked !== status.locked) { await connection.query(`INSERT INTO lock_log (date, action) VALUES ('${(new Date()).toISOString()}', '${newStatus.locked ? 'locked' : 'unlocked'}')`) history.lockLog.unshift({event: newStatus.locked ? 'locked' : 'unlocked', date: new Date()}) }else if(newStatus.catsInside < status.catsInside) { await connection.query(`INSERT INTO cat_log (date, action, cats_inside) VALUES ('${(new Date()).toISOString()}', 'left', ${newStatus.catsInside})`) history.catLog.unshift({event: 'left', date: new Date(), catsInside: newStatus.catsInside}) }else { await connection.query(`INSERT INTO cat_log (date, action, cats_inside) VALUES ('${(new Date()).toISOString()}', 'entered', ${newStatus.catsInside})`) history.catLog.unshift({event: 'entered', date: new Date(), catsInside: newStatus.catsInside}) } status = newStatus }