import {z} from 'zod' export type CameraId = string; export type OsdIsNameEnabled = boolean; export type OsdIsDateEnabled = boolean; export type OsdIsLogoEnabled = boolean; export type OsdIsDebugEnabled = boolean; export type OsdOverlayLocation = 'topLeft' | 'topMiddle' | 'topRight' | 'bottomLeft' | 'bottomMiddle' | 'bottomRight'; export type LedIsEnabled = boolean; export type LedWelcomeLed = boolean; export type LedFloodLed = boolean; export type LcdMessage = {type: 'DO_NOT_DISTURB', resetAt?: (number | null) | undefined} | {type: 'LEAVE_PACKAGE_AT_DOOR', resetAt?: (number | null) | undefined} | {type: 'CUSTOM_MESSAGE', resetAt?: (number | null) | undefined, text: string} | {type: 'IMAGE', resetAt?: (number | null) | undefined, text: string}; export type MicVolume = number; export type VideoMode = 'default' | 'highFps' | 'sport' | 'slowShutter' | 'lprReflex' | 'lprNoneReflex'; export type HdrType = 'auto' | 'on' | 'off'; export type ObjectTypes = Array<'person' | 'vehicle' | 'package' | 'licensePlate' | 'face' | 'animal'>; export type AudioTypes = Array<'alrmSmoke' | 'alrmCmonx' | 'alrmSiren' | 'alrmBabyCry' | 'alrmSpeak' | 'alrmBark' | 'alrmBurglar' | 'alrmCarHorn' | 'alrmGlassBreak'>; export type PatchApiV1CamerasIdArgs = {id: CameraId, body: {name?: string | undefined, osdSettings?: ({isNameEnabled?: OsdIsNameEnabled | undefined, isDateEnabled?: OsdIsDateEnabled | undefined, isLogoEnabled?: OsdIsLogoEnabled | undefined, isDebugEnabled?: OsdIsDebugEnabled | undefined, overlayLocation?: OsdOverlayLocation | undefined}) | undefined, ledSettings?: ({isEnabled?: LedIsEnabled | undefined, welcomeLed?: LedWelcomeLed | undefined, floodLed?: LedFloodLed | undefined}) | undefined, lcdMessage?: LcdMessage | undefined, micVolume?: MicVolume | undefined, videoMode?: VideoMode | undefined, hdrType?: HdrType | undefined, smartDetectSettings?: ({objectTypes?: ObjectTypes | undefined, audioTypes?: AudioTypes | undefined}) | undefined}}; export type PatchApiV1CamerasIdOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const cameraId = z.string(); export const cameraModelKey = z.literal("camera"); export const deviceState = z.enum(["CONNECTED", "CONNECTING", "DISCONNECTED"]); export const name = z.string(); export const mac = z.string(); export const isMicEnabled = z.boolean(); export const osdIsNameEnabled = z.boolean(); export const osdIsDateEnabled = z.boolean(); export const osdIsLogoEnabled = z.boolean(); export const osdIsDebugEnabled = z.boolean(); export const osdOverlayLocation = z.enum(["topLeft", "topMiddle", "topRight", "bottomLeft", "bottomMiddle", "bottomRight"]); export const osdSettings = z.object({isNameEnabled: osdIsNameEnabled, isDateEnabled: osdIsDateEnabled, isLogoEnabled: osdIsLogoEnabled, isDebugEnabled: osdIsDebugEnabled, overlayLocation: osdOverlayLocation}); export const ledIsEnabled = z.boolean(); export const ledWelcomeLed = z.boolean(); export const ledFloodLed = z.boolean(); export const ledSettings = z.object({isEnabled: ledIsEnabled, welcomeLed: ledWelcomeLed, floodLed: ledFloodLed}); export const lcdMessageUnion = z.object({type: z.enum(["LEAVE_PACKAGE_AT_DOOR", "DO_NOT_DISTURB", "CUSTOM_MESSAGE", "IMAGE"]).optional(), resetAt: z.number().nullable().optional(), text: z.string().optional()}); export const micVolume = z.number().gte(0).lte(100); export const activePatrolSlot = z.number(); export const videoMode = z.enum(["default", "highFps", "sport", "slowShutter", "lprReflex", "lprNoneReflex"]); export const hdrType = z.enum(["auto", "on", "off"]); export const cameraFeatureFlags = z.object({supportFullHdSnapshot: z.boolean(), hasHdr: z.boolean(), smartDetectTypes: z.array(z.enum(["person", "vehicle", "package", "licensePlate", "face", "animal"])), smartDetectAudioTypes: z.array(z.enum(["alrmSmoke", "alrmCmonx", "alrmSiren", "alrmBabyCry", "alrmSpeak", "alrmBark", "alrmBurglar", "alrmCarHorn", "alrmGlassBreak"])), videoModes: z.array(z.enum(["default", "highFps", "homekit", "sport", "slowShutter", "lprReflex", "lprNoneReflex"])), hasMic: z.boolean(), hasLedStatus: z.boolean(), hasSpeaker: z.boolean()}); export const objectTypes = z.array(z.enum(["person", "vehicle", "package", "licensePlate", "face", "animal"])); export const audioTypes = z.array(z.enum(["alrmSmoke", "alrmCmonx", "alrmSiren", "alrmBabyCry", "alrmSpeak", "alrmBark", "alrmBurglar", "alrmCarHorn", "alrmGlassBreak"])); export const smartDetectSettings = z.object({objectTypes: objectTypes, audioTypes: audioTypes}); export const hasPackageCamera = z.boolean(); export const camera = z.object({id: cameraId, modelKey: cameraModelKey, state: deviceState, name: name.nullable(), mac: mac, isMicEnabled: isMicEnabled, osdSettings: osdSettings, ledSettings: ledSettings, lcdMessage: lcdMessageUnion, micVolume: micVolume, activePatrolSlot: activePatrolSlot.nullable(), videoMode: videoMode, hdrType: hdrType, featureFlags: cameraFeatureFlags, smartDetectSettings: smartDetectSettings, hasPackageCamera: hasPackageCamera}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Patch camera settings * * PATCH /v1/cameras/{id} */ export const patchApiV1CamerasId = async (args: PatchApiV1CamerasIdArgs, options?: PatchApiV1CamerasIdOptions) => { const {baseUrl = "https://api.ui.com/v1/connector/consoles/942A6FF664C0000000000964970E0000000009E710560000000068A9873F:9999999999/proxy/protect/integration", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") const url = `${baseUrl.replace(/\/+$/, '')}/v1/cameras/${encodeURIComponent(String(args.id))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "PATCH", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(camera, await res.json()) };