OH3: Image card in MainUI - How to refresh image?

I’m trying to get auto-refresh of an image in Main UI (Image card) working.

In OH2 sitemap I used:

Image refresh=60000 url=""

I managed to get the chart displayed in Main UI with the Image card/widget.
However, it does not refresh automatically.

The image card states: “Image item to show - preferred if the image changes”
Image card

I created the a string item “urltestitem” which holds the URL:

Since I couldn’t find the refresh cycle to be configured in the image card, I used the following rule to update the item every minute:

rule "URL Test"
    Time cron "0 * * ? * * *"

I also tried:


It seems as if the above does not trigger the image card to refresh the image - probably because the string (URL) doesn’t change.
The image in the card gets only updated when I change the string (URL) manually (e.g. now-6h -> 12h).

I wonder:

  • Is there a (simple) way to add the refresh function to the card - e.g. YAML code?
  • What have I done wrong in the rule above?


I’m sorry I can’t exactly answer your question but I saw that you are trying to get a rendered image from grafana.
Have you ever thought about embedding the panel as an iFrame and then specifiying the refresh interval by adding &refresh=5s to the URL?
That way you prevent a reload and the iframe will pull the data without refreshing.

I just wanted to leave this here in case it is useful to you - it took me a long time before I found out that was an easy way…

1 Like

Currently not

Nothing - the rule itself works as intended but as you already assumed, the image isn’t refreshing due to the fact that the link doesn’t change.

I would go with iFrame soloution that @BobMiles proposed, as it’s fits best for your usecase.

Is there a plan to add that functionality?

How do you embed an iFrame?
I tried with URL in Web Frame card, but that is not the same as iFrame, is it?
My observation was that I could not just grab the chart, there was lots of stuff around (header, return button, etc.)

The Web Frame Card is right.
You can just embed the chart - make sure you get the URL in grafana by clicking on the chart context menu and select share - embed. The chart title has to be empty if you don’t want that to be on it.
Maybe you could post a screenshot of what you currently have and I can assist further.

Nothing I can say for sure tbh - but at least it sounds like a doable enhancement IMHO. If this is something that would bring a benefit for you (besides the fact that you can use the iFrame soloution in your case) and others, it’s worth opening a github enhancement issue here, I think.

I’d be grateful for any further assistance in this matter.

Appearance of the rendered image in Image card:

I’m quite pleased with the appearance of the rendered image. I just miss the ability to change the period of the time series ( e.g. now-24h -> now).

Appearance of the frame in Web frame card:

Green marked part:
The big plus with the frame is the part marked green - these are meaningful controls for the chart allowing the changes I miss by using the rendered image.

Red marked parts:
Other users (family members) might get confused when they click anywhere in the red parts. I don’t even want anyone to be able to browse the dashboard or start sharing.
Can this be removed somehow?

Blue marked area:
Irrespective of the hight I assign to the frame, there is a quite large unused area at the bottom of the frame.
Can this be removed somehow?

Never done anything in github before … let’s see


you have embedded the dashboard URL. You have to click the panel (chart) menu (it is even displayed on your screenshot) and select share. There you will find a tab “embed” where you will find the correct URL. Just exchange the &from and &to time ranges in the URL to your liking.
Maybe you can even construct the URL string with a dynamic time range, but let’s first get you going with the embedding!

Well, so easy. Thank you so much for guiding me that way.


Select time ranges or dynamic time range:

How would you approach this?

In OH2 I used the visibility function to select the desired time range by switching between different URLs of the rendered charts containing:

  • “from=now-6h&to=now”
  • “from=now-12h&to=now”
  • “from=now-1d&to=now”
  • “from=now-7d&to=now”
  • “from=now-30d&to=now”

The embedding works so well - no need to open an enhancement issue for the image card.
Thanks a lot.

1 Like

That’s looking good!

I would say you could use a String item that has different options to choose from.

For example:
My_Sting_Item with options:

  • 6h
  • 10d
  • 1M

and so on…

And then instead of the plain URL you split it exactly where that string part goes (i.e. behind from=…)

So it would look like:

src: 'http://grafana.superpanel&options&from=' + '=(items.My_String_Item.state)' + '&to=now&refresh=30s'

In order to test the logic, I tried to split the existing URL string (for now without item):

  src: '' + '6h' + '&to=now&panelId=2'

Entered this to the YAML code:

component: oh-webframe-card
  title: PV Leistung vs. Verbrauch Haus
  borders: false
  noBorder: false
  outline: true
  src: '' + '6h' + '&to=now&panelId=2'

Getting the following errors:
web frame url string

Did I miss anything?

Hmmm maybe the concatenation works different, could you try & instead of +?

Doesn’t work.
Have now 3 error messages, whereas the second one above (Implicit map keys…) comes up twice.

Works now with “+” !
The “=” was missing before the string.

  src: =''
    + '12h' + '&to=now&panelId=2'

Will get to work on the string item next - probably tomorrow - let’s see.

1 Like

I almost got there…

Steps done:

  1. String item created: “test_time_range”

  2. List item added to UI with dynamic title to immediately show the selected option:
    list item for UI

component: oh-list-item
  title: =(items.test_time_range.state)
  icon: oh:graph
  action: options
  actionOptions: 6h=6 Std,12h=12 Std,1d=1 Tag,7d=7 Tage,30d=30 Tage
  actionItem: test_time_range
  1. Composing the url:
='' + '=(items.test_time_range.state)' + '&to=now&panelId=2'

gives the following result:

The expression “=(items.test_time_range.state)” itself is added as a string instead of the resulting string of the item state.

Going without apostrophs:

='' + =(items.test_time_range.state) + '&to=now&panelId=2'

result in an error message:
“Error: Expected expression after + at character 91”

Do you know how to get around that one?

This isn’t a valid expression - you don’t need the second = to get the item-state. Try:

"='' + items.test_time_range.state + '&to=now&panelId=2'"

That made the trick !
Thanks a lot !

Here the result of the exercise:

Is there a smart way to get “buttons” to select the time range somewhere in the green marked spaces?
… or any other smart way to place buttons nicely next to each other in a card or a cell?
… in a way what “mapping” did in OH2?

This is also a good use case for the oh-repeater and the f7-segmented/oh-button combination with a variable.

component: f7-card
    - component: f7-card-content
          - component: f7-segmented
              round: true
              outline: true
                - component: oh-repeater
                    fragment: true
                    for: period
                      - value: 6h
                        label: 6 Std
                      - value: 12h
                        label: 12 Std
                      - value: 1d
                        label: 1 Tag
                      - value: 7d
                        label: 7 Tage
                      - value: 30d
                        label: 30 Tage
                      - component: oh-button
                          text: =loop.period.label
                          fill: =vars.selectedPeriod === loop.period.value
                          round: true
                          outline: true
                          action: variable
                          actionVariable: selectedPeriod
                          actionVariableValue: =loop.period.value
          - component: oh-webframe-card
              visible: =vars.selectedPeriod != undefined
              src: ='' + vars.selectedPeriod + '&to=now&panelId=2'


No item needed, if you don’t mind having your period uninitialized before you select it.
That said, you can initialize it at the page level, with

  - selectedPeriod: 6h  

in the page config (not possible at the widget level).