JSScripting and QuantityType state "W"

  • Platform information:
    • Hardware: Raspi 4
    • OS: Linux openhabian 5.10.63-v7l+ #1496 SMP Wed Dec 1 15:58:56 GMT 2021 armv7l
    • openHAB version: 3.2
    • add-ons: only “JSScripting” installed, no Groovy or JRuby
    • upgraded with openhabian-config - upgrade

Hi all

with the help of this forum I could always solve my problems in the past and so I ask for help with the following very simple rule which I want to transfer from DSL to JScripting.

Item Definition:

Number:Power SchalterWZHifiPower “Power” {channel=“tplinksmarthome:hs110:1825AF:power”}

The old rule in DSL looks like this:

rule “Power Check”
when
Item SchalterWZHifiPower changed
then
if(SchalterWZHifiPower.state < 20|“W”)
Fernseh_OpState.postUpdate(0)
else Fernseh_OpState.postUpdate(2)
end

The new one looks like that, but of course it is not running as expected:

var opstate = items.getItem(“Fernseh_OpState”);
var runtime = (typeof(require) === “function”) ? require("@runtime") : {
events: events,
items: items,
};

if(runtime.items[“SchalterWZHifiPower”].state < “20|W”){
console.log(“Power below 20 W”)
//Post an update
opstate.postUpdate(0);
} else {
console.log(“Power above 20 W”)
opstate.postUpdate(2);
}

If I run the rule the result is like this:

2022-01-06 09:58:11.528 [WARN ] [le.handler.ItemStateConditionHandler] - Received a QuantityType state ‘8.648 W’ with unit for item SchalterWZHifiPower, but the condition is defined as a plain number without unit (20), please consider adding a unit to the condition.
2022-01-06 09:58:11.632 [INFO ] [org.openhab.automation.script ] - Power above 20 W
2022-01-06 09:58:11.636 [DEBUG] [org.openhab.automation.script.items ] - Posted update 2 to Fernseh_OpState

Based on the error / warning I can see two problems:

  1. the condition seems to be defined as a plain number, which I do not understand since I added the < 20|“W”) condition
  2. the rule itself does not work, the postupdate will always “2”

Thank you for your effort to point me into the right direction.

best regards

Marcus

The magic pipe character for creating quantities is only for DSL

In other scripting languages, you must do it the correct way e.g.for javascript I think -
new QuantityType("20 W")

Here was a wrong approach.

Please check out the post of @rlkoshak below for a better explanation and working example.

Which completely defeats the point of Quantities. If you want to compare a length, you’d want units - is 2 m longer than 4 ft? If you want to guess and hope, is 2 longer than 4?

The rule above compares the power of one item to a peak value.
No need to compare different items/states/units in this usecase.

If you have a usecase for Quantities => Use Quantities
If you have a usecase that doesn’t need the Quantities urgently => Use Quantities or direct values.

Of course one has to decide on its own which is the best way for the specific usecase.

Yes. It is nice to compare X with 100W, and not worry about if X was expressed as 0.15kW or 150W today. It does not have to be done that way, hope and guess is available as well.

I don’t think so unless there is some shenanigans going on.

items.getItem('Fernseh_OpState').state ;   // the toString representation of the state
items.getItem('Fernseh_OpState'_.rawState; // the actual Java State Object

Neither would strip off the units.

You could use

items.getItem('Fernseh_OpState').rawState.intValue()

to convert the QuantityType to a primitive int, for example, but the rawState will literally be a QuantityType Object.

  • If you are not trying to be compatible with both Nashorn and JS Scripting, skip messing with @runtime. But if you do want to use it, you don’t need the typeof. I strongly recommend sticking to the JS Scripting library as documented in the add-ons docs where possible unless you have a compelling reason not to.

  • When using the library and keeping the QuantityTypes the following should work:

    var QuantityType = Java.type('org.openhab.core.library.types.QuantityType`);
    if(items.getItem(‘SchalterWZHifiPower’).rawState.compareTo(new QuantityType(“20 W”) < 0) {

NOTE, there is an issue to get all the core OH types included somewhere in the library so the above will become

if(items.getItem('SchalterWZHifiPower').rawState.compareTo(new types.QuantityType('20 W') < 0){

This is the most full proof and flexible approach because you cannot guarantee that SchalterWZHifiPower will alway give you the value in W. The binding, State Description and more can change that.

It’s possible that the following might work too, but I’ve never tried it

if(items.getItem('SchalterWZHifiPower').rawState < new QuantityType('20 W')) {

Given the warning message you got, I suspect it will work now. But the only way to add a unit to the condition is to create a new QuantityType.

There is a valueOf static method on QuantityType so instead of importing it you could do something like:

val state = items.getItem('SchalterWZHifiPower').rawState;
if(rawState < rawState.valueOf('20 W')) {

Of course that would only work if state really is a QuantityType.

Unless the unit of the Item changed to kW or something else like that.

Anyway, here is a JS Scripting version that uses the library instead of trying to straddle Nashorn and JS Scripting at the same time.

NOTE: The library is imported by default unless you unset that in Settings → JS Scripting

var state = event.itemState; // why pull the state from the Item when you have it in the event?
items.getItem('Fernseh_OpState').postUpdate((state < state.valueOf('20 W') ? 0 : 2);

Or if you prefer to break it up a bit:

var state = event.itemState;
var updateItem = items.getItem('Fernseh_OpState');
if(state < state.valueOf('20 W')) {
  updateItem.postUpdate(0);
}
else {
  updateItem.postUpdate(2);
}

Hm i debugged that for a personal script and rawState gave me the number as direct output.
Are you sure?!

Edit:
Maybe i should add that this was in a file based openhab-js script for completeness.

As said:

I’m sure that’s how it’s supposed to work. I’m not sure that’s how it is working. If rawState is in fact not giving you a QuantityType Object, it’s not the “raw state”. The whole purpose of getting the raw state is to be able to access the Java stuff when we need to.

The code appears to be just calling .state on the rawItem which is the Java Item Object returned by the ItemRegistry. So it should be a QuantityType. What do you get when you log out ...rawState.class?

But the decision isn’t always yours. The binding authors can and do change the units of Channels despite what you’ve decided.

You are right.
It returns the QuantityType class and to get it a bit more mysterious it also returns the Unit too now, when using rawState.

I would bet money that it didin’t do this, when i was debugging. Pretty Strange.
I will edit my posts above to point to your complete and safe examples.

Edit:

I want to add a friendly greeting to @rossko57 before leaving this topic.
The objective dicsussion with @rlkoshak had way more outcome in a few minutes than your sarcasm based two-liners did. Maybe something to think about. :slight_smile:
You may now “hope or guess”, if i will read your answer if you write one.

I am suitably chastened. If only only I’d thought to suggest new QuantityType() to begin with.