homebridge-camera-ui
Version:
User Interface for RTSP capable cameras.
91 lines (73 loc) • 2.7 kB
JavaScript
'use-strict';
const logger = require('../services/logger/logger.service');
const NotificationsModel = require('./components/notifications/notifications.model');
const Streams = require('./services/streams.service');
const closeTimeout = {};
const timeout = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
class SocketIO {
constructor(server) {
this.closeTimeout = null;
this.rooms = [];
this.io = require('socket.io')(server, {
cors: {
origin: '*',
},
});
this.io.on('connection', async (socket) => {
logger.debug(`${socket.conn.remoteAddress} connected to server`, false, '[Socket]');
const notifications = (await NotificationsModel.list({})) || [];
socket.emit('notification_size', notifications.length);
socket.on('join_stream', (data) => {
if (data.feed) {
logger.debug(
`New WebSocket connection from ${socket.conn.remoteAddress} to room: stream/${data.feed}`,
false,
'[Socket]'
);
socket.join(`stream/${data.feed}`);
this.handleStream(data.feed, data.destroy);
}
});
socket.on('leave_stream', (data) => {
if (data.feed) {
logger.debug(
`${socket.conn.remoteAddress} disconnected or closed from room: stream/${data.feed}`,
false,
'[Socket]'
);
socket.leave(`stream/${data.feed}`);
this.handleStream(data.feed);
}
});
socket.on('disconnect', () => {
logger.debug(`${socket.conn.remoteAddress} disconnected from server`, false, '[Socket]');
for (const cameraName of this.rooms) {
this.handleStream(cameraName);
}
});
});
}
async handleStream(cameraName, destroy) {
if (destroy) {
Streams.stopStream(cameraName);
await timeout(1000);
}
const clients = this.io.sockets.adapter.rooms.get(`stream/${cameraName}`)?.size || 0;
logger.debug(`Active sockets in room (stream/${cameraName}): ${clients}`, false, '[Socket]');
if (closeTimeout[cameraName]) {
clearTimeout(closeTimeout[cameraName]);
closeTimeout[cameraName] = null;
}
if (clients) {
if (!this.rooms.includes(cameraName)) {
this.rooms.push(cameraName);
}
Streams.startStream(cameraName);
} else {
logger.debug('If no clients connects to the Websocket, the stream will be closed in 15s', cameraName, '[Socket]');
this.rooms = this.rooms.filter((room) => room !== cameraName);
closeTimeout[cameraName] = setTimeout(() => Streams.stopStream(cameraName), 15000);
}
}
}
module.exports = SocketIO;