Add packaged per-camera X4 wake and preview recovery
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import {Button,SettingsCard,StatusBadge} from '@nodedc/ui-react';
|
||||
import type {RecoveryStatus} from './model';
|
||||
|
||||
export function RecoverySettings({value,online,enabled,pending,change}:{
|
||||
value:RecoveryStatus; online:boolean; enabled:boolean; pending:boolean; change:(enabled:boolean)=>void;
|
||||
}) {
|
||||
const failed=['exhausted','unavailable','preview_failed'].includes(value.phase);
|
||||
const label=!value.enabled?'Выключено':failed?'Требуется проверка камеры':
|
||||
['waiting','waking','restoring_preview'].includes(value.phase)?'Восстанавливаем подключение':'Включено';
|
||||
return <SettingsCard title="Восстановление подключения" description="После потери связи камера сможет включаться по Bluetooth. Ранее запущенный просмотр возобновится, запись на карту повторно не запускается."
|
||||
actions={<StatusBadge tone={failed&&value.enabled?'warning':'neutral'}>{label}</StatusBadge>}>
|
||||
<p>На X4 включите «Пробуждение по Bluetooth» и оставьте USB подключённым. Перед ручным выключением камеры отключите восстановление здесь.</p>
|
||||
<Button disabled={!enabled||(!online&&!value.enabled)} loading={pending} onClick={()=>change(!value.enabled)}>
|
||||
{value.enabled?'Отключить восстановление':'Включить восстановление'}
|
||||
</Button>
|
||||
</SettingsCard>;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import type {SensorDetailProps} from '../../../../packages/sensor-ui/src/extensi
|
||||
import {perform} from '../../../../packages/sensor-ui/src/contracts';
|
||||
import {LiveViewport} from '../../../../packages/sensor-ui/src/LiveViewport';
|
||||
import {CameraSettings} from './CameraSettings';
|
||||
import {RecoverySettings} from './RecoverySettings';
|
||||
import {cameraStatus,fileName,type CameraFiles,type CameraSettings as Settings} from './model';
|
||||
|
||||
export function X4Detail({device,transport,enabled,back,refresh,failure}:SensorDetailProps){
|
||||
@@ -22,7 +23,7 @@ export function X4Detail({device,transport,enabled,back,refresh,failure}:SensorD
|
||||
},[transport,device.id,device.snapshot.context.session_id,status.function_mode]);
|
||||
useEffect(()=>{if(available)void load().catch(error=>{if(mounted.current)failure(error);});},[available,load]);
|
||||
async function action(name:string,parameters:Record<string,unknown>={},key=name){
|
||||
if(running.current||!enabled||(!available&&name!=='refresh'))return;
|
||||
if(running.current||!enabled||(!available&&!['refresh','recovery.configure','preview.stop'].includes(name)))return;
|
||||
running.current=true;setPending(key);failure(null);
|
||||
try{
|
||||
const result=name==='refresh'?(available?await load():undefined):await perform<unknown>(transport,device,name,parameters);
|
||||
@@ -40,11 +41,12 @@ export function X4Detail({device,transport,enabled,back,refresh,failure}:SensorD
|
||||
return <div className="sensor-content"><div><Button onClick={back}>К устройствам</Button></div>
|
||||
<SettingsCard title={device.name} description={`${device.model}${device.firmware?' · '+device.firmware:''}`} actions={<IconButton label="Обновить состояние камеры" loading={pending==='refresh'} disabled={!enabled||busy} onClick={()=>void action('refresh')}><Icon name="refresh"/></IconButton>}>
|
||||
{!available&&<p>Нет свежей связи с камерой.</p>}
|
||||
<div className="sensor-actions"><Button disabled={!available||busy||status.preview!==0} loading={pending==='preview.start'} onClick={()=>void action('preview.start')}>Начать просмотр</Button><Button disabled={!available||busy||status.preview===0} loading={pending==='preview.stop'} onClick={()=>void action('preview.stop')}>Остановить просмотр</Button><Button disabled={!available||busy||status.recording!==0} loading={pending==='verify'} onClick={()=>void action('verify')}>Проверить изображение</Button></div>
|
||||
<div className="sensor-actions"><Button disabled={!available||busy||status.preview!==0} loading={pending==='preview.start'} onClick={()=>void action('preview.start')}>Начать просмотр</Button><Button disabled={!enabled||busy||(!available&&!status.recovery?.preview_wanted)||(available&&status.preview===0&&!status.recovery?.preview_wanted)} loading={pending==='preview.stop'} onClick={()=>void action('preview.stop')}>Остановить просмотр</Button><Button disabled={!available||busy||status.recording!==0} loading={pending==='verify'} onClick={()=>void action('verify')}>Проверить изображение</Button></div>
|
||||
{status.alerts?.temperature_high&&<p>Камера сообщает о перегреве.</p>}
|
||||
{status.alerts?.storage_full&&<p>На карте камеры закончилось место.</p>}
|
||||
{status.alerts?.battery_low&&<p>Камера сообщает о низком заряде.</p>}
|
||||
</SettingsCard>
|
||||
{status.recovery?.supported&&<RecoverySettings value={status.recovery} online={available} enabled={enabled&&!busy} pending={pending==='recovery.configure'} change={value=>void action('recovery.configure',{enabled:value,wakeup_confirmed:value})}/>}
|
||||
<LiveViewport device={viewDevice} layer="preview" title="Изображение X4" note="Запись сохраняется на карте памяти камеры." inactiveMessage="Нажмите «Начать просмотр», чтобы получить изображение." transport={transport} failure={failure}/>
|
||||
<SettingsCard title="Съёмка" description="Фото и видеозапись сохраняются на карте памяти X4." actions={<StatusBadge tone={available&&status.recording===1?'success':status.recording===0?'neutral':'warning'}>{available?recordLabel:'Состояние недоступно'}</StatusBadge>}>
|
||||
<div className="sensor-actions"><Button disabled={!available||busy||status.recording!==0||mode!==7} loading={pending==='record.start'} onClick={()=>void action('record.start')}>Начать запись</Button><Button disabled={!available||busy||status.recording===0} loading={pending==='record.stop'} onClick={()=>void action('record.stop')}>Остановить запись</Button><Button disabled={!available||busy||status.recording!==0||mode!==6} loading={pending==='photo.capture'} onClick={()=>void action('photo.capture')}>Сделать фото</Button></div>
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import type {Sensor} from '../../../../packages/sensor-ui/src/contracts';
|
||||
|
||||
export interface RecoveryStatus {
|
||||
supported:boolean; enabled:boolean; preview_wanted:boolean; phase:string;
|
||||
}
|
||||
|
||||
export interface CameraStatus {
|
||||
connected:boolean; preview:number|null; recording:number|null; function_mode:number|null;
|
||||
firmware?:string; battery?:{level:number}; storage?:{free_bytes:number};
|
||||
alerts?:{battery_low?:boolean;storage_full?:boolean;temperature_high?:boolean};
|
||||
recovery?:RecoveryStatus;
|
||||
}
|
||||
export interface CameraSettings {
|
||||
mode:number; photo_modes:number[]; video_modes:number[]; photo_sizes:number[];
|
||||
|
||||
Reference in New Issue
Block a user