How to get a jpg file into an image item

  • Platform information:

############### openHABianDevice ############################################
###############################################################################
Ip = Unable to parse ip . Please debug.
Release = Raspbian GNU/Linux 10 (buster)
Kernel = Linux 5.10.17-v7l+
Platform = Raspberry Pi 4 Model B Rev 1.2
Uptime = 8 day(s). 23:9:57
CPU Usage = 7.71% avg over 4 cpu(s) (4 core(s) x 1 socket(s))
CPU Load = 1m: 0.49, 5m: 0.53, 15m: 0.45
Memory = Free: 2.20GB (58%), Used: 1.58GB (42%), Total: 3.78GB
Swap = Free: 1.99GB (100%), Used: 0.00GB (0%), Total: 1.99GB
Root = Free: 206.18GB (95%), Used: 10.14GB (5%), Total: 227.97GB

  • Issue of the topic:
    i want to store a jpg file from my ip-camera when motion is detect in an image item to display it in a sitemap.
    I use a rule for this and i can store the jpg from the ipcamera with wget on the raspi.
    ls -l /etc/openhab2/html/
    total 2288
    drwxr-xr-x 2 openhab openhab 4096 Apr 15 08:35 camera1
    -rw-rw-r-- 1 openhab openhab 451 Oct 26 08:38 index.html
    -rw-rw-r-- 1 openhab openhab 282 Oct 26 08:38 readme.txt
    -rw-r–r-- 1 openhabian openhab 843848 Apr 18 19:00 snapbase64.jpg
    -rw-r–r-- 1 openhabian openhab 844752 Apr 18 19:15 snapbase64.jpg.b64
    -rw-r–r-- 1 openhab openhab 633564 Apr 18 19:12 snap.jpg

With base64 i want to encode the jpg to a base64 file. When i execute the base64 command on the raspi it is working and i get the B64 file. When i use executeCommandline in the rule i only get an error message. see below code

When i try to store the B64 file either in a rawtype variable or in an item of type image i only get error messeages. I tried several variants but the error messages are nearly the same. see below

Item:

Image  Upcam1ImageJPG           "Upcam1 Image JPG"

rule including the log messages:

rule Upcam1_motion
when 
	Item Upcam1CellMotionAlarm received update 
then

    if (EnableLog_Upcam_Rules.state == ON) logInfo("Upcam1_motion_rule","Upcam1 motion: " + Upcam1CellMotionAlarm.state.toString)
    // only state ON should be persist

    if (Upcam1CellMotionAlarm.state == ON) 
    {
        var String eclResult = "none"
        Upcam1CellMotionAlarm.persist("influxdb")
        Upcam1LastMotionDateS.setState(Date.state)
        // create a snapshot
        //Upcam1UpdateImageNow.sendCommand("ON") 
        eclResult = executeCommandLine("wget http://guest:9zJtlNdSmSrPSy7@192.168.178.66/web/tmpfs/snap.jpg -O /etc/openhab2/html/snap.jpg" , 1000)
        if (EnableLog_Upcam_Rules.state == ON) logInfo("Upcam1_motion_rule","Upcam1 motion jpg holen: " + eclResult)

        eclResult = executeCommandLine("base64 --wrap=0 /etc/openhab2/html/snap.jpg > /etc/openhab2/html/snapbase64.jpg.b64" , 1000)
        if (EnableLog_Upcam_Rules.state == ON) logInfo("Upcam1_motion_rule","Upcam1 motion jpg in B64: " + eclResult)
//Log entry:->2021-04-18 20:04:15.148 [INFO ] [home.model.script.Upcam1_motion_rule] - Upcam1 motion jpg in B64: base64: extra operand ‘/etc/openhab2/html/snap.jpg’ Try 'base64 --help' for more information.

        var rawTypejpg = RawType.valueOf({url="http://ohsh:8080/static/snapbase64.jpg.b64"})
        var rawTypejpg =RawType.valueOf(url="http://ohsh:8080/static/snapbase64.jpg.b64")
        //if (EnableLog_Upcam_Rules.state == ON) logInfo("Upcam1_motion_rule","Upcam1 motion rawTypejpg: " + rawTypejpg.substring(0,100)) 

        Upcam1ImageJPG.postUpdate(url="http://ohsh:8080/static/snapbase64.jpg.b64")
        //Upcam1ImageJPG.postUpdate(rawTypejpg)
        if (EnableLog_Upcam_Rules.state == ON) logInfo("Upcam1_motion_rule","Upcam1 motion UpcamImageJPG update")


/*
Log entry for the var / postupdate lines:->
2021-04-18 19:12:47.722 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Upcam1_motion': 
An error occurred during the script execution: Couldn't invoke 'assignValueTo' for feature JvmVoid:  (eProxyURI: jmk_Upcam1.rules#|::0.2.0.2.0.1.1.0.7.7.0.0.0::0::/1)

2021-04-18 19:24:49.249 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Upcam1_motion': 
An error occurred during the script execution: Couldn't invoke 'assignValueTo' for feature JvmVoid:  (eProxyURI: jmk_Upcam1.rules#|::0.2.0.2.0.1.1.0.7.2.7.0.0.0::0::/1)

2021-04-18 20:02:49.523 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Upcam1_motion': 
An error occurred during the script execution: Couldn't invoke 'assignValueTo' for feature JvmVoid:  (eProxyURI: jmk_Upcam1.rules#|::0.2.0.2.0.1.1.0.7.2.7.0::0::/1)

2021-04-18 20:04:15.153 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Upcam1_motion': 
An error occurred during the script execution: Couldn't invoke 'assignValueTo' for feature JvmVoid:  (eProxyURI: jmk_Upcam1.rules#|::0.2.0.2.0.1.1.0.7.7.0::0::/1)
*/

    } 

end

Any hint what i am doing wrong and how to fix this problem are welcome

If the camera works with the IPCamera binding that would probably be your best bet for a simple and comprehensive solution. It can pull the image on demand (there’s a switch) or poll for it and it puts the image into an Item for you and it opens a service on a port where you can access the image or feed directly. It can even generate animated GIFs when motion is detected and stuff like that.

You don’t state which version of openHAB you are using. If it’s openHAB 3 your calls to executeCommandLine are not correct. See Actions | openHAB for details.

If it’s openHAB 2, add some logging to determine which line it’s failing on.
Other things I notice are all those url= in the calls to valueOf and postUpdate. They don’t make any sense.

First of all, an Image Item takes the base64 encoded image or a URL where OH can download the image itself. You are encoding the image as base64 yourself so the URL is irrelevant and not used.

Secondly, this isn’t Python. You can’t pass arguments to functions that way. You have to pass the expected arguments in the order they are expected. valueOf expects a single String as an argument, and that argument is not named “url”. The same goes for postUpdate. It can take either a String or a Command or a State. An in none of these cases are the arguments named “url”.

So, what get’s returned by an operation =, e.g. url="blah.blah.blah"? A void is what’s returned. So what you are doing is calling valueOf and postUpdate with void as the argument. void basically means “nothing”. It’s even more of a nothing than null is. You can’t do anything with void. You can’t even assign it to a variable or pass it as an argument.

have a look at this post: How to set the image content of an image item - #2 by Wolfgang_S
It does not explain how to do the base64 encoding but describes how the content of the item has to be ‘formatted’ using a base64 encoded image.
The encoded image including mime type needs to be stored in memory not the URL.

@Wolfgang_S: i know this post but was not able to translate it to my case. Good hint that the image needs to be in memory.
@rlkoshak: thanks for the comprehensive reply. I am running Openhab 2.5.12 (latest version) as for my production system i want to wait at least until 3.1 is released.
I am using the IPCamera binding e.g. for the motion event and also to display the jpg / livevideo in a sitemap. Unfortunatly i was not able to “freeze” an image when a motion event was raised.

The issue with the executeCommandLine is solved. The error message i got was a bit missleading, the issue was that there is not write access where the outputfile should be stored. I got the right error message from a trial with openssl and with the below command i get a base64 coded file.

eclResult = executeCommandLine("openssl base64 -in '/etc/openhab2/html/snap.jpg' -out '/etc/openhab2/misc/snapbase64.jpg'" , 1000)

If i got your and Wolfgang_s comments right i would need to read the base64 coded file into e.g. an array and use this array as “string” for the postUpdate of the image item. It looks like that there is no simple way to get an jpg file into an image item.
I also haven’t found a way to store an image from an IPCamera channel in an Image Item. This is what i use currently in a sitemap:

            Default item=Upcam1LastMotionDateS  //filled in the motion rule with the date/time when the event was raised
            Image                                   url="http://ohsh:8080/static/auto.jpg" visibility=[Upcam1ImageJPGupdate=="ON"]
            Text label="Bewegungsmelder groß"       icon="camera"   {Webview  url="http://ohsh:8080/static/snap.jpg" height=15}

            Switch item=Upcam1UpdateImageNow
            Text label="Aktueller Snapshot"         icon="camera"   {Image url="http://192.168.178.62:50003/ipcamera.jpg"}
            Text label="Mjpeg Stream"               icon="camera"   {Video url="http://192.168.178.62:50003/ipcamera.mjpeg" encoding="mjpeg"}   

and these are the items defined for the IPCamera binding

Switch Upcam1UpdateImageNow     "Upcam1 Image updates"                                          { channel="ipcamera:onvif:19216817866:image" }
String Upcam1RTSPStreamUrl      "Upcam1 RTSP Stream"                                            { channel="ipcamera:onvif:19216817866:rtspUrl" }
String Upcam1HlsStreamUrl       "Upcam1 HLS Stream"                                             { channel="ipcamera:onvif:19216817866:hlsUrl" }
String Upcam1ImageUrl           "Upcam1 Image Url"                                              { channel="ipcamera:onvif:19216817866:imageUrl" }

Switch Upcam1CellMotionAlarm    "Upcam1 Cell Motion detected"                                   { channel="ipcamera:onvif:19216817866:cellMotionAlarm" }
String Upcam1LastMotionDateS    "letzte Bewegung Eingang [%1$ta, %1$td.%1$tm.  %1$tH:%1$tM]"

Image  Upcam1ImageJPG           "Upcam1 Image JPG"
Switch Upcam1ImageJPGupdate                         //for internal use to manage the visibility of the image

Any hint how to store the jpg from the IPCamera channel in an Image Item are welcome.

best regards

When the Switch linked to the Motion Alarm Channel turns ON, send an ON command to the Switch Item linked to the Poll Image Channel. That will cause the binding to populate the Image Item linked to the Image Channel with the latest frame from the camera.

At least that appears to work for me.

Thanks, will test it tomorrow

Hello,

maybe I can finally help!

I was also looking a long time for a way to save an image from an ipcam by rule into an image item. After a long time of searching and testing, I now have the following solution working:

import java.util.Base64
import java.io.ByteArrayOutputStream
import java.net.URL

rule "Image Test"
when
	Item TestImageSwitch received command ON
then	
	var userImageDataBytes = newByteArrayOfSize(0)
	var url = new URL("http://cam01.home/mjpeg/snap.cgi?chn=0")
	var byteStreamOutput = new ByteArrayOutputStream()
	var urlConnection = url.openConnection()
	urlConnection.setRequestProperty("Authorization", "Basic YWRtaW46MTIzNDU2")
	var inputStream = urlConnection.getInputStream()
	var n = 0
	var buffer = newByteArrayOfSize(1024)
	do {
		n = inputStream.read(buffer)
		if (n > 0)  {
		byteStreamOutput.write(buffer, 0, n)
		}
	} while (n > 0)
	userImageDataBytes = byteStreamOutput.toByteArray()
	//var rawType = new RawType(userImageDataBytes, "image/jpeg")
	//TestImage.postUpdate(rawType)
	var String encodedString = Base64.getMimeEncoder().encodeToString(userImageDataBytes).replaceAll("\\r\\n", "")
	var ImageTMP = "data:image/jpg;base64," + encodedString
	//logInfo("IamgeTest",StringUtils.substring(encodedString, 0, 2000))
	TestImage.postUpdate(ImageTMP)	
end

I think you can easily modify the rule for your request :slight_smile:

Just a warning: you just posted the credentials for your camera to a public forum. Perhaps isn’t a huge deal if it’s only accessible from your LAN, but still I would recommend to change the password and remove it from this post. (unless you have thought of that and posted a fake auth-string, otherwise you have a really bad password :wink:)

The last part is the answer :wink:

1 Like

Hello,
this looks really good an i will test it during the weekend

At the point when you save a picture in an alternate document design, you may lose some quality because of the restrictions of the new record type!

@Bloodboy : your code works for me as well and solved my problem. My challange was to identiy that user+password has to be base64 encode, but this is due to my low experience with java.
This solution is fast if your jpg input is not to big, if you have e.g. a HD-jpg it takes more then 2 sec for the do-while part.
@Virgil6 : could you pls. elaborate your statement and give an example
@rlkoshak : i will test you proposal in my openhab3 test environment
Thanks to all for the support

I do a time lapse of the weather so I generate a jpg image every minute and I send this image via MQTT to OH3 and display it in an oh-image-card.

The image is displayed on my overview page and it refreshes every minute.
I don’t convert to base64 as it “just works”
Here is the mosquito code:

mosquitto_pub -h 192.168.0.164 -t raw/weatherimage -f image.jpg

image

The image is about 92kb.
Here is what it looks like in the item view: