I don’t see any obvious reason for this behavior, and the widget appears to function as expected when tested in the widget editor. This is just a guess, but I can only surmise that this has something to do with calling an f7-card
as a popup. Since you’re only using it as a container anyway and not really taking advantage of any card specific features, you might try changing the base component here to a f7-popup
. That might also make the final bit of css easier to fix that last problem of hidden bottom.
If i use f7-popup instead of f7-card or f7-block, then video height becomes NaN.
The error with non-loading video seems to come from parent widget not passing modalConfig (it’s shown as [object Object] in page inspector). Inside parent widget modalConfig is described like this:
actionModalConfig:
camerahls: =props.camerahls
history: =props.history
doorItem: =props.doorItem
lockItem: =props.lockItem
motionItem: =props.motionItem
But how then video becomes fine after some switching here and there and why buttons and door/motion states do work normally?
Tested with
- component: oh-video
config:
hideControls: false
startManually: false
url: =items[props.camerahls].state
to get away from all these ternary and undefined variables and got the same issue! No video on initial popover, but if i close popover and reopen it again - then i see hls stream working from the very first milliseconds, as if the stream itself started in the first popover.
I have had a lot of trouble today playing with the - component: oh-video-card and using it with the url: I found behaviour similar to yours until I changed to using it like this…
- component: oh-video-card
config:
item: =[props.camera + '_HLSURL']
props.camera is the equipment level group, then all your member items can be guessed based off the auto naming convention that is used when you create equipment from things.
When ever you refresh the page, it fails a lot of the time if your using the url and not the item.
I can’t use item because for mp4 history i have to use URL. Maybe some kind of auto-refresh (like changing some variable inside key: ) needed on the first widget load.
Do you have more than one widget on a page calling this popup widget? I wonder if there’s some conflict with the settings.
It’s worth testing with matt1’s suggestion just to see if that is the problem. 1) Because it might be worth a github issue (if there isn’t one already) and 2) It would be possible (and only a little awkward) to convert this to a system that uses an item state instead of a variable if that turns out to be a fix.
Already tested, indeed if item: props.item is used instead of url: items[props.item].state, then there is no problem.
So widgets for my doorbell now are looking like this:
uid: ClickablePTZCamera
tags:
- video
props:
parameters:
- context: item
label: Camera image URL
name: camerajpeg
required: true
type: TEXT
- context: item
label: Camera stream URL
name: camerahls
required: false
type: TEXT
- context: item
label: Motion item
name: motionItem
required: false
type: TEXT
- context: item
label: Item for the door lock
name: lockItem
required: false
type: TEXT
- context: item
label: Item for door state
name: doorItem
required: false
type: TEXT
- context: item
description: Ipcamera MP4 history length item
label: MP4 history length
name: history
required: true
type: TEXT
timestamp: Aug 10, 2022, 8:41:38 PM
component: f7-card
config:
style:
border-radius: var(--f7-card-expandable-border-radius)
box-shadow: 5px 5px 10px 1px var(--f7-bars-bg-color)
color: var(--f7-text-color)
font-size: medium
font-weight: 500
max-height: 150px
noShadow: false
slots:
default:
- component: oh-image
config:
action: popover
actionModal: widget:Video
actionModalConfig:
camerahls: =props.camerahls
history: =props.history
doorItem: =props.doorItem
lockItem: =props.lockItem
motionItem: =props.motionItem
item: =[props.camerajpeg]
lazy: true
style:
border-radius: var(--f7-card-expandable-border-radius)
height: 150px
margin: 0px
padding: 0px
width: 100%
z-index: -2
- component: f7-row
config:
style:
position: absolute
top: 2px
width: 99%
z-index: 30
slots:
default:
- component: oh-icon
config:
icon: "=(items[props.doorItem].state === 'ON') ? 'door-closed' : 'door'"
style:
color: "=(items[props.doorItem].state === 'ON') ? 'cyan' : 'red'"
z-index: 99
visible: =props.doorItem !== undefined
width: 22
- component: oh-button
config:
action: command
actionCommand: ON
actionItem: =props.lockItem
class: card-prevent-open
iconF7: "=(items[props.lockItem].state === 'ON') ? 'lock_open' : 'lock'"
iconSize: 23
style:
color: "=(items[props.lockItem].state === 'ON') ? 'cyan' : 'var(--f7-card-header-text-color)'"
margin-left: auto
margin-right: auto
z-index: 99
visible: =props.lockItem !== undefined
- component: oh-icon
config:
icon: "=(items[props.motionItem].state === 'ON') ? 'mymotion-on' : 'mymotion-off'"
style:
z-index: 99
visible: =props.motionItem !== undefined
width: 23
uid: Video
tags:
- video
props:
parameters:
- context: item
label: Camera stream URL
name: camerahls
required: true
type: TEXT
- context: item
description: Ipcamera MP4 history length item
label: MP4 history length
name: history
required: true
type: TEXT
- context: item
label: Motion item
name: motionItem
required: false
type: TEXT
- context: item
label: Item for the door lock
name: lockItem
required: false
type: TEXT
- context: item
label: Item for door state
name: doorItem
required: false
type: TEXT
parameterGroups: []
timestamp: Aug 10, 2022, 11:19:10 PM
component: f7-block
config:
key: =Math.random() + vars.archive + vars.rewind
style:
margin: 0
margin-left: auto
noShadow: false
padding: 0
color: (--var-f7-text-color)
text-shadow: 1px 0px 2px black, -1px 0px 2px black, 0px 0px 2px black, 0px 0px 3px black
width: 97%
slots:
default:
- component: oh-video
config:
hideControls: false
startManually: false
item: =props.camerahls
visible: =(vars.archive !== 2)
- component: oh-video
config:
hideControls: false
startManually: false
url: ="http://192.168.2.9:8080/static/doorphone/Domofon" + (vars.rewind || items[props.history].state -1) + ".mp4"
type: video/mp4
visible: =(vars.archive == 2)
- component: f7-row
config:
style:
position: absolute
top: 10px
width: 99%
z-index: 30
slots:
default:
- component: oh-button
config:
action: variable
actionVariable: archive
actionVariableValue: 2
iconColor: white
iconF7: folder
iconSize: 30
visible: =(vars.archive !== 2)
tooltip: Видеоархив
- component: oh-button
config:
action: variable
actionVariable: archive
actionVariableValue: 1
iconColor: white
iconF7: videocam
iconSize: 30
visible: =(vars.archive == 2)
tooltip: Камера
- component: oh-button
config:
action: variable
actionVariable: rewind
actionVariableValue: =(vars.rewind != undefined)?(( vars.rewind > 1 )?(vars.rewind - 1):1):(items[props.history].state -2)
iconColor: white
iconF7: backward_end
iconSize: 30
visible: =(vars.archive == 2)
tooltip: Назад
- component: oh-icon
config:
icon: "=(items[props.doorItem].state === 'ON') ? 'door-closed' : 'door'"
style:
color: "=(items[props.doorItem].state === 'ON') ? 'cyan' : 'red'"
z-index: 99
visible: =((props.doorItem !== undefined) && (vars.archive !== 2))
width: 30
- component: oh-button
config:
action: command
actionCommand: ON
actionItem: =props.lockItem
class: card-prevent-open
iconF7: "=(items[props.lockItem].state === 'ON') ? 'lock_open' : 'lock'"
iconSize: 30
style:
color: "=(items[props.lockItem].state === 'ON') ? 'white' : 'red'"
margin-left: auto
margin-right: auto
z-index: 99
visible: =((props.lockItem !== undefined) && (vars.archive !== 2))
- component: oh-icon
config:
icon: "=(items[props.motionItem].state === 'ON') ? 'mymotion-on' : 'mymotion-off'"
style:
z-index: 99
visible: =((props.motionItem !== undefined) && (vars.archive !== 2))
width: 30
- component: oh-button
config:
action: variable
actionVariable: rewind
actionVariableValue: =( vars.rewind < items[props.history].state - 1)?(vars.rewind + 1):(items[props.history].state - 1)
iconColor: white
iconF7: forward_end
iconSize: 30
visible: =(vars.archive == 2)
tooltip: Вперёд
- component: oh-button
config:
iconColor: white
iconF7: clear
iconSize: 30
popoverClose: .popover.modal-in
style:
z-index: 99
tooltip: Закрыть
And I’m pretty happy with them except the issue mentioned above. And note popoverClose: .popover.modal-in that’s the only way i’ve figured out to close the popover, adding class didn’t helped, maybe because the popover is called from another widget.
Try the following code, but make sure you have all items created first with the default naming convention, or just create the items with the “create equipment from thing” feature of oh3. You will need to tick the show advanced box to see the extra channels and add the mp4History and mp4HistoryLength channels to items/equipment, as well as all the non advanced channels.
Issues still to solve:
-
How to get variables to default to a set value on first startup? You need to click on the next or previous for it to show the first recording when it is undefined. This can be solved by reading this post: Using vars in custom widgets: when are vars updated? - Add-ons / UIs - openHAB Community
-
If there is an easier way to fetch a uniqueID of a thing AND the IP of openhab. This would make the setup easier instead of needing a baseURL to be filled in by someone who may not know these details.
uid: CameraHistory
tags: []
props:
parameters:
- context: item
label: Select the Camera (Equipment)
name: camera
required: true
type: TEXT
- description: "example: http://192.168.1.2:8080/ipcamera/DoorbellCamera/"
label: Base URL
name: cameraBaseURL
required: true
type: TEXT
timestamp: Aug 11, 2022, 11:42:00 PM
component: f7-card
config:
class: videoPopover
key: "=(vars.rewind === undefined) ? Math.random() : Math.random() + vars.rewind"
style:
--f7-card-margin-horizontal: 0px
border-radius: var(--f7-card-expandable-border-radius)
box-shadow: 5px 5px 10px 1px var(--f7-bars-bg-color)
color: var(--f7-text-color)
font-size: medium
font-weight: 500
height: auto
margin: 5
noShadow: false
padding: 0
text-shadow: 1px 0px 2px var(--f7-bars-bg-color), -1px 0px 2px var(--f7-bars-bg-color), 0px 0px 2px var(--f7-bars-bg-color), 0px 0px 3px var(--f7-bars-bg-color)
width: 100%
slots:
default:
- component: oh-video-card
config:
hideControls: false
startManually: false
style:
height: auto
width: auto
item: =[props.camera + '_HLSURL']
visible: =vars.archive != 2
- component: oh-video-card
config:
hideControls: false
startManually: false
style:
height: auto
width: auto
url: =props.cameraBaseURL + items[props.camera + '_MP4History'].state.split(",")[vars.rewind] +".mp4"
visible: =vars.archive == 2
- component: f7-row
config:
style:
position: absolute
top: 10px
width: 99%
z-index: 30
slots:
default:
- component: oh-button
config:
action: variable
actionVariable: archive
actionVariableValue: 2
iconColor: white
iconF7: folder
iconSize: 30
visible: =(vars.archive !== 2)
- component: Label
config:
text: =items[props.camera+'_MP4HistoryLength'].state
style:
position: absolute
left: 45px
top: 2px
color: white
font-size: 18px
z-index: 2
visible: =vars.archive != 2 && items[props.camera+'_MP4HistoryLength'].state > 0
- component: oh-button
config:
action: variable
actionVariable: archive
actionVariableValue: 1
iconColor: white
iconF7: videocam
iconSize: 30
visible: =(vars.archive == 2)
- component: oh-button
config:
action: variable
actionVariable: rewind
actionVariableValue: =(vars.rewind+1 < items[props.camera +'_MP4HistoryLength'].state)?(vars.rewind+1):(items[props.camera +'_MP4HistoryLength'].state-1)
iconColor: white
iconF7: backward_end
iconSize: 30
visible: =vars.archive == 2 && items[props.camera+'_MP4HistoryLength'].state > 0
- component: oh-button
config:
action: variable
actionVariable: rewind
actionVariableValue: =(vars.rewind > 1)?(vars.rewind-1):(0)
iconColor: white
iconF7: forward_end
iconSize: 30
visible: =vars.archive == 2 && items[props.camera+'_MP4HistoryLength'].state > 0
- component: oh-button
config:
iconColor: white
iconF7: clear
iconSize: 30
tooltip: Clear cameras mp4 history
action: toggle
actionItem: =props.camera+'_MP4HistoryLength'
actionCommand: "0"
visible: =vars.archive == 2 && items[props.camera+'_MP4HistoryLength'].state > 0
The first issue is not related to undefined variables but to the way oh-video and oh-video-card handles item: and url: properties. And… I’ve found a fix! And the fix is a bit crazy.
uid: Video
tags:
- video
props:
parameters:
- context: item
label: Camera stream URL
name: camerahls
required: true
type: TEXT
- context: item
description: Ipcamera MP4 history length item
label: MP4 history length
name: history
required: true
type: TEXT
- context: item
label: Motion item
name: motionItem
required: false
type: TEXT
- context: item
label: Item for the door lock
name: lockItem
required: false
type: TEXT
- context: item
label: Item for door state
name: doorItem
required: false
type: TEXT
parameterGroups: []
timestamp: Aug 13, 2022, 2:12:21 PM
component: f7-block
config:
key: =Math.random() + vars.archive + vars.rewind
style:
color: (--var-f7-text-color)
margin: 0
margin-left: auto
noShadow: false
padding: 0
text-shadow: 1px 0px 2px black, -1px 0px 2px black, 0px 0px 2px black, 0px 0px 3px black
width: 97%
slots:
default:
- component: oh-video
config:
hideControls: false
item: =props.camerahls
startManually: false
visible: =(vars.archive !== 2)
- component: oh-video-card
config:
hideControls: false
startManually: false
type: video/mp4
url: ="http://192.168.2.9:8080/static/doorphone/Domofon" + (vars.rewind || items[props.history].state -1) + ".mp4"
visible: =(vars.archive == 2)
- component: f7-row
config:
style:
position: absolute
top: 10px
width: 99%
z-index: 30
slots:
default:
- component: oh-button
config:
action: variable
actionVariable: archive
actionVariableValue: 2
iconColor: white
iconF7: folder
iconSize: 30
tooltip: Видеоархив
visible: '=(items[props.history].state !== NULL ? vars.archive !== 2 : false)'
- component: oh-button
config:
action: variable
actionVariable: archive
actionVariableValue: 1
iconColor: white
iconF7: videocam
iconSize: 30
tooltip: Камера
visible: =(vars.archive == 2)
- component: oh-button
config:
action: variable
actionVariable: rewind
actionVariableValue: =(vars.rewind != undefined)?(( vars.rewind > 1 )?(vars.rewind - 1):1):(items[props.history].state -2)
iconColor: white
iconF7: backward_end
iconSize: '=(vars.rewind !== undefined ? ((vars.rewind > 1 )? 30 : 0):30)'
tooltip: Назад
visible: =(vars.archive == 2)
- component: oh-icon
config:
icon: "=(items[props.doorItem].state === 'ON') ? 'door-closed' : 'door'"
style:
color: "=(items[props.doorItem].state === 'ON') ? 'cyan' : 'red'"
z-index: 99
visible: =((props.doorItem !== undefined) && (vars.archive !== 2))
width: 30
- component: oh-button
config:
action: command
actionCommand: ON
actionItem: =props.lockItem
class: card-prevent-open
iconF7: "=(items[props.lockItem].state === 'ON') ? 'lock_open' : 'lock'"
iconSize: 30
style:
color: "=(items[props.lockItem].state === 'ON') ? 'white' : 'red'"
margin-left: auto
margin-right: auto
z-index: 99
visible: =((props.lockItem !== undefined) && (vars.archive !== 2))
- component: oh-icon
config:
icon: "=(items[props.motionItem].state === 'ON') ? 'mymotion-on' : 'mymotion-off'"
style:
z-index: 99
visible: =((props.motionItem !== undefined) && (vars.archive !== 2))
width: 30
- component: oh-button
config:
action: variable
actionVariable: rewind
actionVariableValue: =( vars.rewind < items[props.history].state - 1)?(vars.rewind + 1):(items[props.history].state - 1)
iconColor: white
iconF7: forward_end
iconSize: '=(vars.rewind !== undefined ? ((vars.rewind < items[props.history].state -1 )? 30 : 0):0)'
tooltip: Вперёд
visible: =(vars.archive == 2)
- component: oh-button
config:
iconColor: white
iconF7: clear
iconSize: 30
popoverClose: .popover.modal-in
style:
z-index: 99
tooltip: Закрыть
So what’s changed? Archive button visibility! So the widget accesses items[props.history].state before user can click to switch to archive, so when user actually switch to archive, that state is available already for oh-video!
@matt1 : When I click at the widget, the screen turns blurry. The small preview of the widget is fine and sharp. This is not only in edit mode; it’s always - also in run mode and in the app. Any idea what’s wrong here?
In the logs I find this message:
2022-08-21 22:46:49.013 [WARN ] [era.internal.handler.IpCameraHandler] - Binding has not been supplied with a FFmpeg Input URL, so some features will not work.
I also noted some “strange” options at the thing I never entered there:
When I use e.g. the JPG path in an image widget, everything looks good.
My camera is an INSTAR 9008 FullHD. Thanks!
Well, the binding has not been supplied with a FFmpeg Input URL, so some features will not work. =)
All options are ok, but does your camera has HLS-stream and is this stream enabled in Ipcamera binding? Do you see the stream, if you pass the URL from HLS-stream channel to videoplayer like VLC? If you don’t, could you check your camera with any tool like ONVIF Device Manager, get the camera’s stream URL from there and paste it to FFmpeg Input property of binding?
It may be a bug if it is happening only when you use in Masonry?
See here…
Expandable card is “blurry” when expanded in oh-masonry - Add-ons / UIs - openHAB Community
They are the DEFAULT settings which are needed for the binding to work, but the binding allows you to modify them if you choose to do something advanced.
If you have set it up as an INSTAR I would like to know why you get the WARN message you posted as ONVIF should discover the FFmeg input url automatically for you. To know what is going on I would need the TRACE level log from when the camera first connects and does its hand shake. Best to start a new thread on the forum for that. It may be that your firewall is blocking the ONVIF port so the binding can not connect.
Found a workaround for the blurring problem:
…which only works in the browser on my PC, but not in the app
did anyone get managed this to work on Android?
on my PC the widget works fine within the browser, and my cams are also working in the OH-app (Basic UI), but they showing just a grey block in the widget on Main UI.
I´ve read the topic, but didn´t find a solution.
Any idea?