[jsr223] Item access in Jython / jsr223

Hello,

After having done my initial steps migrating DSL to Jython, I struggled with the way openHAB items are accessed currently. E.g.

Get the state of an Item:
items["My_Item"]
# or after importing anything within the ``core`` package
items.My_Item
# or
ir.getItem("My_Item").state

What is the reason items scanned from .items files are not placed into Python’s globals() dictionary thus getting available directly like this:

My_Item # item
My_Item.state # the item's state

Items are complex to understand for beginners already (mix from meta information like name, label, type, and actual value). Mapping them “technical” like described above is adding an additional level of complexity? Especially the bracket operator selecting the item by name and shortcutting it to its state is nearly C++ like. :wink:

  • Harald

I have >2000 Items. Rather than add all of them into the default script scope for every script that loads, they are available inside the items object in the default script scope and accessible as a Python dictionary. Do you carry all of your socks around all day every day, or do you store them in a drawer and pull out the ones you want when you need them?

This is something to reconsider in OH 3.0, but I don’t see it changing.

Your socks made me laugh, great picture! :slight_smile:

But please do not get me wrong. I’m well aware of pattern like modularization, encapsulation, and other mechanisms important to tame large systems. The reason I asked for this globalization of items is my thinking of what this scripting is targeted for. I think it should have simplicity and usability for non IT architects as top priority. Many of my friends do not have a Master in computer science and still want to get their home automated. :wink:

I see part of the future “face” of openHAB is designed currently. Decisions made now will influence the future of openHAB strongly.

openHAB users think in things (and items) collaborating, they are the stars in this world. So items do probably deserve the privilege of being global objects? And openHAB scripting will not be a general purpose IT platform, but a purpose built system optimized for its target group.

Or back to the socks: as long as you are only interesting in socks, you do not need a drawer?

Just my 2 cents, have a nice day. :slight_smile:

  • Harald

Entry level users will have a UI editor for building and editing rules. They can even use scripted automation within them as Scripted Conditions and Actions. There will be a marketplace of rule templates that they can select from and create their rules from these templates. This is still a WIP.

Scripted automation is geared towards more technical users. I don’t want the word technical there to scare people off though. The reality is that it’s easier to learn Python than the rules DSL, and it is a skill that can be used in places other than OH. The scripts and libraries that are built can be included in bundles and templates shared in the marketplace. No more copy/paste in the forum! They can also collaborate through the helper library repository. The people using scripted automation will be providing the building blocks used by the people who only want to use the UI rule editor.

If Items are included, do we also include Things? These are also exposed through in the default script scope through the things object. Log dir(), locals() and globals()… things are already a bit crowded. Using items and things also helps to prevent namespace collisions. I see benefits to both ways, but I think it is best as it was implemented.

Scripted automation allows scripting languages that can run on the JVM to have objects injected into their script scopes to abstract the rule engine and shield the user from its complexity and instability (it will change but the interfaces won’t). If a user finds scripted automation too complex, then they should use the UI rule editor, which will be getting a lot of attention in OH 3.0.

What else to expect from an IT architect :wink: I keep my fingers cross PaperUI will cover the rule definition requirements of a large portion of openHAB users one day.

I found a simple approach that might be of interest for those migrating their code from DSL currently. At least it is looking a lot nicer compared to items[“some_item_name”]:

item("Security_HomematicMotion_Illuminance")
item("Light_Wohnzimmer_Bright")

#
#	Rule is setting Light_Wohnzimmer_Bright depending on illumination measured and
#	with a anti-hysteresis mechanism to work around quick ON / OFFs
#

brightness_threshold = 80 # Lux
brightness_anti_hysteresis = 20 # plus / minus Lux

@rule("Rule_Light_Wohnzimmer_Bright")
@when("System started")
@when("Item Security_HomematicMotion_Illuminance changed")
def rule_light_wohnzimmer_bright(event):

	#	Check brightness and set Light_Wohnzimmer_Bright accordingly
	if Security_HomematicMotion_Illuminance.state != NULL:
	
		if Light_Wohnzimmer_Bright.state == NULL:
		
			#	Brightness not yet analyzed
			if Security_HomematicMotion_Illuminance.state > DecimalType(brightness_threshold):
				new_bright = "ON"
			else:
				new_bright = "OFF"
				
			events.postUpdate(Light_Wohnzimmer_Bright, new_bright)
		
		elif Light_Wohnzimmer_Bright.state == ON:
		
			#	Brightness is ON, we want to see a lower brightness to switch to OFF
			if Security_HomematicMotion_Illuminance.state < DecimalType(brightness_threshold - brightness_anti_hysteresis):
				events.postUpdate(Light_Wohnzimmer_Bright, "OFF")
		
		else:
		
			#	Brightness is OFF, we want to see a higher brightness to switch to ON
			if Security_HomematicMotion_Illuminance.state > DecimalType(brightness_threshold + brightness_anti_hysteresis):
				events.postUpdate(Light_Wohnzimmer_Bright, "ON")

I’m not deep enough in Python so far to provide item() somewhere and import it, but this is how it is looking. It could be added to the helper library as a choice too.

def item(itemname):
	assert itemRegistry.getItem(itemname) != NULL
	globals()[itemname] = itemRegistry.getItem(itemname)
	LogAction.logInfo(LOG, "item {} added as global variable {}", itemname, globals()[itemname])

Paper UI has already been removed in OH 3.0. There is a new UI that has a rule editor with more features.

I disagree and would reject this if submitted to the Jython helper libraries for the reasons I’ve already provided. It is also more effort to use than what already exists, is poorly written, and teaches bad habits.

I do not think so but will stop commenting on this further.

Thanks for contributing on other topics.

  • Harald

I was looking for somthing similar…
I don’t understand why the items[“some_item_name”] returns state of an item.
It should return the item. That way, you can use all attributes of that item. And,… everything bewteen the quotes isn’t checked by the syntax checker. It’s a bad habit, using quoted strings…
What I don’t like about your solution, is that vscode doesn’t recognize the item.
So, my temporay solution, (until i find something better):

def scriptLoaded(*args):
global some_item_name_Item
_some_item_name_Item=ir.getItem(“some_item_name”)

I attach “_Item” to the variable name… (just for clarity)
And I make it global, like you did, but the syntax checker from vscode recognizes the variable
the “def scriptLoaded” is executed when the script is loaded.

in my other functions I can use:
some_item_name_Item.getState()
some_item_name_Item.getLabel()
some_item_name_Item… whatever method or attribute
works perfect for me