Ohadm - A simple script to manipulate openHAB objects and sync them to YAML files

Hi,

Just wanted to share a very crude and simple (and potentially buggy) script I ended up writing, which allows to fetch some of your managed openHAB objects and store them locally as YAML files. You can then edit them and update them back, or create new objects. It can come handy when you want for instance to duplicate stuff easily, or use more powerful tools/editors, while the objects once updated back remain editable in the UI.

You can use it for these types of objects for now:

  • UI pages
  • UI widgets
  • HABPanel panel configurations
  • Rules
  • Things
  • Items

Prerequisites

The following tools must be available - note that as it interacts using the REST API you can work remotely, like on your workstation or laptop; these don’t have to be on your openHAB system:

The Script

https://gist.github.com/ghys/071cf630ede8e61634f4f7b2d90df260

For instance use (preferably in an empty directory):

wget https://gist.githubusercontent.com/ghys/071cf630ede8e61634f4f7b2d90df260/raw/34d7e664d463825bfefe964ef62f66d2182d597f/ohadm
chmod +x ohadm

Usage

Initial configuration

Edit the script and change the OH_HOST & OH_API_TOKEN variables at the beginning of the script.

Create an API token by navigating to http://$OH_HOST:8080/createApiToken. Enter your admin credentials, choose a name (e.g. ohadm) and specify admin for the scope. Copy the resulting token (oh.ohadm...) into the script before leaving the page. You can revoke the token at any time from the UI when you don’t need it anymore.

Operations

  • ohadm fetch <type> - Fetch all objects of a certain type

Examples:
./ohadm fetch pages
./ohadm fetch widgets
./ohadm fetch panelconfigs
./ohadm fetch rules
./ohadm fetch things
./ohadm fetch items

For object types, singular & plural forms are equivalent (widget[s], page[s]).

This will create a directory and put every objects of that type in its own .yml file:

$ ./ohadm fetch widgets
$ find widgets/
widgets/
widgets/widget_91ad261b1f.yml
widgets/UniversalRemote.yml
widgets/mode_test.yml
widgets/thermostat.yml
widgets/widget_980ed7320e.yml
widgets/printer_status_list_v1.yml
...

You can then edit these files with an editor or perhaps process them in bulk, for instance yq has a lot of operators to manipulate YAML.

  • ohadm update <type> <uid> - Update an object

Examples:
./ohadm update page mypage1
./ohadm update widget widget_91ad261b1f
./ohadm update thing "exec:command:command1"

This will convert the <type>/<uid>.yml file to JSON and update the corresponding object in openHAB.
You’ll get the raw response from the API, with the status code, inspect it to make sure the operation has succeeded. Usually when you get your object back as JSON it means it was updated successfully, otherwise you’d get a non-HTTP 200 OK, sometimes with an error message.

  • ohadm create <type> <uid> - Create an object

Examples:
./ohadm create page mypage2
./ohadm create rule rule1_copy

The <type>/<uid>.yml file must already exist. This will create the corresponding object in openHAB.

IMPORTANT: the uid (or UID for things) property in the YAML must match the name of the file, otherwise it won’t work.
Beware of channels UIDs with things when duplicating a thing as well, they might still have the UID of the original thing.

  • ohadm delete <type> <uid> - Delete an object

Examples:
./ohadm delete widget old_widget
./ohadm delete panelconfig kitchen_backup

The corresponding <type>/<uid>.yml doesn’t have to exist on the filesystem in this case, but if it does exist, it will be removed!

  • ohadm get <type> - Display objects in a table

Examples:
./ohadm get widgets
./ohadm get items | grep Rollershutter
./ohadm get rules | grep ERROR$
./ohadm get things | grep OFFLINE

Useful to quickly get a status of your objects in a tabular layout.
Filtering can easily be done with grep.

  • ohadm describe <type> [<uid>] - Dump objects as YAML

Examples:

Get a YAML representation of the specified item:
./ohadm describe item MyItem1

Output the date of the last update of the specified widget:
./ohadm describe widget widget_4064e9fb1e | yq e ".timestamp" -

Output the status of the specified thing:
./ohadm describe thing hue:0210:001234567abc:4 | yq e ".statusInfo.status" -

Displays all rules which are currently not idle along with their status:
./ohadm describe rules | yq e '[.[] | select(.status.status != "IDLE")] | map({.uid: .status})' -

Displays all things not online along with their status:
./ohadm describe things | yq e '[.[] | select(.statusInfo.status != "ONLINE")] | map({.UID: .statusInfo})' -

Display the names of all items that have the tags “Control” and “Light”:
./ohadm describe items | yq e '[.[] | select(.tags | contains(["Control", "Light"]))] | .[].name' -

Dump the object (or all objects if <uid> is omitted) in YAML. Especially useful for filtering with yq as shown in the examples above.

Notes

:warning: You use this tool at your own risk :slight_smile:
Since there are no checks on the object structures apart from those performed by the API, you can end up with invalid objects!
Some objects will have additional informations (for example rules and things will have a statusInfo), normally it’s safe to upload those back as they will be ignored.

Hope it’s useful for you, and contributions are welcome.

11 Likes

Look great. Do you think it could be extended to items?

Yes, quite easily. I updated it.

(Before anyone asks: the .yml files for items will have state descriptions and states, but editing them will have no effect since it’s not updateable with the API.)
There’s a slight difference with the items API compared to the others, so if you want to create an item, you have to use
ohadm update MyItem1

3 Likes

I added get (which is not an alias for fetch anymore) and describe operations with examples.

Hello Yannick,
This is a very nice Idea!
I am at my very beginning with OH and driectly begin with the OH3.
I was just wondering if i will work with UI or with text files. Your script seems to be able to export all object whatever they where created using UI our text files.
if yes, this would be great.
I have two instance of OH running, one is on IOTSTACK in a docker config on a RPI4 with SSD but i could not get vscode extension working with this config.
The other one is on openhabian SD running on RPI3B.
I was wondering if your script coud allow to export some elements from one config to another even if they are created with the UI.
Thanks for your feedback.

i tried to install it in order to test:
Fetch things give some warning but it is working …
ERROR: ld.so: object ‘/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so’ from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignor ed.

it seems that these message are coming from trouble installing yq with snapd… but the things yml file are well created…

The get items and get thing are also very nice, for example to have the UID list of thing to use them in items decription in the files.

So this is fantastic and yml files are easy to read and can be easily managed on other tools !! thanks for this great tool!

Hello Yannick,
I made some trial yeserday with your script.
I generated te YAML files using Python YAML package.
I could create items (using the update commands) but when i try to update the Thing, the channels linkedItems are not updated. Other fields in the channels like ‘decription’ are well updated.

Any idea?

Sorry, missed your earlier message - glad if it helps!

That’s to be expected - the Things GET & PUT operations (to retrieve & update a thing, respectively) don’t have the same schemas - the PUT schema is only a subset of the GET schema. Elements that are part of the GET response but not part of the PUT payload are for information purposes only and not meant to be updateable. To create links you have to call another separate endpoint which this tool doesn’t support. Similarly you won’t be able to update the status of the Thing by modifying what’s under statusInfo.

You can see it in the UI in Developer Tools > API Explorer, under things.

This is the schema for a GET request:

and this is schema for the PUT request:

Hello Yannic, thanks for your feedback.
I have created the link between channels and Items using the UI and it is working well.
But that means I cannot use these yaml files to recreate later my complete configuration on another Openhab instance…

So the next step would be a tool that convert the yaml into opehab config files.

I also used your script to create all locations group and relate them to the corresponding floor of the house.
I am surprised that when browsing location from home page, the location of hierarchy of the semantic model is not automatically translated in the layout of location tab. Is is normal?

IMO a better approach would be another yaml for the links.

1 Like

It would be nice but I am not sure how the link can be created using the rest API… hoping Yannick can help us because I really like the ability to combine configuration with UI and YML file in import/ export like most platform do.

1 Like