From 5166fc1a8ef64c6e4df0bd2b5eaa9a3f51a52c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20D=C3=B6ring?= <simon.doering@stud.hs-bochum.de> Date: Mon, 4 Jan 2021 22:38:35 +0100 Subject: [PATCH] Add functionality to read config file --- README.md | 13 +++--- camera-server/example-config.json | 4 ++ camera-server/src/config/config.ts | 71 ++++++++++++++++++++++++++++++ camera-server/src/server.ts | 30 ++----------- 4 files changed, 86 insertions(+), 32 deletions(-) create mode 100644 camera-server/example-config.json create mode 100644 camera-server/src/config/config.ts diff --git a/README.md b/README.md index 3e44884..3472c15 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 0000000..da5cef6 --- /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 0000000..5f75e8d --- /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 0dae587..16d5d1f 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()); } -- GitLab