merasabkuch commited on
Commit
5774ae9
1 Parent(s): 64cb18f

Upload 3 files

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