[OH3] adding items through Python/Jython and JSON

Hi,
maybe this is of use to someone.

Context
I like the new OH3 UI for inspecting and maintaining items, but for me it is to cumbersome to set up a large number of new items.
When setting up new items, I want to be able to specify item-data but also metadata (as especially with OH3, metadata gets more and more powerful).
I did not want to use .items files, as I still have to copy&paste them over when importing items.

Solution
I set up a class in Jython, which will work on a list of items, each item represented by a dictionary which can define item data and metadata.
Items can also be nested as child-items in the dictionary, this will make the parent item part of the parent-groups.
In the dictionary, you have only to provide the key-values which you are actually needing for an item and omit the rest.

I believe the example in the code should be enough to get you going. If you have any questions or suggestions for the code - I’m happy to hear them.

Cheers,
Bastian

from core.items import add_item
from core.metadata import set_metadata
import inspect

##### improve typing and linting START
# as per https://github.com/CrazyIvan359/openhab-stubs/blob/master/Usage.md
import typing as t
if t.TYPE_CHECKING:  # imports used only for type hints
    from core.jsr223 import items, itemRegistry
# you can delete this whole block if you don't want to setup typing and linting
##### improve typing and linting END

class ItemCreator:
    def __init__(self):
        self.item_list = None

    def run(self):
        self._create_branch(self.item_list, None)

    def _create_branch(self, item_list, parent=None):

        def extract_and_check_add_item_parameters(param_dict):
            # extract all dictionary values, which can be handled by add_item
            add_item_parameters = dict()
            for key, value in param_dict.items():
                if key in inspect.getargspec(add_item)[0]:
                    add_item_parameters[key] = value
            return add_item_parameters

        def create_list_or_none(list_or_none, element_or_list_or_none):
            if list_or_none == element_or_list_or_none == None:
                return None
            elif list_or_none == None:
                if isinstance(element_or_list_or_none, list):
                    return element_or_list_or_none
                else:
                    return [element_or_list_or_none]
            elif isinstance(list_or_none, list):
                if isinstance(element_or_list_or_none, list):
                    list_or_none.extend(element_or_list_or_none)
                    return list_or_none
                else:
                    list_or_none.append(element_or_list_or_none)
                    return list_or_none


        for item in item_list:
            item_name = item["item_or_item_name"]

            add_item_parameters = extract_and_check_add_item_parameters(item)

            # extend groups with parent
            if "groups" in add_item_parameters or parent != None:
                add_item_parameters["groups"] = \
                                    create_list_or_none(
                                        add_item_parameters.get("groups"),
                                        parent)

            # delete item first
            # TODO: add functionality to do updates
            if item_name in items:
                itemRegistry.remove(item_name)

            # create item
            add_item(**add_item_parameters)

            # add metadata
            if "metadata" in item:
                for metadata_set in item["metadata"]:
                    set_metadata(item_name, **metadata_set)

            # process child-items
            if "child_items" in item:
                self._create_branch(item["child_items"],
                                item_name)

etod_items = [
    # {
    #     "item_or_item_name":  "DemoItem",
    #     "item_type":          "type",
    #     # optional
    #     "label":      "Label"
    #     "category":   "category",
    #     "groups":     ["group_1", "group_2"],
    #     "tags":       ["tag_1", "tag_2"],
    #     "gi_base_type":       "?",
    #     "group_function":     "?",
    #     "metadata": [
    #         {
    #             "namespace": "namespace-name",
    #             "value": "value",
    #             "configuration": {
    #                 "key1": "value",
    #                 "key2": 42,
    #             },
    #     ],
    #     "child_items": [],
    # },
    {
        "item_or_item_name":    "ETimeOfDay",
        "item_type":            "Group",
        "label":        "Tageszeit",
        "tags":         ["Equipment"],
        "child_items": [
            {
                "item_or_item_name":     "TimeOfDay",
                "item_type":     "String",
                "label":    "Tageszeit",
                "tags":     ["Status"],
            },
            {
                "item_or_item_name":    "ETimeOfDay_Ctrl_Day",
                "item_type":            "Group",
                "label":        "Steuerung Tageszeiten",
                "tags":         ["Equipment"],
                "child_items": [
                    {
                        "item_or_item_name":    "DTWeekday_Day",
                        "item_type":            "DateTime",
                        "label":        "Start Tag Wochentag",
                        "tags":         ["Control"],
                        "metadata": [
                            {
                                "namespace": "init",
                                "value": "2020-01-01T07:00:00",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                },
                            },
                            {
                                "namespace": "etod",
                                "value": "DAY",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                    "type": "weekday",
                                },
                            },
                        ],
                    },
                    {
                        "item_or_item_name":    "DTWeekday_Night",
                        "item_type":            "DateTime",
                        "label":        "Start Nacht Wochentag",
                        "tags":         ["Control"],
                        "metadata": [
                            {
                                "namespace": "init",
                                "value": "2020-01-01T23:00:00",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                },
                            },
                            {
                                "namespace": "etod",
                                "value": "NIGHT",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                    "type": "weekday",
                                },
                            },
                        ],
                    },
                    {
                        "item_or_item_name":    "DTWeekend_Day",
                        "item_type":            "DateTime",
                        "label":        "Start Tag Wochenende",
                        "tags":         ["Control"],
                        "metadata": [
                            {
                                "namespace": "init",
                                "value": "2020-01-01T08:00:00",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                },
                            },
                            {
                                "namespace": "etod",
                                "value": "DAY",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                    "type": "weekend",
                                },
                            },
                        ],
                    },
                    {
                        "item_or_item_name":    "DTWeekend_Night",
                        "item_type":            "DateTime",
                        "label":        "Start Nacht Wochenende",
                        "tags":         ["Control"],
                        "metadata": [
                            {
                                "namespace": "init",
                                "value": "2020-01-01T23:00:00",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                },
                            },
                            {
                                "namespace": "etod",
                                "value": "NIGHT",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                    "type": "weekend",
                                },
                            },
                        ],
                    },
                    {
                        "item_or_item_name":    "DTHoliday_Day",
                        "item_type":            "DateTime",
                        "label":        "Start Tag Feiertag",
                        "tags":         ["Control"],
                        "metadata": [
                            {
                                "namespace": "init",
                                "value": "2020-01-01T08:00:00",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                },
                            },
                            {
                                "namespace": "etod",
                                "value": "DAY",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                    "type": "holiday",
                                },
                            },
                        ],
                    },
                    {
                        "item_or_item_name":    "DTHoliday_Night",
                        "item_type":            "DateTime",
                        "label":        "Start Nacht Feiertag",
                        "tags":         ["Control"],
                        "metadata": [
                            {
                                "namespace": "init",
                                "value": "2020-01-01T23:00:00",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                },
                            },
                            {
                                "namespace": "etod",
                                "value": "NIGHT",
                                "configuration": {
                                    "etod_item": "TTimeOfDay_Day",
                                    "type": "holiday",
                                },
                            },
                        ],
                    },

                ]
            },
        ]
    },
]


item_creator = ItemCreator()

item_creator.item_list = etod_items
# item_creator.run()

Just for your Information:
HABApp provides a very flexible way to build your items based on your things.
If you use yaml anchors it does basically what your wrote here. :slight_smile:

@Spaceman_Spiff Thanks for that addition. It’s good, to have multiple options to choose from.

I’v seen mentions of HABApp in a few posts in the forum and it seems to be a powerful companion to OH. I didn’t check it out yet, though - maybe I should :wink: