Skip to content

Commit 99355bc

Browse files
committed
SOFIE-47 | add automatic configuration of peripheral devices if there is only 1 studio
1 parent b6af173 commit 99355bc

File tree

2 files changed

+123
-1
lines changed

2 files changed

+123
-1
lines changed

meteor/server/api/__tests__/peripheralDevice.test.ts

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
import { EmptyPieceTimelineObjectsBlob } from '@sofie-automation/corelib/dist/dataModel/Piece'
99
import { literal, getRandomId, getRandomString } from '@sofie-automation/corelib/dist/lib'
1010
import { LogLevel } from '@sofie-automation/meteor-lib/dist/lib'
11-
import { protectString, ProtectedString } from '@sofie-automation/corelib/dist/protectedString'
11+
import { protectString, ProtectedString, unprotectString } from '@sofie-automation/corelib/dist/protectedString'
1212
import { getCurrentTime } from '../../lib/lib'
1313
import { waitUntil } from '../../../__mocks__/helpers/jest'
1414
import { setupDefaultStudioEnvironment, DefaultEnvironment } from '../../../__mocks__/helpers/database'
@@ -45,7 +45,9 @@ import {
4545
RundownPlaylists,
4646
Rundowns,
4747
Segments,
48+
Studios,
4849
} from '../../collections'
50+
import { applyAndValidateOverrides } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
4951
import { SupressLogMessages } from '../../../__mocks__/suppressLogging'
5052
import { JSONBlobStringify } from '@sofie-automation/shared-lib/dist/lib/JSONBlob'
5153
import { PeripheralDeviceCommand } from '@sofie-automation/corelib/dist/dataModel/PeripheralDeviceCommand'
@@ -165,6 +167,48 @@ describe('test peripheralDevice general API methods', () => {
165167
name: 'Earth',
166168
})
167169
})
170+
171+
test('initialize auto-assign to single studio', async () => {
172+
if (DEBUG) setLogLevel(LogLevel.DEBUG)
173+
174+
const localEnv = await setupDefaultStudioEnvironment()
175+
// Prepare a new device id, not present in the DB yet
176+
const newDeviceId = getRandomId()
177+
const token = getRandomString()
178+
const options: PeripheralDeviceInitOptions = {
179+
category: PeripheralDeviceCategory.PLAYOUT,
180+
type: PeripheralDeviceType.PLAYOUT,
181+
subType: 'test',
182+
name: 'autoAssignDevice',
183+
connectionId: 'testconn',
184+
configManifest: {
185+
deviceConfigSchema: JSONBlobStringify({}),
186+
subdeviceManifest: {},
187+
},
188+
documentationUrl: 'http://example.com',
189+
}
190+
191+
// Ensure it's not present yet
192+
expect(await PeripheralDevices.findOneAsync(newDeviceId)).toBeFalsy()
193+
194+
// Initialize the device
195+
await MeteorCall.peripheralDevice.initialize(newDeviceId, token, options)
196+
197+
// Ensure the device exists and is assigned to the only studio in the db
198+
const initDevice = (await PeripheralDevices.findOneAsync(newDeviceId)) as PeripheralDevice
199+
expect(initDevice).toBeTruthy()
200+
expect(initDevice.studioAndConfigId).toBeTruthy()
201+
expect(initDevice.studioAndConfigId!.studioId).toBe(localEnv.studio._id)
202+
203+
// Ensure it is created in the "parent devices" mapping (deviceSettings)
204+
const studio = await Studios.findOneAsync(localEnv.studio._id)
205+
const deviceSettings = applyAndValidateOverrides(studio!.peripheralDeviceSettings.deviceSettings).obj
206+
expect(deviceSettings[unprotectString(newDeviceId)]).toBeTruthy()
207+
208+
const playoutDevices = applyAndValidateOverrides(studio!.peripheralDeviceSettings.playoutDevices).obj
209+
expect(playoutDevices[unprotectString(newDeviceId)]).toBeFalsy()
210+
})
211+
168212
beforeEach(async () => {
169213
QueueStudioJobSpy.mockReset()
170214
QueueStudioJobSpy.mockClear()
@@ -746,3 +790,40 @@ describe('test peripheralDevice general API methods', () => {
746790
})
747791
})
748792
})
793+
794+
test('initialize auto-assign to single studio', async () => {
795+
if (DEBUG) setLogLevel(LogLevel.DEBUG)
796+
797+
const localEnv = await setupDefaultStudioEnvironment()
798+
799+
const newDeviceId = getRandomId()
800+
const token = getRandomString()
801+
const options: PeripheralDeviceInitOptions = {
802+
category: PeripheralDeviceCategory.PLAYOUT,
803+
type: PeripheralDeviceType.PLAYOUT,
804+
subType: 'test',
805+
name: 'autoAssignDevice',
806+
connectionId: 'testconn',
807+
configManifest: {
808+
deviceConfigSchema: JSONBlobStringify({}),
809+
subdeviceManifest: {},
810+
},
811+
documentationUrl: 'http://example.com',
812+
}
813+
814+
expect(await PeripheralDevices.findOneAsync(newDeviceId)).toBeFalsy()
815+
816+
await MeteorCall.peripheralDevice.initialize(newDeviceId, token, options)
817+
818+
const initDevice = (await PeripheralDevices.findOneAsync(newDeviceId)) as PeripheralDevice
819+
expect(initDevice).toBeTruthy()
820+
expect(initDevice.studioAndConfigId).toBeTruthy()
821+
expect(initDevice.studioAndConfigId!.studioId).toBe(localEnv.studio._id)
822+
823+
const studio = await Studios.findOneAsync(localEnv.studio._id)
824+
const deviceSettings = applyAndValidateOverrides(studio!.peripheralDeviceSettings.deviceSettings).obj
825+
expect(deviceSettings[unprotectString(newDeviceId)]).toBeTruthy()
826+
827+
const playoutDevices = applyAndValidateOverrides(studio!.peripheralDeviceSettings.playoutDevices).obj
828+
expect(playoutDevices[unprotectString(newDeviceId)]).toBeFalsy()
829+
})

meteor/server/api/peripheralDevice.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ export namespace ServerPeripheralDeviceAPI {
166166

167167
documentationUrl: options.documentationUrl,
168168
})
169+
170+
// If there is only one Studio, assign the device to that studio.
171+
// Overall plan at the moment is to have only 1 studio per sofie instance in mid-term future
172+
await assignToStudioIfOnlyOnePresent(deviceId, options)
169173
}
170174
if (options.configManifest?.translations) {
171175
await upsertBundles(
@@ -175,6 +179,43 @@ export namespace ServerPeripheralDeviceAPI {
175179
}
176180
return deviceId
177181
}
182+
183+
async function assignToStudioIfOnlyOnePresent(deviceId: PeripheralDeviceId, options: PeripheralDeviceInitOptions) {
184+
if ((await Studios.countDocuments()) !== 1) {
185+
return
186+
}
187+
188+
const studio = await Studios.findOneAsync({})
189+
190+
if (!studio) {
191+
return
192+
}
193+
194+
const configId = unprotectString(deviceId)
195+
196+
await Studios.updateAsync(studio._id, {
197+
$push: {
198+
[`peripheralDeviceSettings.deviceSettings.overrides`]: {
199+
op: 'set',
200+
path: configId,
201+
value: {
202+
name: options.name,
203+
options: {},
204+
},
205+
},
206+
},
207+
})
208+
209+
await PeripheralDevices.updateAsync(deviceId, {
210+
$set: {
211+
studioAndConfigId: {
212+
configId,
213+
studioId: studio._id,
214+
},
215+
},
216+
})
217+
}
218+
178219
export async function unInitialize(
179220
context: MethodContext,
180221
deviceId: PeripheralDeviceId,

0 commit comments

Comments
 (0)