diff --git a/README.md b/README.md index b26eb1d9849abfb6ae16fa5a0917270f564cfd04..905df5baf8f19f2fb9ad625a9c799ab968c495c4 100644 --- a/README.md +++ b/README.md @@ -114,10 +114,16 @@ For the syntax of the commands the following convention is used in this document * `<a | b>` is a parameter that is required and has to hold either the value `a` or `b`. -* `[param]` is a parameter that is optional +* `[param]` is a parameter that is optional. This is the list of the available commands: +### Room Control Commands + +| Command | Description +| --------------------------------- | ----------- +| `edit_pin` | Changes the pin of the Janus room. This pin is required to join the room as a viewer or sender. Note that this does not automatically kick the current participants of the Janus room. The noVNC pin also needs to be changed accordingly as it is expected to equal the Janus room pin. <br/><br/> **Usage**: `edit_pin <pin>` + ### Slot Control Commands | Command | Description diff --git a/camera-server/src/io-interface/handlers/input-handlers.ts b/camera-server/src/io-interface/handlers/input-handlers.ts index 4522f7f4a0303afc42ac81fe2ea9d20672a22e80..76caf8735b42b470eefddcb1e41e531d051bc08b 100644 --- a/camera-server/src/io-interface/handlers/input-handlers.ts +++ b/camera-server/src/io-interface/handlers/input-handlers.ts @@ -9,6 +9,7 @@ import { emitControllerBitrateLimit } from '../../socket-io/handlers/sender-handlers'; import { setBitrate } from '../../janus/handlers'; +import { room } from '../../janus/janus-room'; import { config } from '../../config/config'; const visibilityCommands = ['hide', 'show']; @@ -16,7 +17,7 @@ const geometryCommands = [ 'set_geometry_relative_to_window', 'set_geometry_relative_to_canvas' ]; -const internalCommands = [ +const internalSlotCommands = [ 'activate_slot', 'deactivate_slot', 'refresh_token', @@ -24,6 +25,7 @@ const internalCommands = [ 'remove_annotation', 'set_bitrate_limit' ]; +const internalRoomCommands = ['edit_pin']; const setAnnotation = (slot: number, annotation: string) => { console.log(`Setting annotation of slot ${slot} to ${annotation}`); @@ -33,7 +35,7 @@ const setAnnotation = (slot: number, annotation: string) => { } }; -const handleInternalCommand = ( +const handleInternalSlotCommand = ( command: string, slot: number, params: string[] @@ -155,7 +157,28 @@ const handleInternalCommand = ( break; default: console.log( - 'Error: handleInternalCommand got unknown command ' + command + 'Error: handleInternalSlotCommand got unknown command ' + + command + ); + break; + } +}; + +const handleInternalRoomCommand = (command: string, params: string[]) => { + switch (command) { + case 'edit_pin': + const newPin = params[0]; + if (newPin === null) { + console.log( + 'Tried to edit janus room pin without providing one' + ); + return; + } + room.editPin(newPin); + break; + default: + console.log( + `Error: handleInternalRoomCommand got unknown command ${command}` ); break; } @@ -173,58 +196,61 @@ export const handleCommand = (line: string) => { return; } - const slotStr = params.shift(); - if (slotStr == null) { - console.log('Error: Got no slot to apply the command on'); - return; - } - - const slot = parseInt(slotStr); - if (isNaN(slot)) { - console.log( - 'Error: Could not parse slot ' + slotStr + ' to an integer' - ); - return; - } - if (slot < 0 || slot > cameraSlotState.length - 1) { - console.log( - `Error: Got invalid slot number ${slot}. There are ${cameraSlotState.length} camera slots.` - ); - return; - } - console.log('command:', command); - console.log('slot:', slot); console.log('params:', params); - const currentCameraState = cameraSlotState[slot]; - - if (visibilityCommands.includes(command)) { - currentCameraState.visibility = { - command, - params - }; - emitCommand = true; - } else if (geometryCommands.includes(command)) { - currentCameraState.geometry = { - command, - params - }; - emitCommand = true; - } else if (internalCommands.includes(command)) { - handleInternalCommand(command, slot, params); + if (internalRoomCommands.includes(command)) { + handleInternalRoomCommand(command, params); } else { - console.log('Command "' + command + '" is not a valid command'); - return; - } + const slotStr = params.shift(); + if (slotStr == null) { + console.log('Error: Got no slot to apply the command on'); + return; + } + + const slot = parseInt(slotStr); + if (isNaN(slot)) { + console.log( + 'Error: Could not parse slot ' + slotStr + ' to an integer' + ); + return; + } + if (slot < 0 || slot > cameraSlotState.length - 1) { + console.log( + `Error: Got invalid slot number ${slot}. There are ${cameraSlotState.length} camera slots.` + ); + return; + } + + const currentCameraState = cameraSlotState[slot]; + + if (visibilityCommands.includes(command)) { + currentCameraState.visibility = { + command, + params + }; + emitCommand = true; + } else if (geometryCommands.includes(command)) { + currentCameraState.geometry = { + command, + params + }; + emitCommand = true; + } else if (internalSlotCommands.includes(command)) { + handleInternalSlotCommand(command, slot, params); + } else { + console.log('Command "' + command + '" is not a valid command'); + return; + } - console.log('new cameraState:', currentCameraState); + console.log('new cameraState:', currentCameraState); - if (currentCameraState.feedActive && emitCommand) { - socketIO.emit('command', { - slot, - command, - params - }); + if (currentCameraState.feedActive && emitCommand) { + socketIO.emit('command', { + slot, + command, + params + }); + } } }; diff --git a/camera-server/src/janus/janus-api.ts b/camera-server/src/janus/janus-api.ts index 73282777c4fefdb595120ee01206f75a4c1a75d9..33e92c5f4afe4dc71ff8e9909cc544e81ff11191 100644 --- a/camera-server/src/janus/janus-api.ts +++ b/camera-server/src/janus/janus-api.ts @@ -113,3 +113,21 @@ export const destroyRoom = ( } }); }; + +export const editRoomPin = ( + sessionId: number, + videoroomId: number, + room: number, + secret: string, + newPin: string +) => { + return postRequest(`/${sessionId}/${videoroomId}`, { + janus: 'message', + body: { + request: 'edit', + room, + secret, + new_pin: newPin + } + }); +}; diff --git a/camera-server/src/janus/janus-room.ts b/camera-server/src/janus/janus-room.ts index 8836ebafad2c155350e8b00416e7968985925a86..64ee1fb7356a2db32a844206b9a460d27f8c0b69 100644 --- a/camera-server/src/janus/janus-room.ts +++ b/camera-server/src/janus/janus-room.ts @@ -149,6 +149,35 @@ class JanusRoom { } } + async editPin(newPin: string) { + console.log(`Changing janus room pin to ${newPin}`); + if (!this._sessionAlive) { + console.log("Error: Janus session timed out - can't send request"); + return; + } + const { data } = await janusAPI.editRoomPin( + this.sessionId, + this.videoroomId, + config.janusRoom, + config.janusRoomSecret, + newPin + ); + if ( + data?.janus === 'success' && + data.plugindata?.data?.videoroom === 'edited' + ) { + console.log('Changed janus room pin'); + } else { + console.log( + `Error: Could not change janus room pin. Janus response: ${JSON.stringify( + data, + null, + 2 + )}` + ); + } + } + async cleaup() { console.log(`Cleaning up janus room ${config.janusRoom}`); if (this._sessionAlive) {