JS Scripting: Storing an PNG into an image-item

Using OH3.4.1 on openHABian.

My use case is:

  1. generate some URL
  2. call that URL (via GET)
  3. save response in an image item
  4. display said image item in OH3-GUI

So for my Dynamic pricing, tibber hourly tariff => making "future" charts or similar? - #2 by Ap15e needs, I’m now at a point where I can put together an URL, which calls quickchart.io and there I’ll have an PNG generated, which I want to use. Because I don’t want to call the API over and over again and because I want to learn some new, I’d like to create the image daily and then access it over the day in an image-item.

So far I’ve gotten here using JS Scripting (ECMA-2021):

// generating the data, here only the output
var data = "16,14,14,14,14,17,24,27,26,25,24,24,23,23,24,25,25,27,28,26,25,24,22,18";

// header, in case it helps
const headers = new Map();
headers.set('Content-Type', "image/png;base64");
headers.set('Content-Transfer-Encoding', "base64");

// creating the URL and sending GET-Request
var quickchartURL = "https://quickchart.io/chart/render/sm-760d4a4b-751f-410a-89d8-28208435e98a?data1="+data;
var quickchartPNG = actions.HTTP.sendHttpGetRequest(quickchartURL, headers, 1000);

// putting the answer into the item
items.getItem("TIB_PricesFutureChart").postUpdate("data:image/png;base64,"+quickchartPNG);

but of course:

2023-01-12 15:17:00.250 [WARN ] [rnal.defaultscope.ScriptBusEventImpl] - State 'data:image/png;base64,�PNG

IHDRX,�_Z�;wIDATx���W˾��_�9�}ϝϽw�u׫��6��q�"D"JPq�3�8�F�8��[�lTpB���Lq
F�yW�g��
[...]
`�A#� � !A�!� FAA1��,G�1)�~END�B`�' cannot be parsed for item 'TIB_PricesFutureChart'.

but, it seems, I’m not getting the base64-encoded response, but the pure binary data from quickchart back. Do I have to somehow base64encode that - and how would I do that with HTTP-Actions?

Yes, that’s what I would expect.

Yes, the Image Item requires either a URL to an Image or the base64 encoded version of the Image, not the binary. So you’ll either need to:

  1. pass that URL to your Image Item but suffer the fact that the URL will get hit every time you refresh a page where the image is displayed

  2. convert the binary to Base64

  3. dump the binary to a png file in the conf/html/static folder and load it from there instead of an Image Item

  4. pull the image outside of OH through some external script driven by cron, or using executeCommandLine/Exec binding to use curl or wget to pull the image directly down into conf/html/static

Personally, I’d probably use 3 or 4 rather than messing with trying to do the base64 encoding. If you choose the encoding route, see Base64 (Java SE 11 & JDK 11 ) because I don’t think btoa() is available based on another thread (you should try it though in case I’m remembering incorrectly).

2 Likes

To add a 5th option:
Use the Image channel of the HTTP Binding:

Adjust parameters to your needs.

Thing is - the parameter are changing daily, so unless I can update the channel-parameters easily via JS Scripting rule, it’s not feasible. There’s an API for that: /things/{thingUID}/config, but no “easy” way to achieve that via rule-functions?

I went with that old-school way! :wink: