import Bluebird from "bluebird" ; import assert from "node:assert" ; import { ReadonlyDeep , } from "type-fest" ; import Camera , { ControlName , ControlRange , ControlValue , ControlValues , } from "uvc-control" ; import CameraControlHelper from "./camera-control-helper.js" ; import Output from "./output.js" ; import { UvccControls , } from "./types/controls.js" ; import isUvccControlValue from "./utilities/is-uvcc-control-value.js" ; export type ControlsValues = Record < string , ControlValues > ; export type ControlRanges = Record < string , ControlRange > ; export default class CameraHelper { constructor ( private readonly output , private readonly cameraControlHelper , private readonly camera ) { assert . strictEqual ( arguments . length , 3 ) ; assert ( typeof this . output === "object" ) ; assert ( typeof this . cameraControlHelper === "object" ) ; assert ( typeof this . camera === "object" ) ; } async getValues ( controlName ) { const gettableControlNames = await this . cameraControlHelper . getGettableControlNames ( ) ; if ( ! gettableControlNames . includes ( controlName ) ) { throw new Error ( `Could not find a gettable control named ${ JSON . stringify ( controlName ) }.` ) ; } const valueObject = await this . camera . get ( controlName ) ; return valueObject ; } async getRange ( controlName ) { const rangedControlNames = await this . cameraControlHelper . getRangedControlNames ( ) ; if ( ! rangedControlNames . includes ( controlName ) ) { throw new Error ( `Could not find a ranged control named ${ JSON . stringify ( controlName ) }.` ) ; } const range = this . camera . range ( controlName ) ; return range ; } async setValues ( controlName , values ) { const settableControlNames = await this . cameraControlHelper . getSettableControlNames ( ) ; if ( ! settableControlNames . includes ( controlName ) ) { throw new Error ( `Could not find a settable control named ${ JSON . stringify ( controlName ) }.` ) ; } await this . camera . set ( controlName , ... values ) ; return undefined ; } async getControlNames ( ) { return this . cameraControlHelper . getControlNames ( ) ; } async getRanges ( ) { return Bluebird . reduce ( this . cameraControlHelper . getRangedControlNames ( ) , async ( object , controlName ) => { try { object [ controlName ] = await this . getRange ( controlName ) ; } catch ( error ) { this . output . verbose ( "Error getting range, ignoring." , controlName , error ) ; } return object ; } , { } as ControlRanges ) ; } async getSettableControls ( ) { return Bluebird . reduce ( this . cameraControlHelper . getSettableControlNames ( ) , async ( object , controlName ) => { try { object [ controlName ] = await this . getValues ( controlName ) ; } catch ( error ) { this . output . verbose ( "Error getting settable value, ignoring." , controlName , error ) ; } return object ; } , { } as ControlsValues ) ; } async setControls ( configuration ) { const controlNames = Object . keys ( configuration ) ; const settableControlNames = await this . cameraControlHelper . getSettableControlNames ( ) ; const nonSettableNames = controlNames . filter ( ( controlName ) => ! settableControlNames . includes ( controlName ) ) ; if ( nonSettableNames . length > 0 ) { throw new Error ( `Could not find a settable controls, aborting setting values: ${ JSON . stringify ( nonSettableNames ) }` ) ; } await Bluebird . map ( controlNames , async ( controlName ) => { const controlValues = configuration [ controlName ] ; if ( ! isUvccControlValue ( controlValues ) ) { throw new TypeError ( `Expected number value for configuration ${ controlName }, got ${ typeof controlValues } ${ JSON . stringify ( controlValues ) }.` ) ; } const controlValuesArray = new Array < number > ( ) . concat ( controlValues ) ; try { await this . setValues ( controlName , controlValuesArray ) ; } catch ( error ) { this . output . verbose ( "Error setting value, ignoring." , controlName , controlValues , error ) ; } } ) ; } }