Polish the snapshot wall and add timed refresh
This commit is contained in:
Binary file not shown.
@@ -2,6 +2,7 @@ sub init()
|
|||||||
m.top.setFocus(true)
|
m.top.setFocus(true)
|
||||||
m.backend = m.top.findNode("backend")
|
m.backend = m.top.findNode("backend")
|
||||||
m.status = m.top.findNode("status")
|
m.status = m.top.findNode("status")
|
||||||
|
m.refreshTimer = m.top.findNode("refreshTimer")
|
||||||
m.cameraPosters = [
|
m.cameraPosters = [
|
||||||
m.top.findNode("poster1"),
|
m.top.findNode("poster1"),
|
||||||
m.top.findNode("poster2"),
|
m.top.findNode("poster2"),
|
||||||
@@ -14,6 +15,7 @@ sub init()
|
|||||||
m.top.findNode("cam3"),
|
m.top.findNode("cam3"),
|
||||||
m.top.findNode("cam4")
|
m.top.findNode("cam4")
|
||||||
]
|
]
|
||||||
|
m.refreshToken = 0
|
||||||
|
|
||||||
loadConfig()
|
loadConfig()
|
||||||
end sub
|
end sub
|
||||||
@@ -27,8 +29,10 @@ sub loadConfig()
|
|||||||
return
|
return
|
||||||
end if
|
end if
|
||||||
|
|
||||||
|
m.config = config
|
||||||
|
|
||||||
if config.doesExist("backend") and config.backend.doesExist("baseUrl") then
|
if config.doesExist("backend") and config.backend.doesExist("baseUrl") then
|
||||||
m.backend.text = "Frigate: " + config.backend.baseUrl
|
m.backend.text = "Frigate snapshot source"
|
||||||
end if
|
end if
|
||||||
|
|
||||||
if not config.doesExist("cameras") then
|
if not config.doesExist("cameras") then
|
||||||
@@ -36,8 +40,23 @@ sub loadConfig()
|
|||||||
return
|
return
|
||||||
end if
|
end if
|
||||||
|
|
||||||
cameras = config.cameras
|
if config.doesExist("backend") and config.backend.doesExist("refreshSeconds") then
|
||||||
m.status.text = cameras.count().toStr() + " cameras loaded, snapshot-first prototype"
|
m.refreshTimer.duration = config.backend.refreshSeconds
|
||||||
|
end if
|
||||||
|
|
||||||
|
m.refreshTimer.observeField("fire", "onRefreshTimerFire")
|
||||||
|
m.refreshTimer.control = "start"
|
||||||
|
|
||||||
|
renderCameras()
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub renderCameras()
|
||||||
|
if m.config = invalid or not m.config.doesExist("cameras") then
|
||||||
|
return
|
||||||
|
end if
|
||||||
|
|
||||||
|
cameras = m.config.cameras
|
||||||
|
m.status.text = cameras.count().toStr() + " cameras loaded, refreshing every " + m.refreshTimer.duration.toStr() + "s"
|
||||||
|
|
||||||
for i = 0 to m.cameraNodes.count() - 1
|
for i = 0 to m.cameraNodes.count() - 1
|
||||||
poster = m.cameraPosters[i]
|
poster = m.cameraPosters[i]
|
||||||
@@ -45,18 +64,8 @@ sub loadConfig()
|
|||||||
|
|
||||||
if i < cameras.count() then
|
if i < cameras.count() then
|
||||||
camera = cameras[i]
|
camera = cameras[i]
|
||||||
label = camera.name
|
poster.uri = addCacheBust(buildSnapshotUrl(m.config, camera))
|
||||||
|
node.text = camera.name
|
||||||
if camera.doesExist("host") then
|
|
||||||
label = label + chr(10) + camera.host
|
|
||||||
end if
|
|
||||||
|
|
||||||
if camera.doesExist("frigateCamera") then
|
|
||||||
label = label + chr(10) + "Frigate ID: " + camera.frigateCamera
|
|
||||||
end if
|
|
||||||
|
|
||||||
poster.uri = buildSnapshotUrl(config, camera)
|
|
||||||
node.text = label
|
|
||||||
else
|
else
|
||||||
poster.uri = ""
|
poster.uri = ""
|
||||||
node.text = "Empty slot"
|
node.text = "Empty slot"
|
||||||
@@ -64,6 +73,11 @@ sub loadConfig()
|
|||||||
end for
|
end for
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
|
sub onRefreshTimerFire()
|
||||||
|
m.refreshToken = m.refreshToken + 1
|
||||||
|
renderCameras()
|
||||||
|
end sub
|
||||||
|
|
||||||
function buildSnapshotUrl(config as Object, camera as Object) as String
|
function buildSnapshotUrl(config as Object, camera as Object) as String
|
||||||
if not config.doesExist("backend") or not config.backend.doesExist("baseUrl") then
|
if not config.doesExist("backend") or not config.backend.doesExist("baseUrl") then
|
||||||
return ""
|
return ""
|
||||||
@@ -88,3 +102,13 @@ function buildSnapshotUrl(config as Object, camera as Object) as String
|
|||||||
|
|
||||||
return baseUrl + path
|
return baseUrl + path
|
||||||
end function
|
end function
|
||||||
|
|
||||||
|
function addCacheBust(url as String) as String
|
||||||
|
token = m.refreshToken.toStr()
|
||||||
|
|
||||||
|
if instr(1, url, "?") > 0 then
|
||||||
|
return url + "&cb=" + token
|
||||||
|
end if
|
||||||
|
|
||||||
|
return url + "?cb=" + token
|
||||||
|
end function
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<Rectangle id="bg" color="0x101418FF" width="1920" height="1080" />
|
<Rectangle id="bg" color="0x101418FF" width="1920" height="1080" />
|
||||||
<Label
|
<Label
|
||||||
id="title"
|
id="title"
|
||||||
translation="[80, 80]"
|
translation="[70, 55]"
|
||||||
width="1760"
|
width="1760"
|
||||||
height="60"
|
height="60"
|
||||||
text="visionLabs"
|
text="visionLabs"
|
||||||
@@ -14,81 +14,82 @@
|
|||||||
color="0xFFFFFFFF" />
|
color="0xFFFFFFFF" />
|
||||||
<Label
|
<Label
|
||||||
id="subtitle"
|
id="subtitle"
|
||||||
translation="[80, 150]"
|
translation="[70, 108]"
|
||||||
width="1760"
|
width="1760"
|
||||||
height="40"
|
height="40"
|
||||||
text="Labs camera viewer for Roku"
|
text="Snapshot wall for Roku"
|
||||||
font="font:MediumSystemFont"
|
font="font:MediumSystemFont"
|
||||||
color="0xC9D1D9FF" />
|
color="0xC9D1D9FF" />
|
||||||
<Label
|
<Label
|
||||||
id="backend"
|
id="backend"
|
||||||
translation="[80, 210]"
|
translation="[70, 145]"
|
||||||
width="1760"
|
width="1760"
|
||||||
height="40"
|
height="40"
|
||||||
text="Frigate: not loaded"
|
text="Direct Frigate snapshots"
|
||||||
font="font:SmallSystemFont"
|
font="font:SmallSystemFont"
|
||||||
color="0x8B949EFF" />
|
color="0x8B949EFF" />
|
||||||
<Label
|
<Label
|
||||||
id="status"
|
id="status"
|
||||||
translation="[80, 260]"
|
translation="[70, 175]"
|
||||||
width="1760"
|
width="1760"
|
||||||
height="60"
|
height="40"
|
||||||
text="Loading camera config..."
|
text="Loading camera wall..."
|
||||||
font="font:MediumSystemFont"
|
font="font:SmallSystemFont"
|
||||||
color="0x8B949EFF" />
|
color="0x8B949EFF" />
|
||||||
|
<Timer id="refreshTimer" repeat="true" duration="15" />
|
||||||
<Poster
|
<Poster
|
||||||
id="poster1"
|
id="poster1"
|
||||||
translation="[80, 360]"
|
translation="[70, 230]"
|
||||||
width="760"
|
width="820"
|
||||||
height="300"
|
height="280"
|
||||||
loadDisplayMode="scaleToFit" />
|
loadDisplayMode="scaleToFit" />
|
||||||
<Label
|
<Label
|
||||||
id="cam1"
|
id="cam1"
|
||||||
translation="[80, 675]"
|
translation="[70, 520]"
|
||||||
width="760"
|
width="820"
|
||||||
height="70"
|
height="40"
|
||||||
text="Cam slot 1"
|
text="Cam slot 1"
|
||||||
font="font:MediumSystemFont"
|
font="font:MediumSystemFont"
|
||||||
color="0xFFFFFFFF" />
|
color="0xFFFFFFFF" />
|
||||||
<Poster
|
<Poster
|
||||||
id="poster2"
|
id="poster2"
|
||||||
translation="[980, 360]"
|
translation="[1030, 230]"
|
||||||
width="760"
|
width="820"
|
||||||
height="300"
|
height="280"
|
||||||
loadDisplayMode="scaleToFit" />
|
loadDisplayMode="scaleToFit" />
|
||||||
<Label
|
<Label
|
||||||
id="cam2"
|
id="cam2"
|
||||||
translation="[980, 675]"
|
translation="[1030, 520]"
|
||||||
width="760"
|
width="820"
|
||||||
height="70"
|
height="40"
|
||||||
text="Cam slot 2"
|
text="Cam slot 2"
|
||||||
font="font:MediumSystemFont"
|
font="font:MediumSystemFont"
|
||||||
color="0xFFFFFFFF" />
|
color="0xFFFFFFFF" />
|
||||||
<Poster
|
<Poster
|
||||||
id="poster3"
|
id="poster3"
|
||||||
translation="[80, 760]"
|
translation="[70, 590]"
|
||||||
width="760"
|
width="820"
|
||||||
height="300"
|
height="280"
|
||||||
loadDisplayMode="scaleToFit" />
|
loadDisplayMode="scaleToFit" />
|
||||||
<Label
|
<Label
|
||||||
id="cam3"
|
id="cam3"
|
||||||
translation="[80, 1015]"
|
translation="[70, 880]"
|
||||||
width="760"
|
width="820"
|
||||||
height="50"
|
height="40"
|
||||||
text="Cam slot 3"
|
text="Cam slot 3"
|
||||||
font="font:MediumSystemFont"
|
font="font:MediumSystemFont"
|
||||||
color="0xFFFFFFFF" />
|
color="0xFFFFFFFF" />
|
||||||
<Poster
|
<Poster
|
||||||
id="poster4"
|
id="poster4"
|
||||||
translation="[980, 760]"
|
translation="[1030, 590]"
|
||||||
width="760"
|
width="820"
|
||||||
height="300"
|
height="280"
|
||||||
loadDisplayMode="scaleToFit" />
|
loadDisplayMode="scaleToFit" />
|
||||||
<Label
|
<Label
|
||||||
id="cam4"
|
id="cam4"
|
||||||
translation="[980, 1015]"
|
translation="[1030, 880]"
|
||||||
width="760"
|
width="820"
|
||||||
height="50"
|
height="40"
|
||||||
text="Cam slot 4"
|
text="Cam slot 4"
|
||||||
font="font:MediumSystemFont"
|
font="font:MediumSystemFont"
|
||||||
color="0xFFFFFFFF" />
|
color="0xFFFFFFFF" />
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"type": "frigate",
|
"type": "frigate",
|
||||||
"baseUrl": "http://192.168.0.223:5000/",
|
"baseUrl": "http://192.168.0.223:5000/",
|
||||||
"mode": "snapshotFirst",
|
"mode": "snapshotFirst",
|
||||||
|
"refreshSeconds": 15,
|
||||||
"notes": "Keep raw camera credentials in Frigate or go2rtc, not in the Roku repo."
|
"notes": "Keep raw camera credentials in Frigate or go2rtc, not in the Roku repo."
|
||||||
},
|
},
|
||||||
"layout": {
|
"layout": {
|
||||||
|
|||||||
Reference in New Issue
Block a user