Script to backup/restore Thing labels and locations in Paper UI

I wasted a lot of time after Openhab updates and when testing experimental addons with deleting and re-adding Things and setting the label and location again on every single Thing. So I took the time and wrote two Python scripts to backup and restore the label and location for every Thing. With those scripts I now only have to delete and re-add the things in PaperUI. After that I can restore the label and location automatically. Maybe I will later also write a script that also automatically deletes and re-adds the Things.

Here are the two scripts:

BackupThingInfo.py

#!/usr/bin/python3

import requests
import json
import csv
from operator import itemgetter

baseUrl = "http://172.17.2.21:8080/rest/things/"

response = requests.get(baseUrl)
thingInfos = response.json()

thingInfos.sort(key=itemgetter("UID"))

with open("ThingsBackup.csv", "w", newline='', encoding="utf8") as csvFile:
    csvWriter = csv.writer(csvFile, delimiter=",",quotechar='"',quoting=csv.QUOTE_MINIMAL)
    csvWriter.writerow(["ThingUid","Label","Location"])
    for thingInfo in thingInfos:
        thingUID = thingInfo.get("UID")
        thingLabel = thingInfo.get("label")
        thingLocation = thingInfo.get("location")

        if thingLocation == None:
            thingLocation = ""
        
        csvWriter.writerow([thingUID, thingLabel, thingLocation])

RestoreThingInfo.py:

#!/usr/bin/python3

import requests
import json
import csv
from time import sleep

baseUrl = "http://172.17.2.21:8080/rest/things/"

with open("ThingsBackup.csv","r", encoding="utf8") as csvFile:
    next(csvFile) # skip headings
    csvReader=csv.reader(csvFile,delimiter=",",quotechar='"')
    for thingUid,label,location in csvReader:
        url = baseUrl + thingUid
        payload = {"label": label, "location": location}
        headers = {"content-type": "application/json"}

        response = requests.put(url, data=json.dumps(payload), headers=headers)

        if response.status_code == 200:
            sleep(1)
            response = requests.get(url)
            thingInfo = response.json()
            thingLabel = thingInfo.get("label")
            thingLocation = thingInfo.get("location")

            if thingLabel == label and thingLocation == location:
                print("Thing {} updated, label: {} location: {}"
                    .format(thingUid, thingLabel, thingLocation))
            else:
                print("Error Thing {} not updated, label: {} location: {}"
                    .format(thingUid, label, location))
        else:
            print("Error {} updating Thing {} label: {} location: {}"
                .format(response.status_code, thingUid, label, location))
3 Likes

When I migrated to Jython, I did the Zwave delete/readd rule that I’d posted, so I just added it to the openhab2-jython repo. We should combine them!

1 Like

I don’t know the Jython rules yet. Is it possible to use every Python module in those rules? Also I wrote my script for Python 3 and as far as I understand Jython only supports Python 2.

You can use the standalone Jython or a full install. Currently, the official release of Jython is 2.7.1, so Python 3 modules won’t work. I’m pretty sure the 2.x versions of the modules you are using will all work though.

You can run executeCommandLine though, so in a way, everything is supported!

I’ve just did some experiments with Jython in Openhab and I did get my first rules to fire. To do a practical example I now tried to implement a script I wrote for my Onkyo receiver, but I’m getting a module error and I don’t find out how to solve it.

The script uses the onkyo-eiscp Python module and this seams to trigger a module error. I’ve managed to configure a lib path in the EXTRA_JAVA_OPTS that Jython finds the eiscp module:
-Dpython.path=/etc/openhab2/automation/lib/python:/usr/local/lib/python2.7/dist-packages

But now I’m getting a different error:
ImportError: No module named netifaces in at line number 4

But netifaces is also installed under /usr/local/lib/python2.7/dist-packages, but it is a c library. Can Jython also use those c libraries somehow or it this a known limitation?

I haven’t tried many modules that aren’t builtin. You may want to try asking in the openhab-scripter GH repo. Send me a link to the module and your full EXTRA_JAVA_OPTS and I will test. But it looks like this is a classpath issue.

Those are my EXTRA_JAVA_OPTS:

EXTRA_JAVA_OPTS="-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=172.17.2.21
-Dcom.sun.management.jmxremote.rmi.port=9010
-Xdebug
-Xrunjdwp:transport=dt_socket,address=8001,server=y,suspend=n
-Xbootclasspath/a:/etc/openhab2/automation/jython/jython-standalone-2.7.0.jar
-Dpython.home=/etc/openhab2/automation/jython
-Dpython.path=/etc/openhab2/automation/lib/python:/usr/local/lib/python2.7/dist-packages
-Dgnu.io.rxtx.SerialPorts=/dev/ttyZigbeeEmber:/dev/ttyZwave:/dev/ttySerialPort0:/dev/ttySerialPort1:dev/ttySerialPort2:dev/ttySerialPort3"

And this is the module I’am trying to use: https://github.com/miracle2k/onkyo-eiscp

You have both the standalone and a full install of Jython? I’m not sure if it will help, but you might want to try removing the path to the standalone and using the path to the full install.

If I’m not mistaken you cannot use a so-called cpython module with Jython. The python module netifiaces is such a module.

I just installed jython 2.7.1 with the installer, but I get this error: https://github.com/jythontools/jython/issues/108

So I can’t use pip. Any idea how to fix this?

This might help… https://github.com/OH-Jython-Scripters/openhab2-jython/wiki/Using-PIP-in-Docker. There are other issues with 2.7.1 though, so you may want to find 2.7.1.path2618, and then there are some things you may need to do to your modules (I’ll be getting these released).

When I try to execute “java -jar /etc/openhab/conf/automation/jython/jython-standalone-2.7.1.jar -m ensurepip” I get the following error:

Exception:
Traceback (most recent call last):
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/basecommand.py", line                                                                                                                      215, in main
    status = self.run(options, args)
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/commands/install.py",                                                                                                                      line 324, in run
    requirement_set.prepare_files(finder)
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/commands/install.py",                                                                                                                      line 324, in run
    requirement_set.prepare_files(finder)
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/req/req_set.py", line                                                                                                                      376, in prepare_files
    discovered_reqs.extend(self._prepare_file(
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/req/req_set.py", line                                                                                                                      376, in prepare_files
    discovered_reqs.extend(self._prepare_file(
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/req/req_set.py", line                                                                                                                      617, in _prepare_file
    unpack_url(
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/req/req_set.py", line                                                                                                                      617, in _prepare_file
    unpack_url(
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/download.py", line 809                                                                                                                     , in unpack_url
    unpack_file_url(link, location, download_dir, hashes=hashes)
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/download.py", line 715                                                                                                                     , in unpack_file_url
    unpack_file(from_path, location, content_type, link)
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/utils/__init__.py", li                                                                                                                     ne 596, in unpack_file
    unzip_file(
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/utils/__init__.py", li                                                                                                                     ne 498, in unzip_file
    ensure_dir(dir)
  File "/tmp/tmpACPp_r/pip-9.0.1-py2.py3-none-any.whl/pip/utils/__init__.py", li                                                                                                                     ne 83, in ensure_dir
    os.makedirs(path)
  File "/etc/openhab2/automation/jython/jython-standalone-2.7.1.jar/Lib/os.py",                                                                                                                      line 174, in makedirs
    mkdir(name, mode)
OSError: [Errno 20000] Unknown error: 20000: '/tmp/pip-build-Pp9Szo/setuptools'

And if I try to execute this command line on the patch version I get this error:
no main manifest attribute, in jython-standalone-2.7.1.patch2618.jar

I also found this project which claims to run CPython unter Jython: https://github.com/Stewori/JyNI

That sounds like something worth spending some time to test, thanks for the link, @TheNetStriker!