diff --git a/README.md b/README.md index 3e44884aeaaaced275b3855a139441ea8bade0b9..3472c150c583737c09660e4cd76f8325ad6a55bf 100644 --- a/README.md +++ b/README.md @@ -6,20 +6,23 @@ Note that the project and its documentation are still in development. In this documentation clients that publish a feed will be referred to as *senders* and clients who receive a feed will be referred to as *receivers* or *viewers*. -# Nodejs Server +# Camera Server CVH-Camera uses a Nodejs server with the socket.io library to send events regarding the camera feeds out to the receivers in realtime. The socket connection is also used to verify feeds that are published in the Janus rooms and only send those to the receivers. This way no unwanted feeds can be shown to the receivers while still having a public password for the Janus room itself. -One instance of the Nodejs server is meant to manage one Janus room. It does this by defining slots for cameras which are all disabled by default. To activate a slot, one has to provide a token for that slot. This token will be required to be able to send a feed on that slot. As mentioned above, only feeds that are verified in that way are shown to the receivers. +One instance of the camera server is meant to manage one Janus room. It does this by defining slots for cameras which are all disabled by default. To activate a slot, one has to provide a token for that slot. This token will be required to be able to send a feed on that slot. As mentioned above, only feeds that are verified in that way are shown to the receivers. One can also refresh the token for a given slot or simply deactivate it. ## Config -The Nodejs server reads the following environment variables to configure some of its behavior: +The camera server can read a path to a config file from the `CONFIG_PATH` environment variable. +This config file has to be in the json format and should have [this structure](./camera-server/example-config.json): -* `PORT`: The port on which the server will listen. Defaults to `5000`. +Below is a description of the config file's properties: -* `CAMERA_SLOTS`: The camera slots available for this room. Defaults to `4`. +* `port`: The port on which the server will listen. Defaults to `5000`. + +* `cameraSlots`: The camera slots available for this room. Defaults to `4`. ## Stdin-Interface diff --git a/camera-server/example-config.json b/camera-server/example-config.json new file mode 100644 index 0000000000000000000000000000000000000000..da5cef680e2d8f5ebc8c688afdc7201c71bfdf07 --- /dev/null +++ b/camera-server/example-config.json @@ -0,0 +1,4 @@ +{ + "port": 5000, + "cameraSlots": 4 +} diff --git a/camera-server/src/config/config.ts b/camera-server/src/config/config.ts new file mode 100644 index 0000000000000000000000000000000000000000..5f75e8d4070905afcef4a9345844729d0aab2254 --- /dev/null +++ b/camera-server/src/config/config.ts @@ -0,0 +1,71 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +interface Config { + port: number; + cameraSlots: number; + // Change type once non-number values are added + [key: string]: number; +} + +let configPath = process.env.CONFIG_PATH; + +let fileContent: string = ''; + +if (configPath) { + try { + fileContent = fs.readFileSync(configPath).toString(); + } catch (err) { + console.log( + `Could not read config at ${path.resolve(configPath)}:`, + err + ); + console.log('Using default values'); + } +} else { + console.log('Got not CONFIG_PATH environment variable'); +} + +const config: Config = { + port: 5000, + cameraSlots: 4 +}; + +if (fileContent) { + let readConfig: any; + + // No need to process error because if-check below sanitises read config + try { + readConfig = JSON.parse(fileContent); + } catch (err) {} + + if (typeof readConfig === 'object' && readConfig !== null) { + console.log(`Reading config at ${path.resolve(configPath!)}`); + // Overwrite default values with values of read config + Object.keys(readConfig).forEach((key) => { + if (config.hasOwnProperty(key)) { + const expectedType = typeof config[key]; + const readType = typeof readConfig[key]; + if (expectedType === readType) { + config[key] = readConfig[key]; + } else { + console.log( + `Error: Read config propety '${key}' is of type ${readType}, but type ${expectedType} was expected` + ); + } + } else { + console.log(`Unknown property ${key} in config`); + } + }); + } else { + console.log( + `Config at ${path.resolve( + configPath! + )} is malformed - using default values` + ); + } +} + +console.log('Using config:', config); + +export { config }; diff --git a/camera-server/src/server.ts b/camera-server/src/server.ts index 0dae5876176e96ddcff2e48a6c147389df3ef398..16d5d1f151668ceceb73cedcb0d017a02a4dbd57 100644 --- a/camera-server/src/server.ts +++ b/camera-server/src/server.ts @@ -4,6 +4,7 @@ import { mountCleanupLogic } from './util/cleanup'; import { ValidationError } from './models/validation-error'; import { CameraSlotState, CommandDescriptor } from './models/camera-slot-state'; import { SenderSocket } from './models/sender-socket'; +import { config } from './config/config'; const readline = require('readline'); const rl = readline.createInterface({ @@ -12,32 +13,7 @@ const rl = readline.createInterface({ terminal: false }); -let port = 5000; -if (process.env.PORT) { - port = +process.env.PORT; - console.log('Using port ' + port + ' from PORT environment variable'); -} else { - console.log( - 'Got no PORT environment variable - using default port ' + port - ); -} - -let cameraSlots = 4; -if (process.env.CAMERA_SLOTS) { - cameraSlots = +process.env.CAMERA_SLOTS; - console.log( - 'Using camera count ' + - cameraSlots + - ' from CAMERA_SLOTS environment variable' - ); -} else { - console.log( - 'Got no CAMERA_SLOTS environment variable - using default count of ' + - cameraSlots - ); -} - -const io = new SocketIOServer(port); +const io = new SocketIOServer(config.port); const visibilityCommands = ['hide', 'show']; const geometryCommands = [ @@ -47,7 +23,7 @@ const geometryCommands = [ const internalCommands = ['activate_slot', 'deactivate_slot', 'refresh_token']; let cameraSlotState: CameraSlotState[] = []; -for (let i = 0; i < cameraSlots; i++) { +for (let i = 0; i < config.cameraSlots; i++) { cameraSlotState.push(new CameraSlotState()); }