Get image data from image item in script

I have an image item that gets an image from MQTT. I can see the image in the model. I’m trying to get this image data or image file in a rule ECMAScript-2021 script.

var item = item || items.getItem('MQTTEventItem_Image')
console.log(`Image: ${item.state}.`)

// Image: raw type (image/jpeg): 10458 bytes.

It is aware of certain things (mime type, image size), but I can’t figure out how to get them. I’ve tried the getMimeType() and toFullString() as documented here but they result in method not found errors.

How can I get the file or the binary contents so I can script further behavior?

(By the way, btoa() and atob() seem to be unavailable in openhab-js. This will probably be my next problem.)

Reviewing the JS Scripting reference docs shows that Item.state returns a String. You want the Item.rawState to access the original Java State Object. JavaScript Scripting - Automation | openHAB

You may have to import and use the Java Classes to do this.

1 Like

How could I have missed this? Awesome, thank you! :+1:

Can I send this binary data using HTTP.sendHttpPostRequest?

I’m trying to send the image data to Matrix/Synapse. I’m using the following command, and as long as the payload is an ASCII string, the upload itself works fine and the base64 string arrives at the server.

var headers = new Map()
headers.set('Content-Length', String(payload.length))

var result = HTTP.sendHttpPostRequest(apiUrl, mimeType, payload, headers, 3000)
console.log(result)

However, Synapse doesn’t recognize base64 encoded data. It wants binary data. How can I send binary data? I have tried the following:

  • Sending item.rawState.getBytes() as payload directly, both as is and escape()ed.

  • Getting the payload from the base64 string as below, sending it both directly and escape()ed:

var dataStr = item.rawState.toFullString().replace('data:image/jpeg;base64,', '')
var Base64 = Java.type('java.util.Base64')
var dec64 = Base64.getDecoder()
var payload = dec64.decode(dataStr)

I have created the following workaround. Not pretty, but sharing since I know of no native way and it may be useful to others.

var result = actions.Exec.executeCommandLine(
  Duration.ofSeconds(3), 
  '/bin/sh', '-c', 
  `echo "${dataStr}" | base64 -d | curl -s -H "Content-Type: ${mimeType}" -H "Content-Length: ${dataLen}" --data-binary @- "${apiUrl}"`)

I used a slightly different set of command line tools, but back when I was saving off images to file, I used executeCommandLine too to convert the Base64 to a binary png file.