diff --git a/meteor/server/api/__tests__/peripheralDevice.test.ts b/meteor/server/api/__tests__/peripheralDevice.test.ts index 3c819cf20a..b65c86f877 100644 --- a/meteor/server/api/__tests__/peripheralDevice.test.ts +++ b/meteor/server/api/__tests__/peripheralDevice.test.ts @@ -8,7 +8,7 @@ import { import { EmptyPieceTimelineObjectsBlob } from '@sofie-automation/corelib/dist/dataModel/Piece' import { literal, getRandomId, getRandomString } from '@sofie-automation/corelib/dist/lib' import { LogLevel } from '@sofie-automation/meteor-lib/dist/lib' -import { protectString, ProtectedString } from '@sofie-automation/corelib/dist/protectedString' +import { protectString, ProtectedString, unprotectString } from '@sofie-automation/corelib/dist/protectedString' import { getCurrentTime } from '../../lib/lib' import { waitUntil } from '../../../__mocks__/helpers/jest' import { setupDefaultStudioEnvironment, DefaultEnvironment } from '../../../__mocks__/helpers/database' @@ -45,7 +45,9 @@ import { RundownPlaylists, Rundowns, Segments, + Studios, } from '../../collections' +import { applyAndValidateOverrides } from '@sofie-automation/corelib/dist/settings/objectWithOverrides' import { SupressLogMessages } from '../../../__mocks__/suppressLogging' import { JSONBlobStringify } from '@sofie-automation/shared-lib/dist/lib/JSONBlob' import { PeripheralDeviceCommand } from '@sofie-automation/corelib/dist/dataModel/PeripheralDeviceCommand' @@ -165,6 +167,7 @@ describe('test peripheralDevice general API methods', () => { name: 'Earth', }) }) + beforeEach(async () => { QueueStudioJobSpy.mockReset() QueueStudioJobSpy.mockClear() @@ -745,4 +748,50 @@ describe('test peripheralDevice general API methods', () => { }) }) }) + + describe('auto-assign devices', () => { + beforeEach(async () => { + env = await setupDefaultStudioEnvironment() + }) + + test('initialize auto-assign to single studio', async () => { + if (DEBUG) setLogLevel(LogLevel.DEBUG) + + // Prepare a new device id, not present in the DB yet + const newDeviceId = getRandomId() + const token = getRandomString() + const options: PeripheralDeviceInitOptions = { + category: PeripheralDeviceCategory.PLAYOUT, + type: PeripheralDeviceType.PLAYOUT, + subType: 'test', + name: 'autoAssignDevice', + connectionId: 'testconn', + configManifest: { + deviceConfigSchema: JSONBlobStringify({}), + subdeviceManifest: {}, + }, + documentationUrl: 'http://example.com', + } + + // Ensure it's not present yet + expect(await PeripheralDevices.findOneAsync(newDeviceId)).toBeFalsy() + + // Initialize the device + await MeteorCall.peripheralDevice.initialize(newDeviceId, token, options) + + // Ensure the device exists and is assigned to the only studio in the db + const initDevice = (await PeripheralDevices.findOneAsync(newDeviceId)) as PeripheralDevice + expect(initDevice).toBeTruthy() + expect(initDevice.studioAndConfigId).toBeTruthy() + expect(initDevice.studioAndConfigId!.studioId).toBe(env.studio._id) + + // Ensure it is created in the "parent devices" mapping (deviceSettings) + const studio = await Studios.findOneAsync(env.studio._id) + const deviceSettings = applyAndValidateOverrides(studio!.peripheralDeviceSettings.deviceSettings).obj + expect(deviceSettings[unprotectString(newDeviceId)]).toBeTruthy() + + const playoutDevices = applyAndValidateOverrides(studio!.peripheralDeviceSettings.playoutDevices).obj + expect(playoutDevices[unprotectString(newDeviceId)]).toBeFalsy() + }) + }) }) diff --git a/meteor/server/api/peripheralDevice.ts b/meteor/server/api/peripheralDevice.ts index be6e118a0a..0cc5ed4f4e 100644 --- a/meteor/server/api/peripheralDevice.ts +++ b/meteor/server/api/peripheralDevice.ts @@ -166,6 +166,10 @@ export namespace ServerPeripheralDeviceAPI { documentationUrl: options.documentationUrl, }) + + // If there is only one Studio, assign the device to that studio. + // Overall plan at the moment is to have only 1 studio per sofie instance in mid-term future + await assignToStudioIfOnlyOnePresent(deviceId, options) } if (options.configManifest?.translations) { await upsertBundles( @@ -175,6 +179,43 @@ export namespace ServerPeripheralDeviceAPI { } return deviceId } + + async function assignToStudioIfOnlyOnePresent(deviceId: PeripheralDeviceId, options: PeripheralDeviceInitOptions) { + if ((await Studios.countDocuments()) !== 1) { + return + } + + const studio = await Studios.findOneAsync({}) + + if (!studio) { + return + } + + const configId = unprotectString(deviceId) + + await Studios.updateAsync(studio._id, { + $push: { + [`peripheralDeviceSettings.deviceSettings.overrides`]: { + op: 'set', + path: configId, + value: { + name: options.name, + options: {}, + }, + }, + }, + }) + + await PeripheralDevices.updateAsync(deviceId, { + $set: { + studioAndConfigId: { + configId, + studioId: studio._id, + }, + }, + }) + } + export async function unInitialize( context: MethodContext, deviceId: PeripheralDeviceId,