Jython java ssl error when using pyunifi

  • Platform information:
    • Hardware: Pi3B+
    • OS: Raspbian GNU/Linux 9 (stretch)
    • Java Runtime Environment: openjdk version “1.8.0_242”
    • openHAB version: 2.5.3 Release Build

I am trying to use pyunifi in a rule in order for me to see whether anyone has joined the guest network (and therefore whether I have guests in the house).

Setup

I have added the path to the python2.7 dist-packages into the EXTRA_JAVA_OPTS as follows:

sudo nano /etc/default/openhab2

then added -Dpython.path=/usr/local/lib/python2.7/dist-packages to the end of EXTRA_JAVA_OPTS so it ends up looking like:

EXTRA_JAVA_OPTS="-Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0:/dev/ttyS0:/dev/ttyS2:/dev/ttyACM0:/dev/ttyAMA0 -Dpython.path=/usr/local/lib/python2.7/dist-packages"

Rule

My rule is as follows (triggered by a test switch for now):

from core.rules import rule
from core.triggers import when
from pyunifi.controller import Controller

@rule("Get Wifi clients", description="See if there are any guests on the wifi")
#@when("Time cron 0 */5 * ? * *")
@when("Item sStartupSwitch changed to ON")
def get_wifi_guest_status(event):
    c = Controller('192.168.1.116', 'admin', 'password', ssl_verify=False)
    wifi_clients = str(c.get_clients())

    if("'is_guest': True" in wifi_clients):
        get_wifi_guest_status.log.info("Guests on wifi")
    else:
        get_wifi_guest_status.log.info("No guests on wifi")

I’ve switched ssl verification off because I haven’t setup an ssl certificate on my device with the controller software.

Logs

23:42:37.806 [ERROR] [jsr223.jython.Get Wifi clients       ] - Traceback (most recent call last):
  File "/etc/openhab2/automation/lib/python/core/log.py", line 51, in wrapper
    return fn(*args, **kwargs)
  File "<script>", line 9, in get_wifi_guest_status
  File "/usr/local/lib/python2.7/dist-packages/pyunifi/controller.py", line 113, in __init__
    self._login()
  File "/usr/local/lib/python2.7/dist-packages/pyunifi/controller.py", line 161, in _login
    r = self.session.post(login_url, json=params)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 578, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 530, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 643, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
SSLError: HTTPSConnectionPool(host='192.168.1.116', port=8443): Max retries exceeded with url: /api/login (Caused by SSLError(SSLError(1, u'General SSLEngine problem (javax.net.ssl.SSLHandshakeException: General SSLEngine problem)'),))

23:42:37.818 [ERROR] [re.automation.internal.RuleEngineImpl] - Failed to execute rule '1e44517b-af42-42b2-9d9b-9b32b31c9653': Fail to execute action: 1
23:42:37.823 [DEBUG] [re.automation.internal.RuleEngineImpl] - 
java.lang.RuntimeException: Fail to execute action: 1
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1197) ~[bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.runRule(RuleEngineImpl.java:993) [bundleFile:?]
	at org.openhab.core.automation.internal.TriggerHandlerCallbackImpl$TriggerData.run(TriggerHandlerCallbackImpl.java:91) [bundleFile:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_242]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_242]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_242]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_242]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_242]
Caused by: org.python.core.PyException
	at org.python.core.Py.AttributeError(Py.java:205) ~[?:?]
	at org.python.core.PyObject.noAttributeError(PyObject.java:1013) ~[?:?]
	at org.python.core.PyObject.__getattr__(PyObject.java:1008) ~[?:?]
	at core.rules$py.execute$6(/etc/openhab2/automation/lib/python/core/rules.py:110) ~[?:?]
	at core.rules$py.call_function(/etc/openhab2/automation/lib/python/core/rules.py) ~[?:?]
	at org.python.core.PyTableCode.call(PyTableCode.java:167) ~[?:?]
	at org.python.core.PyBaseCode.call(PyBaseCode.java:307) ~[?:?]
	at org.python.core.PyBaseCode.call(PyBaseCode.java:198) ~[?:?]
	at org.python.core.PyFunction.__call__(PyFunction.java:482) ~[?:?]
	at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237) ~[?:?]
	at org.python.core.PyMethod.__call__(PyMethod.java:228) ~[?:?]
	at org.python.core.PyMethod.__call__(PyMethod.java:218) ~[?:?]
	at org.python.core.PyMethod.__call__(PyMethod.java:213) ~[?:?]
	at org.python.core.PyObject._jcallexc(PyObject.java:3626) ~[?:?]
	at org.python.core.PyObject._jcall(PyObject.java:3658) ~[?:?]
	at org.python.proxies.core.rules$_FunctionRule$16.execute(Unknown Source) ~[?:?]
	at org.openhab.core.automation.module.script.rulesupport.shared.simple.SimpleRuleActionHandlerDelegate.execute(SimpleRuleActionHandlerDelegate.java:34) ~[?:?]
	at org.openhab.core.automation.module.script.rulesupport.internal.delegates.SimpleActionHandlerDelegate.execute(SimpleActionHandlerDelegate.java:59) ~[?:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1189) ~[bundleFile:?]
	... 7 more

Is this something to do with the fact I’m trying to use this python module in jython, and therefore something funky is going on, or is there a simple solution? Kinda stumped at the moment!

If that app is checking the validity of the default ssl certificate it will fail. Is that app Python 2 compatible?

As I wrote, I’ve set the option for the app not to use SSL verification.

It is python2 compatible - it’s installed by pip into the python2.7 dist-packages folder.

Edit: to be clear, I can run all of the pyunifi code successfully through the python console on the same device. Just have this problem when running it from an OpenHAB. rule.

Any reason not to use the unifi binding?

The binding, as I understand it, won’t provide a list of clients connected to the network - you have to define them yourself.

I want to know what new unknown clients have connected, not whether ones that I already know about (and therefore defined in items) have connected.

EDIT: The binding which comes through OpenHAB does not have that feature, but unpublished snapshot versions do. For anyone else who stumbles across this:

1 Like

I take it you’re using the beta Jython add-on?

I’ll take a look at this later tonight…

Yes, correct. It’s been working brilliantly otherwise - great work!

  1. Have you tried this using the openhab account?
  2. Can you successfully run it using the Jython console running as the openhab account?

The console is different than when running through a javax.script.ScriptEngine though, so even if it works in the console, it may not work in OH. This package makes heavy use of requests, which has caused trouble for others too. It will be interesting to see if Jython 2.7.2 might help things (an update for the beta addon is on its way).

I have not on both counts, I’ll give it a go. Can you give pointers to the jython console - I’ve never used it…!

It’s just like the Python console… but Jython :wink:!

It’s easiest to use it with a full install of Jython, so start there. Jython is included in most Linux distros too.

I do not have a UniFi device, or I’d test this out myself.

No problem - I appreciate the help!

On the topic of running commands as the openhab user, that seems to work:

pi@raspberrypi:~ $ sudo -u openhab python
Python 2.7.13 (default, Sep 26 2018, 18:42:22) 
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from pyunifi.controller import Controller
>>> c = Controller('192.168.1.73', 'admin', 'password', ssl_verify=False)
/usr/local/lib/python2.7/dist-packages/urllib3/connectionpool.py:986: InsecureRequestWarning: Unverified HTTPS request is being made to host '192.168.1.73'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning,
>>> wifi_clients = str(c.get_clients())
>>> "'is_guest': True" in wifi_clients
False
>>> 

I’ll get onto the Jython in a bit. As you mention, I looks like I can sudo apt install jython on my distro, but it requires pulling 136 new packages. Just to double check - if I install this I won’t mess anything up related to openHAB and its jython stuff (as you can tell, I don’t know much about the connections!)?

It is safe to have separate Jython installs. OH won’t know anything about it, so there won’t be any conflict.

Right, so I have Jython 2.5.3 (, Jun 21 2017, 18:15:51)

Once in the console, I have appended the dist-packages as confirmed below:

>>> sys.path.append("/usr/local/lib/python2.7/dist-packages")
>>> sys.path
['', '/usr/lib/site-python', '/usr/share/jython/Lib', '__classpath__', '__pyclasspath__/', '/usr/share/jython/Lib/site-packages', '/usr/local/lib/python2.7/dist-packages']

Then, trying to import the pyunifi module I get the following error:

>>> from pyunifi.controller import Controller
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pyunifi/controller.py", line 27
    APIError) as err:
             ^
SyntaxError: mismatched input 'as' expecting COLON

Have I just tried to import python into java, and that’s why it’s not working, or is it more nuanced than that?

You will need at least Jython 2.7.0, which is also what is in the beta addon ATM.

Ah, balls. 2.5.3 is what comes from apt install on Raspbian Stretch. OK, I’ll manually install and update this post with results.

EDIT:
@5iver - success, looks like that seems to work with jython run as an openHAB user. Below the details:

Installing Jython

pi@raspberrypi:~ $ wget https://repo1.maven.org/maven2/org/python/jython-installer/2.7.2/jython-installer-2.7.2.jar
--2020-06-08 14:47:36--  https://repo1.maven.org/maven2/org/python/jython-installer/2.7.2/jython-installer-2.7.2.jar
Resolving repo1.maven.org (repo1.maven.org)... 151.101.60.209
Connecting to repo1.maven.org (repo1.maven.org)|151.101.60.209|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 80153928 (76M) [application/java-archive]
Saving to: ‘jython-installer-2.7.2.jar’

jython-installer-2.7.2.jar              100%[=============================================================================>]  76.44M  2.52MB/s    in 28s     

2020-06-08 14:48:05 (2.72 MB/s) - ‘jython-installer-2.7.2.jar’ saved [80153928/80153928]

pi@raspberrypi:~ $ java -jar jython-installer-2.7.2.jar --console
Welcome to Jython !
You are about to install Jython version 2.7.2
(at any time, answer c to cancel the installation)
For the installation process, the following languages are available: English, German
Please select your language [E/g] >>> E
Do you want to read the license agreement now ? [y/N] >>> N
Do you accept the license agreement ? [Y/n] >>> Y
The following installation types are available:
  1. All (everything, including sources)
  2. Standard (core, library modules, demos and examples, documentation)
  3. Minimum (core)
  9. Standalone (a single, executable .jar)
Please select the installation type [ 1 /2/3/9] >>> 2
Do you want to install additional parts ? [y/N] >>> N
Do you want to exclude parts from the installation ? [y/N] >>> N
Please enter the target directory >>> jython
Unable to find directory /home/pi/jython, create it ? [Y/n] >>> Y
Your java version to start Jython is: Raspbian / 1.8.0_252
Your operating system version is: Linux / 4.19.66-v7+
Summary:
  - mod: true
  - demo: true
  - doc: true
  - src: false
  - ensurepip: true
  - JRE: /usr/lib/jvm/java-8-openjdk-armhf/jre
Please confirm copying of files to directory /home/pi/jython [Y/n] >>> Y
 10 %
 20 %
 30 %
 40 %
 50 %
 60 %
 70 %
Generating start scripts ...
Installing pip and setuptools
 90 %
DEPRECATION: A future version of pip will drop support for Python 2.7.
Looking in links: /tmp/tmpyxIbXx
Collecting setuptools
Collecting pip
Installing collected packages: setuptools, pip
Successfully installed pip-19.1 setuptools-41.0.1
 100 %
Do you want to show the contents of README ? [y/N] >>> N
Congratulations! You successfully installed Jython 2.7.2 to directory /home/pi/jython.

Running Jython console

pi@raspberrypi:~ $ cd jython/
pi@raspberrypi:~/jython $ sudo -u openhab java -jar jython.jar
org.python.package WARNING invalid index file
org.python.package WARNING failed to write cache for '/home/pi/jython/jython.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/resources.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/rt.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/jsse.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/jce.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/charsets.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/dnsns.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/sunpkcs11.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/sunec.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/localedata.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/jaccess.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/nashorn.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/java-atk-wrapper.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/icedtea-sound.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/cldrdata.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/zipfs.jar' (Permission denied)
org.python.package WARNING failed to write cache for '/usr/lib/jvm/java-8-openjdk-armhf/jre/lib/ext/sunjce_provider.jar' (Permission denied)
org.python.package WARNING failed to write index file (/home/pi/jython/.jython_cache/packages/packages.idx (Permission denied))
Jython 2.7.2 (v2.7.2:925a3cc3b49d, Mar 21 2020, 10:03:58)
[OpenJDK Client VM (Raspbian)] on java1.8.0_252
Type "help", "copyright", "credits" or "license" for more information.
>>>

Appending dist-packages path

>>> import sys
>>> sys.path
['', '/home/pi/jython/Lib', '__classpath__', '__pyclasspath__/', '/home/pi/jython/Lib/site-packages']
>>> sys.path.append("/usr/local/lib/python2.7/dist-packages")
>>> sys.path
['', '/home/pi/jython/Lib', '__classpath__', '__pyclasspath__/', '/home/pi/jython/Lib/site-packages', '/usr/local/lib/python2.7/dist-packages']

Detecting wifi clients

>>> from pyunifi.controller import Controller
>>> c = Controller('192.168.1.73', 'admin', 'password', ssl_verify=False)
/usr/local/lib/python2.7/dist-packages/urllib3/connectionpool.py:979: InsecureRequestWarning: Unverified HTTPS request is being made to host '192.168.1.73'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  warnings.warn(
>>> wifi_clients = str(c.get_clients())
>>> "'is_guest': True" in wifi_clients
False

Notes:
1: I currently don’t have any clients connected to the guest network, so I expect a False return.
2: After committing the line from pyunifi.controller import Controller, it takes about 15 seconds before the prompt allows me to continue.

Hopefully, Jython 2.7.2 was the fix. To test, you could remove the beta Jython addon and do a manual install of it and the helper libraries, or wait for me to update the addon. You could test the other way around too, by installing Jython 2.7.0 and trying it in the console.

Remember, Jython in the console and inside OH are not the same things. But worst case, you’d be able to call a Jython or Python script through executeCommandLine to run a script that uses the pyunifi package.

1 Like

I’m happy to wait for the updated addon, no worries!

It would be a shame to do that, what with all the python goodness available with your work, but indeed that is an option if the updated bundle doesn’t work out. Fingers crossed!

I meant something different… from a Jython script, you can call executeComandLine to call any other script that can run from a terminal. So, you will still have scripted automation, Jython, and the helper libraries, but you can call Python3 scripts from inside them.