Spaces:
Running
Running
File size: 5,898 Bytes
5774ae9 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
// server.js (Node.js with Express and ws)
const express = require('express');
const { WebSocketServer } = require('ws');
const cors = require('cors'); // Import CORS
const { initializeApp, cert } = require('firebase-admin/app');
const { getFirestore } = require('firebase-admin/firestore');
var admin = require("firebase-admin");
const serviceAccount = require("./serviceAcc.json");
initializeApp({
credential: cert(serviceAccount)
});
const db = getFirestore();
const app = express();
const port = process.env.PORT || 8080;
const wss = new WebSocketServer({ noServer: true });
app.use(cors());
var initialData = {};
let currentDeviceStates = {};
const fetchInitialData = async () => {
const devices = [];
const rooms = [];
const users = [];
try {
const deviceSnapshot = await db.collection('Devices').get();
deviceSnapshot.forEach(doc => devices.push({ id: doc.id, ...doc.data() }));
const roomsSnapshot = await db.collectionGroup('Rooms').get(); // Get all rooms across hostels
roomsSnapshot.forEach(doc => rooms.push({ id: doc.id, ...doc.data(), hostelId: doc.ref.parent.parent.id })); // Include hostelId
const usersSnapshot = await db.collection('Users').get();
usersSnapshot.forEach(doc => users.push({ id: doc.id, ...doc.data() }));
initialData = { devices, rooms, users };
// console.log("Initial data fetched:", initialData);
//for each hostel id mantain a list of rooms with devices pertaining to that hostel
//setall to off
initialData.devices.forEach(device => {
device.state = false;
} );
initialData.rooms.forEach(room => {
if (!currentDeviceStates[room.id]) {
currentDeviceStates[room.id] = [];
}
const roomDevices = initialData.devices.filter(device => device.hostelId === room.hostelId);
currentDeviceStates[room.id] = { ...room, devices: roomDevices };
});
} catch (error) {
console.error("Error fetching initial data:", error);
// return { devices: [], rooms: [], users: [] };
initialData = { devices, rooms, users };
}
};
fetchInitialData();
const connectedClients = {}; // Store connected clients per room
wss.on('connection', (ws) => {
ws.on('message', async (message) => {
try {
const parsedMessage = JSON.parse(message);
const { roomId, userId, apiKey } = parsedMessage;
// Helper function to check authorization
const isAuthorized = (roomId, userId, apiKey) => {
return initialData.users.some(user => user.id === userId && user.roomId === roomId) || apiKey === "masterPassword@tiet@123";
};
switch (parsedMessage.type) {
case 'joinRoom':
if (!roomId || !userId) {
ws.send(JSON.stringify({ error: 'Invalid room or user ID' }));
return;
}
if (!isAuthorized(roomId, userId, apiKey)) {
console.log("Unauthorized joinRoom attempt.");
ws.send(JSON.stringify({ error: 'Unauthorized' }));
return;
}
// Store the connected client
if (!connectedClients[roomId]) {
connectedClients[roomId] = [];
}
connectedClients[roomId].push(ws);
ws.send(JSON.stringify({ type: 'roomData', roomData: currentDeviceStates[roomId], roomId: roomId }));
break;
case 'updateDeviceState':
const { deviceId, state } = parsedMessage;
if (!deviceId || state === undefined || !roomId || (!userId && !apiKey)) { // Check for undefined state or missing userId/apiKey
ws.send(JSON.stringify({ error: 'Invalid device ID, state, room ID, user ID, or API key' }));
return;
}
if (!isAuthorized(roomId, userId, apiKey)) {
console.log("Unauthorized updateDeviceState attempt.");
ws.send(JSON.stringify({ error: 'Unauthorized' }));
return;
}
const room = currentDeviceStates[roomId];
if (room) { // Check if the room exists
const device = room.devices.find(dev => dev.id === deviceId);
if (device) { // Check if the device exists
device.state = state;
// Broadcast to all clients in the room
if (connectedClients[roomId]) {
connectedClients[roomId].forEach(client => {
client.send(JSON.stringify({ type: 'deviceUpdate', deviceId, state, roomId: roomId }));
});
}
} else {
ws.send(JSON.stringify({ error: 'Device not found' }));
}
} else {
ws.send(JSON.stringify({ error: 'Room not found' }));
}
break;
default:
console.log('Unknown message type:', parsedMessage.type);
}
} catch (error) {
console.error('Error handling message:', error);
ws.send(JSON.stringify({ error: 'Invalid message format' })); // Send error back to client
}
});
ws.on('close', () => {
for (const roomId in connectedClients) {
connectedClients[roomId] = connectedClients[roomId].filter(client => client !== ws);
}
});
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
});
console.log('WebSocket server started on port 8080');
const server = app.listen(port, () => console.log(`Listening on port ${port}`));
server.on('upgrade', (request, socket, head) => {
wss.handleUpgrade(request, socket, head, ws => {
wss.emit('connection', ws, request);
});
}); |