Files

57 lines
5.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
let cameraSettingsContext=null,cameraSettingsGeneration=0;
const videoLabels={resolution:'分辨率',fps:'帧率(帧/秒)',bitrate:'码率上限(kbps)',quality:'画质等级',gop:'关键帧间隔(帧)'};
function clearCameraSettings(){cameraSettingsGeneration++;cameraSettingsContext=null;for(const id of ['camera-settings-info','camera-image-fields','camera-video-fields','camera-settings-status'])$('#'+id).replaceChildren();}
function settingsInput(key,label,value,rule){
const enumLabel=v=>key==='dayNight'?({AUTO:'自动日夜',ON:'日间(红外截止)',OFF:'夜间(红外通过)'})[v]||v:({ON:'开启',OFF:'关闭',AUTO:'自动',MANUAL:'手动'})[v]||v;
return `<label>${esc(label)}${rule.choices?`<select name="${esc(key)}">${rule.choices.map(v=>`<option value="${esc(v)}" ${v===value?'selected':''}>${esc(enumLabel(v))}</option>`).join('')}</select>`:`<input name="${esc(key)}" type="number" value="${esc(value)}" min="${rule.min}" max="${rule.max}" step="${['fps','bitrate','gop'].includes(key)?'1':'any'}" required><small>${rule.min}–${rule.max}</small>`}</label>`;
}
function renderCameraSettings(data){
const d=data.device;
$('#camera-settings-info').innerHTML=`<dl>${[['厂商',d.Manufacturer],['型号',d.Model],['固件',d.FirmwareVersion],['镜头视频源',data.source],['码流配置',data.profile],['设备报告编码',data.video.codec]].map(([k,v])=>`<div><dt>${esc(k)}</dt><dd>${esc(v||'未提供')}</dd></div>`).join('')}</dl>`;
$('#camera-image-fields').innerHTML=Object.entries(data.imaging).map(([k,r])=>settingsInput(k,r.label,r.value,r)).join('')||'<p class="description">设备未提供可调图像参数。</p>';
$('#camera-video-fields').innerHTML=Object.entries(data.video.options).map(([k,r])=>settingsInput(k,videoLabels[k],data.video.values[k],r)).join('')||'<p class="description">设备未提供可调码流参数。</p>';
$('#camera-settings-status').textContent=data.notes.join(';');
$('#camera-image-form button[type=submit]').disabled=!Object.keys(data.imaging).length;
$('#camera-video-form button[type=submit]').disabled=!Object.keys(data.video.options).length;
}
async function loadCameraSettings(){
if(!cameraSettingsContext)return;const context=cameraSettingsContext,generation=++cameraSettingsGeneration;
context.settings=null;context.quality=$('#camera-settings-quality').value;
$('#camera-settings-status').textContent='正在读取设备实际参数…';
$$('#camera-settings-dialog form input,#camera-settings-dialog form select,#camera-settings-dialog form button[type=submit]').forEach(b=>b.disabled=true);$('#camera-settings-reload').disabled=true;
try{const result=await api('/api/camera/settings?'+new URLSearchParams({camera:context.id,quality:context.quality}));
if(generation!==cameraSettingsGeneration||context!==cameraSettingsContext||!loggedIn)return;context.settings=result;renderCameraSettings(result);
}catch(e){if(!e.stale&&generation===cameraSettingsGeneration)$('#camera-settings-status').textContent=e.message;}
finally{if(generation===cameraSettingsGeneration)$('#camera-settings-reload').disabled=false;}
}
async function openCameraSettings(id){
if(!isAdmin())return;clearCameraSettings();cameraSettingsContext={id,settings:null,quality:'main'};
$('#camera-settings-title').textContent=(state.cameras.find(c=>c.id===id)?.name||'摄像机')+' · 参数设置';$('#camera-settings-quality').value='main';$('#camera-settings-quality').disabled=false;
$('#camera-settings-dialog').showModal();await loadCameraSettings();
}
function changedCameraValues(form,section,settings){
const rules=section==='imaging'?settings.imaging:settings.video.options,values={};
for(const [key,rule]of Object.entries(rules)){
const value=rule.choices?form.elements[key].value:Number(form.elements[key].value);
if(value!==(section==='imaging'?rule.value:settings.video.values[key]))values[key]=value;
}
return values;
}
async function saveCameraSettings(form,section){
const context=cameraSettingsContext;if(!context?.settings)return;
const values=changedCameraValues(form,section,context.settings);if(!Object.keys(values).length){toast('参数没有变化');return;}
const generation=++cameraSettingsGeneration;
$$('#camera-settings-dialog form input,#camera-settings-dialog form select,#camera-settings-dialog form button[type=submit]').forEach(b=>b.disabled=true);$('#camera-settings-reload').disabled=true;$('#camera-settings-quality').disabled=true;
$('#camera-settings-status').textContent='正在保存并读取设备返回值…';
try{const result=await api('/api/camera/settings',{camera:context.id,quality:context.quality,revision:context.settings.revision,section,values});
if(generation!==cameraSettingsGeneration||context!==cameraSettingsContext||!loggedIn)return;
context.settings=result.settings;if(result.settings)renderCameraSettings(result.settings);$('#camera-settings-status').textContent=result.message;toast(result.message);
}catch(e){if(!e.stale&&generation===cameraSettingsGeneration){context.settings=null;$('#camera-settings-status').textContent=e.message+'。请点击“重新读取”核对设备状态。';}}
finally{if(generation===cameraSettingsGeneration){$('#camera-settings-reload').disabled=false;$('#camera-settings-quality').disabled=false;}}
}
for(const [id,section]of [['camera-image-form','imaging'],['camera-video-form','video']])$('#'+id).addEventListener('submit',e=>{e.preventDefault();saveCameraSettings(e.currentTarget,section);});
$('#camera-settings-reload').onclick=loadCameraSettings;$('#camera-settings-quality').onchange=loadCameraSettings;
$('#camera-settings-dialog').addEventListener('close',clearCameraSettings);
document.addEventListener('click',e=>{const b=e.target.closest('[data-camera-settings]');if(b)openCameraSettings(b.dataset.cameraSettings);});