Ambigous feature call: ColorItem sendCommand HSBType

I am finding type conversions and casts in OH2 rather “complex” to put it in a delicate way. Having read the very useful section in Rules documentation, then a number of posts, notably by always-helpful @rlkoshak :+1: I am still lost as to the error I am seeing about sending a simple HSBType command to a Color item—something I assumed was not only possible, but the recommended way of doing things:

val HSBType nightBedroomLightColour = new HSBType("0,100,1")     // Dark red
hue_Bedroom_Wall_Color.sendCommand(nightBedroomLightColour)

while this functions, it throws this warning in VSCode:

Ambiguous feature call.
The extension methods
	sendCommand(Item, Number) in BusEvent and
	sendCommand(Item, Command) in BusEvent
both match.(org.eclipse.xtext.xbase.validation.IssueCodes.ambiguous_feature_call)

Why is that—I am not asking about the nature of multiple inheritance here, but the error I am seeing? Is it really necessary to cast the HSBType to something like a string to make it work without warnings? :no_mouth:

On a similar note, I get more warnings about comparing PercentType against an int etc. I realise the Rules DSL is more strongly typed than it seems, therefore the support one gets from VSCode addins is very helpful. But I am also asking myself if its strong typing is a help or a hindrance…I spent a good few hours yesterday and today just trying to understand it—and I have written a good number of lines of code in very strongly typed languages in my life.

On a practical note of matters of documentation. I also wanted to figure out how to get brightness (and other) components of a Color item. The official Rules page and many forum posts link to this as a source of that information: https://www.eclipse.org/projects/archives.php?org/eclipse/smarthome/core/library/types/HSBType.html . Unfortunately, that page just shows a generic “Eclipse archived project” page and so it is not possible to examine the underlying Java doc. Is there a live link to that?

In any case, I ended up casting the state like this:

(hue_Bedroom_Wall_Color.state as HSBType).brightness
(hue_Bedroom_Wall_Color.state as HSBType).hue

but is that the way to go?

All of that (odd) type mangling, or having to torture date/times through strings to make them work in rules, it all makes me wonder if I should just throw in the Rules DSL towel in and see if the Jython grass is greener. :confused:

Try to set your color like this

val HSBType nightBedroomLightColour =  new HSBType(new DecimalType(0), new PercentType(100), new PercentType(1) ) 

Thank you for suggesting it. May I ask why is this constructor better than the string-based one when essentially defining a constant from a literal, as is in my case? Your version is much more verbose, but what is the benefit? In any case, it throws the same Ambiguous feature call. warning.

So far as VSCode is concerned, an HSBType is not a commandfor an Item. Hence the warning.

It’s a circumvention - send a string, and the command parser will do its best to parse out something it expects.

I always feel it is the OH Actions/methods being picky, not Rules per se.

Try this
someSwitch.sendCommand( otherSwitch.state )
It’ll not work. State is ON/OFF, expected commands ON/OFF, why not?
Because a state is not a command.
someSwitch.sendCommand( otherSwitch.state.toString )
This is fine, we reduce to lowest common denominator (string) and it parses itself back. Bonkers, that’s the way it is, it’s not changing now.

Indeed. I wonder—not having tried, only starting to read @rlkoshak odyssey now—if Python’s innate ability to convert types without causing too many accidents would work in these cases. However, seeing all the decorators that effectively take stringified code, I am unsure…

I’ve little experience with Color Items. I don’t see what is ambiguous about that call as I don’t think that HSBType is of type Number, though I could be wrong. You should be able to make VSCode happy by disambuiguating it and casting it.

hue_Bedroom_Wall_Color.sendCommand(nightBedroomLightColour as HSBType)

Frankly, if you are just getting started with OH, your time would be much better spent on coding Rules in Scripted Automation rather than Rules DSL. If you are already a coder, the recommendation is even stronger. The best documented right now is coding Rules in Jython (see [beta testers wanted!] Jython addon w/ helper libraries (requires OH 2.5.x)) though JavaScript and Groovy are currently supported.

Rules DSL suffers from having a leg in two worlds, XTend which is weakly types and Java which is strongly typed. All the times you see errors and warnings like these occur when the two worlds meet. It’s always had it’s quirks and will always have it’s quirks. And it absolutely will not bend to your desires. You have to approach the code in the ways that it likes. And the way it likes is not the way you expect as someone who already knows how to code.

The Rule of thumb is if it’s a Number type (DecimalType, PercentType) cast the state to Number before comparison or doing mathematical operations with it. If it’s a QuantityType (e.g. Number:Temperature) it gets a little more complicated.

That works. You can also use

    hue_Bedroom_Wall_Color.getStateAs(PercentType) // brightness
    hue_Bedroom_Wall_Color.getStateAs(OnOffType) // switch

When you reference an Item in a Rules DSL Rule, you are referencing it as a GenericItem. As such, the getState() method (which Rules DSL lets you call with just .state) returns a State Object. You need to cast it down to HSBType in order to access the getBrightness() and getHue() methods.

1 Like

Thank you for your patient explanations @rlkoshak.

I am afraid not. It will (correctly) complain that nightBedroomLightColour is already a HSBType and that this cast is unnecessary. Anyway, your comment that this is a language with feet in two worlds explains a lot.

Very tempting. Would it be much easier in terms of typing? I see I still have to deal with much of the “old” framework’s abstraction. I will keep on reading your essay on that journey. But I am seriously tempted, as the time spent on digging obscure and, frankly, rather hacky techniques like casting things through strings, plus all the debugging that entails, would probably be saved by doing things in a “proper” programming language. I wish, however, it was a more modern Python than 2.7. :confused:

Sort of. You’ve already noticed that a lot of the casting problems are dealt with by using Strings all over the place. QuantityType is still a little challenging, but no more so than in Rules DSL. But in Scripted Automation there is no more MyItem.sendCommand(Command) or MyItem.postUpdate(State). There is just events.sendCommand("MyItem", "Command") and events.postUpdate("MyItem", "State"). Instead of MyItem.state you have items["MyItem"] (note there are other ways to get an Item’s state but this is the more typical way). And you still have the problem that you are operating on Java Objects in some other language and there are places where differences between the languages appear.

Were it just the typing problems with Rules DSL I wouldn’t make such a strong recommendation. But I bet you’ve yet to encounter some of the other many Rules DSL problems like:

  • only 5 can run at a given time
  • lambdas (the closest thing to functions/methods supported) are not thread safe, do not have a context (i.e. cannot see global variables) and have a maximum of 7 arguments you can pass to them
  • there is no support for libraries
  • global variables are only global to the one .rules file
  • there is no support for custom classes or data structures
  • it’s relatively slow (which isn’t really a problem frankly)
  • there is a problem where .rules files can be loaded before the .items files and they start executing before all Items are defined
  • certain concepts like locks can be very dangerous because some errors, particularly type errors, are caught and reported outside your Rule so you can’t catch the error and unlock the lock after the error occurs.

I could go on. Rules DSL served it’s purpose and if you are willing to bend to to the language you can come up with some elegant solutions (see the DP posts). It’s also relatively easy for new users who are not programmers to grasp though Python has since caught up on that front. But all signs are that Rules DSL will be replaced as the default language in OH 3.

For the types of things you would be doing in openHAB Rules, the Python 3 and Python 2.7 would be virtually identical in my experience.

I am afraid I have already run into several of the issues you have listed:

I am literally working around the issue of sharing a lock between Lambda (timer) and the rule that fired it off. :confused: Add to your list no functions in Rules DSL for organising oneself better. I also wonder if Jython+OH solves the issue of persistence not being ready when rules start firing on system restart.

I like list and dictionary comprehension a lot in Python 3—unsure if they ever made it back to Python 2.7. I am ok without the walrus operator :grinning: in 3.8 but in general, it would be a much safer jump for me if I knew 3.x was clearly on the horizon. The Jython project seems a bit quiet about it.

It is good to hear your reports. I will give it a go, but since I am already 80% done migrating my rules from OH1 to OH2, this may be a project for new rules or even for OH3.

Yes it does. Rules are loaded and start running very late in the startup process with Scripted Automation giving everything else plenty of time to start up before the first Rule runs.

They did.

You’d have to troll the OH issues on GitHub. I imagine it is but I’ve not payed much attention. The last I saw someone mentioned that Jython has picked back up 3 development. I’ve also seen GraalVM mentioned for OH but don’t know the status of either.

1 Like

In case anyone stumbles over this (since it is currently the first result on google for the Ambiguous feature call error with HSBType): For me, the only solution was to cast directly to Number, so iteration over all colors is possible like this:

       var i = 0;  
       for (i = 0; i < 720; i++){
          var HSBType MyColor
          MyColor = new HSBType(new DecimalType(i % 360), new PercentType(100), new PercentType(100));  
          MyItem.sendCommand(Color as Number);
        }

That code doesn’t make sense. Do you mean

MyItem.sendCommand(MyColor as Number)

That makes a little more sense but still should complain at runtime that HSBType cannot be coereced to a Number. Though maybe it can but then you’d probably only get back the Dimmer value.

A better fool-proof approach is to use toString.

MyItem.sendCommand(MyColor.toString())

Note, in Rules DSL don’t use semicolons except with a return statement. I can’t remember why but their use is discouraged.

From HSBType javadocs we can confirm that it is actually Number as well. For those who are interested, the chain goes HSBType<PercentType<DecimalType<Number HSBType (openHAB Core 3.2.0-SNAPSHOT API)

Therefore you probably have to use string commands or cast the HSBType to Command to disambiguate the method.

Coercing to number is probably not what you want as it takes the brightness component of the HSBType and commands ColorItem with that. Hue and saturation components are ignored

1 Like