From f2504072ce576444617a0a5e91aafcb4e5694c9a Mon Sep 17 00:00:00 2001 From: Carlos Valente <34649812+cpvalente@users.noreply.github.com> Date: Sun, 26 Nov 2023 19:02:16 +0100 Subject: [PATCH] feat: add change endpoint to ws (#618) * feat: add change endpoint to ws --- apps/server/src/adapters/OscAdapter.ts | 30 +++++++++++++++++-- apps/server/src/adapters/WebsocketAdapter.ts | 3 +- apps/server/src/app.ts | 6 ++-- .../src/controllers/integrationController.ts | 29 ++++++++---------- 4 files changed, 44 insertions(+), 24 deletions(-) diff --git a/apps/server/src/adapters/OscAdapter.ts b/apps/server/src/adapters/OscAdapter.ts index 6bbdc0a7b..d07896983 100644 --- a/apps/server/src/adapters/OscAdapter.ts +++ b/apps/server/src/adapters/OscAdapter.ts @@ -3,7 +3,7 @@ import { LogOrigin, OSCSettings } from 'ontime-types'; import { Server } from 'node-osc'; import { IAdapter } from './IAdapter.js'; -import { dispatchFromAdapter } from '../controllers/integrationController.js'; +import { dispatchFromAdapter, type ChangeOptions } from '../controllers/integrationController.js'; import { logger } from '../classes/Logger.js'; export class OscServer implements IAdapter { @@ -36,12 +36,36 @@ export class OscServer implements IAdapter { return; } + let transformedPayload: unknown = args; + // we need to transform the params for the change endpoint + // OSC: ontime/change/{eventID}/{propertyName} value + if (path === 'change') { + if (params.length < 2) { + logger.error(LogOrigin.Rx, 'OSC IN: No params provided for change'); + return; + } + + if (args === undefined) { + logger.error(LogOrigin.Rx, 'OSC IN: No valid payload provided for change'); + return; + } + + const eventId = params[0]; + const property = params[1]; + const value: string | number | boolean = args as string | number | boolean; + + transformedPayload = { + eventId, + property, + value, + } satisfies ChangeOptions; + } + try { const reply = dispatchFromAdapter( path, { - payload: args, - params, + payload: transformedPayload, }, 'osc', ); diff --git a/apps/server/src/adapters/WebsocketAdapter.ts b/apps/server/src/adapters/WebsocketAdapter.ts index 53fe92b80..0383a1bf6 100644 --- a/apps/server/src/adapters/WebsocketAdapter.ts +++ b/apps/server/src/adapters/WebsocketAdapter.ts @@ -17,6 +17,7 @@ import { LogOrigin } from 'ontime-types'; import { WebSocket, WebSocketServer } from 'ws'; +import type { Server } from 'http'; import getRandomName from '../utils/getRandomName.js'; import { IAdapter } from './IAdapter.js'; @@ -43,7 +44,7 @@ export class SocketServer implements IAdapter { this.wss = null; } - init(server) { + init(server: Server) { this.wss = new WebSocketServer({ path: '/ws', server }); this.wss.on('connection', (ws) => { diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 9f142c381..2d0b359d2 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -3,7 +3,7 @@ import { LogOrigin, OSCSettings } from 'ontime-types'; import 'dotenv/config'; import express from 'express'; import expressStaticGzip from 'express-static-gzip'; -import http from 'http'; +import http, { type Server } from 'http'; import cors from 'cors'; // import utils @@ -107,8 +107,8 @@ enum OntimeStartOrder { } let step = OntimeStartOrder.InitAssets; -let expressServer = null; -let oscServer = null; +let expressServer: Server | null = null; +let oscServer: OscServer | null = null; const checkStart = (currentState: OntimeStartOrder) => { if (step !== currentState) { diff --git a/apps/server/src/controllers/integrationController.ts b/apps/server/src/controllers/integrationController.ts index a37579a37..243d60b65 100644 --- a/apps/server/src/controllers/integrationController.ts +++ b/apps/server/src/controllers/integrationController.ts @@ -1,5 +1,3 @@ -import { OntimeEvent } from 'ontime-types'; - import { messageService } from '../services/message-service/MessageService.js'; import { PlaybackService } from '../services/PlaybackService.js'; import { eventStore } from '../stores/EventStore.js'; @@ -7,19 +5,23 @@ import { parse, updateEvent } from './integrationController.config.js'; import { isKeyOfType } from 'ontime-types/src/utils/guards.js'; import { event } from '../models/eventsDefinition.js'; +export type ChangeOptions = { + eventId: string; + property: string; + value: unknown; +}; + //TODO: re-throwing the error does not add any extra information or value export function dispatchFromAdapter( type: string, args: { payload: unknown; - params?: Array; }, _source?: 'osc' | 'ws', ) { const payload = args.payload; const typeComponents = type.toLowerCase().split('/'); const mainType = typeComponents[0]; - const params = args.params || []; switch (mainType) { case 'test-ontime': { @@ -267,21 +269,14 @@ export function dispatchFromAdapter( return { topic: 'timer', payload: timer }; } - // ontime/change/{eventID}/{propertyName} + // WS: {type: 'change', payload: { eventId, property, value } } case 'change': { - if (params.length < 2) { - throw new Error('Too few parameters, 3 expected'); + const { eventId, property, value } = payload as ChangeOptions; + if (!isKeyOfType(property, event)) { + throw new Error(`Cannot update unknown event property ${property}`); } - if (payload === undefined) { - throw new Error('No payload found'); - } - const eventID = params[0]; - const propertyName = params[1] as keyof OntimeEvent; - if (!isKeyOfType(propertyName, event)) { - throw new Error(`Cannot update unknown event property ${propertyName}`); - } - const parsedPayload = parse(propertyName, payload); - return updateEvent(eventID, propertyName, parsedPayload); + const parsedPayload = parse(property, value); + return updateEvent(eventId, property, parsedPayload); } default: {