iobroker.agent-dvr 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +5 -0
- package/README.md +5 -4
- package/admin/assets/{index-ulvdM37k.js → index-DD1mpQy7.js} +1 -1
- package/admin/i18n/de.json +3 -1
- package/admin/i18n/en.json +3 -1
- package/admin/i18n/es.json +3 -1
- package/admin/i18n/fr.json +3 -1
- package/admin/i18n/it.json +3 -1
- package/admin/i18n/nl.json +3 -1
- package/admin/i18n/pl.json +3 -1
- package/admin/i18n/pt.json +3 -1
- package/admin/i18n/ru.json +3 -1
- package/admin/i18n/uk.json +3 -1
- package/admin/i18n/zh-cn.json +3 -1
- package/admin/index_m.html +1 -1
- package/build/main.js +11 -8
- package/build/main.js.map +2 -2
- package/io-package.json +14 -14
- package/package.json +1 -1
package/build/main.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/main.ts"],
|
|
4
|
-
"sourcesContent": ["import * as utils from '@iobroker/adapter-core';\nimport * as http from 'node:http';\nimport * as https from 'node:https';\nimport { getWidgetLabels, type WidgetLabels } from './lib/widget-i18n';\n\n// =====================================================================\n// Agent DVR -> ioBroker Adapter\n// API reference: https://ispysoftware.github.io/Agent_API/ (v7.5)\n// =====================================================================\n\n// ---- Types ----\n\ninterface ApiResult {\n\tok: boolean;\n\tdata?: string;\n\terror?: string;\n}\n\ninterface AgentDvrEvent {\n\tfn?: string;\n\ttg?: string;\n\tc?: number;\n\td?: number | string;\n\tsb?: number;\n\t[key: string]: unknown;\n}\n\ninterface Device {\n\toid: number | string;\n\tot: number;\n\tname: string;\n\traw: Record<string, unknown>;\n}\n\ntype RegistryKind = 'cam' | 'sys' | 'ptz' | 'ptzHold' | 'push' | 'setProfile' | 'snapshotB64';\n\ninterface RegistryEntry {\n\tkind: RegistryKind;\n\tpath?: string | null;\n\tparams?: string[];\n\toid?: number | string;\n\tot?: number;\n\tdir?: number;\n\tfid?: string;\n}\n\n// ---- Commands ----\n\nconst CAM_COMMANDS = [\n\t{ id: 'record', path: '/command/record', params: ['oid', 'ot'], name: 'Start recording' },\n\t{ id: 'recordStop', path: '/command/recordStop', params: ['oid', 'ot'], name: 'Stop recording' },\n\t{ id: 'recordRestart', path: '/command/recordRestart', params: ['oid', 'ot'], name: 'Restart recording' },\n\t{ id: 'triggerRecord', path: '/command/triggerRecord', params: ['oid', 'ot'], name: 'Trigger recording (timeout)' },\n\t{ id: 'snapshot', path: '/command/snapshot', params: ['oid'], name: 'Take snapshot' },\n\t{ id: 'detect', path: '/command/detect', params: ['oid', 'ot'], name: 'Trigger motion detection' },\n\t{ id: 'alertOn', path: '/command/alertOn', params: ['oid', 'ot'], name: 'Arm alerts' },\n\t{ id: 'alertOff', path: '/command/alertOff', params: ['oid', 'ot'], name: 'Disarm alerts' },\n\t{ id: 'switchOn', path: '/command/switchOn', params: ['oid', 'ot'], name: 'Switch device on' },\n\t{ id: 'switchOff', path: '/command/switchOff', params: ['oid', 'ot'], name: 'Switch device off' },\n\t{ id: 'objectDetectOn', path: '/command/objectdetecton', params: ['oid', 'ot'], name: 'Enable object detection' },\n\t{\n\t\tid: 'objectDetectOff',\n\t\tpath: '/command/objectdetectoff',\n\t\tparams: ['oid', 'ot'],\n\t\tname: 'Disable object detection',\n\t},\n\t{ id: 'recOnAlert', path: '/command/recordOnAlertOn', params: ['oid', 'ot'], name: 'Record on alert: on' },\n\t{ id: 'recOnDetect', path: '/command/recordOnDetectOn', params: ['oid', 'ot'], name: 'Record on detect: on' },\n\t{ id: 'purge', path: '/command/purge', params: ['oid', 'ot'], name: 'Purge folder (caution!)' },\n] as const;\n\nconst SYS_COMMANDS = [\n\t{ id: 'arm', path: '/command/arm', name: 'Arm system' },\n\t{ id: 'disarm', path: '/command/disarm', name: 'Disarm system' },\n\t{ id: 'allOn', path: '/command/allOn', name: 'All devices on' },\n\t{ id: 'allOff', path: '/command/allOff', name: 'All devices off' },\n\t{ id: 'reloadConfig', path: '/command/reloadConfig', name: 'Reload config' },\n\t{ id: 'reloadObjects', path: '/command/reloadObjects', name: 'Reload objects' },\n\t{ id: 'runStorageMgmt', path: '/command/runStorageMgmt', name: 'Run storage management' },\n\t{ id: 'blockExternal', path: '/command/blockExternal', name: 'Block external access' },\n\t{ id: 'unblockExternal', path: '/command/unblockExternal', name: 'Unblock external access' },\n\t{ id: 'restart', path: '/command/restart', name: 'Restart Agent DVR' },\n\t{ id: 'refresh', path: null, name: 'Refresh data now' },\n] as const;\n\nconst PTZ_DIRS = [\n\t{ id: 'left', dir: 1, hold: true },\n\t{ id: 'upLeft', dir: 2, hold: true },\n\t{ id: 'up', dir: 3, hold: true },\n\t{ id: 'upRight', dir: 4, hold: true },\n\t{ id: 'right', dir: 5, hold: true },\n\t{ id: 'downRight', dir: 6, hold: true },\n\t{ id: 'down', dir: 7, hold: true },\n\t{ id: 'downLeft', dir: 8, hold: true },\n\t{ id: 'zoomIn', dir: 9, hold: true },\n\t{ id: 'zoomOut', dir: 10, hold: true },\n\t{ id: 'stop', dir: 11, hold: false },\n\t{ id: 'center', dir: 0, hold: false },\n] as const;\n\nconst SKIP_KEYS = ['icons', 'image', 'thumbnail', 'base64'];\n\n// ---- Module-level helpers ----\n\nfunction sanitize(s: unknown): string {\n\treturn (\n\t\tString(s)\n\t\t\t.replace(/[\\s.[\\]*?\"'`,;:/\\\\]+/g, '_')\n\t\t\t.replace(/[^A-Za-z0-9_-]/g, '_')\n\t\t\t.replace(/_+/g, '_')\n\t\t\t.replace(/^_+|_+$/g, '') || 'x'\n\t);\n}\n\nfunction asJson(data: unknown): Record<string, unknown> | null {\n\tif (data == null) {\n\t\treturn null;\n\t}\n\tif (typeof data === 'object') {\n\t\treturn data as Record<string, unknown>;\n\t}\n\tif (typeof data === 'string') {\n\t\ttry {\n\t\t\treturn JSON.parse(data) as Record<string, unknown>;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\treturn null;\n}\n\nfunction toStr(v: unknown): string {\n\tif (v == null) {\n\t\treturn '';\n\t}\n\tif (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') {\n\t\treturn String(v);\n\t}\n\treturn Object.prototype.toString.call(v);\n}\n\nfunction escHtml(s: unknown): string {\n\treturn toStr(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n}\n\nfunction parseSizeGb(s: unknown): number | null {\n\tif (s == null) {\n\t\treturn null;\n\t}\n\tconst m = toStr(s)\n\t\t.trim()\n\t\t.match(/([\\d.,]+)\\s*([KMGT]?B)?/i);\n\tif (!m) {\n\t\treturn null;\n\t}\n\tlet v = parseFloat(m[1].replace(',', '.'));\n\tif (isNaN(v)) {\n\t\treturn null;\n\t}\n\tconst u = (m[2] || 'GB').toUpperCase();\n\tif (u === 'TB') {\n\t\tv *= 1024;\n\t} else if (u === 'MB') {\n\t\tv /= 1024;\n\t} else if (u === 'KB') {\n\t\tv /= 1048576;\n\t} else if (u === 'B') {\n\t\tv /= 1073741824;\n\t}\n\treturn Math.round(v * 100) / 100;\n}\n\nfunction findWH(obj: unknown, depth: number): [number, number] | null {\n\tif (!obj || typeof obj !== 'object' || depth > 5) {\n\t\treturn null;\n\t}\n\tconst o = obj as Record<string, unknown>;\n\tfor (const [kw, kh] of [\n\t\t['width', 'height'],\n\t\t['w', 'h'],\n\t\t['sourceWidth', 'sourceHeight'],\n\t\t['videoWidth', 'videoHeight'],\n\t\t['imageWidth', 'imageHeight'],\n\t]) {\n\t\tconst w = o[kw],\n\t\t\th = o[kh];\n\t\tif (typeof w === 'number' && typeof h === 'number' && w >= 100 && h >= 100 && w <= 12000 && h <= 12000) {\n\t\t\tconst r = w / h;\n\t\t\tif (r >= 0.3 && r <= 4) {\n\t\t\t\treturn [w, h];\n\t\t\t}\n\t\t}\n\t}\n\tfor (const k of Object.keys(o)) {\n\t\tconst g = findWH(o[k], depth + 1);\n\t\tif (g) {\n\t\t\treturn g;\n\t\t}\n\t}\n\treturn null;\n}\n\nfunction detectOt(elem: Record<string, unknown>): number {\n\tconst v = elem.typeID ?? elem.ot ?? elem.objectTypeID ?? elem.type;\n\treturn v === 1 || v === 2 ? v : 2;\n}\n\nfunction findDevices(json: Record<string, unknown>): Device[] {\n\tconst list = Array.isArray(json.objectList) ? json.objectList : [];\n\tconst out: Device[] = [];\n\tfor (const e of list) {\n\t\tif (!e || typeof e !== 'object') {\n\t\t\tcontinue;\n\t\t}\n\t\tconst el = e as Record<string, unknown>;\n\t\tconst rawId = el.id ?? el.oid;\n\t\tif (rawId === undefined || rawId === null) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst id = rawId as number | string;\n\t\tconst name = typeof el.name === 'string' ? el.name : `obj_${id}`;\n\t\tout.push({ oid: id, ot: detectOt(el), name, raw: el });\n\t}\n\treturn out;\n}\n\n// ---- HTML/CSS gallery helpers ----\n\ninterface WidgetColors {\n\tcardBg?: string;\n\ttagBg?: string;\n\ttagText?: string;\n\taccent?: string;\n\tmodalBg?: string;\n\tradius?: number;\n}\n\nfunction advCssVars(c?: WidgetColors): string {\n\tconst cardBg = c?.cardBg || 'rgba(127,127,127,.15)';\n\tconst tagBg = c?.tagBg || 'rgba(0,0,0,.55)';\n\tconst tagText = c?.tagText || '#fff';\n\tconst accent = c?.accent || '#8ab4f8';\n\tconst modalBg = c?.modalBg || '#1c1c1e';\n\tconst radius = c?.radius != null ? `${c.radius}px` : '8px';\n\treturn `--adv-card-bg:${cardBg};--adv-tag-bg:${tagBg};--adv-tag-color:${tagText};--adv-accent:${accent};--adv-modal-bg:${modalBg};--adv-radius:${radius};`;\n}\n\nfunction galleryCss(minCol: number, maxW: number, compact = false, colors?: WidgetColors): string {\n\tconst gap = compact ? 6 : 12;\n\treturn (\n\t\t`.advgrid{${advCssVars(colors)}display:grid;grid-template-columns:repeat(auto-fill,minmax(${minCol}px,1fr));gap:${gap}px;max-width:100%}` +\n\t\t`.advgrid .advlb{display:none}` +\n\t\t`.advcell{display:flex;flex-direction:column;cursor:pointer;text-decoration:none;color:inherit;font-family:inherit}` +\n\t\t`.advimg{position:relative;display:block;border-radius:var(--adv-radius);overflow:hidden;background:var(--adv-card-bg)}` +\n\t\t`.advimg img{width:100%;height:auto;display:block}` +\n\t\t`.advimgfix img{height:100%;object-fit:cover}` +\n\t\t`.advtag{position:absolute;background:var(--adv-tag-bg);color:var(--adv-tag-color);font-size:.6rem;padding:2px 4px;border-radius:3px;line-height:1;max-width:85%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}` +\n\t\t`.advplay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .15s;background:rgba(0,0,0,.2)}` +\n\t\t`.advplay::before{content:\"\";border-style:solid;border-width:11px 0 11px 18px;border-color:transparent transparent transparent #fff;filter:drop-shadow(0 1px 2px rgba(0,0,0,.6))}` +\n\t\t`.advcell:hover .advplay{opacity:1}` +\n\t\t`.advcap{font-size:${compact ? '.65rem' : '.72rem'};margin-top:${compact ? 2 : 4}px;line-height:1.25;opacity:.85}` +\n\t\t`.advmodal{display:none;position:fixed;inset:0;z-index:99999;align-items:center;justify-content:center}` +\n\t\t`.advgrid .advlb:checked + .advthumb + .advmodal{display:flex}` +\n\t\t`.advbackdrop{position:absolute;inset:0;background:transparent;cursor:pointer}` +\n\t\t`.advbox{position:relative;z-index:1;display:flex;flex-direction:column;gap:8px;max-width:min(92vw,${maxW}px);background:var(--adv-modal-bg);padding:12px;border-radius:14px;box-shadow:0 16px 48px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.08)}` +\n\t\t`.advvideo{width:100%;max-height:80vh;border-radius:8px;background:#000;display:block}` +\n\t\t`.advclose{position:absolute;top:18px;right:18px;width:32px;height:32px;border-radius:50%;background:rgba(0,0,0,.65);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:15px;z-index:2;border:2px solid rgba(255,255,255,.35)}` +\n\t\t`.advinfo{color:#fff;font-size:.8rem;text-align:center}` +\n\t\t`.advinfo a{color:var(--adv-accent)}` +\n\t\t`.advempty{padding:24px;text-align:center;opacity:.7;font-family:inherit}`\n\t);\n}\n\nfunction galleryCssJs(minCol: number, compact = false, colors?: WidgetColors): string {\n\tconst gap = compact ? 6 : 12;\n\treturn (\n\t\t`.advroot{${advCssVars(colors)}font-family:inherit;color:inherit}` +\n\t\t`.advbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:10px}` +\n\t\t`.advsearchjs{flex:1 1 160px;min-width:120px;padding:6px 10px;border-radius:8px;border:1px solid rgba(127,127,127,.4);background:rgba(127,127,127,.08);color:inherit;font:inherit}` +\n\t\t`.advtagsjs{display:flex;flex-wrap:wrap;gap:6px}` +\n\t\t`.advtagbtn{padding:4px 10px;border-radius:999px;border:1px solid rgba(127,127,127,.4);background:transparent;color:inherit;cursor:pointer;font:inherit;font-size:.8rem}` +\n\t\t`.advtagbtn.on{background:var(--adv-accent);color:#fff;border-color:var(--adv-accent)}` +\n\t\t`.advgridjs{display:grid;grid-template-columns:repeat(auto-fill,minmax(${minCol}px,1fr));gap:${gap}px}` +\n\t\t`.advcelljs{display:flex;flex-direction:column;cursor:pointer}` +\n\t\t`.advimgjs{position:relative;display:block;border-radius:var(--adv-radius);overflow:hidden;background:var(--adv-card-bg)}` +\n\t\t`.advimgjs img{width:100%;height:auto;display:block}` +\n\t\t`.advimgjs.advimgfix img{height:100%;object-fit:cover}` +\n\t\t`.advtagjs{position:absolute;background:var(--adv-tag-bg);color:var(--adv-tag-color);font-size:.6rem;padding:2px 4px;border-radius:3px;line-height:1;max-width:85%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}` +\n\t\t`.advplayjs{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .15s;background:rgba(0,0,0,.2)}` +\n\t\t`.advplayjs::before{content:\"\";border-style:solid;border-width:11px 0 11px 18px;border-color:transparent transparent transparent #fff;filter:drop-shadow(0 1px 2px rgba(0,0,0,.6))}` +\n\t\t`.advcelljs:hover .advplayjs{opacity:1}` +\n\t\t`.advcapjs{font-size:${compact ? '.65rem' : '.72rem'};margin-top:${compact ? 2 : 4}px;line-height:1.25;opacity:.85}` +\n\t\t`.advemptyjs{padding:24px;text-align:center;opacity:.7}`\n\t);\n}\n\n// Client-side browser code for the JS widget variant.\n// Stored as a string: TypeScript never type-checks browser code running in DOM context.\nconst ADV_CLIENT_CODE = `\n(function(){\nfunction esc(s){return String(s==null?'':s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"');}\nvar MODAL_CSS='.advmodaljs{display:none;position:fixed;inset:0;z-index:99999;align-items:center;justify-content:center}.advbackdropjs{position:absolute;inset:0;background:transparent;cursor:pointer}.advboxjs{position:relative;z-index:1;display:flex;flex-direction:column;gap:8px;max-width:min(92vw,900px);background:#1c1c1e;padding:12px;border-radius:14px;box-shadow:0 16px 48px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.08)}.advvideojs{width:100%;max-height:80vh;border-radius:8px;background:#000;display:block}.advclosejs{position:absolute;top:18px;right:18px;width:32px;height:32px;border-radius:50%;background:rgba(0,0,0,.65);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:15px;z-index:2;border:2px solid rgba(255,255,255,.35)}.advinfojs{color:#fff;font-size:.8rem;text-align:center}';\nvar modalEl=null,modalVideo=null,modalInfo=null,modalBox=null;\nfunction getModal(){\n if(modalEl&&document.body.contains(modalEl))return modalEl;\n if(!document.getElementById('advmodalcss')){var st=document.createElement('style');st.id='advmodalcss';st.textContent=MODAL_CSS;document.head.appendChild(st);}\n modalEl=document.createElement('div');modalEl.className='advmodaljs';\n var bd=document.createElement('div');bd.className='advbackdropjs';\n modalBox=document.createElement('div');modalBox.className='advboxjs';\n var cl=document.createElement('span');cl.className='advclosejs';cl.textContent='\u2715';\n modalVideo=document.createElement('video');modalVideo.className='advvideojs';\n modalVideo.setAttribute('controls','');modalVideo.setAttribute('preload','none');modalVideo.setAttribute('playsinline','');\n modalInfo=document.createElement('div');modalInfo.className='advinfojs';\n modalBox.appendChild(cl);modalBox.appendChild(modalVideo);modalBox.appendChild(modalInfo);\n modalEl.appendChild(bd);modalEl.appendChild(modalBox);\n document.body.appendChild(modalEl);\n bd.addEventListener('click',closeModal);cl.addEventListener('click',closeModal);\n return modalEl;\n}\nfunction openSrc(src,label,maxW){\n var m=getModal();\n if(maxW)modalBox.style.maxWidth='min(92vw,'+maxW+'px)';\n modalVideo.setAttribute('src',src);modalInfo.textContent=label;m.style.display='flex';\n}\nfunction closeModal(){\n if(!modalEl)return;\n try{modalVideo.pause();}catch(e){}\n modalVideo.removeAttribute('src');try{modalVideo.load();}catch(e){}\n modalEl.style.display='none';\n}\ndocument.addEventListener('keydown',function(e){if(e.key==='Escape'||e.keyCode===27)closeModal();});\nfunction initRoot(root){\n var dataEl=root.querySelector('script.advdata');\n if(!dataEl)return;\n var D;try{D=JSON.parse(dataEl.textContent);}catch(e){return;}\n var cfg=D.cfg||{},items=D.items||[],live=D.live||null;\n var grid=root.querySelector('.advgridjs'),search=root.querySelector('.advsearchjs'),tagsBox=root.querySelector('.advtagsjs');\n var state={q:'',tag:cfg.default_tag||''};\n var tagset={};\n items.forEach(function(it){String(it.tag||'').split(/[,\\\\s]+/).forEach(function(t){if(t)tagset[t]=1;});});\n var tags=Object.keys(tagset);\n if(cfg.show_tags&&tags.length){\n var mk=function(label,val){\n var b=document.createElement('button');b.className='advtagbtn';b.textContent=label;b.setAttribute('data-tag',val);\n b.addEventListener('click',function(){state.tag=state.tag===val?'':val;updateTagBtns();render();});\n tagsBox.appendChild(b);\n };\n mk(cfg.labels&&cfg.labels.all||'All','');tags.forEach(function(t){mk(t,t);});\n }\n function updateTagBtns(){var bs=tagsBox.querySelectorAll('.advtagbtn');for(var i=0;i<bs.length;i++)bs[i].classList.toggle('on',bs[i].getAttribute('data-tag')===state.tag);}\n updateTagBtns();\n if(search)search.addEventListener('input',function(){state.q=this.value.toLowerCase();render();});\n function badge(it){if(!(cfg.show_tags&&it.tag))return '';var pos=String(cfg.tag_position||'bottom-left').split('-');return '<span class=\"advtagjs\" style=\"'+pos[0]+':5px;'+pos[1]+':5px\">'+esc(it.tag)+'</span>';}\n function render(){\n var html='';\n if(live){var ar=cfg.live_aspect||'',arStyle=ar?' style=\"aspect-ratio:'+ar.replace('/',' / ')+'\"':'',arCls=ar?' advimgfix':'';\n html+='<div class=\"advcelljs\" data-live=\"1\"><span class=\"advimgjs'+arCls+'\"'+arStyle+'><img loading=\"lazy\" src=\"'+esc(live.thumb)+'\"><span class=\"advtagjs\" style=\"top:5px;left:5px\">● '+(cfg.labels&&cfg.labels.live||'LIVE')+'</span><span class=\"advplayjs\"></span></span><span class=\"advcapjs\">'+esc(live.name)+'</span></div>';}\n items.forEach(function(it,i){\n if(state.tag&&String(it.tag||'').toLowerCase().indexOf(state.tag.toLowerCase())<0)return;\n if(state.q){var hay=((it.date||'')+' '+(it.time||'')+' '+(it.tag||'')).toLowerCase();if(hay.indexOf(state.q)<0)return;}\n html+='<div class=\"advcelljs\" data-i=\"'+i+'\"><span class=\"advimgjs\"><img loading=\"lazy\" src=\"'+esc(it.thumb)+'\">'+badge(it)+'<span class=\"advplayjs\"></span></span><span class=\"advcapjs\">'+esc(it.date)+' '+esc(it.time)+'<br>'+esc(it.dur)+'s · '+esc(it.size)+' MB</span></div>';\n });\n grid.innerHTML=html||'<div class=\"advemptyjs\">'+(cfg.labels&&cfg.labels.noRecordings||'No recordings')+'</div>';\n var cells=grid.querySelectorAll('.advcelljs');\n for(var k=0;k<cells.length;k++)(function(cell){\n cell.addEventListener('click',function(){\n if(cell.getAttribute('data-live')==='1'){openSrc(live.video,(live.name||'')+' \u00B7 Live',cfg.max_modal_width);return;}\n var it=items[parseInt(cell.getAttribute('data-i'),10)],maxW=Number(cfg.max_modal_width)||900;\n if(cfg.player_url){var u=cfg.player_url.replace(/{video}/g,encodeURIComponent(it.video)).replace(/{videoRaw}/g,it.video).replace(/{fn}/g,encodeURIComponent(it.fn||'')).replace(/{date}/g,encodeURIComponent(it.date)).replace(/{time}/g,encodeURIComponent(it.time)).replace(/{duration}/g,encodeURIComponent(it.dur)).replace(/{size}/g,encodeURIComponent(it.size)).replace(/{tags}/g,encodeURIComponent(it.tag));window.open(u,'_blank');}\n else{openSrc(it.video,esc(it.date)+' '+esc(it.time)+(it.dur!=null?' \u00B7 '+it.dur+'s':'')+(it.size!=null?' \u00B7 '+it.size+' MB':'')+(it.tag?' \u00B7 '+it.tag:''),maxW);}\n });\n })(cells[k]);\n }\n render();\n}\nfunction scan(){var roots=document.querySelectorAll('.advroot');for(var i=0;i<roots.length;i++)if(!roots[i].__adv){roots[i].__adv=1;initRoot(roots[i]);}}\nwindow.ADVscan=scan;scan();\n})();\n`.trim();\n\n// ---- Adapter class ----\n\nclass AgentDvr extends utils.Adapter {\n\tprivate pollTimer: ioBroker.Interval | undefined = undefined;\n\tprivate pollBusy = false;\n\tprivate refreshTimer: ioBroker.Timeout | undefined = undefined;\n\tprivate authHeader: string | null = null;\n\tprivate baseUrl = '';\n\tprivate wt: WidgetLabels = getWidgetLabels('en');\n\n\tprivate readonly ensuredFolders = new Set<string>();\n\tprivate readonly registry = new Map<string, RegistryEntry>();\n\tprivate readonly ptzActive = new Map<string | number, string>();\n\tprivate readonly widgetSig: Record<string, string> = {};\n\tprivate profileSig = '';\n\tprivate lastCamNames: { key: string; name: string }[] = [];\n\tprivate readonly lastEventFn: Record<string | number, string> = {};\n\tprivate readonly camAspect: Record<string | number, string> = {};\n\tprivate readonly devById = new Map<string | number, Device>();\n\tprivate readonly eventBusy: Record<string | number, boolean> = {};\n\n\tpublic constructor(options: Partial<utils.AdapterOptions> = {}) {\n\t\tsuper({ ...options, name: 'agent-dvr' });\n\t\tthis.on('ready', this.onReady.bind(this));\n\t\tthis.on('stateChange', this.onStateChange.bind(this));\n\t\tthis.on('message', this.onMessage.bind(this));\n\t\tthis.on('unload', this.onUnload.bind(this));\n\t}\n\n\t// ---- lifecycle ----\n\n\tprivate async ensureWebInstance(): Promise<void> {\n\t\tconst instanceId = `system.adapter.${this.namespace}`;\n\t\tconst obj = await this.getForeignObjectAsync(instanceId);\n\t\tif (obj && !obj.native?.webInstance) {\n\t\t\tawait this.extendForeignObjectAsync(instanceId, { native: { webInstance: '*' } });\n\t\t\tthis.log.info('webInstance set \u2014 web adapter will reload the extension');\n\t\t}\n\t}\n\n\tprivate async onReady(): Promise<void> {\n\t\tvoid this.setState('info.connection', false, true);\n\t\tawait this.ensureWebInstance();\n\n\t\tconst sysConfig = await this.getForeignObjectAsync('system.config');\n\t\tconst rawLang = (sysConfig?.common as unknown as { language?: string } | undefined)?.language;\n\t\tthis.wt = getWidgetLabels(rawLang ?? 'en');\n\n\t\tconst pollSeconds = Math.max(5, Math.min(3600, this.config.pollSeconds || 30));\n\t\tthis.baseUrl = `http://${this.config.ip}:${this.config.port || 8090}`;\n\n\t\tif (this.config.user || this.config.pass) {\n\t\t\tthis.authHeader = `Basic ${Buffer.from(`${this.config.user}:${this.config.pass}`).toString('base64')}`;\n\t\t}\n\n\t\tawait this.buildSystem();\n\t\ttry {\n\t\t\tawait this.poll();\n\t\t} catch (e) {\n\t\t\tthis.log.warn(`First poll error: ${(e as Error).message}`);\n\t\t}\n\n\t\tthis.pollTimer = this.setInterval(\n\t\t\t() => this.poll().catch(e => this.log.warn(`Poll error: ${(e as Error).message}`)),\n\t\t\tpollSeconds * 1000,\n\t\t);\n\n\t\tthis.subscribeStates('*');\n\t\tthis.log.info(`Agent DVR adapter ready. Polling ${this.baseUrl} every ${pollSeconds}s.`);\n\t}\n\n\tprivate onUnload(callback: () => void): void {\n\t\ttry {\n\t\t\tif (this.pollTimer !== undefined) {\n\t\t\t\tthis.clearInterval(this.pollTimer);\n\t\t\t\tthis.pollTimer = undefined;\n\t\t\t}\n\t\t\tif (this.refreshTimer !== undefined) {\n\t\t\t\tthis.clearTimeout(this.refreshTimer);\n\t\t\t\tthis.refreshTimer = undefined;\n\t\t\t}\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t\tcallback();\n\t}\n\n\tprivate onMessage(obj: ioBroker.Message): void {\n\t\tif (!obj) {\n\t\t\treturn;\n\t\t}\n\t\tif (obj.command === 'getGo2rtcStreams') {\n\t\t\tconst overrideUrl =\n\t\t\t\ttypeof obj.message === 'object' && obj.message !== null\n\t\t\t\t\t? (obj.message.url as string | undefined)\n\t\t\t\t\t: undefined;\n\t\t\tvoid this.fetchGo2rtcStreams(overrideUrl).then(result => {\n\t\t\t\tthis.sendTo(obj.from, obj.command, result, obj.callback);\n\t\t\t});\n\t\t} else if (obj.command === 'getAgentDvrCameras') {\n\t\t\tthis.sendTo(obj.from, obj.command, { cameras: this.lastCamNames }, obj.callback);\n\t\t} else if (obj.command === 'getAvailableSources') {\n\t\t\tvoid this.fetchAvailableSources().then(result => {\n\t\t\t\tthis.sendTo(obj.from, obj.command, result, obj.callback);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async fetchAvailableSources(): Promise<{ result: { source: string; name: string }[] }> {\n\t\tconst deadline = new Promise<{ result: { source: string; name: string }[] }>(res =>\n\t\t\tthis.setTimeout(() => res({ result: [{ source: '!', name: 'Timeout' }] }), 5000),\n\t\t);\n\t\treturn Promise.race([this._doFetchAvailableSources(), deadline]);\n\t}\n\n\tprivate async _doFetchAvailableSources(): Promise<{ result: { source: string; name: string }[] }> {\n\t\tconst rows: { source: string; name: string }[] = [];\n\t\tfor (const c of this.lastCamNames) {\n\t\t\trows.push({ source: 'AgentDVR', name: `${c.name} (${c.key})` });\n\t\t}\n\t\tconst { streams } = await this.fetchGo2rtcStreams();\n\t\tfor (const s of streams) {\n\t\t\trows.push({ source: 'go2rtc', name: s });\n\t\t}\n\t\tif (!rows.length) {\n\t\t\trows.push({ source: '\u2014', name: 'Keine Quellen gefunden (Adapter hat noch nicht gepollt)' });\n\t\t}\n\t\treturn { result: rows };\n\t}\n\n\tprivate fetchGo2rtcStreams(overrideUrl?: string): Promise<{ streams: string[]; error?: string }> {\n\t\t// go2rtc l\u00E4uft immer auf plain-HTTP; https:// \u2192 http:// erzwingen\n\t\tconst url = (overrideUrl || this.config.go2rtcUrl || '').replace(/^https:\\/\\//i, 'http://');\n\t\tif (!url) {\n\t\t\treturn Promise.resolve({ streams: [], error: 'go2rtcUrl nicht konfiguriert' });\n\t\t}\n\t\tlet target: URL;\n\t\ttry {\n\t\t\ttarget = new URL('/api/streams', url);\n\t\t} catch {\n\t\t\treturn Promise.resolve({ streams: [], error: `Ung\u00FCltige URL: ${url}` });\n\t\t}\n\t\tlet httpReq: ReturnType<typeof http.get> | undefined;\n\t\tconst fetch = new Promise<{ streams: string[]; error?: string }>(resolve => {\n\t\t\tconst mod = target.protocol === 'https:' ? https : http;\n\t\t\thttpReq = mod.get(target.toString(), res => {\n\t\t\t\tlet body = '';\n\t\t\t\tres.on('data', (c: Buffer) => {\n\t\t\t\t\tbody += c.toString();\n\t\t\t\t});\n\t\t\t\tres.on('end', () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst parsed = JSON.parse(body);\n\t\t\t\t\t\tconst streams = Object.keys(parsed || {});\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tstreams,\n\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\tstreams.length === 0 ? 'go2rtc antwortet, aber keine Streams konfiguriert' : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tresolve({ streams: [], error: `Ung\u00FCltige JSON-Antwort von go2rtc (HTTP ${res.statusCode})` });\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tres.on('error', (e: Error) => resolve({ streams: [], error: `Stream-Fehler: ${e.message}` }));\n\t\t\t});\n\t\t\thttpReq.on('error', (e: Error) => resolve({ streams: [], error: `Verbindungsfehler: ${e.message}` }));\n\t\t});\n\t\tconst timeout = new Promise<{ streams: string[]; error?: string }>(resolve =>\n\t\t\tthis.setTimeout(() => {\n\t\t\t\thttpReq?.destroy();\n\t\t\t\tresolve({ streams: [], error: `Timeout beim Abrufen von ${target.toString()}` });\n\t\t\t}, 3000),\n\t\t);\n\t\treturn Promise.race([fetch, timeout]);\n\t}\n\n\tprivate onStateChange(id: string, state: ioBroker.State | null | undefined): void {\n\t\tif (!state || state.ack !== false) {\n\t\t\treturn;\n\t\t}\n\t\tconst relId = this.getRelId(id);\n\t\tconst entry = this.registry.get(relId);\n\t\tif (entry) {\n\t\t\tthis.runCommand(relId, entry, state.val).catch(e =>\n\t\t\t\tthis.log.warn(`Command error: ${(e as Error).message}`),\n\t\t\t);\n\t\t}\n\t}\n\n\t// ---- helpers ----\n\n\tprivate getRelId(fullId: string): string {\n\t\treturn fullId.startsWith(`${this.namespace}.`) ? fullId.slice(this.namespace.length + 1) : fullId;\n\t}\n\n\tprivate apiGet(path: string): Promise<ApiResult> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst timeout = Math.max(1000, Math.min(30000, this.config.httpTimeoutMs || 8000));\n\t\t\tconst opts: http.RequestOptions = {\n\t\t\t\thostname: this.config.ip,\n\t\t\t\tport: this.config.port || 8090,\n\t\t\t\tpath,\n\t\t\t\tmethod: 'GET',\n\t\t\t\ttimeout,\n\t\t\t};\n\t\t\tif (this.authHeader) {\n\t\t\t\topts.headers = { Authorization: this.authHeader };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst req = http.request(opts, res => {\n\t\t\t\t\tlet data = '';\n\t\t\t\t\tres.on('data', (c: Buffer) => {\n\t\t\t\t\t\tdata += c.toString();\n\t\t\t\t\t});\n\t\t\t\t\tres.on('end', () => {\n\t\t\t\t\t\tif (res.statusCode && res.statusCode >= 400) {\n\t\t\t\t\t\t\tresolve({ ok: false, error: `HTTP ${res.statusCode}` });\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve({ ok: true, data });\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tres.on('error', (e: Error) => resolve({ ok: false, error: e.message }));\n\t\t\t\t});\n\t\t\t\treq.on('error', (e: Error) => resolve({ ok: false, error: e.message }));\n\t\t\t\treq.on('timeout', () => {\n\t\t\t\t\treq.destroy();\n\t\t\t\t\tresolve({ ok: false, error: 'timeout' });\n\t\t\t\t});\n\t\t\t\treq.end();\n\t\t\t} catch (e) {\n\t\t\t\tresolve({ ok: false, error: String((e as Error).message || e) });\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate apiGetBuffer(path: string): Promise<{ ok: boolean; data?: Buffer; error?: string }> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst timeout = Math.max(1000, Math.min(30000, this.config.httpTimeoutMs || 8000));\n\t\t\tconst opts: http.RequestOptions = {\n\t\t\t\thostname: this.config.ip,\n\t\t\t\tport: this.config.port || 8090,\n\t\t\t\tpath,\n\t\t\t\tmethod: 'GET',\n\t\t\t\ttimeout,\n\t\t\t};\n\t\t\tif (this.authHeader) {\n\t\t\t\topts.headers = { Authorization: this.authHeader };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst req = http.request(opts, res => {\n\t\t\t\t\tconst chunks: Buffer[] = [];\n\t\t\t\t\tres.on('data', (c: Buffer) => chunks.push(c));\n\t\t\t\t\tres.on('end', () => {\n\t\t\t\t\t\tif (res.statusCode && res.statusCode >= 400) {\n\t\t\t\t\t\t\tresolve({ ok: false, error: `HTTP ${res.statusCode}` });\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve({ ok: true, data: Buffer.concat(chunks) });\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tres.on('error', (e: Error) => resolve({ ok: false, error: e.message }));\n\t\t\t\t});\n\t\t\t\treq.on('error', (e: Error) => resolve({ ok: false, error: e.message }));\n\t\t\t\treq.on('timeout', () => {\n\t\t\t\t\treq.destroy();\n\t\t\t\t\tresolve({ ok: false, error: 'timeout' });\n\t\t\t\t});\n\t\t\t\treq.end();\n\t\t\t} catch (e) {\n\t\t\t\tresolve({ ok: false, error: String((e as Error).message || e) });\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async ensureFolder(id: string, name: string, type: 'device' | 'channel' = 'channel'): Promise<void> {\n\t\tif (this.ensuredFolders.has(id)) {\n\t\t\treturn;\n\t\t}\n\t\tawait this.setObjectNotExistsAsync(id, { type, common: { name }, native: {} });\n\t\tthis.ensuredFolders.add(id);\n\t}\n\n\tprivate async ensurePath(fullId: string): Promise<void> {\n\t\tconst parts = fullId.split('.');\n\t\tlet acc = parts[0];\n\t\tfor (let i = 1; i < parts.length - 1; i++) {\n\t\t\tacc += `.${parts[i]}`;\n\t\t\tif (!this.ensuredFolders.has(acc)) {\n\t\t\t\tawait this.setObjectNotExistsAsync(acc, { type: 'channel', common: { name: parts[i] }, native: {} });\n\t\t\t\tthis.ensuredFolders.add(acc);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate guessRole(id: string, val: unknown): ioBroker.CommonType {\n\t\tif (typeof val === 'string' && /^https?:\\/\\//i.test(val)) {\n\t\t\treturn 'string';\n\t\t}\n\t\treturn 'string';\n\t}\n\n\tprivate async writeLeaf(id: string, val: unknown): Promise<void> {\n\t\tconst t = typeof val;\n\t\tlet common: ioBroker.StateCommon;\n\t\tif (t === 'boolean') {\n\t\t\tcommon = { name: id.split('.').pop() || id, type: 'boolean', role: 'indicator', read: true, write: false };\n\t\t} else if (t === 'number') {\n\t\t\tcommon = { name: id.split('.').pop() || id, type: 'number', role: 'value', read: true, write: false };\n\t\t} else {\n\t\t\tconst role = typeof val === 'string' && /^https?:\\/\\//i.test(val) ? 'text.url' : 'text';\n\t\t\tcommon = { name: id.split('.').pop() || id, type: 'string', role, read: true, write: false };\n\t\t}\n\t\tif (!this.ensuredFolders.has(id)) {\n\t\t\tawait this.ensurePath(id);\n\t\t\tawait this.setObjectNotExistsAsync(id, { type: 'state', common, native: {} });\n\t\t\tthis.ensuredFolders.add(id);\n\t\t}\n\t\tawait this.setStateAsync(id, { val: (val === undefined ? null : val) as ioBroker.StateValue, ack: true });\n\t}\n\n\tprivate async flattenWrite(obj: unknown, prefix: string, depth: number): Promise<void> {\n\t\tconst maxDepth = Math.max(1, Math.min(10, this.config.maxDepth || 6));\n\t\tconst maxArray = Math.max(1, Math.min(500, this.config.maxArray || 30));\n\t\tif (depth > maxDepth) {\n\t\t\treturn;\n\t\t}\n\t\tif (obj === null || obj === undefined) {\n\t\t\tawait this.writeLeaf(prefix, obj);\n\t\t\treturn;\n\t\t}\n\t\tif (typeof obj === 'object') {\n\t\t\tif (Array.isArray(obj)) {\n\t\t\t\tif (obj.length > maxArray) {\n\t\t\t\t\tawait this.writeLeaf(`${prefix}.count`, obj.length);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (let i = 0; i < obj.length; i++) {\n\t\t\t\t\tawait this.flattenWrite(obj[i], `${prefix}.${i}`, depth + 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (const k of Object.keys(obj)) {\n\t\t\t\t\tif (SKIP_KEYS.includes(k)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.flattenWrite((obj as Record<string, unknown>)[k], `${prefix}.${sanitize(k)}`, depth + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tawait this.writeLeaf(prefix, obj);\n\t\t}\n\t}\n\n\tprivate async ensureControl(\n\t\tid: string,\n\t\tname: string,\n\t\tentry: RegistryEntry,\n\t\trole: 'button' | 'switch',\n\t): Promise<void> {\n\t\tif (!this.ensuredFolders.has(id)) {\n\t\t\tawait this.ensurePath(id);\n\t\t\tawait this.setObjectNotExistsAsync(id, {\n\t\t\t\ttype: 'state',\n\t\t\t\tcommon: { name, type: 'boolean', role, read: role === 'switch', write: true, def: false },\n\t\t\t\tnative: {},\n\t\t\t});\n\t\t\tawait this.setStateAsync(id, { val: false, ack: true });\n\t\t\tthis.ensuredFolders.add(id);\n\t\t}\n\t\tthis.registry.set(id, entry);\n\t}\n\n\tprivate ensureButton(id: string, name: string, entry: RegistryEntry): Promise<void> {\n\t\treturn this.ensureControl(id, name, entry, 'button');\n\t}\n\n\tprivate async ensureSelector(\n\t\tid: string,\n\t\tname: string,\n\t\tentry: RegistryEntry,\n\t\tstates: Record<number, string>,\n\t): Promise<void> {\n\t\tif (!this.ensuredFolders.has(id)) {\n\t\t\tawait this.ensurePath(id);\n\t\t\tawait this.setObjectNotExistsAsync(id, {\n\t\t\t\ttype: 'state',\n\t\t\t\tcommon: { name, type: 'number', role: 'level', read: true, write: true, states },\n\t\t\t\tnative: {},\n\t\t\t});\n\t\t\tawait this.setStateAsync(id, { val: 0, ack: true });\n\t\t\tthis.ensuredFolders.add(id);\n\t\t}\n\t\tthis.registry.set(id, entry);\n\t}\n\n\tprivate async fetchSnapshotB64(oid: number | string, snapId: string): Promise<void> {\n\t\tconst imgRes = await this.apiGetBuffer(`/photo.jpg?oid=${oid}`);\n\t\tif (imgRes.ok && imgRes.data) {\n\t\t\tawait this.setStateAsync(snapId, {\n\t\t\t\tval: `data:image/jpeg;base64,${imgRes.data.toString('base64')}`,\n\t\t\t\tack: true,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async ensureFlag(id: string, name: string): Promise<void> {\n\t\tif (this.ensuredFolders.has(id)) {\n\t\t\treturn;\n\t\t}\n\t\tawait this.ensurePath(id);\n\t\tawait this.setObjectNotExistsAsync(id, {\n\t\t\ttype: 'state',\n\t\t\tcommon: { name, type: 'boolean', role: 'indicator', read: true, write: false, def: false },\n\t\t\tnative: {},\n\t\t});\n\t\tthis.ensuredFolders.add(id);\n\t\tawait this.setStateAsync(id, { val: false, ack: true });\n\t}\n\n\tprivate async pulse(id: string): Promise<void> {\n\t\tawait this.setStateAsync(id, { val: true, ack: true });\n\t\tthis.setTimeout(() => this.setStateAsync(id, { val: false, ack: true }).catch(() => {}), 1500);\n\t}\n\n\t// ---- system structure ----\n\n\tprivate async buildSystem(): Promise<void> {\n\t\tawait this.ensureFolder('system', 'System', 'channel');\n\t\tawait this.writeLeaf('system.online', false);\n\t\tawait this.writeLeaf('system.lastUpdate', '');\n\t\tawait this.writeLeaf('system.lastPoll', 0);\n\t\tawait this.writeLeaf('system.cameraCount', 0);\n\n\t\tif (this.config.enableSystemControls) {\n\t\t\tawait this.ensureFolder('system.control', 'Control', 'channel');\n\t\t\tfor (const c of SYS_COMMANDS) {\n\t\t\t\tawait this.ensureButton(`system.control.${c.id}`, c.name, { kind: 'sys', path: c.path });\n\t\t\t}\n\t\t\tawait this.ensureFolder('system.profile', 'Profile', 'channel');\n\t\t\tawait this.ensureSelector(\n\t\t\t\t'system.profile.selector',\n\t\t\t\t'Active profile',\n\t\t\t\t{ kind: 'setProfile' },\n\t\t\t\t{ 0: 'Home', 1: 'Away', 2: 'Night' },\n\t\t\t);\n\t\t\tif (!this.ensuredFolders.has('system.profile.list')) {\n\t\t\t\tawait this.setObjectNotExistsAsync('system.profile.list', {\n\t\t\t\t\ttype: 'state',\n\t\t\t\t\tcommon: {\n\t\t\t\t\t\tname: 'Available profiles (JSON)',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\trole: 'json',\n\t\t\t\t\t\tread: true,\n\t\t\t\t\t\twrite: false,\n\t\t\t\t\t},\n\t\t\t\t\tnative: {},\n\t\t\t\t});\n\t\t\t\tthis.ensuredFolders.add('system.profile.list');\n\t\t\t\tawait this.setStateAsync('system.profile.list', { val: '[]', ack: true });\n\t\t\t}\n\t\t}\n\t}\n\n\t// ---- camera aspect detection ----\n\n\tprivate async detectAspect(d: Device): Promise<void> {\n\t\tif (this.camAspect[d.oid] !== undefined) {\n\t\t\treturn;\n\t\t}\n\t\tlet wh = findWH(d.raw, 0);\n\t\tif (!wh) {\n\t\t\tconst res = await this.apiGet(`/command/getObject?oid=${d.oid}&ot=2`);\n\t\t\tconst j = asJson(res.data);\n\t\t\tif (j) {\n\t\t\t\twh = findWH(j, 0);\n\t\t\t}\n\t\t}\n\t\tthis.camAspect[d.oid] = wh ? `${wh[0]}/${wh[1]}` : '';\n\t\tif (wh) {\n\t\t\tthis.log.debug(`cam ${d.oid} resolution ${wh[0]}x${wh[1]} -> AR ${this.camAspect[d.oid]}`);\n\t\t}\n\t}\n\n\t// ---- device folder name ----\n\n\tprivate deviceFolder(d: Device): string {\n\t\treturn `${d.ot === 1 ? 'mic' : 'cam'}_${sanitize(d.oid)}_${sanitize(d.name)}`;\n\t}\n\n\t// ---- device status data points ----\n\n\tprivate readonly STATUS_DPS = [\n\t\t{ key: 'recording', role: 'indicator.working', name: 'Active recording' },\n\t\t{ key: 'online', role: 'indicator.reachable', name: 'Online' },\n\t\t{ key: 'connected', role: 'indicator.connected', name: 'Stream connected' },\n\t\t{ key: 'detected', role: 'indicator', name: 'Motion detected' },\n\t\t{ key: 'alerted', role: 'indicator.alarm', name: 'Alert active' },\n\t] as const;\n\n\tprivate async writeStatusDps(d: Device, fid: string): Promise<void> {\n\t\tconst data = d.raw.data as Record<string, unknown> | undefined;\n\t\tif (!data || typeof data !== 'object') {\n\t\t\treturn;\n\t\t}\n\t\tconst sfid = `${fid}.status`;\n\t\tif (!this.ensuredFolders.has(sfid)) {\n\t\t\tawait this.ensureFolder(sfid, 'Status', 'channel');\n\t\t}\n\t\tfor (const dp of this.STATUS_DPS) {\n\t\t\tif (!(dp.key in data)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst id = `${sfid}.${dp.key}`;\n\t\t\tawait this.setObjectNotExistsAsync(id, {\n\t\t\t\ttype: 'state',\n\t\t\t\tcommon: { name: dp.name, type: 'boolean', role: dp.role, read: true, write: false, def: false },\n\t\t\t\tnative: {},\n\t\t\t});\n\t\t\tawait this.setStateAsync(id, { val: !!data[dp.key], ack: true });\n\t\t}\n\t}\n\n\t// ---- build device data points ----\n\n\tprivate async buildDevice(d: Device): Promise<void> {\n\t\tconst fid = this.deviceFolder(d);\n\t\tthis.devById.set(d.oid, d);\n\n\t\tawait this.ensureFolder(fid, d.name, 'device');\n\t\tif (d.ot === 2) {\n\t\t\tawait this.detectAspect(d);\n\t\t}\n\t\tawait this.flattenWrite(d.raw, fid, 0);\n\t\tawait this.writeStatusDps(d, fid);\n\n\t\tawait this.ensureFolder(`${fid}.control`, 'Control', 'channel');\n\t\tfor (const c of CAM_COMMANDS) {\n\t\t\tif (c.id === 'snapshot' && d.ot !== 2) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tawait this.ensureButton(`${fid}.control.${c.id}`, c.name, {\n\t\t\t\tkind: 'cam',\n\t\t\t\tpath: c.path,\n\t\t\t\tparams: [...c.params],\n\t\t\t\toid: d.oid,\n\t\t\t\tot: d.ot,\n\t\t\t});\n\t\t}\n\n\t\tif (this.config.enablePtz && d.ot === 2) {\n\t\t\tawait this.ensureFolder(`${fid}.control.ptz`, 'PTZ', 'channel');\n\t\t\tfor (const p of PTZ_DIRS) {\n\t\t\t\tconst cid = `${fid}.control.ptz.${p.id}`;\n\t\t\t\tif (p.hold) {\n\t\t\t\t\tawait this.ensureControl(\n\t\t\t\t\t\tcid,\n\t\t\t\t\t\t`PTZ ${p.id} (hold)`,\n\t\t\t\t\t\t{ kind: 'ptzHold', oid: d.oid, dir: p.dir },\n\t\t\t\t\t\t'switch',\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tawait this.ensureButton(cid, `PTZ ${p.id}`, { kind: 'ptz', oid: d.oid, dir: p.dir });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.config.enableUrls && d.ot === 2) {\n\t\t\tawait this.ensureFolder(`${fid}.urls`, 'URLs', 'channel');\n\t\t\tawait this.writeLeaf(`${fid}.urls.snapshot`, `${this.baseUrl}/grab.jpg?oid=${d.oid}`);\n\t\t\tawait this.writeLeaf(`${fid}.urls.photo`, `${this.baseUrl}/photo.jpg?oid=${d.oid}`);\n\t\t\tawait this.writeLeaf(`${fid}.urls.mjpeg`, `${this.baseUrl}/video.mjpg?oids=${d.oid}`);\n\t\t\tawait this.writeLeaf(`${fid}.urls.mp4`, `${this.baseUrl}/video.mp4?oids=${d.oid}`);\n\t\t}\n\n\t\tif (d.ot === 2) {\n\t\t\tconst snapId = `${fid}.snapshot_b64`;\n\t\t\tif (!this.ensuredFolders.has(snapId)) {\n\t\t\t\tawait this.ensurePath(snapId);\n\t\t\t\tawait this.setObjectNotExistsAsync(snapId, {\n\t\t\t\t\ttype: 'state',\n\t\t\t\t\tcommon: {\n\t\t\t\t\t\tname: 'Snapshot (Base64)',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\trole: 'state',\n\t\t\t\t\t\tread: true,\n\t\t\t\t\t\twrite: false,\n\t\t\t\t\t},\n\t\t\t\t\tnative: {},\n\t\t\t\t});\n\t\t\t\tawait this.setStateAsync(snapId, { val: '', ack: true });\n\t\t\t\tthis.ensuredFolders.add(snapId);\n\t\t\t}\n\t\t\tawait this.ensureButton(`${fid}.control.refreshSnapshotB64`, 'Refresh snapshot (Base64)', {\n\t\t\t\tkind: 'snapshotB64',\n\t\t\t\toid: d.oid,\n\t\t\t\tfid,\n\t\t\t});\n\t\t\tif (this.config.enableSnapshotB64) {\n\t\t\t\tawait this.fetchSnapshotB64(d.oid, snapId);\n\t\t\t}\n\t\t}\n\n\t\tawait this.updateCameraEvents(d, fid);\n\t}\n\n\t// ---- event formatting ----\n\n\tprivate fmtEvent(\n\t\tev: Record<string, unknown>,\n\t\toid: number | string,\n\t): {\n\t\tfn: string;\n\t\tsizeMB: number;\n\t\tdur: string;\n\t\ttag: string;\n\t\tdate: string;\n\t\ttime: string;\n\t\tthumb: string;\n\t\tvideo: string;\n\t} {\n\t\tconst e = ev as AgentDvrEvent;\n\t\tconst fn = e.fn ?? '';\n\t\tconst dot = fn.lastIndexOf('.');\n\t\tconst jpg = `${dot > 0 ? fn.slice(0, dot) : fn}_large.jpg`;\n\t\tconst sizeMB = e.sb ? Math.round((Number(e.sb) / 1048576) * 100) / 100 : 0;\n\t\tconst dur = e.d != null ? String(e.d) : '';\n\t\tconst tag = e.tg ?? '';\n\t\tconst ms = (parseFloat(String(e.c ?? 0)) - 621355968000000000) / 10000;\n\t\tconst dt = new Date(ms);\n\t\tconst two = (n: number): string => String(n).padStart(2, '0');\n\t\tconst date = `${two(dt.getDate())}.${two(dt.getMonth() + 1)}.`;\n\t\tconst time = `${two(dt.getHours())}:${two(dt.getMinutes())}`;\n\t\tconst thumb = `${this.baseUrl}/fileThumb.jpg?oid=${oid}&fn=${encodeURIComponent(jpg)}`;\n\t\tconst video = `${this.baseUrl}/streamFile.cgi?oid=${oid}&ot=2&fn=${encodeURIComponent(fn)}`;\n\t\treturn { fn, sizeMB, dur, tag, date, time, thumb, video };\n\t}\n\n\t// ---- gallery HTML builders ----\n\n\tprivate effectiveMinCol(): number {\n\t\tconst sizeMap: Record<string, number> = { small: 120, medium: 180, large: 240 };\n\t\tconst ts = this.config.widgetThumbSize;\n\t\treturn ts && sizeMap[ts] ? sizeMap[ts] : this.config.widgetMinCol || 150;\n\t}\n\n\tprivate async pruneStaleDevices(activeFolders: Set<string>): Promise<void> {\n\t\tconst allObjs = await this.getAdapterObjectsAsync();\n\t\tconst stale: string[] = [];\n\t\tfor (const fullId of Object.keys(allObjs)) {\n\t\t\tconst obj = allObjs[fullId];\n\t\t\tif (obj.type !== 'device') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst rel = fullId.slice(this.namespace.length + 1);\n\t\t\tif (/^(cam|mic)_/.test(rel) && !activeFolders.has(rel)) {\n\t\t\t\tstale.push(rel);\n\t\t\t}\n\t\t}\n\t\tfor (const rel of stale) {\n\t\t\tthis.log.info(`[agent-dvr] removing stale device: ${rel}`);\n\t\t\tawait this.delObjectAsync(rel, { recursive: true });\n\t\t\t// clean up internal cache\n\t\t\tfor (const [oid, d] of this.devById) {\n\t\t\t\tif (this.deviceFolder(d) === rel) {\n\t\t\t\t\tthis.devById.delete(oid);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate sortedEvents(events: Record<string, unknown>[]): Record<string, unknown>[] {\n\t\t// newest-first by default; widgetSortNewest=false reverses to oldest-first\n\t\treturn this.config.widgetSortNewest === false ? [...events].reverse() : events;\n\t}\n\n\tprivate buildGalleryHtml(d: Device, events: Record<string, unknown>[]): string {\n\t\treturn (this.config.widgetMode || 'nojs') === 'js'\n\t\t\t? this.buildGalleryHtmlJs(d, events)\n\t\t\t: this.buildGalleryHtmlNojs(d, events);\n\t}\n\n\tprivate buildGalleryHtmlNojs(d: Device, events: Record<string, unknown>[]): string {\n\t\tconst oid = d.oid;\n\t\tconst minCol = this.effectiveMinCol();\n\t\tconst maxW = this.config.widgetMaxModalWidth || 900;\n\t\tconst showTags = this.config.widgetShowTags;\n\t\tconst pos = (this.config.widgetTagPosition || 'bottom-left').split('-');\n\t\tconst tagStyle = `${pos[0]}:5px;${pos[1]}:5px`;\n\t\tconst playerUrl = (this.config.widgetPlayerUrl || '').trim();\n\t\tconst compact = !!this.config.widgetCompact;\n\t\tconst PAUSE_ATTR = ` onchange=\"if(!this.checked){var m=this.nextElementSibling.nextElementSibling,v=m&&m.querySelector('video');if(v){v.pause();}}\"`;\n\n\t\tconst items = this.sortedEvents(events)\n\t\t\t.map((ev, i) => {\n\t\t\t\tconst p = this.fmtEvent(ev, oid);\n\t\t\t\tconst id = `adv${sanitize(oid)}_${i}`;\n\t\t\t\tconst badge =\n\t\t\t\t\tshowTags && p.tag ? `<span class=\"advtag\" style=\"${tagStyle}\">${escHtml(p.tag)}</span>` : '';\n\t\t\t\tconst inner =\n\t\t\t\t\t`<span class=\"advimg\"><img src=\"${p.thumb}\" loading=\"lazy\" alt=\"\">${badge}<span class=\"advplay\"></span></span>` +\n\t\t\t\t\t`<span class=\"advcap\">${escHtml(p.date)} ${escHtml(p.time)}<br>${escHtml(p.dur)}s · ${escHtml(p.sizeMB)} MB</span>`;\n\t\t\t\tif (playerUrl) {\n\t\t\t\t\tconst href = playerUrl\n\t\t\t\t\t\t.replace(/{video}/g, encodeURIComponent(p.video))\n\t\t\t\t\t\t.replace(/{videoRaw}/g, p.video)\n\t\t\t\t\t\t.replace(/{fn}/g, encodeURIComponent(p.fn))\n\t\t\t\t\t\t.replace(/{date}/g, encodeURIComponent(p.date))\n\t\t\t\t\t\t.replace(/{time}/g, encodeURIComponent(p.time))\n\t\t\t\t\t\t.replace(/{duration}/g, encodeURIComponent(p.dur))\n\t\t\t\t\t\t.replace(/{size}/g, encodeURIComponent(String(p.sizeMB)))\n\t\t\t\t\t\t.replace(/{tags}/g, encodeURIComponent(p.tag));\n\t\t\t\t\treturn `<a class=\"advcell\" href=\"${escHtml(href)}\" target=\"_blank\" rel=\"noopener\">${inner}</a>`;\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t`<input class=\"advlb\" type=\"checkbox\" id=\"${id}\"${PAUSE_ATTR}>` +\n\t\t\t\t\t`<label class=\"advcell advthumb\" for=\"${id}\">${inner}</label>` +\n\t\t\t\t\t`<div class=\"advmodal\"><label class=\"advbackdrop\" for=\"${id}\"></label>` +\n\t\t\t\t\t`<div class=\"advbox\"><label class=\"advclose\" for=\"${id}\">✕</label>` +\n\t\t\t\t\t`<video class=\"advvideo\" controls preload=\"none\" playsinline src=\"${p.video}\"></video>` +\n\t\t\t\t\t`<div class=\"advinfo\">${escHtml(p.date)} ${escHtml(p.time)} · ${escHtml(p.dur)}s · ${escHtml(p.sizeMB)} MB${\n\t\t\t\t\t\tp.tag ? ` · ${escHtml(p.tag)}` : ''\n\t\t\t\t\t} · <a href=\"${p.video}\" download target=\"_blank\">${this.wt.download}</a></div></div></div>`\n\t\t\t\t);\n\t\t\t})\n\t\t\t.join('');\n\n\t\tconst gridClass = compact ? 'advgrid advcompact' : 'advgrid';\n\t\tconst grid = items\n\t\t\t? `<div class=\"${gridClass}\">${items}</div>`\n\t\t\t: `<div class=\"advempty\">${this.wt.noRecordings}</div>`;\n\t\tconst colors: WidgetColors = {\n\t\t\tcardBg: this.config.widgetColorCardBg || undefined,\n\t\t\ttagBg: this.config.widgetColorTagBg || undefined,\n\t\t\ttagText: this.config.widgetColorTagText || undefined,\n\t\t\taccent: this.config.widgetColorAccent || undefined,\n\t\t\tmodalBg: this.config.widgetColorModalBg || undefined,\n\t\t\tradius: this.config.widgetBorderRadius,\n\t\t};\n\t\treturn `<style>${galleryCss(minCol, maxW, compact, colors)}</style>${grid}`;\n\t}\n\n\tprivate buildGalleryHtmlJs(d: Device, events: Record<string, unknown>[]): string {\n\t\tconst oid = d.oid;\n\t\tconst minCol = this.effectiveMinCol();\n\t\tconst maxW = this.config.widgetMaxModalWidth || 900;\n\t\tconst showSearch = this.config.widgetShowSearch !== false;\n\t\tconst compact = !!this.config.widgetCompact;\n\t\tconst defaultTag = (this.config.widgetDefaultTag || '').trim();\n\t\tconst items = this.sortedEvents(events).map(ev => {\n\t\t\tconst p = this.fmtEvent(ev, oid);\n\t\t\treturn {\n\t\t\t\tfn: p.fn,\n\t\t\t\tdate: p.date,\n\t\t\t\ttime: p.time,\n\t\t\t\tdur: p.dur,\n\t\t\t\tsize: p.sizeMB,\n\t\t\t\ttag: p.tag,\n\t\t\t\tthumb: p.thumb,\n\t\t\t\tvideo: p.video,\n\t\t\t};\n\t\t});\n\t\tconst cfg = {\n\t\t\tmin_col: minCol,\n\t\t\tshow_tags: !!this.config.widgetShowTags,\n\t\t\tmax_modal_width: maxW,\n\t\t\tlive_aspect: this.camAspect[oid] || this.config.widgetLiveAspect || '',\n\t\t\tplayer_url: (this.config.widgetPlayerUrl || '').trim(),\n\t\t\ttag_position: this.config.widgetTagPosition || 'bottom-left',\n\t\t\tcompact,\n\t\t\tdefault_tag: defaultTag,\n\t\t\tlabels: { noRecordings: this.wt.noRecordings, all: this.wt.all, live: this.wt.live },\n\t\t};\n\t\tconst data = JSON.stringify({ items, live: null, cfg }).replace(/</g, '\\\\u003c');\n\t\tconst boot = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n\t\tconst searchHtml = showSearch\n\t\t\t? `<input class=\"advsearchjs\" type=\"text\" placeholder=\"${escHtml(this.wt.search)}\">`\n\t\t\t: '';\n\t\tconst colors: WidgetColors = {\n\t\t\tcardBg: this.config.widgetColorCardBg || undefined,\n\t\t\ttagBg: this.config.widgetColorTagBg || undefined,\n\t\t\ttagText: this.config.widgetColorTagText || undefined,\n\t\t\taccent: this.config.widgetColorAccent || undefined,\n\t\t\tmodalBg: this.config.widgetColorModalBg || undefined,\n\t\t\tradius: this.config.widgetBorderRadius,\n\t\t};\n\t\treturn (\n\t\t\t`<style>${galleryCssJs(minCol, compact, colors)}</style>` +\n\t\t\t`<div class=\"advroot\"><script type=\"application/json\" class=\"advdata\">${data}</script>` +\n\t\t\t`<div class=\"advbar\">${searchHtml}<div class=\"advtagsjs\"></div></div>` +\n\t\t\t`<div class=\"advgridjs\"></div></div>` +\n\t\t\t`<script type=\"text/plain\" class=\"advcode\">${ADV_CLIENT_CODE}</script>` +\n\t\t\t`<img alt=\"\" src=\"${boot}\" style=\"display:none\" onload=\"(function(){if(window.ADVscan){window.ADVscan();return;}var c=document.querySelector('script.advcode');if(!c)return;var s=document.createElement('script');s.textContent=c.textContent;document.body.appendChild(s);})()\">`\n\t\t);\n\t}\n\n\tprivate buildOverviewHtml(cams: Device[]): string {\n\t\tconst ts = Date.now();\n\t\tconst minCol = this.config.widgetMinCol || 150;\n\t\tconst maxW = this.config.widgetMaxModalWidth || 900;\n\t\tconst PAUSE_ATTR = ` onchange=\"if(!this.checked){var m=this.nextElementSibling.nextElementSibling,v=m&&m.querySelector('video');if(v){v.pause();}}\"`;\n\t\tconst tiles = cams\n\t\t\t.map(d => {\n\t\t\t\tconst oid = d.oid;\n\t\t\t\tconst id = `advlive${sanitize(oid)}`;\n\t\t\t\tconst grab = `${this.baseUrl}/grab.jpg?oid=${oid}&ot=2&maintainAR=1&ts=${ts}`;\n\t\t\t\tconst webm = `${this.baseUrl}/video.webm?oid=${oid}&ot=2`;\n\t\t\t\tconst name = escHtml(d.name || `Camera ${oid}`);\n\t\t\t\tconst arRaw = this.camAspect[oid] || this.config.widgetLiveAspect || '';\n\t\t\t\tconst ar = arRaw ? String(arRaw).replace('/', ' / ') : '';\n\t\t\t\tconst fix = ar ? ' advimgfix' : '';\n\t\t\t\tconst arStyle = ar ? ` style=\"aspect-ratio:${ar}\"` : '';\n\t\t\t\tconst inner =\n\t\t\t\t\t`<span class=\"advimg${fix}\"${arStyle}><img src=\"${grab}\" loading=\"lazy\" alt=\"\">` +\n\t\t\t\t\t`<span class=\"advtag\" style=\"top:5px;left:5px\">● ${escHtml(this.wt.live)}</span><span class=\"advplay\"></span></span>` +\n\t\t\t\t\t`<span class=\"advcap\">${name}</span>`;\n\t\t\t\treturn (\n\t\t\t\t\t`<input class=\"advlb\" type=\"checkbox\" id=\"${id}\"${PAUSE_ATTR}>` +\n\t\t\t\t\t`<label class=\"advcell advthumb\" for=\"${id}\">${inner}</label>` +\n\t\t\t\t\t`<div class=\"advmodal\"><label class=\"advbackdrop\" for=\"${id}\"></label>` +\n\t\t\t\t\t`<div class=\"advbox\"><label class=\"advclose\" for=\"${id}\">✕</label>` +\n\t\t\t\t\t`<video class=\"advvideo\" controls preload=\"none\" playsinline src=\"${webm}\"></video>` +\n\t\t\t\t\t`<div class=\"advinfo\">${name} · Live</div></div></div>`\n\t\t\t\t);\n\t\t\t})\n\t\t\t.join('');\n\t\tconst grid = tiles ? `<div class=\"advgrid\">${tiles}</div>` : `<div class=\"advempty\">No cameras</div>`;\n\t\treturn `<style>${galleryCss(minCol, maxW)}</style>${grid}`;\n\t}\n\n\t// ---- event data points ----\n\n\tprivate async writeEventDps(d: Device, fid: string, events: Record<string, unknown>[]): Promise<void> {\n\t\tconst oid = d.oid;\n\t\tawait this.ensureFolder(`${fid}.events`, 'Events', 'channel');\n\t\tawait this.ensureFolder(`${fid}.events.last`, 'Last event', 'channel');\n\n\t\tconst two = (n: number): string => String(n).padStart(2, '0');\n\t\tconst now = new Date();\n\t\tconst td = `${two(now.getDate())}.${two(now.getMonth() + 1)}.`;\n\t\tconst todayCount = events.filter(ev => this.fmtEvent(ev, oid).date === td).length;\n\n\t\tawait this.writeLeaf(`${fid}.events.count`, events.length);\n\t\tawait this.writeLeaf(`${fid}.events.today`, todayCount);\n\n\t\tif (events.length) {\n\t\t\tconst p = this.fmtEvent(events[0], oid);\n\t\t\tconst tsMs = (parseFloat(String((events[0] as AgentDvrEvent).c ?? 0)) - 621355968000000000) / 10000;\n\t\t\tawait this.writeLeaf(`${fid}.events.last.time`, `${p.date} ${p.time}`);\n\t\t\tawait this.writeLeaf(`${fid}.events.last.timestamp`, Math.round(tsMs));\n\t\t\tawait this.writeLeaf(`${fid}.events.last.tag`, p.tag);\n\t\t\tawait this.writeLeaf(`${fid}.events.last.duration`, p.dur ? parseFloat(p.dur) : 0);\n\t\t\tawait this.writeLeaf(`${fid}.events.last.size_mb`, p.sizeMB);\n\t\t\tawait this.writeLeaf(`${fid}.events.last.thumb`, p.thumb);\n\t\t\tawait this.writeLeaf(`${fid}.events.last.video`, p.video);\n\t\t}\n\n\t\t// JSON list for web UI \u2014 browser never needs to talk to AgentDVR for recordings\n\t\tconst jsonId = `${fid}.events.json`;\n\t\tif (!this.ensuredFolders.has(jsonId)) {\n\t\t\tawait this.ensurePath(jsonId);\n\t\t\tawait this.setObjectNotExistsAsync(jsonId, {\n\t\t\t\ttype: 'state',\n\t\t\t\tcommon: { name: 'Recordings list (web UI)', type: 'string', role: 'json', read: true, write: false },\n\t\t\t\tnative: {},\n\t\t\t});\n\t\t\tthis.ensuredFolders.add(jsonId);\n\t\t}\n\t\tawait this.setStateAsync(jsonId, {\n\t\t\tval: JSON.stringify(\n\t\t\t\tevents.slice(0, Math.max(1, this.config.widgetAnzahl || 50)).map(ev => {\n\t\t\t\t\tconst p = this.fmtEvent(ev, oid);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdate: p.date,\n\t\t\t\t\t\ttime: p.time,\n\t\t\t\t\t\tdur: p.dur,\n\t\t\t\t\t\tsize: p.sizeMB,\n\t\t\t\t\t\ttag: p.tag,\n\t\t\t\t\t\tthumb: p.thumb,\n\t\t\t\t\t\tvideo: p.video,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t),\n\t\t\tack: true,\n\t\t});\n\n\t\tawait this.ensureFlag(`${fid}.events.new`, 'New event');\n\n\t\tif (this.config.enablePush) {\n\t\t\tconst pid = `${fid}.events.pushTrigger`;\n\t\t\tif (!this.ensuredFolders.has(pid)) {\n\t\t\t\tawait this.ensurePath(pid);\n\t\t\t\tawait this.setObjectNotExistsAsync(pid, {\n\t\t\t\t\ttype: 'state',\n\t\t\t\t\tcommon: {\n\t\t\t\t\t\tname: 'Push trigger (AgentDVR action)',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\trole: 'text',\n\t\t\t\t\t\tread: true,\n\t\t\t\t\t\twrite: true,\n\t\t\t\t\t\tdef: '',\n\t\t\t\t\t},\n\t\t\t\t\tnative: {},\n\t\t\t\t});\n\t\t\t\tawait this.setStateAsync(pid, { val: '', ack: true });\n\t\t\t\tthis.ensuredFolders.add(pid);\n\t\t\t}\n\t\t\tthis.registry.set(pid, { kind: 'push', oid, fid });\n\t\t}\n\n\t\tconst ignore = (this.config.eventTagsIgnore || 'detected')\n\t\t\t.split(',')\n\t\t\t.map(s => s.trim().toLowerCase())\n\t\t\t.filter(Boolean);\n\t\tconst tokensOf = (s: string): string[] =>\n\t\t\ts\n\t\t\t\t.toLowerCase()\n\t\t\t\t.split(/[,\\s]+/)\n\t\t\t\t.filter(Boolean);\n\n\t\tfor (const kw of (this.config.eventTags || '')\n\t\t\t.split(',')\n\t\t\t.map(s => s.trim())\n\t\t\t.filter(Boolean)) {\n\t\t\tawait this.ensureFlag(`${fid}.events.detected_${sanitize(kw)}`, `Detected: ${kw}`);\n\t\t}\n\n\t\tif (this.config.eventTagsDynamic) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const ev of events) {\n\t\t\t\ttokensOf((ev as AgentDvrEvent).tg ?? '').forEach(t => seen.add(t));\n\t\t\t}\n\t\t\tfor (const t of seen) {\n\t\t\t\tif (ignore.includes(t)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tawait this.ensureFlag(`${fid}.events.detected_${sanitize(t)}`, `Detected: ${t}`);\n\t\t\t}\n\t\t}\n\n\t\tlet newCount = 0;\n\t\tif (events.length) {\n\t\t\tconst prev = this.lastEventFn[oid];\n\t\t\tif (prev !== undefined) {\n\t\t\t\tconst i = events.findIndex(e => (e as AgentDvrEvent).fn === prev);\n\t\t\t\tnewCount = i === -1 ? events.length : i;\n\t\t\t}\n\t\t\tthis.lastEventFn[oid] = (events[0] as AgentDvrEvent).fn ?? '';\n\t\t}\n\n\t\tif (newCount > 0) {\n\t\t\tawait this.pulse(`${fid}.events.new`);\n\t\t\tconst tags = new Set<string>();\n\t\t\tfor (let i = 0; i < newCount && i < events.length; i++) {\n\t\t\t\ttokensOf((events[i] as AgentDvrEvent).tg ?? '').forEach(t => tags.add(t));\n\t\t\t}\n\t\t\tfor (const t of tags) {\n\t\t\t\tif (ignore.includes(t)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst tid = `${fid}.events.detected_${sanitize(t)}`;\n\t\t\t\tawait this.ensureFlag(tid, `Detected: ${t}`);\n\t\t\t\tawait this.pulse(tid);\n\t\t\t}\n\t\t\tthis.log.debug(`${newCount} new event(s) cam ${oid} [${[...tags].join(',')}]`);\n\t\t}\n\t}\n\n\t// ---- camera events + widget ----\n\n\tprivate async updateCameraEvents(d: Device, fid: string): Promise<void> {\n\t\tif (d.ot !== 2) {\n\t\t\treturn;\n\t\t}\n\t\tif (!this.config.enableWidget && !this.config.enableEventDps) {\n\t\t\treturn;\n\t\t}\n\t\tif (this.eventBusy[d.oid]) {\n\t\t\treturn;\n\t\t}\n\t\tthis.eventBusy[d.oid] = true;\n\t\ttry {\n\t\t\tconst evRes = await this.apiGet(`/q/getEvents?oid=${d.oid}&ot=2`);\n\t\t\tconst evJson = asJson(evRes.data);\n\t\t\tif (!evJson) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst events = (\n\t\t\t\tArray.isArray(evJson.events) ? evJson.events : Array.isArray(evJson) ? evJson : []\n\t\t\t) as Record<string, unknown>[];\n\n\t\t\tif (this.config.enableEventDps) {\n\t\t\t\tawait this.writeEventDps(d, fid, events);\n\t\t\t}\n\n\t\t\tif (this.config.enableWidget) {\n\t\t\t\tconst wId = `${fid}.widget`;\n\t\t\t\tif (!this.ensuredFolders.has(wId)) {\n\t\t\t\t\tawait this.ensurePath(wId);\n\t\t\t\t\tawait this.setObjectNotExistsAsync(wId, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'HTML gallery widget',\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\trole: 'html',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: false,\n\t\t\t\t\t\t\tdef: '',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tthis.ensuredFolders.add(wId);\n\t\t\t\t}\n\t\t\t\tconst ev = events.slice(0, Math.max(1, this.config.widgetAnzahl || 50));\n\t\t\t\tconst f = (ev[0] ?? {}) as AgentDvrEvent;\n\t\t\t\tconst l = (ev[ev.length - 1] ?? {}) as AgentDvrEvent;\n\t\t\t\tconst sig = `${ev.length}|${f.fn ?? ''}|${l.fn ?? ''}`;\n\t\t\t\tif (this.widgetSig[wId] !== sig) {\n\t\t\t\t\tawait this.setStateAsync(wId, { val: this.buildGalleryHtml(d, ev), ack: true });\n\t\t\t\t\tthis.widgetSig[wId] = sig;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.eventBusy[d.oid] = false;\n\t\t}\n\t}\n\n\tprivate pushRefresh(oid: number | string): void {\n\t\tconst d = this.devById.get(oid);\n\t\tif (!d) {\n\t\t\tthis.log.warn(`Push: camera ${oid} unknown (available after first poll)`);\n\t\t\treturn;\n\t\t}\n\t\tconst fid = this.deviceFolder(d);\n\t\tfor (const ms of [0, 1500, 3500, 6000]) {\n\t\t\tthis.setTimeout(\n\t\t\t\t() =>\n\t\t\t\t\tthis.updateCameraEvents(d, fid).catch(e =>\n\t\t\t\t\t\tthis.log.warn(`Push refresh error: ${(e as Error).message}`),\n\t\t\t\t\t),\n\t\t\t\tms,\n\t\t\t);\n\t\t}\n\t}\n\n\t// ---- main poll ----\n\n\tprivate async poll(): Promise<void> {\n\t\tif (this.pollBusy) {\n\t\t\tthis.log.debug('poll() skipped \u2014 previous run still in progress');\n\t\t\treturn;\n\t\t}\n\t\tthis.pollBusy = true;\n\t\ttry {\n\t\t\tconst res = await this.apiGet('/command/getObjects');\n\t\t\tconst json = asJson(res.data);\n\n\t\t\tif (!res.ok || !json) {\n\t\t\t\tawait this.setStateAsync('info.connection', false, true);\n\t\t\t\tawait this.setStateAsync('system.online', { val: false, ack: true });\n\t\t\t\tthis.log.warn(`AgentDVR unreachable: ${res.error || 'invalid response'}`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait this.setStateAsync('info.connection', true, true);\n\t\t\tawait this.setStateAsync('system.online', { val: true, ack: true });\n\n\t\t\tif (json.settings) {\n\t\t\t\tawait this.flattenWrite(json.settings, 'system.settings', 0);\n\t\t\t}\n\n\t\t\tif (this.config.storeRawJson) {\n\t\t\t\tconst clean: Record<string, unknown> = { ...json };\n\t\t\t\tdelete clean.icons;\n\t\t\t\tawait this.writeLeaf('system.raw_getObjects', JSON.stringify(clean).slice(0, 60000));\n\t\t\t}\n\n\t\t\tconst devices = findDevices(json);\n\t\t\tthis.lastCamNames = devices.filter(d => d.ot === 2).map(d => ({ key: this.deviceFolder(d), name: d.name }));\n\t\t\tawait this.setStateAsync('system.cameraCount', { val: devices.filter(d => d.ot === 2).length, ack: true });\n\n\t\t\tconst activeFolders = new Set(devices.map(d => this.deviceFolder(d)));\n\t\t\tfor (const d of devices) {\n\t\t\t\tawait this.buildDevice(d);\n\t\t\t}\n\t\t\tawait this.pruneStaleDevices(activeFolders);\n\n\t\t\tconst stats = asJson((await this.apiGet('/command/getSystemStats')).data);\n\t\t\tif (stats) {\n\t\t\t\tawait this.flattenWrite(stats, 'system.stats', 0);\n\t\t\t\tconst gb = parseSizeGb(stats.disk_free);\n\t\t\t\tif (gb !== null) {\n\t\t\t\t\tawait this.writeLeaf('system.disk_free_gb', gb);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst status = asJson((await this.apiGet('/command/getStatus')).data);\n\t\t\tif (status) {\n\t\t\t\tawait this.flattenWrite(status, 'system.status', 0);\n\t\t\t}\n\n\t\t\tif (this.config.enableSystemControls && Array.isArray(json.profiles)) {\n\t\t\t\tconst states: Record<number, string> = {};\n\t\t\t\tlet activeInd: number | null = null;\n\t\t\t\tfor (const p of json.profiles) {\n\t\t\t\t\tif (p && typeof p === 'object') {\n\t\t\t\t\t\tconst po = p as Record<string, unknown>;\n\t\t\t\t\t\tconst ind = po.id ?? po.ind ?? po.index;\n\t\t\t\t\t\tconst pname = po.name;\n\t\t\t\t\t\tif (typeof ind === 'number' && (typeof pname === 'string' || typeof pname === 'number')) {\n\t\t\t\t\t\t\tstates[ind] = String(pname);\n\t\t\t\t\t\t\tif (po.active === true) {\n\t\t\t\t\t\t\t\tactiveInd = ind;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (Object.keys(states).length > 0) {\n\t\t\t\t\tconst sig = JSON.stringify(states);\n\t\t\t\t\tif (sig !== this.profileSig) {\n\t\t\t\t\t\tthis.profileSig = sig;\n\t\t\t\t\t\tawait this.extendObjectAsync('system.profile.selector', { common: { states } });\n\t\t\t\t\t\tawait this.setStateAsync('system.profile.list', { val: sig, ack: true });\n\t\t\t\t\t}\n\t\t\t\t\tif (activeInd !== null) {\n\t\t\t\t\t\tawait this.setStateAsync('system.profile.selector', { val: activeInd, ack: true });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.config.enableOverview) {\n\t\t\t\tconst cams = devices.filter(d => d.ot === 2);\n\t\t\t\tconst ovId = 'overview';\n\t\t\t\tif (!this.ensuredFolders.has(ovId)) {\n\t\t\t\t\tawait this.setObjectNotExistsAsync(ovId, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'Overview (all cameras)',\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\trole: 'html',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: false,\n\t\t\t\t\t\t\tdef: '',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tthis.ensuredFolders.add(ovId);\n\t\t\t\t}\n\t\t\t\tawait this.setStateAsync(ovId, { val: this.buildOverviewHtml(cams), ack: true });\n\t\t\t}\n\n\t\t\tawait this.setStateAsync('system.lastUpdate', { val: new Date().toISOString(), ack: true });\n\t\t\tawait this.setStateAsync('system.lastPoll', { val: Date.now(), ack: true });\n\t\t} finally {\n\t\t\tthis.pollBusy = false;\n\t\t}\n\t}\n\n\tprivate scheduleRefresh(): void {\n\t\tif (this.refreshTimer !== undefined) {\n\t\t\tthis.clearTimeout(this.refreshTimer);\n\t\t\tthis.refreshTimer = undefined;\n\t\t}\n\t\tthis.refreshTimer = this.setTimeout(\n\t\t\t() => this.poll().catch(e => this.log.warn(`Refresh error: ${(e as Error).message}`)),\n\t\t\t1500,\n\t\t);\n\t}\n\n\t// ---- command execution ----\n\n\tprivate ptzUrl(oid: number | string, dir: number): string {\n\t\treturn `/ptz.cgi?oid=${encodeURIComponent(String(oid))}&dir=${dir}`;\n\t}\n\n\tprivate buildCommandUrl(entry: RegistryEntry): string {\n\t\tif (entry.kind === 'ptz') {\n\t\t\treturn this.ptzUrl(entry.oid!, entry.dir!);\n\t\t}\n\t\tif (entry.kind === 'sys') {\n\t\t\treturn entry.path as string;\n\t\t}\n\t\tconst qs: string[] = [];\n\t\tfor (const p of entry.params || []) {\n\t\t\tif (p === 'oid') {\n\t\t\t\tqs.push(`oid=${encodeURIComponent(String(entry.oid))}`);\n\t\t\t} else if (p === 'ot') {\n\t\t\t\tqs.push(`ot=${encodeURIComponent(String(entry.ot))}`);\n\t\t\t}\n\t\t}\n\t\treturn (entry.path || '') + (qs.length ? `?${qs.join('&')}` : '');\n\t}\n\n\tprivate async clearPtzSiblings(stateId: string): Promise<void> {\n\t\tconst prefix = stateId.slice(0, stateId.lastIndexOf('.') + 1);\n\t\tfor (const p of PTZ_DIRS) {\n\t\t\tif (!p.hold) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst sid = prefix + p.id;\n\t\t\tif (sid !== stateId) {\n\t\t\t\tawait this.setStateAsync(sid, { val: false, ack: true });\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async runCommand(relId: string, entry: RegistryEntry, val: ioBroker.StateValue): Promise<void> {\n\t\tif (entry.kind === 'setProfile') {\n\t\t\tconst ind = typeof val === 'number' ? val : parseInt(String(val ?? ''), 10);\n\t\t\tif (!isNaN(ind)) {\n\t\t\t\tconst url = `/command/setProfile?ind=${ind}`;\n\t\t\t\tconst cmdRes = await this.apiGet(url);\n\t\t\t\tif (cmdRes.ok) {\n\t\t\t\t\tthis.log.debug(`OK: ${url}`);\n\t\t\t\t\tawait this.setStateAsync(relId, { val: ind, ack: true });\n\t\t\t\t} else {\n\t\t\t\t\tthis.log.warn(`Command failed (${url}): ${cmdRes.error}`);\n\t\t\t\t}\n\t\t\t\tthis.scheduleRefresh();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (entry.kind === 'snapshotB64') {\n\t\t\tconst snapId = `${entry.fid}.snapshot_b64`;\n\t\t\tawait this.fetchSnapshotB64(entry.oid!, snapId);\n\t\t\tawait this.setStateAsync(relId, { val: false, ack: true });\n\t\t\treturn;\n\t\t}\n\n\t\tif (entry.kind === 'push') {\n\t\t\tthis.log.info(`Push trigger cam ${entry.oid}`);\n\t\t\tawait this.setStateAsync(relId, { val: '', ack: true });\n\t\t\tthis.pushRefresh(entry.oid!);\n\t\t\treturn;\n\t\t}\n\n\t\tif (entry.kind === 'ptzHold') {\n\t\t\tconst oid = entry.oid!;\n\t\t\tconst startMove = async (): Promise<void> => {\n\t\t\t\tawait this.clearPtzSiblings(relId);\n\t\t\t\tawait this.apiGet(this.ptzUrl(oid, entry.dir!));\n\t\t\t\tthis.ptzActive.set(oid, relId);\n\t\t\t\tawait this.setStateAsync(relId, { val: true, ack: true });\n\t\t\t};\n\t\t\tconst stopMove = async (): Promise<void> => {\n\t\t\t\tawait this.apiGet(this.ptzUrl(oid, 11));\n\t\t\t\tif (this.ptzActive.get(oid) === relId) {\n\t\t\t\t\tthis.ptzActive.delete(oid);\n\t\t\t\t}\n\t\t\t\tawait this.setStateAsync(relId, { val: false, ack: true });\n\t\t\t};\n\t\t\tif (val) {\n\t\t\t\tif (this.ptzActive.get(oid) === relId) {\n\t\t\t\t\tawait stopMove();\n\t\t\t\t} else {\n\t\t\t\t\tawait startMove();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait stopMove();\n\t\t\t}\n\t\t\tthis.scheduleRefresh();\n\t\t\treturn;\n\t\t}\n\n\t\tif (!val) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (entry.kind === 'sys' && entry.path === null) {\n\t\t\tawait this.poll().catch(e => this.log.warn(`Manual refresh error: ${(e as Error).message}`));\n\t\t\tawait this.setStateAsync(relId, { val: false, ack: true });\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = this.buildCommandUrl(entry);\n\t\tconst cmdRes = await this.apiGet(url);\n\t\tif (cmdRes.ok) {\n\t\t\tthis.log.debug(`OK: ${url}`);\n\t\t} else {\n\t\t\tthis.log.warn(`Command failed (${url}): ${cmdRes.error}`);\n\t\t}\n\n\t\tawait this.setStateAsync(relId, { val: false, ack: true });\n\t\tthis.scheduleRefresh();\n\t}\n}\n\nif (require.main !== module) {\n\tmodule.exports = (options: Partial<utils.AdapterOptions> | undefined) => new AgentDvr(options);\n} else {\n\t(() => new AgentDvr())();\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import * as utils from '@iobroker/adapter-core';\nimport * as http from 'node:http';\nimport * as https from 'node:https';\nimport { getWidgetLabels, type WidgetLabels } from './lib/widget-i18n';\n\n// =====================================================================\n// Agent DVR -> ioBroker Adapter\n// API reference: https://ispysoftware.github.io/Agent_API/ (v7.5)\n// =====================================================================\n\n// ---- Types ----\n\ninterface ApiResult {\n\tok: boolean;\n\tdata?: string;\n\terror?: string;\n}\n\ninterface AgentDvrEvent {\n\tfn?: string;\n\ttg?: string;\n\tc?: number;\n\td?: number | string;\n\tsb?: number;\n\t[key: string]: unknown;\n}\n\ninterface Device {\n\toid: number | string;\n\tot: number;\n\tname: string;\n\traw: Record<string, unknown>;\n}\n\ntype RegistryKind = 'cam' | 'sys' | 'ptz' | 'ptzHold' | 'push' | 'setProfile' | 'snapshotB64';\n\ninterface RegistryEntry {\n\tkind: RegistryKind;\n\tpath?: string | null;\n\tparams?: string[];\n\toid?: number | string;\n\tot?: number;\n\tdir?: number;\n\tfid?: string;\n}\n\n// ---- Commands ----\n\nconst CAM_COMMANDS = [\n\t{ id: 'record', path: '/command/record', params: ['oid', 'ot'], name: 'Start recording' },\n\t{ id: 'recordStop', path: '/command/recordStop', params: ['oid', 'ot'], name: 'Stop recording' },\n\t{ id: 'recordRestart', path: '/command/recordRestart', params: ['oid', 'ot'], name: 'Restart recording' },\n\t{ id: 'triggerRecord', path: '/command/triggerRecord', params: ['oid', 'ot'], name: 'Trigger recording (timeout)' },\n\t{ id: 'snapshot', path: '/command/snapshot', params: ['oid'], name: 'Take snapshot' },\n\t{ id: 'detect', path: '/command/detect', params: ['oid', 'ot'], name: 'Trigger motion detection' },\n\t{ id: 'alertOn', path: '/command/alertOn', params: ['oid', 'ot'], name: 'Arm alerts' },\n\t{ id: 'alertOff', path: '/command/alertOff', params: ['oid', 'ot'], name: 'Disarm alerts' },\n\t{ id: 'switchOn', path: '/command/switchOn', params: ['oid', 'ot'], name: 'Switch device on' },\n\t{ id: 'switchOff', path: '/command/switchOff', params: ['oid', 'ot'], name: 'Switch device off' },\n\t{ id: 'objectDetectOn', path: '/command/objectdetecton', params: ['oid', 'ot'], name: 'Enable object detection' },\n\t{\n\t\tid: 'objectDetectOff',\n\t\tpath: '/command/objectdetectoff',\n\t\tparams: ['oid', 'ot'],\n\t\tname: 'Disable object detection',\n\t},\n\t{ id: 'recOnAlert', path: '/command/recordOnAlertOn', params: ['oid', 'ot'], name: 'Record on alert: on' },\n\t{ id: 'recOnDetect', path: '/command/recordOnDetectOn', params: ['oid', 'ot'], name: 'Record on detect: on' },\n\t{ id: 'purge', path: '/command/purge', params: ['oid', 'ot'], name: 'Purge folder (caution!)' },\n] as const;\n\nconst SYS_COMMANDS = [\n\t{ id: 'arm', path: '/command/arm', name: 'Arm system' },\n\t{ id: 'disarm', path: '/command/disarm', name: 'Disarm system' },\n\t{ id: 'allOn', path: '/command/allOn', name: 'All devices on' },\n\t{ id: 'allOff', path: '/command/allOff', name: 'All devices off' },\n\t{ id: 'reloadConfig', path: '/command/reloadConfig', name: 'Reload config' },\n\t{ id: 'reloadObjects', path: '/command/reloadObjects', name: 'Reload objects' },\n\t{ id: 'runStorageMgmt', path: '/command/runStorageMgmt', name: 'Run storage management' },\n\t{ id: 'blockExternal', path: '/command/blockExternal', name: 'Block external access' },\n\t{ id: 'unblockExternal', path: '/command/unblockExternal', name: 'Unblock external access' },\n\t{ id: 'restart', path: '/command/restart', name: 'Restart Agent DVR' },\n\t{ id: 'refresh', path: null, name: 'Refresh data now' },\n] as const;\n\nconst PTZ_DIRS = [\n\t{ id: 'left', dir: 1, hold: true },\n\t{ id: 'upLeft', dir: 2, hold: true },\n\t{ id: 'up', dir: 3, hold: true },\n\t{ id: 'upRight', dir: 4, hold: true },\n\t{ id: 'right', dir: 5, hold: true },\n\t{ id: 'downRight', dir: 6, hold: true },\n\t{ id: 'down', dir: 7, hold: true },\n\t{ id: 'downLeft', dir: 8, hold: true },\n\t{ id: 'zoomIn', dir: 9, hold: true },\n\t{ id: 'zoomOut', dir: 10, hold: true },\n\t{ id: 'stop', dir: 11, hold: false },\n\t{ id: 'center', dir: 0, hold: false },\n] as const;\n\nconst SKIP_KEYS = ['icons', 'image', 'thumbnail', 'base64'];\n\n// ---- Module-level helpers ----\n\nfunction sanitize(s: unknown): string {\n\treturn (\n\t\tString(s)\n\t\t\t.replace(/[\\s.[\\]*?\"'`,;:/\\\\]+/g, '_')\n\t\t\t.replace(/[^A-Za-z0-9_-]/g, '_')\n\t\t\t.replace(/_+/g, '_')\n\t\t\t.replace(/^_+|_+$/g, '') || 'x'\n\t);\n}\n\nfunction asJson(data: unknown): Record<string, unknown> | null {\n\tif (data == null) {\n\t\treturn null;\n\t}\n\tif (typeof data === 'object') {\n\t\treturn data as Record<string, unknown>;\n\t}\n\tif (typeof data === 'string') {\n\t\ttry {\n\t\t\treturn JSON.parse(data) as Record<string, unknown>;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\treturn null;\n}\n\nfunction toStr(v: unknown): string {\n\tif (v == null) {\n\t\treturn '';\n\t}\n\tif (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') {\n\t\treturn String(v);\n\t}\n\treturn Object.prototype.toString.call(v);\n}\n\nfunction escHtml(s: unknown): string {\n\treturn toStr(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n}\n\nfunction parseSizeGb(s: unknown): number | null {\n\tif (s == null) {\n\t\treturn null;\n\t}\n\tconst m = toStr(s)\n\t\t.trim()\n\t\t.match(/([\\d.,]+)\\s*([KMGT]?B)?/i);\n\tif (!m) {\n\t\treturn null;\n\t}\n\tlet v = parseFloat(m[1].replace(',', '.'));\n\tif (isNaN(v)) {\n\t\treturn null;\n\t}\n\tconst u = (m[2] || 'GB').toUpperCase();\n\tif (u === 'TB') {\n\t\tv *= 1024;\n\t} else if (u === 'MB') {\n\t\tv /= 1024;\n\t} else if (u === 'KB') {\n\t\tv /= 1048576;\n\t} else if (u === 'B') {\n\t\tv /= 1073741824;\n\t}\n\treturn Math.round(v * 100) / 100;\n}\n\nfunction findWH(obj: unknown, depth: number): [number, number] | null {\n\tif (!obj || typeof obj !== 'object' || depth > 5) {\n\t\treturn null;\n\t}\n\tconst o = obj as Record<string, unknown>;\n\tfor (const [kw, kh] of [\n\t\t['width', 'height'],\n\t\t['w', 'h'],\n\t\t['sourceWidth', 'sourceHeight'],\n\t\t['videoWidth', 'videoHeight'],\n\t\t['imageWidth', 'imageHeight'],\n\t]) {\n\t\tconst w = o[kw],\n\t\t\th = o[kh];\n\t\tif (typeof w === 'number' && typeof h === 'number' && w >= 100 && h >= 100 && w <= 12000 && h <= 12000) {\n\t\t\tconst r = w / h;\n\t\t\tif (r >= 0.3 && r <= 4) {\n\t\t\t\treturn [w, h];\n\t\t\t}\n\t\t}\n\t}\n\tfor (const k of Object.keys(o)) {\n\t\tconst g = findWH(o[k], depth + 1);\n\t\tif (g) {\n\t\t\treturn g;\n\t\t}\n\t}\n\treturn null;\n}\n\nfunction detectOt(elem: Record<string, unknown>): number {\n\tconst v = elem.typeID ?? elem.ot ?? elem.objectTypeID ?? elem.type;\n\treturn v === 1 || v === 2 ? v : 2;\n}\n\nfunction findDevices(json: Record<string, unknown>): Device[] {\n\tconst list = Array.isArray(json.objectList) ? json.objectList : [];\n\tconst out: Device[] = [];\n\tfor (const e of list) {\n\t\tif (!e || typeof e !== 'object') {\n\t\t\tcontinue;\n\t\t}\n\t\tconst el = e as Record<string, unknown>;\n\t\tconst rawId = el.id ?? el.oid;\n\t\tif (rawId === undefined || rawId === null) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst id = rawId as number | string;\n\t\tconst name = typeof el.name === 'string' ? el.name : `obj_${id}`;\n\t\tout.push({ oid: id, ot: detectOt(el), name, raw: el });\n\t}\n\treturn out;\n}\n\n// ---- HTML/CSS gallery helpers ----\n\ninterface WidgetColors {\n\tcardBg?: string;\n\ttagBg?: string;\n\ttagText?: string;\n\taccent?: string;\n\tmodalBg?: string;\n\tradius?: number;\n}\n\nfunction advCssVars(c?: WidgetColors): string {\n\tconst cardBg = c?.cardBg || 'rgba(127,127,127,.15)';\n\tconst tagBg = c?.tagBg || 'rgba(0,0,0,.55)';\n\tconst tagText = c?.tagText || '#fff';\n\tconst accent = c?.accent || '#8ab4f8';\n\tconst modalBg = c?.modalBg || '#1c1c1e';\n\tconst radius = c?.radius != null ? `${c.radius}px` : '8px';\n\treturn `--adv-card-bg:${cardBg};--adv-tag-bg:${tagBg};--adv-tag-color:${tagText};--adv-accent:${accent};--adv-modal-bg:${modalBg};--adv-radius:${radius};`;\n}\n\nfunction galleryCss(minCol: number, maxW: number, compact = false, colors?: WidgetColors): string {\n\tconst gap = compact ? 6 : 12;\n\treturn (\n\t\t`.advgrid{${advCssVars(colors)}display:grid;grid-template-columns:repeat(auto-fill,minmax(${minCol}px,1fr));gap:${gap}px;max-width:100%}` +\n\t\t`.advgrid .advlb{display:none}` +\n\t\t`.advcell{display:flex;flex-direction:column;cursor:pointer;text-decoration:none;color:inherit;font-family:inherit}` +\n\t\t`.advimg{position:relative;display:block;border-radius:var(--adv-radius);overflow:hidden;background:var(--adv-card-bg)}` +\n\t\t`.advimg img{width:100%;height:auto;display:block}` +\n\t\t`.advimgfix img{height:100%;object-fit:cover}` +\n\t\t`.advtag{position:absolute;background:var(--adv-tag-bg);color:var(--adv-tag-color);font-size:.6rem;padding:2px 4px;border-radius:3px;line-height:1;max-width:85%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}` +\n\t\t`.advplay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .15s;background:rgba(0,0,0,.2)}` +\n\t\t`.advplay::before{content:\"\";border-style:solid;border-width:11px 0 11px 18px;border-color:transparent transparent transparent #fff;filter:drop-shadow(0 1px 2px rgba(0,0,0,.6))}` +\n\t\t`.advcell:hover .advplay{opacity:1}` +\n\t\t`.advcap{font-size:${compact ? '.65rem' : '.72rem'};margin-top:${compact ? 2 : 4}px;line-height:1.25;opacity:.85}` +\n\t\t`.advmodal{display:none;position:fixed;inset:0;z-index:99999;align-items:center;justify-content:center}` +\n\t\t`.advgrid .advlb:checked + .advthumb + .advmodal{display:flex}` +\n\t\t`.advbackdrop{position:absolute;inset:0;background:transparent;cursor:pointer}` +\n\t\t`.advbox{position:relative;z-index:1;display:flex;flex-direction:column;gap:8px;max-width:min(92vw,${maxW}px);background:var(--adv-modal-bg);padding:12px;border-radius:14px;box-shadow:0 16px 48px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.08)}` +\n\t\t`.advvideo{width:100%;max-height:80vh;border-radius:8px;background:#000;display:block}` +\n\t\t`.advclose{position:absolute;top:18px;right:18px;width:32px;height:32px;border-radius:50%;background:rgba(0,0,0,.65);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:15px;z-index:2;border:2px solid rgba(255,255,255,.35)}` +\n\t\t`.advinfo{color:#fff;font-size:.8rem;text-align:center}` +\n\t\t`.advinfo a{color:var(--adv-accent)}` +\n\t\t`.advempty{padding:24px;text-align:center;opacity:.7;font-family:inherit}`\n\t);\n}\n\nfunction galleryCssJs(minCol: number, compact = false, colors?: WidgetColors): string {\n\tconst gap = compact ? 6 : 12;\n\treturn (\n\t\t`.advroot{${advCssVars(colors)}font-family:inherit;color:inherit}` +\n\t\t`.advbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:10px}` +\n\t\t`.advsearchjs{flex:1 1 160px;min-width:120px;padding:6px 10px;border-radius:8px;border:1px solid rgba(127,127,127,.4);background:rgba(127,127,127,.08);color:inherit;font:inherit}` +\n\t\t`.advtagsjs{display:flex;flex-wrap:wrap;gap:6px}` +\n\t\t`.advtagbtn{padding:4px 10px;border-radius:999px;border:1px solid rgba(127,127,127,.4);background:transparent;color:inherit;cursor:pointer;font:inherit;font-size:.8rem}` +\n\t\t`.advtagbtn.on{background:var(--adv-accent);color:#fff;border-color:var(--adv-accent)}` +\n\t\t`.advgridjs{display:grid;grid-template-columns:repeat(auto-fill,minmax(${minCol}px,1fr));gap:${gap}px}` +\n\t\t`.advcelljs{display:flex;flex-direction:column;cursor:pointer}` +\n\t\t`.advimgjs{position:relative;display:block;border-radius:var(--adv-radius);overflow:hidden;background:var(--adv-card-bg)}` +\n\t\t`.advimgjs img{width:100%;height:auto;display:block}` +\n\t\t`.advimgjs.advimgfix img{height:100%;object-fit:cover}` +\n\t\t`.advtagjs{position:absolute;background:var(--adv-tag-bg);color:var(--adv-tag-color);font-size:.6rem;padding:2px 4px;border-radius:3px;line-height:1;max-width:85%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}` +\n\t\t`.advplayjs{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .15s;background:rgba(0,0,0,.2)}` +\n\t\t`.advplayjs::before{content:\"\";border-style:solid;border-width:11px 0 11px 18px;border-color:transparent transparent transparent #fff;filter:drop-shadow(0 1px 2px rgba(0,0,0,.6))}` +\n\t\t`.advcelljs:hover .advplayjs{opacity:1}` +\n\t\t`.advcapjs{font-size:${compact ? '.65rem' : '.72rem'};margin-top:${compact ? 2 : 4}px;line-height:1.25;opacity:.85}` +\n\t\t`.advemptyjs{padding:24px;text-align:center;opacity:.7}`\n\t);\n}\n\n// Client-side browser code for the JS widget variant.\n// Stored as a string: TypeScript never type-checks browser code running in DOM context.\nconst ADV_CLIENT_CODE = `\n(function(){\nfunction esc(s){return String(s==null?'':s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"');}\nvar MODAL_CSS='.advmodaljs{display:none;position:fixed;inset:0;z-index:99999;align-items:center;justify-content:center}.advbackdropjs{position:absolute;inset:0;background:transparent;cursor:pointer}.advboxjs{position:relative;z-index:1;display:flex;flex-direction:column;gap:8px;max-width:min(92vw,900px);background:#1c1c1e;padding:12px;border-radius:14px;box-shadow:0 16px 48px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.08)}.advvideojs{width:100%;max-height:80vh;border-radius:8px;background:#000;display:block}.advclosejs{position:absolute;top:18px;right:18px;width:32px;height:32px;border-radius:50%;background:rgba(0,0,0,.65);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:15px;z-index:2;border:2px solid rgba(255,255,255,.35)}.advinfojs{color:#fff;font-size:.8rem;text-align:center}';\nvar modalEl=null,modalVideo=null,modalInfo=null,modalBox=null;\nfunction getModal(){\n if(modalEl&&document.body.contains(modalEl))return modalEl;\n if(!document.getElementById('advmodalcss')){var st=document.createElement('style');st.id='advmodalcss';st.textContent=MODAL_CSS;document.head.appendChild(st);}\n modalEl=document.createElement('div');modalEl.className='advmodaljs';\n var bd=document.createElement('div');bd.className='advbackdropjs';\n modalBox=document.createElement('div');modalBox.className='advboxjs';\n var cl=document.createElement('span');cl.className='advclosejs';cl.textContent='\u2715';\n modalVideo=document.createElement('video');modalVideo.className='advvideojs';\n modalVideo.setAttribute('controls','');modalVideo.setAttribute('preload','none');modalVideo.setAttribute('playsinline','');\n modalInfo=document.createElement('div');modalInfo.className='advinfojs';\n modalBox.appendChild(cl);modalBox.appendChild(modalVideo);modalBox.appendChild(modalInfo);\n modalEl.appendChild(bd);modalEl.appendChild(modalBox);\n document.body.appendChild(modalEl);\n bd.addEventListener('click',closeModal);cl.addEventListener('click',closeModal);\n return modalEl;\n}\nfunction openSrc(src,label,maxW){\n var m=getModal();\n if(maxW)modalBox.style.maxWidth='min(92vw,'+maxW+'px)';\n modalVideo.setAttribute('src',src);modalInfo.textContent=label;m.style.display='flex';\n}\nfunction closeModal(){\n if(!modalEl)return;\n try{modalVideo.pause();}catch(e){}\n modalVideo.removeAttribute('src');try{modalVideo.load();}catch(e){}\n modalEl.style.display='none';\n}\ndocument.addEventListener('keydown',function(e){if(e.key==='Escape'||e.keyCode===27)closeModal();});\nfunction initRoot(root){\n var dataEl=root.querySelector('script.advdata');\n if(!dataEl)return;\n var D;try{D=JSON.parse(dataEl.textContent);}catch(e){return;}\n var cfg=D.cfg||{},items=D.items||[],live=D.live||null;\n var grid=root.querySelector('.advgridjs'),search=root.querySelector('.advsearchjs'),tagsBox=root.querySelector('.advtagsjs');\n var state={q:'',tag:cfg.default_tag||''};\n var tagset={};\n items.forEach(function(it){String(it.tag||'').split(/[,\\\\s]+/).forEach(function(t){if(t)tagset[t]=1;});});\n var tags=Object.keys(tagset);\n if(cfg.show_tags&&tags.length){\n var mk=function(label,val){\n var b=document.createElement('button');b.className='advtagbtn';b.textContent=label;b.setAttribute('data-tag',val);\n b.addEventListener('click',function(){state.tag=state.tag===val?'':val;updateTagBtns();render();});\n tagsBox.appendChild(b);\n };\n mk(cfg.labels&&cfg.labels.all||'All','');tags.forEach(function(t){mk(t,t);});\n }\n function updateTagBtns(){var bs=tagsBox.querySelectorAll('.advtagbtn');for(var i=0;i<bs.length;i++)bs[i].classList.toggle('on',bs[i].getAttribute('data-tag')===state.tag);}\n updateTagBtns();\n if(search)search.addEventListener('input',function(){state.q=this.value.toLowerCase();render();});\n function badge(it){if(!(cfg.show_tags&&it.tag))return '';var pos=String(cfg.tag_position||'bottom-left').split('-');return '<span class=\"advtagjs\" style=\"'+pos[0]+':5px;'+pos[1]+':5px\">'+esc(it.tag)+'</span>';}\n function render(){\n var html='';\n if(live){var ar=cfg.live_aspect||'',arStyle=ar?' style=\"aspect-ratio:'+ar.replace('/',' / ')+'\"':'',arCls=ar?' advimgfix':'';\n html+='<div class=\"advcelljs\" data-live=\"1\"><span class=\"advimgjs'+arCls+'\"'+arStyle+'><img loading=\"lazy\" src=\"'+esc(live.thumb)+'\"><span class=\"advtagjs\" style=\"top:5px;left:5px\">● '+(cfg.labels&&cfg.labels.live||'LIVE')+'</span><span class=\"advplayjs\"></span></span><span class=\"advcapjs\">'+esc(live.name)+'</span></div>';}\n items.forEach(function(it,i){\n if(state.tag&&String(it.tag||'').toLowerCase().indexOf(state.tag.toLowerCase())<0)return;\n if(state.q){var hay=((it.date||'')+' '+(it.time||'')+' '+(it.tag||'')).toLowerCase();if(hay.indexOf(state.q)<0)return;}\n html+='<div class=\"advcelljs\" data-i=\"'+i+'\"><span class=\"advimgjs\"><img loading=\"lazy\" src=\"'+esc(it.thumb)+'\">'+badge(it)+'<span class=\"advplayjs\"></span></span><span class=\"advcapjs\">'+esc(it.date)+' '+esc(it.time)+'<br>'+esc(it.dur)+'s · '+esc(it.size)+' MB</span></div>';\n });\n grid.innerHTML=html||'<div class=\"advemptyjs\">'+(cfg.labels&&cfg.labels.noRecordings||'No recordings')+'</div>';\n var cells=grid.querySelectorAll('.advcelljs');\n for(var k=0;k<cells.length;k++)(function(cell){\n cell.addEventListener('click',function(){\n if(cell.getAttribute('data-live')==='1'){openSrc(live.video,(live.name||'')+' \u00B7 Live',cfg.max_modal_width);return;}\n var it=items[parseInt(cell.getAttribute('data-i'),10)],maxW=Number(cfg.max_modal_width)||900;\n if(cfg.player_url){var u=cfg.player_url.replace(/{video}/g,encodeURIComponent(it.video)).replace(/{videoRaw}/g,it.video).replace(/{fn}/g,encodeURIComponent(it.fn||'')).replace(/{date}/g,encodeURIComponent(it.date)).replace(/{time}/g,encodeURIComponent(it.time)).replace(/{duration}/g,encodeURIComponent(it.dur)).replace(/{size}/g,encodeURIComponent(it.size)).replace(/{tags}/g,encodeURIComponent(it.tag));window.open(u,'_blank');}\n else{openSrc(it.video,esc(it.date)+' '+esc(it.time)+(it.dur!=null?' \u00B7 '+it.dur+'s':'')+(it.size!=null?' \u00B7 '+it.size+' MB':'')+(it.tag?' \u00B7 '+it.tag:''),maxW);}\n });\n })(cells[k]);\n }\n render();\n}\nfunction scan(){var roots=document.querySelectorAll('.advroot');for(var i=0;i<roots.length;i++)if(!roots[i].__adv){roots[i].__adv=1;initRoot(roots[i]);}}\nwindow.ADVscan=scan;scan();\n})();\n`.trim();\n\n// ---- Adapter class ----\n\nclass AgentDvr extends utils.Adapter {\n\tprivate pollTimer: ioBroker.Interval | undefined = undefined;\n\tprivate pollBusy = false;\n\tprivate refreshTimer: ioBroker.Timeout | undefined = undefined;\n\tprivate authHeader: string | null = null;\n\tprivate baseUrl = '';\n\tprivate wt: WidgetLabels = getWidgetLabels('en');\n\n\tprivate readonly ensuredFolders = new Set<string>();\n\tprivate readonly registry = new Map<string, RegistryEntry>();\n\tprivate readonly ptzActive = new Map<string | number, string>();\n\tprivate readonly widgetSig: Record<string, string> = {};\n\tprivate profileSig = '';\n\tprivate lastCamNames: { key: string; name: string }[] = [];\n\tprivate readonly lastEventFn: Record<string | number, string> = {};\n\tprivate readonly camAspect: Record<string | number, string> = {};\n\tprivate readonly devById = new Map<string | number, Device>();\n\tprivate readonly eventBusy: Record<string | number, boolean> = {};\n\n\tpublic constructor(options: Partial<utils.AdapterOptions> = {}) {\n\t\tsuper({ ...options, name: 'agent-dvr' });\n\t\tthis.on('ready', this.onReady.bind(this));\n\t\tthis.on('stateChange', this.onStateChange.bind(this));\n\t\tthis.on('message', this.onMessage.bind(this));\n\t\tthis.on('unload', this.onUnload.bind(this));\n\t}\n\n\t// ---- lifecycle ----\n\n\tprivate async ensureWebInstance(): Promise<void> {\n\t\tconst instanceId = `system.adapter.${this.namespace}`;\n\t\tconst obj = await this.getForeignObjectAsync(instanceId);\n\t\tif (obj && !obj.native?.webInstance) {\n\t\t\tawait this.extendForeignObjectAsync(instanceId, { native: { webInstance: '*' } });\n\t\t\tthis.log.info('webInstance set \u2014 web adapter will reload the extension');\n\t\t}\n\t}\n\n\tprivate async onReady(): Promise<void> {\n\t\tvoid this.setState('info.connection', false, true);\n\t\tawait this.ensureWebInstance();\n\n\t\tconst sysConfig = await this.getForeignObjectAsync('system.config');\n\t\tconst rawLang = (sysConfig?.common as unknown as { language?: string } | undefined)?.language;\n\t\tthis.wt = getWidgetLabels(rawLang ?? 'en');\n\n\t\tconst pollSeconds = Math.max(5, Math.min(3600, this.config.pollSeconds || 30));\n\t\tthis.baseUrl = `http://${this.config.ip}:${this.config.port || 8090}`;\n\n\t\tif (this.config.user || this.config.pass) {\n\t\t\tthis.authHeader = `Basic ${Buffer.from(`${this.config.user}:${this.config.pass}`).toString('base64')}`;\n\t\t}\n\n\t\tawait this.buildSystem();\n\t\ttry {\n\t\t\tawait this.poll();\n\t\t} catch (e) {\n\t\t\tthis.log.warn(`First poll error: ${(e as Error).message}`);\n\t\t}\n\n\t\tthis.pollTimer = this.setInterval(\n\t\t\t() => this.poll().catch(e => this.log.warn(`Poll error: ${(e as Error).message}`)),\n\t\t\tpollSeconds * 1000,\n\t\t);\n\n\t\tthis.subscribeStates('*');\n\t\tthis.log.info(`Agent DVR adapter ready. Polling ${this.baseUrl} every ${pollSeconds}s.`);\n\t}\n\n\tprivate onUnload(callback: () => void): void {\n\t\ttry {\n\t\t\tif (this.pollTimer !== undefined) {\n\t\t\t\tthis.clearInterval(this.pollTimer);\n\t\t\t\tthis.pollTimer = undefined;\n\t\t\t}\n\t\t\tif (this.refreshTimer !== undefined) {\n\t\t\t\tthis.clearTimeout(this.refreshTimer);\n\t\t\t\tthis.refreshTimer = undefined;\n\t\t\t}\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t\tcallback();\n\t}\n\n\tprivate onMessage(obj: ioBroker.Message): void {\n\t\tif (!obj) {\n\t\t\treturn;\n\t\t}\n\t\tif (obj.command === 'getGo2rtcStreams') {\n\t\t\tconst overrideUrl =\n\t\t\t\ttypeof obj.message === 'object' && obj.message !== null\n\t\t\t\t\t? (obj.message.url as string | undefined)\n\t\t\t\t\t: undefined;\n\t\t\tvoid this.fetchGo2rtcStreams(overrideUrl).then(result => {\n\t\t\t\tthis.sendTo(obj.from, obj.command, result, obj.callback);\n\t\t\t});\n\t\t} else if (obj.command === 'getAgentDvrCameras') {\n\t\t\tthis.sendTo(obj.from, obj.command, { cameras: this.lastCamNames }, obj.callback);\n\t\t} else if (obj.command === 'getAvailableSources') {\n\t\t\tvoid this.fetchAvailableSources().then(result => {\n\t\t\t\tthis.sendTo(obj.from, obj.command, result, obj.callback);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async fetchAvailableSources(): Promise<{ result: { source: string; name: string }[] }> {\n\t\tconst deadline = new Promise<{ result: { source: string; name: string }[] }>(res =>\n\t\t\tthis.setTimeout(() => res({ result: [{ source: '!', name: 'Timeout' }] }), 5000),\n\t\t);\n\t\treturn Promise.race([this._doFetchAvailableSources(), deadline]);\n\t}\n\n\tprivate async _doFetchAvailableSources(): Promise<{ result: { source: string; name: string }[] }> {\n\t\tconst rows: { source: string; name: string }[] = [];\n\t\tfor (const c of this.lastCamNames) {\n\t\t\trows.push({ source: 'AgentDVR', name: `${c.name} (${c.key})` });\n\t\t}\n\t\tconst { streams } = await this.fetchGo2rtcStreams();\n\t\tfor (const s of streams) {\n\t\t\trows.push({ source: 'go2rtc', name: s });\n\t\t}\n\t\tif (!rows.length) {\n\t\t\trows.push({ source: '\u2014', name: 'No sources found (adapter has not polled yet)' });\n\t\t}\n\t\treturn { result: rows };\n\t}\n\n\tprivate fetchGo2rtcStreams(overrideUrl?: string): Promise<{ streams: string[]; error?: string }> {\n\t\t// go2rtc only accepts plain HTTP; force https:// \u2192 http://\n\t\tconst url = (overrideUrl || this.config.go2rtcUrl || '').replace(/^https:\\/\\//i, 'http://');\n\t\tif (!url) {\n\t\t\treturn Promise.resolve({ streams: [], error: 'go2rtcUrl not configured' });\n\t\t}\n\t\tlet target: URL;\n\t\ttry {\n\t\t\ttarget = new URL('/api/streams', url);\n\t\t} catch {\n\t\t\treturn Promise.resolve({ streams: [], error: `Invalid URL: ${url}` });\n\t\t}\n\t\tlet httpReq: ReturnType<typeof http.get> | undefined;\n\t\tconst fetch = new Promise<{ streams: string[]; error?: string }>(resolve => {\n\t\t\tconst mod = target.protocol === 'https:' ? https : http;\n\t\t\thttpReq = mod.get(target.toString(), res => {\n\t\t\t\tlet body = '';\n\t\t\t\tres.on('data', (c: Buffer) => {\n\t\t\t\t\tbody += c.toString();\n\t\t\t\t});\n\t\t\t\tres.on('end', () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst parsed = JSON.parse(body);\n\t\t\t\t\t\tconst streams = Object.keys(parsed || {});\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tstreams,\n\t\t\t\t\t\t\terror: streams.length === 0 ? 'go2rtc reachable but no streams configured' : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tstreams: [],\n\t\t\t\t\t\t\terror: `Invalid JSON response from go2rtc (HTTP ${res.statusCode})`,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tres.on('error', (e: Error) => resolve({ streams: [], error: `Stream error: ${e.message}` }));\n\t\t\t});\n\t\t\thttpReq.on('error', (e: Error) => resolve({ streams: [], error: `Connection error: ${e.message}` }));\n\t\t});\n\t\tconst timeout = new Promise<{ streams: string[]; error?: string }>(resolve =>\n\t\t\tthis.setTimeout(() => {\n\t\t\t\thttpReq?.destroy();\n\t\t\t\tresolve({ streams: [], error: `Timeout fetching ${target.toString()}` });\n\t\t\t}, 3000),\n\t\t);\n\t\treturn Promise.race([fetch, timeout]);\n\t}\n\n\tprivate onStateChange(id: string, state: ioBroker.State | null | undefined): void {\n\t\tif (!state || state.ack !== false) {\n\t\t\treturn;\n\t\t}\n\t\tconst relId = this.getRelId(id);\n\t\tconst entry = this.registry.get(relId);\n\t\tif (entry) {\n\t\t\tthis.runCommand(relId, entry, state.val).catch(e =>\n\t\t\t\tthis.log.warn(`Command error: ${(e as Error).message}`),\n\t\t\t);\n\t\t}\n\t}\n\n\t// ---- helpers ----\n\n\tprivate getRelId(fullId: string): string {\n\t\treturn fullId.startsWith(`${this.namespace}.`) ? fullId.slice(this.namespace.length + 1) : fullId;\n\t}\n\n\tprivate apiGet(path: string): Promise<ApiResult> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst timeout = Math.max(1000, Math.min(30000, this.config.httpTimeoutMs || 8000));\n\t\t\tconst opts: http.RequestOptions = {\n\t\t\t\thostname: this.config.ip,\n\t\t\t\tport: this.config.port || 8090,\n\t\t\t\tpath,\n\t\t\t\tmethod: 'GET',\n\t\t\t\ttimeout,\n\t\t\t};\n\t\t\tif (this.authHeader) {\n\t\t\t\topts.headers = { Authorization: this.authHeader };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst req = http.request(opts, res => {\n\t\t\t\t\tlet data = '';\n\t\t\t\t\tres.on('data', (c: Buffer) => {\n\t\t\t\t\t\tdata += c.toString();\n\t\t\t\t\t});\n\t\t\t\t\tres.on('end', () => {\n\t\t\t\t\t\tif (res.statusCode && res.statusCode >= 400) {\n\t\t\t\t\t\t\tresolve({ ok: false, error: `HTTP ${res.statusCode}` });\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve({ ok: true, data });\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tres.on('error', (e: Error) => resolve({ ok: false, error: e.message }));\n\t\t\t\t});\n\t\t\t\treq.on('error', (e: Error) => resolve({ ok: false, error: e.message }));\n\t\t\t\treq.on('timeout', () => {\n\t\t\t\t\treq.destroy();\n\t\t\t\t\tresolve({ ok: false, error: 'timeout' });\n\t\t\t\t});\n\t\t\t\treq.end();\n\t\t\t} catch (e) {\n\t\t\t\tresolve({ ok: false, error: String((e as Error).message || e) });\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate apiGetBuffer(path: string): Promise<{ ok: boolean; data?: Buffer; error?: string }> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst timeout = Math.max(1000, Math.min(30000, this.config.httpTimeoutMs || 8000));\n\t\t\tconst opts: http.RequestOptions = {\n\t\t\t\thostname: this.config.ip,\n\t\t\t\tport: this.config.port || 8090,\n\t\t\t\tpath,\n\t\t\t\tmethod: 'GET',\n\t\t\t\ttimeout,\n\t\t\t};\n\t\t\tif (this.authHeader) {\n\t\t\t\topts.headers = { Authorization: this.authHeader };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst req = http.request(opts, res => {\n\t\t\t\t\tconst chunks: Buffer[] = [];\n\t\t\t\t\tres.on('data', (c: Buffer) => chunks.push(c));\n\t\t\t\t\tres.on('end', () => {\n\t\t\t\t\t\tif (res.statusCode && res.statusCode >= 400) {\n\t\t\t\t\t\t\tresolve({ ok: false, error: `HTTP ${res.statusCode}` });\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve({ ok: true, data: Buffer.concat(chunks) });\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tres.on('error', (e: Error) => resolve({ ok: false, error: e.message }));\n\t\t\t\t});\n\t\t\t\treq.on('error', (e: Error) => resolve({ ok: false, error: e.message }));\n\t\t\t\treq.on('timeout', () => {\n\t\t\t\t\treq.destroy();\n\t\t\t\t\tresolve({ ok: false, error: 'timeout' });\n\t\t\t\t});\n\t\t\t\treq.end();\n\t\t\t} catch (e) {\n\t\t\t\tresolve({ ok: false, error: String((e as Error).message || e) });\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async ensureFolder(id: string, name: string, type: 'device' | 'channel' = 'channel'): Promise<void> {\n\t\tif (this.ensuredFolders.has(id)) {\n\t\t\treturn;\n\t\t}\n\t\tawait this.setObjectNotExistsAsync(id, { type, common: { name }, native: {} });\n\t\tthis.ensuredFolders.add(id);\n\t}\n\n\tprivate async ensurePath(fullId: string): Promise<void> {\n\t\tconst parts = fullId.split('.');\n\t\tlet acc = parts[0];\n\t\tfor (let i = 1; i < parts.length - 1; i++) {\n\t\t\tacc += `.${parts[i]}`;\n\t\t\tif (!this.ensuredFolders.has(acc)) {\n\t\t\t\tawait this.setObjectNotExistsAsync(acc, { type: 'channel', common: { name: parts[i] }, native: {} });\n\t\t\t\tthis.ensuredFolders.add(acc);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate guessRole(id: string, val: unknown): ioBroker.CommonType {\n\t\tif (typeof val === 'string' && /^https?:\\/\\//i.test(val)) {\n\t\t\treturn 'string';\n\t\t}\n\t\treturn 'string';\n\t}\n\n\tprivate async writeLeaf(id: string, val: unknown): Promise<void> {\n\t\tconst t = typeof val;\n\t\tlet common: ioBroker.StateCommon;\n\t\tif (t === 'boolean') {\n\t\t\tcommon = { name: id.split('.').pop() || id, type: 'boolean', role: 'indicator', read: true, write: false };\n\t\t} else if (t === 'number') {\n\t\t\tcommon = { name: id.split('.').pop() || id, type: 'number', role: 'value', read: true, write: false };\n\t\t} else {\n\t\t\tconst role = typeof val === 'string' && /^https?:\\/\\//i.test(val) ? 'text.url' : 'text';\n\t\t\tcommon = { name: id.split('.').pop() || id, type: 'string', role, read: true, write: false };\n\t\t}\n\t\tif (!this.ensuredFolders.has(id)) {\n\t\t\tawait this.ensurePath(id);\n\t\t\tawait this.setObjectNotExistsAsync(id, { type: 'state', common, native: {} });\n\t\t\tthis.ensuredFolders.add(id);\n\t\t}\n\t\tawait this.setStateAsync(id, { val: (val === undefined ? null : val) as ioBroker.StateValue, ack: true });\n\t}\n\n\tprivate async flattenWrite(obj: unknown, prefix: string, depth: number): Promise<void> {\n\t\tconst maxDepth = Math.max(1, Math.min(10, this.config.maxDepth || 6));\n\t\tconst maxArray = Math.max(1, Math.min(500, this.config.maxArray || 30));\n\t\tif (depth > maxDepth) {\n\t\t\treturn;\n\t\t}\n\t\tif (obj === null || obj === undefined) {\n\t\t\tawait this.writeLeaf(prefix, obj);\n\t\t\treturn;\n\t\t}\n\t\tif (typeof obj === 'object') {\n\t\t\tif (Array.isArray(obj)) {\n\t\t\t\tif (obj.length > maxArray) {\n\t\t\t\t\tawait this.writeLeaf(`${prefix}.count`, obj.length);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (let i = 0; i < obj.length; i++) {\n\t\t\t\t\tawait this.flattenWrite(obj[i], `${prefix}.${i}`, depth + 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (const k of Object.keys(obj)) {\n\t\t\t\t\tif (SKIP_KEYS.includes(k)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.flattenWrite((obj as Record<string, unknown>)[k], `${prefix}.${sanitize(k)}`, depth + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tawait this.writeLeaf(prefix, obj);\n\t\t}\n\t}\n\n\tprivate async ensureControl(\n\t\tid: string,\n\t\tname: string,\n\t\tentry: RegistryEntry,\n\t\trole: 'button' | 'switch',\n\t): Promise<void> {\n\t\tif (!this.ensuredFolders.has(id)) {\n\t\t\tawait this.ensurePath(id);\n\t\t\tawait this.setObjectNotExistsAsync(id, {\n\t\t\t\ttype: 'state',\n\t\t\t\tcommon: { name, type: 'boolean', role, read: role === 'switch', write: true, def: false },\n\t\t\t\tnative: {},\n\t\t\t});\n\t\t\tawait this.setStateAsync(id, { val: false, ack: true });\n\t\t\tthis.ensuredFolders.add(id);\n\t\t}\n\t\tthis.registry.set(id, entry);\n\t}\n\n\tprivate ensureButton(id: string, name: string, entry: RegistryEntry): Promise<void> {\n\t\treturn this.ensureControl(id, name, entry, 'button');\n\t}\n\n\tprivate async ensureSelector(\n\t\tid: string,\n\t\tname: string,\n\t\tentry: RegistryEntry,\n\t\tstates: Record<number, string>,\n\t): Promise<void> {\n\t\tif (!this.ensuredFolders.has(id)) {\n\t\t\tawait this.ensurePath(id);\n\t\t\tawait this.setObjectNotExistsAsync(id, {\n\t\t\t\ttype: 'state',\n\t\t\t\tcommon: { name, type: 'number', role: 'level', read: true, write: true, states },\n\t\t\t\tnative: {},\n\t\t\t});\n\t\t\tawait this.setStateAsync(id, { val: 0, ack: true });\n\t\t\tthis.ensuredFolders.add(id);\n\t\t}\n\t\tthis.registry.set(id, entry);\n\t}\n\n\tprivate async fetchSnapshotB64(oid: number | string, snapId: string): Promise<void> {\n\t\tconst imgRes = await this.apiGetBuffer(`/photo.jpg?oid=${oid}`);\n\t\tif (imgRes.ok && imgRes.data) {\n\t\t\tawait this.setStateAsync(snapId, {\n\t\t\t\tval: `data:image/jpeg;base64,${imgRes.data.toString('base64')}`,\n\t\t\t\tack: true,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async ensureFlag(id: string, name: string): Promise<void> {\n\t\tif (this.ensuredFolders.has(id)) {\n\t\t\treturn;\n\t\t}\n\t\tawait this.ensurePath(id);\n\t\tawait this.setObjectNotExistsAsync(id, {\n\t\t\ttype: 'state',\n\t\t\tcommon: { name, type: 'boolean', role: 'indicator', read: true, write: false, def: false },\n\t\t\tnative: {},\n\t\t});\n\t\tthis.ensuredFolders.add(id);\n\t\tawait this.setStateAsync(id, { val: false, ack: true });\n\t}\n\n\tprivate async pulse(id: string): Promise<void> {\n\t\tawait this.setStateAsync(id, { val: true, ack: true });\n\t\tthis.setTimeout(() => this.setStateAsync(id, { val: false, ack: true }).catch(() => {}), 1500);\n\t}\n\n\t// ---- system structure ----\n\n\tprivate async buildSystem(): Promise<void> {\n\t\tawait this.ensureFolder('system', 'System', 'channel');\n\t\tawait this.writeLeaf('system.online', false);\n\t\tawait this.writeLeaf('system.lastUpdate', '');\n\t\tawait this.writeLeaf('system.lastPoll', 0);\n\t\tawait this.writeLeaf('system.cameraCount', 0);\n\n\t\tif (this.config.enableSystemControls) {\n\t\t\tawait this.ensureFolder('system.control', 'Control', 'channel');\n\t\t\tfor (const c of SYS_COMMANDS) {\n\t\t\t\tawait this.ensureButton(`system.control.${c.id}`, c.name, { kind: 'sys', path: c.path });\n\t\t\t}\n\t\t\tawait this.ensureFolder('system.profile', 'Profile', 'channel');\n\t\t\tawait this.ensureSelector(\n\t\t\t\t'system.profile.selector',\n\t\t\t\t'Active profile',\n\t\t\t\t{ kind: 'setProfile' },\n\t\t\t\t{ 0: 'Home', 1: 'Away', 2: 'Night' },\n\t\t\t);\n\t\t\tif (!this.ensuredFolders.has('system.profile.list')) {\n\t\t\t\tawait this.setObjectNotExistsAsync('system.profile.list', {\n\t\t\t\t\ttype: 'state',\n\t\t\t\t\tcommon: {\n\t\t\t\t\t\tname: 'Available profiles (JSON)',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\trole: 'json',\n\t\t\t\t\t\tread: true,\n\t\t\t\t\t\twrite: false,\n\t\t\t\t\t},\n\t\t\t\t\tnative: {},\n\t\t\t\t});\n\t\t\t\tthis.ensuredFolders.add('system.profile.list');\n\t\t\t\tawait this.setStateAsync('system.profile.list', { val: '[]', ack: true });\n\t\t\t}\n\t\t}\n\t}\n\n\t// ---- camera aspect detection ----\n\n\tprivate async detectAspect(d: Device): Promise<void> {\n\t\tif (this.camAspect[d.oid] !== undefined) {\n\t\t\treturn;\n\t\t}\n\t\tlet wh = findWH(d.raw, 0);\n\t\tif (!wh) {\n\t\t\tconst res = await this.apiGet(`/command/getObject?oid=${d.oid}&ot=2`);\n\t\t\tconst j = asJson(res.data);\n\t\t\tif (j) {\n\t\t\t\twh = findWH(j, 0);\n\t\t\t}\n\t\t}\n\t\tthis.camAspect[d.oid] = wh ? `${wh[0]}/${wh[1]}` : '';\n\t\tif (wh) {\n\t\t\tthis.log.debug(`cam ${d.oid} resolution ${wh[0]}x${wh[1]} -> AR ${this.camAspect[d.oid]}`);\n\t\t}\n\t}\n\n\t// ---- device folder name ----\n\n\tprivate deviceFolder(d: Device): string {\n\t\treturn `${d.ot === 1 ? 'mic' : 'cam'}_${sanitize(d.oid)}_${sanitize(d.name)}`;\n\t}\n\n\t// ---- device status data points ----\n\n\tprivate readonly STATUS_DPS = [\n\t\t{ key: 'recording', role: 'indicator.working', name: 'Active recording' },\n\t\t{ key: 'online', role: 'indicator.reachable', name: 'Online' },\n\t\t{ key: 'connected', role: 'indicator.connected', name: 'Stream connected' },\n\t\t{ key: 'detected', role: 'indicator', name: 'Motion detected' },\n\t\t{ key: 'alerted', role: 'indicator.alarm', name: 'Alert active' },\n\t] as const;\n\n\tprivate async writeStatusDps(d: Device, fid: string): Promise<void> {\n\t\tconst data = d.raw.data as Record<string, unknown> | undefined;\n\t\tif (!data || typeof data !== 'object') {\n\t\t\treturn;\n\t\t}\n\t\tconst sfid = `${fid}.status`;\n\t\tif (!this.ensuredFolders.has(sfid)) {\n\t\t\tawait this.ensureFolder(sfid, 'Status', 'channel');\n\t\t}\n\t\tfor (const dp of this.STATUS_DPS) {\n\t\t\tif (!(dp.key in data)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst id = `${sfid}.${dp.key}`;\n\t\t\tawait this.setObjectNotExistsAsync(id, {\n\t\t\t\ttype: 'state',\n\t\t\t\tcommon: { name: dp.name, type: 'boolean', role: dp.role, read: true, write: false, def: false },\n\t\t\t\tnative: {},\n\t\t\t});\n\t\t\tawait this.setStateAsync(id, { val: !!data[dp.key], ack: true });\n\t\t}\n\t}\n\n\t// ---- build device data points ----\n\n\tprivate async buildDevice(d: Device): Promise<void> {\n\t\tconst fid = this.deviceFolder(d);\n\t\tthis.devById.set(d.oid, d);\n\n\t\tawait this.ensureFolder(fid, d.name, 'device');\n\t\tif (d.ot === 2) {\n\t\t\tawait this.detectAspect(d);\n\t\t}\n\t\tawait this.flattenWrite(d.raw, fid, 0);\n\t\tawait this.writeStatusDps(d, fid);\n\n\t\tawait this.ensureFolder(`${fid}.control`, 'Control', 'channel');\n\t\tfor (const c of CAM_COMMANDS) {\n\t\t\tif (c.id === 'snapshot' && d.ot !== 2) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tawait this.ensureButton(`${fid}.control.${c.id}`, c.name, {\n\t\t\t\tkind: 'cam',\n\t\t\t\tpath: c.path,\n\t\t\t\tparams: [...c.params],\n\t\t\t\toid: d.oid,\n\t\t\t\tot: d.ot,\n\t\t\t});\n\t\t}\n\n\t\tif (this.config.enablePtz && d.ot === 2) {\n\t\t\tawait this.ensureFolder(`${fid}.control.ptz`, 'PTZ', 'channel');\n\t\t\tfor (const p of PTZ_DIRS) {\n\t\t\t\tconst cid = `${fid}.control.ptz.${p.id}`;\n\t\t\t\tif (p.hold) {\n\t\t\t\t\tawait this.ensureControl(\n\t\t\t\t\t\tcid,\n\t\t\t\t\t\t`PTZ ${p.id} (hold)`,\n\t\t\t\t\t\t{ kind: 'ptzHold', oid: d.oid, dir: p.dir },\n\t\t\t\t\t\t'switch',\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tawait this.ensureButton(cid, `PTZ ${p.id}`, { kind: 'ptz', oid: d.oid, dir: p.dir });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.config.enableUrls && d.ot === 2) {\n\t\t\tawait this.ensureFolder(`${fid}.urls`, 'URLs', 'channel');\n\t\t\tawait this.writeLeaf(`${fid}.urls.snapshot`, `${this.baseUrl}/grab.jpg?oid=${d.oid}`);\n\t\t\tawait this.writeLeaf(`${fid}.urls.photo`, `${this.baseUrl}/photo.jpg?oid=${d.oid}`);\n\t\t\tawait this.writeLeaf(`${fid}.urls.mjpeg`, `${this.baseUrl}/video.mjpg?oids=${d.oid}`);\n\t\t\tawait this.writeLeaf(`${fid}.urls.mp4`, `${this.baseUrl}/video.mp4?oids=${d.oid}`);\n\t\t}\n\n\t\tif (d.ot === 2) {\n\t\t\tconst snapId = `${fid}.snapshot_b64`;\n\t\t\tif (!this.ensuredFolders.has(snapId)) {\n\t\t\t\tawait this.ensurePath(snapId);\n\t\t\t\tawait this.setObjectNotExistsAsync(snapId, {\n\t\t\t\t\ttype: 'state',\n\t\t\t\t\tcommon: {\n\t\t\t\t\t\tname: 'Snapshot (Base64)',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\trole: 'state',\n\t\t\t\t\t\tread: true,\n\t\t\t\t\t\twrite: false,\n\t\t\t\t\t},\n\t\t\t\t\tnative: {},\n\t\t\t\t});\n\t\t\t\tawait this.setStateAsync(snapId, { val: '', ack: true });\n\t\t\t\tthis.ensuredFolders.add(snapId);\n\t\t\t}\n\t\t\tawait this.ensureButton(`${fid}.control.refreshSnapshotB64`, 'Refresh snapshot (Base64)', {\n\t\t\t\tkind: 'snapshotB64',\n\t\t\t\toid: d.oid,\n\t\t\t\tfid,\n\t\t\t});\n\t\t\tif (this.config.enableSnapshotB64) {\n\t\t\t\tawait this.fetchSnapshotB64(d.oid, snapId);\n\t\t\t}\n\t\t}\n\n\t\tawait this.updateCameraEvents(d, fid);\n\t}\n\n\t// ---- event formatting ----\n\n\tprivate fmtEvent(\n\t\tev: Record<string, unknown>,\n\t\toid: number | string,\n\t): {\n\t\tfn: string;\n\t\tsizeMB: number;\n\t\tdur: string;\n\t\ttag: string;\n\t\tdate: string;\n\t\ttime: string;\n\t\tthumb: string;\n\t\tvideo: string;\n\t} {\n\t\tconst e = ev as AgentDvrEvent;\n\t\tconst fn = e.fn ?? '';\n\t\tconst dot = fn.lastIndexOf('.');\n\t\tconst jpg = `${dot > 0 ? fn.slice(0, dot) : fn}_large.jpg`;\n\t\tconst sizeMB = e.sb ? Math.round((Number(e.sb) / 1048576) * 100) / 100 : 0;\n\t\tconst dur = e.d != null ? String(e.d) : '';\n\t\tconst tag = e.tg ?? '';\n\t\tconst ms = (parseFloat(String(e.c ?? 0)) - 621355968000000000) / 10000;\n\t\tconst dt = new Date(ms);\n\t\tconst two = (n: number): string => String(n).padStart(2, '0');\n\t\tconst date = `${two(dt.getDate())}.${two(dt.getMonth() + 1)}.`;\n\t\tconst time = `${two(dt.getHours())}:${two(dt.getMinutes())}`;\n\t\tconst thumb = `${this.baseUrl}/fileThumb.jpg?oid=${oid}&fn=${encodeURIComponent(jpg)}`;\n\t\tconst video = `${this.baseUrl}/streamFile.cgi?oid=${oid}&ot=2&fn=${encodeURIComponent(fn)}`;\n\t\treturn { fn, sizeMB, dur, tag, date, time, thumb, video };\n\t}\n\n\t// ---- gallery HTML builders ----\n\n\tprivate effectiveMinCol(): number {\n\t\tconst sizeMap: Record<string, number> = { small: 120, medium: 180, large: 240 };\n\t\tconst ts = this.config.widgetThumbSize;\n\t\treturn ts && sizeMap[ts] ? sizeMap[ts] : this.config.widgetMinCol || 150;\n\t}\n\n\tprivate async pruneStaleDevices(activeFolders: Set<string>): Promise<void> {\n\t\tconst allObjs = await this.getAdapterObjectsAsync();\n\t\tconst stale: string[] = [];\n\t\tfor (const fullId of Object.keys(allObjs)) {\n\t\t\tconst obj = allObjs[fullId];\n\t\t\tif (obj.type !== 'device') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst rel = fullId.slice(this.namespace.length + 1);\n\t\t\tif (/^(cam|mic)_/.test(rel) && !activeFolders.has(rel)) {\n\t\t\t\tstale.push(rel);\n\t\t\t}\n\t\t}\n\t\tfor (const rel of stale) {\n\t\t\tthis.log.info(`[agent-dvr] removing stale device: ${rel}`);\n\t\t\tawait this.delObjectAsync(rel, { recursive: true });\n\t\t\t// clean up internal cache\n\t\t\tfor (const [oid, d] of this.devById) {\n\t\t\t\tif (this.deviceFolder(d) === rel) {\n\t\t\t\t\tthis.devById.delete(oid);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate sortedEvents(events: Record<string, unknown>[]): Record<string, unknown>[] {\n\t\t// newest-first by default; widgetSortNewest=false reverses to oldest-first\n\t\treturn this.config.widgetSortNewest === false ? [...events].reverse() : events;\n\t}\n\n\tprivate buildGalleryHtml(d: Device, events: Record<string, unknown>[]): string {\n\t\treturn (this.config.widgetMode || 'nojs') === 'js'\n\t\t\t? this.buildGalleryHtmlJs(d, events)\n\t\t\t: this.buildGalleryHtmlNojs(d, events);\n\t}\n\n\tprivate buildGalleryHtmlNojs(d: Device, events: Record<string, unknown>[]): string {\n\t\tconst oid = d.oid;\n\t\tconst minCol = this.effectiveMinCol();\n\t\tconst maxW = this.config.widgetMaxModalWidth || 900;\n\t\tconst showTags = this.config.widgetShowTags;\n\t\tconst pos = (this.config.widgetTagPosition || 'bottom-left').split('-');\n\t\tconst tagStyle = `${pos[0]}:5px;${pos[1]}:5px`;\n\t\tconst playerUrl = (this.config.widgetPlayerUrl || '').trim();\n\t\tconst compact = !!this.config.widgetCompact;\n\t\tconst PAUSE_ATTR = ` onchange=\"if(!this.checked){var m=this.nextElementSibling.nextElementSibling,v=m&&m.querySelector('video');if(v){v.pause();}}\"`;\n\n\t\tconst items = this.sortedEvents(events)\n\t\t\t.map((ev, i) => {\n\t\t\t\tconst p = this.fmtEvent(ev, oid);\n\t\t\t\tconst id = `adv${sanitize(oid)}_${i}`;\n\t\t\t\tconst badge =\n\t\t\t\t\tshowTags && p.tag ? `<span class=\"advtag\" style=\"${tagStyle}\">${escHtml(p.tag)}</span>` : '';\n\t\t\t\tconst inner =\n\t\t\t\t\t`<span class=\"advimg\"><img src=\"${p.thumb}\" loading=\"lazy\" alt=\"\">${badge}<span class=\"advplay\"></span></span>` +\n\t\t\t\t\t`<span class=\"advcap\">${escHtml(p.date)} ${escHtml(p.time)}<br>${escHtml(p.dur)}s · ${escHtml(p.sizeMB)} MB</span>`;\n\t\t\t\tif (playerUrl) {\n\t\t\t\t\tconst href = playerUrl\n\t\t\t\t\t\t.replace(/{video}/g, encodeURIComponent(p.video))\n\t\t\t\t\t\t.replace(/{videoRaw}/g, p.video)\n\t\t\t\t\t\t.replace(/{fn}/g, encodeURIComponent(p.fn))\n\t\t\t\t\t\t.replace(/{date}/g, encodeURIComponent(p.date))\n\t\t\t\t\t\t.replace(/{time}/g, encodeURIComponent(p.time))\n\t\t\t\t\t\t.replace(/{duration}/g, encodeURIComponent(p.dur))\n\t\t\t\t\t\t.replace(/{size}/g, encodeURIComponent(String(p.sizeMB)))\n\t\t\t\t\t\t.replace(/{tags}/g, encodeURIComponent(p.tag));\n\t\t\t\t\treturn `<a class=\"advcell\" href=\"${escHtml(href)}\" target=\"_blank\" rel=\"noopener\">${inner}</a>`;\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t`<input class=\"advlb\" type=\"checkbox\" id=\"${id}\"${PAUSE_ATTR}>` +\n\t\t\t\t\t`<label class=\"advcell advthumb\" for=\"${id}\">${inner}</label>` +\n\t\t\t\t\t`<div class=\"advmodal\"><label class=\"advbackdrop\" for=\"${id}\"></label>` +\n\t\t\t\t\t`<div class=\"advbox\"><label class=\"advclose\" for=\"${id}\">✕</label>` +\n\t\t\t\t\t`<video class=\"advvideo\" controls preload=\"none\" playsinline src=\"${p.video}\"></video>` +\n\t\t\t\t\t`<div class=\"advinfo\">${escHtml(p.date)} ${escHtml(p.time)} · ${escHtml(p.dur)}s · ${escHtml(p.sizeMB)} MB${\n\t\t\t\t\t\tp.tag ? ` · ${escHtml(p.tag)}` : ''\n\t\t\t\t\t} · <a href=\"${p.video}\" download target=\"_blank\">${this.wt.download}</a></div></div></div>`\n\t\t\t\t);\n\t\t\t})\n\t\t\t.join('');\n\n\t\tconst gridClass = compact ? 'advgrid advcompact' : 'advgrid';\n\t\tconst grid = items\n\t\t\t? `<div class=\"${gridClass}\">${items}</div>`\n\t\t\t: `<div class=\"advempty\">${this.wt.noRecordings}</div>`;\n\t\tconst colors: WidgetColors = {\n\t\t\tcardBg: this.config.widgetColorCardBg || undefined,\n\t\t\ttagBg: this.config.widgetColorTagBg || undefined,\n\t\t\ttagText: this.config.widgetColorTagText || undefined,\n\t\t\taccent: this.config.widgetColorAccent || undefined,\n\t\t\tmodalBg: this.config.widgetColorModalBg || undefined,\n\t\t\tradius: this.config.widgetBorderRadius,\n\t\t};\n\t\treturn `<style>${galleryCss(minCol, maxW, compact, colors)}</style>${grid}`;\n\t}\n\n\tprivate buildGalleryHtmlJs(d: Device, events: Record<string, unknown>[]): string {\n\t\tconst oid = d.oid;\n\t\tconst minCol = this.effectiveMinCol();\n\t\tconst maxW = this.config.widgetMaxModalWidth || 900;\n\t\tconst showSearch = this.config.widgetShowSearch !== false;\n\t\tconst compact = !!this.config.widgetCompact;\n\t\tconst defaultTag = (this.config.widgetDefaultTag || '').trim();\n\t\tconst items = this.sortedEvents(events).map(ev => {\n\t\t\tconst p = this.fmtEvent(ev, oid);\n\t\t\treturn {\n\t\t\t\tfn: p.fn,\n\t\t\t\tdate: p.date,\n\t\t\t\ttime: p.time,\n\t\t\t\tdur: p.dur,\n\t\t\t\tsize: p.sizeMB,\n\t\t\t\ttag: p.tag,\n\t\t\t\tthumb: p.thumb,\n\t\t\t\tvideo: p.video,\n\t\t\t};\n\t\t});\n\t\tconst cfg = {\n\t\t\tmin_col: minCol,\n\t\t\tshow_tags: !!this.config.widgetShowTags,\n\t\t\tmax_modal_width: maxW,\n\t\t\tlive_aspect: this.camAspect[oid] || this.config.widgetLiveAspect || '',\n\t\t\tplayer_url: (this.config.widgetPlayerUrl || '').trim(),\n\t\t\ttag_position: this.config.widgetTagPosition || 'bottom-left',\n\t\t\tcompact,\n\t\t\tdefault_tag: defaultTag,\n\t\t\tlabels: { noRecordings: this.wt.noRecordings, all: this.wt.all, live: this.wt.live },\n\t\t};\n\t\tconst data = JSON.stringify({ items, live: null, cfg }).replace(/</g, '\\\\u003c');\n\t\tconst boot = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n\t\tconst searchHtml = showSearch\n\t\t\t? `<input class=\"advsearchjs\" type=\"text\" placeholder=\"${escHtml(this.wt.search)}\">`\n\t\t\t: '';\n\t\tconst colors: WidgetColors = {\n\t\t\tcardBg: this.config.widgetColorCardBg || undefined,\n\t\t\ttagBg: this.config.widgetColorTagBg || undefined,\n\t\t\ttagText: this.config.widgetColorTagText || undefined,\n\t\t\taccent: this.config.widgetColorAccent || undefined,\n\t\t\tmodalBg: this.config.widgetColorModalBg || undefined,\n\t\t\tradius: this.config.widgetBorderRadius,\n\t\t};\n\t\treturn (\n\t\t\t`<style>${galleryCssJs(minCol, compact, colors)}</style>` +\n\t\t\t`<div class=\"advroot\"><script type=\"application/json\" class=\"advdata\">${data}</script>` +\n\t\t\t`<div class=\"advbar\">${searchHtml}<div class=\"advtagsjs\"></div></div>` +\n\t\t\t`<div class=\"advgridjs\"></div></div>` +\n\t\t\t`<script type=\"text/plain\" class=\"advcode\">${ADV_CLIENT_CODE}</script>` +\n\t\t\t`<img alt=\"\" src=\"${boot}\" style=\"display:none\" onload=\"(function(){if(window.ADVscan){window.ADVscan();return;}var c=document.querySelector('script.advcode');if(!c)return;var s=document.createElement('script');s.textContent=c.textContent;document.body.appendChild(s);})()\">`\n\t\t);\n\t}\n\n\tprivate buildOverviewHtml(cams: Device[]): string {\n\t\tconst ts = Date.now();\n\t\tconst minCol = this.config.widgetMinCol || 150;\n\t\tconst maxW = this.config.widgetMaxModalWidth || 900;\n\t\tconst PAUSE_ATTR = ` onchange=\"if(!this.checked){var m=this.nextElementSibling.nextElementSibling,v=m&&m.querySelector('video');if(v){v.pause();}}\"`;\n\t\tconst tiles = cams\n\t\t\t.map(d => {\n\t\t\t\tconst oid = d.oid;\n\t\t\t\tconst id = `advlive${sanitize(oid)}`;\n\t\t\t\tconst grab = `${this.baseUrl}/grab.jpg?oid=${oid}&ot=2&maintainAR=1&ts=${ts}`;\n\t\t\t\tconst webm = `${this.baseUrl}/video.webm?oid=${oid}&ot=2`;\n\t\t\t\tconst name = escHtml(d.name || `Camera ${oid}`);\n\t\t\t\tconst arRaw = this.camAspect[oid] || this.config.widgetLiveAspect || '';\n\t\t\t\tconst ar = arRaw ? String(arRaw).replace('/', ' / ') : '';\n\t\t\t\tconst fix = ar ? ' advimgfix' : '';\n\t\t\t\tconst arStyle = ar ? ` style=\"aspect-ratio:${ar}\"` : '';\n\t\t\t\tconst inner =\n\t\t\t\t\t`<span class=\"advimg${fix}\"${arStyle}><img src=\"${grab}\" loading=\"lazy\" alt=\"\">` +\n\t\t\t\t\t`<span class=\"advtag\" style=\"top:5px;left:5px\">● ${escHtml(this.wt.live)}</span><span class=\"advplay\"></span></span>` +\n\t\t\t\t\t`<span class=\"advcap\">${name}</span>`;\n\t\t\t\treturn (\n\t\t\t\t\t`<input class=\"advlb\" type=\"checkbox\" id=\"${id}\"${PAUSE_ATTR}>` +\n\t\t\t\t\t`<label class=\"advcell advthumb\" for=\"${id}\">${inner}</label>` +\n\t\t\t\t\t`<div class=\"advmodal\"><label class=\"advbackdrop\" for=\"${id}\"></label>` +\n\t\t\t\t\t`<div class=\"advbox\"><label class=\"advclose\" for=\"${id}\">✕</label>` +\n\t\t\t\t\t`<video class=\"advvideo\" controls preload=\"none\" playsinline src=\"${webm}\"></video>` +\n\t\t\t\t\t`<div class=\"advinfo\">${name} · Live</div></div></div>`\n\t\t\t\t);\n\t\t\t})\n\t\t\t.join('');\n\t\tconst grid = tiles ? `<div class=\"advgrid\">${tiles}</div>` : `<div class=\"advempty\">No cameras</div>`;\n\t\treturn `<style>${galleryCss(minCol, maxW)}</style>${grid}`;\n\t}\n\n\t// ---- event data points ----\n\n\tprivate async writeEventDps(d: Device, fid: string, events: Record<string, unknown>[]): Promise<void> {\n\t\tconst oid = d.oid;\n\t\tawait this.ensureFolder(`${fid}.events`, 'Events', 'channel');\n\t\tawait this.ensureFolder(`${fid}.events.last`, 'Last event', 'channel');\n\n\t\tconst two = (n: number): string => String(n).padStart(2, '0');\n\t\tconst now = new Date();\n\t\tconst td = `${two(now.getDate())}.${two(now.getMonth() + 1)}.`;\n\t\tconst todayCount = events.filter(ev => this.fmtEvent(ev, oid).date === td).length;\n\n\t\tawait this.writeLeaf(`${fid}.events.count`, events.length);\n\t\tawait this.writeLeaf(`${fid}.events.today`, todayCount);\n\n\t\tif (events.length) {\n\t\t\tconst p = this.fmtEvent(events[0], oid);\n\t\t\tconst tsMs = (parseFloat(String((events[0] as AgentDvrEvent).c ?? 0)) - 621355968000000000) / 10000;\n\t\t\tawait this.writeLeaf(`${fid}.events.last.time`, `${p.date} ${p.time}`);\n\t\t\tawait this.writeLeaf(`${fid}.events.last.timestamp`, Math.round(tsMs));\n\t\t\tawait this.writeLeaf(`${fid}.events.last.tag`, p.tag);\n\t\t\tawait this.writeLeaf(`${fid}.events.last.duration`, p.dur ? parseFloat(p.dur) : 0);\n\t\t\tawait this.writeLeaf(`${fid}.events.last.size_mb`, p.sizeMB);\n\t\t\tawait this.writeLeaf(`${fid}.events.last.thumb`, p.thumb);\n\t\t\tawait this.writeLeaf(`${fid}.events.last.video`, p.video);\n\t\t}\n\n\t\t// JSON list for web UI \u2014 browser never needs to talk to AgentDVR for recordings\n\t\tconst jsonId = `${fid}.events.json`;\n\t\tif (!this.ensuredFolders.has(jsonId)) {\n\t\t\tawait this.ensurePath(jsonId);\n\t\t\tawait this.setObjectNotExistsAsync(jsonId, {\n\t\t\t\ttype: 'state',\n\t\t\t\tcommon: { name: 'Recordings list (web UI)', type: 'string', role: 'json', read: true, write: false },\n\t\t\t\tnative: {},\n\t\t\t});\n\t\t\tthis.ensuredFolders.add(jsonId);\n\t\t}\n\t\tawait this.setStateAsync(jsonId, {\n\t\t\tval: JSON.stringify(\n\t\t\t\tevents.slice(0, Math.max(1, this.config.widgetAnzahl || 50)).map(ev => {\n\t\t\t\t\tconst p = this.fmtEvent(ev, oid);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdate: p.date,\n\t\t\t\t\t\ttime: p.time,\n\t\t\t\t\t\tdur: p.dur,\n\t\t\t\t\t\tsize: p.sizeMB,\n\t\t\t\t\t\ttag: p.tag,\n\t\t\t\t\t\tthumb: p.thumb,\n\t\t\t\t\t\tvideo: p.video,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t),\n\t\t\tack: true,\n\t\t});\n\n\t\tawait this.ensureFlag(`${fid}.events.new`, 'New event');\n\n\t\tif (this.config.enablePush) {\n\t\t\tconst pid = `${fid}.events.pushTrigger`;\n\t\t\tif (!this.ensuredFolders.has(pid)) {\n\t\t\t\tawait this.ensurePath(pid);\n\t\t\t\tawait this.setObjectNotExistsAsync(pid, {\n\t\t\t\t\ttype: 'state',\n\t\t\t\t\tcommon: {\n\t\t\t\t\t\tname: 'Push trigger (AgentDVR action)',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\trole: 'text',\n\t\t\t\t\t\tread: true,\n\t\t\t\t\t\twrite: true,\n\t\t\t\t\t\tdef: '',\n\t\t\t\t\t},\n\t\t\t\t\tnative: {},\n\t\t\t\t});\n\t\t\t\tawait this.setStateAsync(pid, { val: '', ack: true });\n\t\t\t\tthis.ensuredFolders.add(pid);\n\t\t\t}\n\t\t\tthis.registry.set(pid, { kind: 'push', oid, fid });\n\t\t}\n\n\t\tconst ignore = (this.config.eventTagsIgnore || 'detected')\n\t\t\t.split(',')\n\t\t\t.map(s => s.trim().toLowerCase())\n\t\t\t.filter(Boolean);\n\t\tconst tokensOf = (s: string): string[] =>\n\t\t\ts\n\t\t\t\t.toLowerCase()\n\t\t\t\t.split(/[,\\s]+/)\n\t\t\t\t.filter(Boolean);\n\n\t\tfor (const kw of (this.config.eventTags || '')\n\t\t\t.split(',')\n\t\t\t.map(s => s.trim())\n\t\t\t.filter(Boolean)) {\n\t\t\tawait this.ensureFlag(`${fid}.events.detected_${sanitize(kw)}`, `Detected: ${kw}`);\n\t\t}\n\n\t\tif (this.config.eventTagsDynamic) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const ev of events) {\n\t\t\t\ttokensOf((ev as AgentDvrEvent).tg ?? '').forEach(t => seen.add(t));\n\t\t\t}\n\t\t\tfor (const t of seen) {\n\t\t\t\tif (ignore.includes(t)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tawait this.ensureFlag(`${fid}.events.detected_${sanitize(t)}`, `Detected: ${t}`);\n\t\t\t}\n\t\t}\n\n\t\tlet newCount = 0;\n\t\tif (events.length) {\n\t\t\tconst prev = this.lastEventFn[oid];\n\t\t\tif (prev !== undefined) {\n\t\t\t\tconst i = events.findIndex(e => (e as AgentDvrEvent).fn === prev);\n\t\t\t\tnewCount = i === -1 ? events.length : i;\n\t\t\t}\n\t\t\tthis.lastEventFn[oid] = (events[0] as AgentDvrEvent).fn ?? '';\n\t\t}\n\n\t\tif (newCount > 0) {\n\t\t\tawait this.pulse(`${fid}.events.new`);\n\t\t\tconst tags = new Set<string>();\n\t\t\tfor (let i = 0; i < newCount && i < events.length; i++) {\n\t\t\t\ttokensOf((events[i] as AgentDvrEvent).tg ?? '').forEach(t => tags.add(t));\n\t\t\t}\n\t\t\tfor (const t of tags) {\n\t\t\t\tif (ignore.includes(t)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst tid = `${fid}.events.detected_${sanitize(t)}`;\n\t\t\t\tawait this.ensureFlag(tid, `Detected: ${t}`);\n\t\t\t\tawait this.pulse(tid);\n\t\t\t}\n\t\t\tthis.log.debug(`${newCount} new event(s) cam ${oid} [${[...tags].join(',')}]`);\n\t\t}\n\t}\n\n\t// ---- camera events + widget ----\n\n\tprivate async updateCameraEvents(d: Device, fid: string): Promise<void> {\n\t\tif (d.ot !== 2) {\n\t\t\treturn;\n\t\t}\n\t\tif (!this.config.enableWidget && !this.config.enableEventDps) {\n\t\t\treturn;\n\t\t}\n\t\tif (this.eventBusy[d.oid]) {\n\t\t\treturn;\n\t\t}\n\t\tthis.eventBusy[d.oid] = true;\n\t\ttry {\n\t\t\tconst evRes = await this.apiGet(`/q/getEvents?oid=${d.oid}&ot=2`);\n\t\t\tconst evJson = asJson(evRes.data);\n\t\t\tif (!evJson) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst events = (\n\t\t\t\tArray.isArray(evJson.events) ? evJson.events : Array.isArray(evJson) ? evJson : []\n\t\t\t) as Record<string, unknown>[];\n\n\t\t\tif (this.config.enableEventDps) {\n\t\t\t\tawait this.writeEventDps(d, fid, events);\n\t\t\t}\n\n\t\t\tif (this.config.enableWidget) {\n\t\t\t\tconst wId = `${fid}.widget`;\n\t\t\t\tif (!this.ensuredFolders.has(wId)) {\n\t\t\t\t\tawait this.ensurePath(wId);\n\t\t\t\t\tawait this.setObjectNotExistsAsync(wId, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'HTML gallery widget',\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\trole: 'html',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: false,\n\t\t\t\t\t\t\tdef: '',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tthis.ensuredFolders.add(wId);\n\t\t\t\t}\n\t\t\t\tconst ev = events.slice(0, Math.max(1, this.config.widgetAnzahl || 50));\n\t\t\t\tconst f = (ev[0] ?? {}) as AgentDvrEvent;\n\t\t\t\tconst l = (ev[ev.length - 1] ?? {}) as AgentDvrEvent;\n\t\t\t\tconst sig = `${ev.length}|${f.fn ?? ''}|${l.fn ?? ''}`;\n\t\t\t\tif (this.widgetSig[wId] !== sig) {\n\t\t\t\t\tawait this.setStateAsync(wId, { val: this.buildGalleryHtml(d, ev), ack: true });\n\t\t\t\t\tthis.widgetSig[wId] = sig;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.eventBusy[d.oid] = false;\n\t\t}\n\t}\n\n\tprivate pushRefresh(oid: number | string): void {\n\t\tconst d = this.devById.get(oid);\n\t\tif (!d) {\n\t\t\tthis.log.warn(`Push: camera ${oid} unknown (available after first poll)`);\n\t\t\treturn;\n\t\t}\n\t\tconst fid = this.deviceFolder(d);\n\t\tfor (const ms of [0, 1500, 3500, 6000]) {\n\t\t\tthis.setTimeout(\n\t\t\t\t() =>\n\t\t\t\t\tthis.updateCameraEvents(d, fid).catch(e =>\n\t\t\t\t\t\tthis.log.warn(`Push refresh error: ${(e as Error).message}`),\n\t\t\t\t\t),\n\t\t\t\tms,\n\t\t\t);\n\t\t}\n\t}\n\n\t// ---- main poll ----\n\n\tprivate async poll(): Promise<void> {\n\t\tif (this.pollBusy) {\n\t\t\tthis.log.debug('poll() skipped \u2014 previous run still in progress');\n\t\t\treturn;\n\t\t}\n\t\tthis.pollBusy = true;\n\t\ttry {\n\t\t\tconst res = await this.apiGet('/command/getObjects');\n\t\t\tconst json = asJson(res.data);\n\n\t\t\tif (!res.ok || !json) {\n\t\t\t\tawait this.setStateAsync('info.connection', false, true);\n\t\t\t\tawait this.setStateAsync('system.online', { val: false, ack: true });\n\t\t\t\tthis.log.warn(`AgentDVR unreachable: ${res.error || 'invalid response'}`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait this.setStateAsync('info.connection', true, true);\n\t\t\tawait this.setStateAsync('system.online', { val: true, ack: true });\n\n\t\t\tif (json.settings) {\n\t\t\t\tawait this.flattenWrite(json.settings, 'system.settings', 0);\n\t\t\t}\n\n\t\t\tif (this.config.storeRawJson) {\n\t\t\t\tconst clean: Record<string, unknown> = { ...json };\n\t\t\t\tdelete clean.icons;\n\t\t\t\tawait this.writeLeaf('system.raw_getObjects', JSON.stringify(clean).slice(0, 60000));\n\t\t\t}\n\n\t\t\tconst devices = findDevices(json);\n\t\t\tthis.lastCamNames = devices.filter(d => d.ot === 2).map(d => ({ key: this.deviceFolder(d), name: d.name }));\n\t\t\tawait this.setStateAsync('system.cameraCount', { val: devices.filter(d => d.ot === 2).length, ack: true });\n\n\t\t\tconst activeFolders = new Set(devices.map(d => this.deviceFolder(d)));\n\t\t\tfor (const d of devices) {\n\t\t\t\tawait this.buildDevice(d);\n\t\t\t}\n\t\t\tawait this.pruneStaleDevices(activeFolders);\n\n\t\t\tconst stats = asJson((await this.apiGet('/command/getSystemStats')).data);\n\t\t\tif (stats) {\n\t\t\t\tawait this.flattenWrite(stats, 'system.stats', 0);\n\t\t\t\tconst gb = parseSizeGb(stats.disk_free);\n\t\t\t\tif (gb !== null) {\n\t\t\t\t\tawait this.writeLeaf('system.disk_free_gb', gb);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst status = asJson((await this.apiGet('/command/getStatus')).data);\n\t\t\tif (status) {\n\t\t\t\tawait this.flattenWrite(status, 'system.status', 0);\n\t\t\t}\n\n\t\t\tif (this.config.enableSystemControls && Array.isArray(json.profiles)) {\n\t\t\t\tconst states: Record<number, string> = {};\n\t\t\t\tlet activeInd: number | null = null;\n\t\t\t\tfor (const p of json.profiles) {\n\t\t\t\t\tif (p && typeof p === 'object') {\n\t\t\t\t\t\tconst po = p as Record<string, unknown>;\n\t\t\t\t\t\tconst ind = po.id ?? po.ind ?? po.index;\n\t\t\t\t\t\tconst pname = po.name;\n\t\t\t\t\t\tif (typeof ind === 'number' && (typeof pname === 'string' || typeof pname === 'number')) {\n\t\t\t\t\t\t\tstates[ind] = String(pname);\n\t\t\t\t\t\t\tif (po.active === true) {\n\t\t\t\t\t\t\t\tactiveInd = ind;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (Object.keys(states).length > 0) {\n\t\t\t\t\tconst sig = JSON.stringify(states);\n\t\t\t\t\tif (sig !== this.profileSig) {\n\t\t\t\t\t\tthis.profileSig = sig;\n\t\t\t\t\t\tawait this.extendObjectAsync('system.profile.selector', { common: { states } });\n\t\t\t\t\t\tawait this.setStateAsync('system.profile.list', { val: sig, ack: true });\n\t\t\t\t\t}\n\t\t\t\t\tif (activeInd !== null) {\n\t\t\t\t\t\tawait this.setStateAsync('system.profile.selector', { val: activeInd, ack: true });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.config.enableOverview) {\n\t\t\t\tconst cams = devices.filter(d => d.ot === 2);\n\t\t\t\tconst ovId = 'overview';\n\t\t\t\tif (!this.ensuredFolders.has(ovId)) {\n\t\t\t\t\tawait this.setObjectNotExistsAsync(ovId, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'Overview (all cameras)',\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\trole: 'html',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: false,\n\t\t\t\t\t\t\tdef: '',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tthis.ensuredFolders.add(ovId);\n\t\t\t\t}\n\t\t\t\tawait this.setStateAsync(ovId, { val: this.buildOverviewHtml(cams), ack: true });\n\t\t\t}\n\n\t\t\tawait this.setStateAsync('system.lastUpdate', { val: new Date().toISOString(), ack: true });\n\t\t\tawait this.setStateAsync('system.lastPoll', { val: Date.now(), ack: true });\n\t\t} finally {\n\t\t\tthis.pollBusy = false;\n\t\t}\n\t}\n\n\tprivate scheduleRefresh(): void {\n\t\tif (this.refreshTimer !== undefined) {\n\t\t\tthis.clearTimeout(this.refreshTimer);\n\t\t\tthis.refreshTimer = undefined;\n\t\t}\n\t\tthis.refreshTimer = this.setTimeout(\n\t\t\t() => this.poll().catch(e => this.log.warn(`Refresh error: ${(e as Error).message}`)),\n\t\t\t1500,\n\t\t);\n\t}\n\n\t// ---- command execution ----\n\n\tprivate ptzUrl(oid: number | string, dir: number): string {\n\t\treturn `/ptz.cgi?oid=${encodeURIComponent(String(oid))}&dir=${dir}`;\n\t}\n\n\tprivate buildCommandUrl(entry: RegistryEntry): string {\n\t\tif (entry.kind === 'ptz') {\n\t\t\treturn this.ptzUrl(entry.oid!, entry.dir!);\n\t\t}\n\t\tif (entry.kind === 'sys') {\n\t\t\treturn entry.path as string;\n\t\t}\n\t\tconst qs: string[] = [];\n\t\tfor (const p of entry.params || []) {\n\t\t\tif (p === 'oid') {\n\t\t\t\tqs.push(`oid=${encodeURIComponent(String(entry.oid))}`);\n\t\t\t} else if (p === 'ot') {\n\t\t\t\tqs.push(`ot=${encodeURIComponent(String(entry.ot))}`);\n\t\t\t}\n\t\t}\n\t\treturn (entry.path || '') + (qs.length ? `?${qs.join('&')}` : '');\n\t}\n\n\tprivate async clearPtzSiblings(stateId: string): Promise<void> {\n\t\tconst prefix = stateId.slice(0, stateId.lastIndexOf('.') + 1);\n\t\tfor (const p of PTZ_DIRS) {\n\t\t\tif (!p.hold) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst sid = prefix + p.id;\n\t\t\tif (sid !== stateId) {\n\t\t\t\tawait this.setStateAsync(sid, { val: false, ack: true });\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async runCommand(relId: string, entry: RegistryEntry, val: ioBroker.StateValue): Promise<void> {\n\t\tif (entry.kind === 'setProfile') {\n\t\t\tconst ind = typeof val === 'number' ? val : parseInt(String(val ?? ''), 10);\n\t\t\tif (!isNaN(ind)) {\n\t\t\t\tconst url = `/command/setProfile?ind=${ind}`;\n\t\t\t\tconst cmdRes = await this.apiGet(url);\n\t\t\t\tif (cmdRes.ok) {\n\t\t\t\t\tthis.log.debug(`OK: ${url}`);\n\t\t\t\t\tawait this.setStateAsync(relId, { val: ind, ack: true });\n\t\t\t\t} else {\n\t\t\t\t\tthis.log.warn(`Command failed (${url}): ${cmdRes.error}`);\n\t\t\t\t}\n\t\t\t\tthis.scheduleRefresh();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (entry.kind === 'snapshotB64') {\n\t\t\tconst snapId = `${entry.fid}.snapshot_b64`;\n\t\t\tawait this.fetchSnapshotB64(entry.oid!, snapId);\n\t\t\tawait this.setStateAsync(relId, { val: false, ack: true });\n\t\t\treturn;\n\t\t}\n\n\t\tif (entry.kind === 'push') {\n\t\t\tthis.log.info(`Push trigger cam ${entry.oid}`);\n\t\t\tawait this.setStateAsync(relId, { val: '', ack: true });\n\t\t\tthis.pushRefresh(entry.oid!);\n\t\t\treturn;\n\t\t}\n\n\t\tif (entry.kind === 'ptzHold') {\n\t\t\tconst oid = entry.oid!;\n\t\t\tconst startMove = async (): Promise<void> => {\n\t\t\t\tawait this.clearPtzSiblings(relId);\n\t\t\t\tawait this.apiGet(this.ptzUrl(oid, entry.dir!));\n\t\t\t\tthis.ptzActive.set(oid, relId);\n\t\t\t\tawait this.setStateAsync(relId, { val: true, ack: true });\n\t\t\t};\n\t\t\tconst stopMove = async (): Promise<void> => {\n\t\t\t\tawait this.apiGet(this.ptzUrl(oid, 11));\n\t\t\t\tif (this.ptzActive.get(oid) === relId) {\n\t\t\t\t\tthis.ptzActive.delete(oid);\n\t\t\t\t}\n\t\t\t\tawait this.setStateAsync(relId, { val: false, ack: true });\n\t\t\t};\n\t\t\tif (val) {\n\t\t\t\tif (this.ptzActive.get(oid) === relId) {\n\t\t\t\t\tawait stopMove();\n\t\t\t\t} else {\n\t\t\t\t\tawait startMove();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait stopMove();\n\t\t\t}\n\t\t\tthis.scheduleRefresh();\n\t\t\treturn;\n\t\t}\n\n\t\tif (!val) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (entry.kind === 'sys' && entry.path === null) {\n\t\t\tawait this.poll().catch(e => this.log.warn(`Manual refresh error: ${(e as Error).message}`));\n\t\t\tawait this.setStateAsync(relId, { val: false, ack: true });\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = this.buildCommandUrl(entry);\n\t\tconst cmdRes = await this.apiGet(url);\n\t\tif (cmdRes.ok) {\n\t\t\tthis.log.debug(`OK: ${url}`);\n\t\t} else {\n\t\t\tthis.log.warn(`Command failed (${url}): ${cmdRes.error}`);\n\t\t}\n\n\t\tawait this.setStateAsync(relId, { val: false, ack: true });\n\t\tthis.scheduleRefresh();\n\t}\n}\n\nif (require.main !== module) {\n\tmodule.exports = (options: Partial<utils.AdapterOptions> | undefined) => new AgentDvr(options);\n} else {\n\t(() => new AgentDvr())();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["url", "cmdRes"]
|
|
7
7
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "agent-dvr",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.2.1": {
|
|
7
|
+
"en": "fix: translate all German user-facing strings and error messages to English\nfix: DashboardPanel shows i18n-aware messages for missing IP and empty camera list\nchore: add .npmignore to exclude src/ and src-admin/ from npm package",
|
|
8
|
+
"de": "Behebung: Alle deutschen Benutzertexte und Fehlermeldungen ins Englische übersetzen.\nBehoben: DashboardPanel zeigt nun i18n-konforme Meldungen für fehlende IP-Adressen und leere Kameralisten an.\nAufgabe: Füge .npmignore hinzu, um src/ und src-admin/ vom npm-Paket auszuschließen",
|
|
9
|
+
"ru": "Исправление: перевести все текстовые сообщения и сообщения об ошибках, отображаемые пользователям на немецком языке, на английский.\nИсправление: В панели управления DashboardPanel отображаются сообщения с поддержкой интернационализации для отсутствующего IP-адреса и пустого списка камер.\nЗадача: добавить файл .npmignore, чтобы исключить папки src/ и src-admin/ из списка пакетов npm.",
|
|
10
|
+
"pt": "Correção: traduzir todas as mensagens de texto e de erro exibidas ao usuário em alemão para o inglês.\nCorreção: O DashboardPanel exibe mensagens compatíveis com i18n para IP ausente e lista de câmeras vazia.\ntarefa: adicione .npmignore para excluir src/ e src-admin/ do pacote npm",
|
|
11
|
+
"nl": "Oplossing: vertaal alle Duitse gebruikersteksten en foutmeldingen naar het Engels.\nOpgelost: DashboardPanel geeft i18n-compatibele meldingen weer voor ontbrekende IP-adressen en een lege cameralijst.\nTaak: voeg .npmignore toe om src/ en src-admin/ uit te sluiten van het npm-pakket.",
|
|
12
|
+
"fr": "Correction : traduire en anglais toutes les chaînes de caractères et les messages d'erreur destinés aux utilisateurs en allemand\nCorrection : Le panneau de bord affiche des messages compatibles avec l'internationalisation (i18n) pour les adresses IP manquantes et les listes de caméras vides.\nTâche : ajouter .npmignore pour exclure src/ et src-admin/ du package npm",
|
|
13
|
+
"it": "Correzione: tradurre in inglese tutte le stringhe e i messaggi di errore visualizzati dall'utente in tedesco.\nCorrezione: DashboardPanel mostra messaggi ottimizzati per l'internazionalizzazione (i18n) in caso di IP mancante e elenco di telecamere vuoto.\ncompito: aggiungi .npmignore per escludere src/ e src-admin/ dal pacchetto npm",
|
|
14
|
+
"es": "Corrección: traducir todas las cadenas de texto y mensajes de error dirigidos al usuario en alemán al inglés.\nCorrección: DashboardPanel muestra mensajes compatibles con i18n para direcciones IP faltantes y listas de cámaras vacías.\ntarea: agregar .npmignore para excluir src/ y src-admin/ del paquete npm",
|
|
15
|
+
"pl": "poprawka: przetłumacz wszystkie niemieckie ciągi znaków i komunikaty o błędach na angielski\nnaprawiono: Panel sterowania wyświetla komunikaty obsługujące protokół i18n w przypadku braku adresu IP i pustej listy kamer\nzadanie: dodaj .npmignore, aby wykluczyć src/ i src-admin/ z pakietu npm",
|
|
16
|
+
"uk": "виправлення: переклад усіх рядків та повідомлень про помилки, що використовуються користувачем з Німеччини, на англійську мову\nвиправлення: DashboardPanel показує повідомлення про i18n-залежність для відсутніх IP-адрес та порожнього списку камер.\nзавдання: додати .npmignore, щоб виключити src/ та src-admin/ з npm-пакета",
|
|
17
|
+
"zh-cn": "修复:将所有面向用户的德语字符串和错误消息翻译成英语\n修复:当缺少 IP 地址或摄像头列表为空时,仪表盘面板会显示国际化提示信息\n任务:添加 .npmignore 文件,将 src/ 和 src-admin/ 目录从 npm 包中排除。"
|
|
18
|
+
},
|
|
6
19
|
"0.2.0": {
|
|
7
20
|
"en": "feat: dashboard camera filter badges with localStorage persistence\nfeat: FLV/MP4 stream auto-reconnect after network error (5 s delay)\nfeat: go2rtc WebSocket auto-reconnect after unexpected disconnect (5 s delay)\nfeat: go2rtc stall detection — retry if stream stays black after 10 s\nfix: cameraStreams missing from io-package.json native defaults (settings not saved)\nfix: adminUI.config \"custom\" → \"materialize\" (404 on adapter settings page)\nfix: remove resolution overlay on FLV stream load\nfix: remove CDN fallback for flv.js — local copy only\nfix: remove AgentDVR/go2rtc section headers from dashboard grid\nfix: cfgGo2rtcMapping_tt tooltip corrected in all 11 languages\nfix: plain setTimeout() replaced by this.setTimeout() (E5005)\nfix: remove obsolete jsonConfig.json — settings handled by React admin (W5046)\nchore: exclude admin/ directory from ESLint to prevent OOM in CI\ndocs: rewrite README and README.de with all tabs and settings documented",
|
|
8
21
|
"de": "Funktion: Filter-Badges für Dashcams mit Speicherung im lokalen Speicher\nFunktion: Automatische Wiederverbindung des FLV/MP4-Streams nach Netzwerkfehlern (5 Sekunden Verzögerung)\nFunktion: Automatische Wiederverbindung von go2rtc-WebSockets nach unerwarteter Trennung (5 Sekunden Verzögerung)\nFunktion: go2rtc-Stall-Erkennung – Wiederholungsversuch, falls der Stream nach 10 Sekunden schwarz bleibt\nBehoben: cameraStreams fehlen in den nativen Standardeinstellungen von io-package.json (Einstellungen werden nicht gespeichert)\nBehebung: adminUI.config \"custom\" → \"materialize\" (404 auf der Adaptereinstellungsseite)\nBehoben: Auflösungsüberlagerung beim Laden des FLV-Streams entfernt\nBehebung: CDN-Fallback für flv.js entfernen – nur lokale Kopie\nBehebung: Entfernen der Abschnittsüberschriften AgentDVR/go2rtc aus dem Dashboard-Raster\nBehoben: Tooltip für cfgGo2rtcMapping_tt in allen 11 Sprachen korrigiert.\nBehebung: Die einfache setTimeout()-Funktion wurde durch this.setTimeout() ersetzt (E5005)\nBehebung: Entfernen der veralteten Datei jsonConfig.json – Einstellungen werden vom React-Admin verwaltet (W5046)\nAufgabe: Das Verzeichnis „admin/“ von ESLint ausschließen, um einen Speichermangel in der CI zu verhindern.\nDokumentation: README und README.de neu schreiben und alle Tabs und Einstellungen dokumentieren",
|
|
@@ -80,19 +93,6 @@
|
|
|
80
93
|
"pl": "selektor profilu: pobieranie dostępnych profili przez getProfiles, zapisywalny dropdown",
|
|
81
94
|
"uk": "вибір профілю: отримання доступних профілів через getProfiles, записуваний список",
|
|
82
95
|
"zh-cn": "配置文件选择器:通过 getProfiles 获取可用配置文件,可写下拉菜单"
|
|
83
|
-
},
|
|
84
|
-
"0.0.2": {
|
|
85
|
-
"en": "setup npm trusted publishing and fix repochecker findings",
|
|
86
|
-
"de": "npm Trusted Publishing eingerichtet und Repochecker-Findings behoben",
|
|
87
|
-
"ru": "настройка npm Trusted Publishing и исправление находок репочекера",
|
|
88
|
-
"pt": "configuração de publicação confiável npm e correção de resultados do repochecker",
|
|
89
|
-
"nl": "npm trusted publishing instellen en repochecker-bevindingen corrigeren",
|
|
90
|
-
"fr": "configuration de la publication de confiance npm et correction des résultats du repochecker",
|
|
91
|
-
"it": "configurazione della pubblicazione attendibile npm e correzione dei risultati del repochecker",
|
|
92
|
-
"es": "configuración de publicación de confianza npm y corrección de hallazgos del repochecker",
|
|
93
|
-
"pl": "konfiguracja zaufanego publikowania npm i poprawki wyników repocheckera",
|
|
94
|
-
"uk": "налаштування довіреної публікації npm та виправлення знахідок репочекера",
|
|
95
|
-
"zh-cn": "设置 npm 可信发布并修复 repochecker 问题"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|