Files
NODEDC_MISSION_CORE/packages/sensor-ui/src/contracts.ts
T

45 lines
3.5 KiB
TypeScript

export interface SensorProfile { id: string; sensor: number; stream: string; index: number; format: string; fps: number; width?: number; height?: number }
export interface SensorOption { id: string; sensor: string; label: string; value: number; min: number; max: number; step: number; read_only: boolean }
export interface Sensor {
kind?:string; connection_label?:string; control?:{generation:number;revision:number;phase:string;can_start:boolean;can_stop?:boolean;acquisition_id:string|null};
live_settings?: Record<string,unknown>;
id: string; name: string; model: string; prepared: boolean; configured?: boolean; verified: boolean; online: boolean; usb: string; firmware?: string; playback_id?: string | null;
snapshot: {context: {session_id: string; device: {device_id: string}; execution: {node_id: string}}; acquisition: string; enrollment: string; message?: string};
profiles?: SensorProfile[]; defaults?: string[]; options?: SensorOption[]; layers: string[];
frames?: Record<string,number>; last_frame?: {observed_at:string}; recording?: {id: string};
recordings?: {id:string;state:string;started_at:string;bytes?:number;sha256?:string}[];
}
export interface SensorInventory {
fresh?: boolean; items: Sensor[]; operations: {operation_id:string;device_id:string;action_id:string;requested_at:string;state:string;error?:string}[];
preparation?: {state:string;started_at:number;steps:{id:string;label:string;state:string;message?:string}[]};
}
export interface SensorCommand {
api_version: 'missioncore.nodedc/plugin-sdk/v0alpha2'; kind:'OperationRequest'; operation_id:string;
session: {session_id:string;device_id:string}; action_id:string; requested_at:string; deadline_at:string;
idempotency_key:string; parameters:Record<string,unknown>;
}
export interface SensorOperation {state:string;error?:string;result?:unknown}
export interface SensorTransport {
enrollment?: import('./enrollment').EnrollmentTransport;
inventory: () => Promise<SensorInventory>;
subscribe?: (receive:(value:SensorInventory)=>void, unavailable:()=>void) => (()=>void);
submit: (value:SensorCommand) => Promise<SensorOperation>;
operation: (id:string) => Promise<SensorOperation>;
}
export function command(device:Sensor,action:string,parameters:Record<string,unknown>={},timeoutMs=60000):SensorCommand {
const id='op_'+crypto.randomUUID().replaceAll('-','');const now=Date.now();
return {api_version:'missioncore.nodedc/plugin-sdk/v0alpha2',kind:'OperationRequest',operation_id:id,idempotency_key:id,
session:{session_id:device.snapshot.context.session_id,device_id:device.id},action_id:action,
requested_at:new Date(now).toISOString(),deadline_at:new Date(now+(action==='prepare'?350000:timeoutMs)).toISOString(),parameters};
}
export async function perform<T>(transport:SensorTransport,device:Sensor,action:string,parameters:Record<string,unknown>={},timeoutMs=60000):Promise<T>{
const request=command(device,action,parameters,timeoutMs);let value=await transport.submit(request);
const deadline=Date.parse(request.deadline_at)+10000;
while (value.state==='running'||value.state==='queued') {
if(Date.now()>deadline) throw new Error('Подтверждение пока не получено. Обновите состояние устройства.');
await new Promise(resolve=>setTimeout(resolve,1000));value=await transport.operation(request.operation_id);
}
if(value.state!=='complete') throw new Error(value.error||'Операция не завершена. Обновите состояние устройства.');
return value.result as T;
}