Fun project: kotlin scripting for openHAB

Should we allow calling Jython and JavaScript (Rhino/Nashorn) code? I am not yet sure. It will confuse users. JS is primarily UI libs and their backend nodeJs libs, most of them primarily target web-site development. Utility libs from JS, like collections, dates, are already available in Kotlin.

But Python has many scripts and modules useful in home automation, at least that we should consider.

I’m a few hundred lines away from completing a Rules DSL to Jython migration (~6000 lines), so I’m a little invested in Jython right now. If Jython could be called through Kotlin, it would make a nice stepping stone for migrating. And using updated Python libraries would be very enticing! At almost every turn, I’m running into newer Python code examples that won’t work in the outdated Jython. Hmmm…

I like what you did with the rule structure, especially the triggers! I’ve made a single Jython decorator that will handle most triggers, and I had started to work on a more Rules DSL-like trigger format.

1 Like

I have revised structure such that only a few programming and OH concepts need to be learned by newbie.
Now Thing Label is also supported as device locator, as long as they lead to unique Thing - which should be true for most users.

Will look into Jython integration. I also suspected Jython and Python may not be always compatible. But still the working code in Jython is also huge, I myself have some.

1 Like

At the risk of being pedantic, there’s something about the use of the word “turn” that seems off to me. Yes, an argument can be made that it’s commonly used in the English language such as “Turn on the light.” or “Turn off the radio”. However, its usage is narrow. The example above highlights what I mean. To turn a light to 60 percent sounds odd.

Wouldn’t “set” be more generic and applicable to a broader group of devices? For example, “My Kitchen Timer”.set(15.minutes) reads better than “My Kitchen Timer”.turn(15.minutes). It remains clear in other circumstances: “Furnace Fan Speed”.set(50.percent), “Pool Pump”.set(ON), “Ceiling Lamp”.set(25.percent).

Anyway, just food for thought.

1 Like

I know. There is sendCommand() too as an alias to turn() function. Set seemed more natural to me too but I was afraid it could conflict with something that is already there on String type or some other extension lib could choose the same in future, then we have a regression situation. And since we do want to support intelligent type casting, the input parameter type I cannot use just smarthome specific base State Type or Command Type. I wanted numbers and strings too as acceptable types of turn()/sendCommand()/updateState() overloaded functions. Note that updateState() doesn’t send command. I need some more natural name for it too.

Any other more appropriate name you can think of for turn()? I had used cmd() as a shorthand. Short names come in handy because newbies are less likely to go through IDE setup process. They will be typing in basic text editors for 10 liner rules.

How does setTo() sound?

Another IDE
What about VS Code integration?

1 Like

From my point of view IntelliJ is the recommended IDE for anyone who wants to develop complex rules and Kotlin Apps. Maybe Eclipse and VSCode work equally well with Kotlin. All are open source projects. We will get there, one step at a time.

For copy and paste 10 liner rules, things are just fine without IDE. Thats why I have removed as much programming noise from syntax as I could.

Call me biased but I like the sound of it. :slight_smile:

The addition of “To” also makes it a bit more conversational like the “isAfter” part of currentTime.isAfter in your example. It remains generic, and concise, and retains clear meaning in all these examples:

    "Internet Radio1".setTo(ON)
    "Internet Radio1".setTo(60.percent) 
    "Kitchen Timer".setTo(15.minutes)
    "Pool Pump".setTo(OFF) 

I guess the only example where it stumbles a tiny bit is when used like a function …. but so did “turn” in the same situation:

    setTo("BedroomLight", ON) 

That still works for me. A purist might advocate for reversing the parameters, setTo(“ON”, “BedroomLight”), to make it read better. I don’t have a complete grasp of the implications but imagine that re-ordering would probably create headaches elsewhere.

I overlooked to mention that I like where you’re going with this. I’m not as convinced as you are that this will be easily digested by non-technical users but more power to you for trying to make it as inclusive as possible.

FWIW, I’ve been using another HA system for over a decade where specifying the units of an object’s property is only a matter of writing Thermostat.Temperature.Celsius so when I see stuff like 30.minutes I’m naturally drawn to it. I guess I’m guilty of sticking with the familiar!

1 Like

Thanks for that.
Perhaps we should keep setTo() and sendCommand() as aliases. We can get rid of turn() as it doesn’t sound natural in many cases.

The thing I like about Kotlin’s DSL is you don’t have your own compiler/translator/auto complete IDE extensions for your DSL. Your DSL is directly interpreted by Kotlin’s IDE/compiler. That obviously puts restrictions on introducing new arbitrary natural language like syntax. Its a trade off. I thought its worth giving up some readability for tooling support and a lightweight maintenance on our part as non-profit community.

The reversing of parms is perfectly doable as it is our context function.

setTo(ON, "Internet Radio1")

I have updated the syntax example file.

UPDATE
Added location support to specify target device.
e.g If you got two things labelled “Lamp” in Bendroom1 and Bendroom2, you can specify which one you mean using location prefix.

"Bedroom1.Lamp".setTo(ON)
"Bedroom2.Lamp".setTo(ON)

UPDATE
Added updateTo(), for updating server side state only, without sending outgoing command. Similar to updateState(), which is also supported.
Generally useful in proxy items and during system boot. In most cases, a rule should never have to touch state of item, let the hardware communicate the real state.

Introduced a concept of living things in the language. Its just a though, nothing implemented yet. I wanted some inputs from community how we model living things that we care about, in the HA system, and be able to write rules against it. A snippet from Kotlin rule example:

// update family member state
"Our.Michael".updateTo(AWAKE)
// other states: AWAY, ASLEEP, OUTSTATION, ATSCHOOL, ATWORK, any suggestions?
// To create family, you have to create String Items and tag them with "family"
// other tags could be "friends", "relatives", "pets", "guests", any suggestions?

Don’t forget the IDE is not just for Rules. The IDE is for ALL of OH. If it can be done in text files in OH, the IDE needs to support it. Live previews of the sitemap is also something important for some and VSCode supports that as well.

These days with VSCode, the same code in OH that loads in and parses the .rules files when OH starts up is what provides the syntax checking in VSCode. It uses the Language Server Protocol so you do have to have a running instance of OH as you type but there is very little that actually needs to be coded in VSCode itself. And the IDE is always up to date with the language.

Not all hardware communicates state. Often we need to infer the state of an Item based on some other information. In my experience on this forum this is the case more often then not. Updates are very important.

Don’t hard code the states. We can’t possibly imagine all the possible states everyone in the world will care about. They need to be user definable.

Yes, Thats why I suggested string item. The hardcoded states are more of hints for the rule writer, so that the re-usable Apps/Rules from dev community and user’s terminology are somehow brought to a common ground.
Modeling living things is an open discussion, I asking everyone please give it a thought and share your views on this.

All IDEs are good, lets see how we can get enough vibrant dev community to port portions of work from one IDE to another. We ported from Eclipse to VSCode in the past with the generosity of some talented developers. IntelliJ wouldn’t be left behind. I think Android community also switched from Eclipse, to IntelliJ. We will get there.

I am particularly avoiding connecting to live instance of OH, because then it becomes site specific code. But surely, it comes in handy for the one who wants it to be site specific.

Re-usability is important to me because, we spend our time here on community to help someone get his setup/rule working, that should somehow come back to community as re-usable code, doc fixes, bug reports and hopefully PRs. So I would always encourage writing site-independent code, so that our “library of apps and rules” keeps on growing. One of the reasons I introduced alias concept in current rule language. And many more such concepts will be there, in developer docs.

Entire work is an open discussion, I am always happy to hear suggestions, in a constructive way. :slight_smile: . If people come with bashing mentality then I would tend to ignore.

Actually it wasn’t so much of a port as the discovery of the LSP and that all we had to do was hook into that. If IntelliJ supports LSP then the work is probably all but done and the integration would be minimal. The key feature is that the syntax checking is done on the OH server, not locally to VSCode.

If you have to refer to Items, Things, or Channels by name then you are necessarily creating site specific code. Regardless, I don’t see how connecting to a running OH instance to check syntax means it is site specific code. And the ability for the IDE to provide code completion and checking against those names at write time instead of compile time is a big enabler, and not just for non-technical users.

I agree which is why I asked about libraries and what the interface between Items et. al. which will all necessarily be site specific and the generic library would look.

But how? That is the million dollar question. Every user will have a unique combination of devices and even devices of the same type will not have a uniform set of capabilities or nomenclature. That is why the Items exist in the first place. It lets us define a normalization layer of all the devices that make up our specific HA system. If we have to write a library that works for Nest but not for Echobee or Honeywell Zwave thermostats because they have different parameters and different ways of presenting them (i.e. Channels) then we have taken a step backwards, not forwards.

Perhaps the aliases can handle this, but honestly if that is what aliases are for then I fail to see how they are doing much beyond the same role that Items serve. And since Items are key to so much of the rest of OH (UIs, Persistence, Events) I question whether aliases in Rules is where they belong. I can see it both ways, but it really does seem to be duplicated functionality intended to solve the same problem.

1 Like

Now thats I call a very helpful discussion. I know exactly what Items are. I have read most of ESH code! :slight_smile: When we put item linking in simple mode, user is saved from a “lot” of clicks, to link/create items manually. Its forced labor.
The Aliases here, are just like items, a layer of abstraction, but they work equally well in item linking simple mode. You can avoid the extra labor as mentioned above. And the aliases are created in rule/kotlin files, so they are in control of app developer, rather than site owner.

You might suggest put item linking in simple mode till you get enough things discovered and approved from Inbox, then switch to item linking manual mode, but that is an additional step, that user would wonder why and when to take, he has to read more docs.

So what I am saying is Items are advanced user’s abstraction mechanism, and aliases are advanced user’s as well as programmer’s abstractions. Because items are site specific. I know that a Number or String declared at top level in rule becomes an Item, but I assume it pollutes site specific global name space of items. Aliases don’t do that.

PaperUI is neither the only nor the recommended (by most of us and I think even the docs) way to create Items. There are all sorts enablers to make that easier and less work. But it is a known and recognized problem.

I think my larger issue is you are approach this strictly from the coding/Rules aspect of OH.

OK, so we replace Items with aliases. What about Persistence? What about the UIs? Those aliases will never be available there. And when you solve a common problem only in one place it leads to inconsistency and complexity across the whole system. I’d rather see you or someone address the problem of the forced labor in a way that improved the whole of OH rather than something that only works in Rules.

Aliases works in Rules. What of the rest of OH?

But are they? The site owner still needs to fill out the aliases. One side of the alias can only come from the site owner.

So only advanced users can use Persistence or have a UI? Even the Control tab in PaperUI requires an Item linked to a Channel.

I never said that. Items will stay for a while since UIs and persistence layer is written against that abstraction. The abstraction is insufficient and far too generic as it is today to write re-usable code. Look at android, an app that requires a location service is not worried about individual phone’s capabilities. The Android system gives it a location based on wifi or A-gps or glonass or gsm triangulation. We here in OH are putting that burden on site owner to create that abstraction via Item concept. It needs to evolve. That concept is trying to solve a lot of problems and cater to a lot of audience, it must be sliced down into separate concerns, like I did with aliases.