Encoding problems with python rule in OH3

Hi, I’m running the latest version of OH3 on Docker.
Migration has not been painless but I was doing fine till yesterday.

I have a rule that is triggered by a sensor state change.
Step 1 : I want to take a snapshot with a cctv cam
Step 2 : I will send the image to another application running on docker.
Step 3 : I will receive results in JSON format.

This is what I have so far:

# imports
from org.slf4j import LoggerFactory
import urllib2
import urllib
import base64

# Start The logger
log = LoggerFactory.getLogger("org.openhab.core.automation.examples")

#take a snapshot
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, "http://192.168.1.99/ISAPI/Streaming/channels/1/picture", "username", "password")
authhandler = urllib2.HTTPDigestAuthHandler(passman)
opener = urllib2.build_opener(authhandler)
res = opener.open("http://192.168.1.99/ISAPI/Streaming/channels/1/picture")

pic = base64.b64encode(res.read())

#(I have saved this "pic" to a file and tested it. I get an base64 encoded image)

#Get the plate 
url = 'http://platerecognizer:8080/v1/plate-reader/'
values = {'regions' : 'gr','regions' : 'de','upload': pic}
data = urllib.urlencode(values)
req = urllib2.Request(url)
req.add_data(data)

import socket
# timeout in seconds
timeout = 10
socket.setdefaulttimeout(timeout)

log.info("start0")

z = urllib2.urlopen(req)    #<---this is where it all goes to hell...

log.info("stop0")

log.info(str(z.read()))

z = urllib2.urlopen(req)
this is where the problem is, but it is cause by the pic variable

when I try to upload any sting I get a response from the server
{“error”: “base64 content could not be decoded.”}
when I use the variable “pic” the connections just hangs forever without a timeout.

the exact same code works in a simple python script…
my bet is that something is going wrong with the encoding since I had a lot of problems getting this far, (something to do with ascci and utf-8 and java or python2 not liking one of them or something)
I’ve been at it for hours but I’m genuinely stuck. any help would be appreciated

Running with what version of Python?

By default Python 2 uses ASCII. Java by default uses UTF-8. Sometimes you’ll have a String from Java in UTF-8 that you want to compare to an ASCII String , or visa versa. But you are working wholly within Python here so encoding differences shouldn’t be a problem.

Is there a reason why you are not using the sendHttpXRequest Actions? They are way easier to use than urllib.

I can’t say what is wrong but I doubt it’s the text encoding itself.

I’m running it with python 2.7.17, if I’m not mistaken openhab comes with python 2.7.2
I have never used the sendHttpXRequest Actions, since I am more familiar with python I thought it would be easier…
From what I found I need to do

from core.actions import HTTP
HTTP.sendHttpPutRequest("someURL.example.com, "application/json", '{"this": "that"}')

but the I get ImportError: No module named core…
how would I approach the post request?

If I do it from the start as a DSL rule, I cannot find anything on doing the digest authentication with the ipcam with an HTTP Action

I’m not sure. It used to mostly work with 2.7.0 and there was a problem with the later point releases, but I’ve not followed what version is installed with the add-on.

One thing to realize is you will never get away from having to to deal with openHAB stuff if writing openHAB rules. And when dealing with openHAB stuff, you will be dealing with Java Objects, not Python. And with no exceptions I can think of, working with what openHAB provides is going to be easier than trying to muddle through using the native Python way to do things. So as long as you stick with running the rules on openHAB itself, you would do well to figure out if openHAB provides a way to do something before redoing it yourself.

That code is using the Helper Libraries. If you want to use Python as your rules language, you should be using the Helper Libraries. It does a whole lot to make that interface between Python and openHAB itself much easier to deal with.

But, if you don’t want to use the Helper Libraries, you just need to import HTTP from it’s Java source directly instead of indirectly through core.actions.

from org.openhab.core.model.script.actions import HTTP

Well, for one you’d use sendHttpPostRequest instead of sendHttpPutRequest.

Note, no matter what language you are writing rules in, the openHAB Actions like sendHttpPutRequest are the same. You are interacting with a Java Object in all cases.

My understanding of these things is that the digest is just a header field. So you’ll need to create a java.util.HashMap<String, String> that lists all the required header entries and pass that map as an argument to the call to the action. I think that Jython is smart enough to convert between java.util.Map and Python dicts so I’d try it with a dict first.

I can’t tell you how to build the header but I’m certain there is a standard way to do such things and there are tons of posts online.

Finally, if your really do want to stay in Python and only Python, look at HABApp. This is a separate service that runs along side of openHAB and lets you write rules in pure Python 3. It interacts with openHAB through openHAB’s REST API so there are a some limitations but lots of users seem happy with it.

I am aware of that, as I said, I am more familiar with python so I just got a bit stubborn thats all :wink:

I been using openhab for over two years now so, I just thought to try something new. I have the same rule working in OH2 but I use the “executeCommandLine”, so I wanted to make it a bit more elegant.

:stuck_out_tongue:

I’m thinking I’ll be better off sticking to DSL rules as I know and love them and start playing around with ECMAScript instead of python. I think I have enough to start looking in the right direction of how to get it working :smile: (tomorrow) Thanks!