Strange String behaviour on 'ON' / 'OFF'

OK in the log file I have the famous line
[ore.internal.items.ItemUpdater] - InstantiationException on org.openhab.core.library.types.StringType

So I have to give up, rather to enter in a complex (for me) and useless modification of OpenHab, I will make an extra test in my Arduino code to make a distinction between String and Switches for the ON/OFF messages.

Thanks for your support, maybe someday someone will correct the MQTT binding

Robert

A small PR could fix the MQTT binding, to post new StringType(wrongType.toString()) in the case where it’s headed for a String item but wrongType is not an accepted state type. Steve, want to take a stab at that?

1 Like

Are you suggesting catching the exception and then retrying the postUpdate with the StringType? If so, the exception is eaten by the ItemUpdater so the subscriber never sees it. Also, the subscriber config only has the item name so it does not know the target item type. Do you know if there’s some reason the MQTT binding wouldn’t store the item in the subscriber config rather than just the name?

Just another question.

Is sit possible that the MQTT Binding implementation is a little bit messy regarding strings. It looks that ASCII numbers are not interpreted as string if not precede by a another character.

So a message 1234 is not interpreted but %12345 is OK as %12345.
But not all special leading characters are working:
for instance /12345 or h12345 are OK but not +12345 or $12345 or <12345.

Is there a rule behind that ?
Robert

There needs to be isolation between bindings and actual Item objects, because Item objects have a lifecycle that is completely independent of bindings. That is one reason a binding should never, ever hold onto an Item object reference. Also, this isolation makes it a pain to learn an item’s type from the itemName, unless you have access to the ItemRegistry, which is a “frowned upon” thing to do in a binding (but some still do). So maybe my characterization of it being a “small PR” is a bit optimistic. :smile:

The cause of the issue with numbers is the exact same cause behind ON and OFF:

You would want to 1) know that you are going to receive a decimal number from your MQTT topic, and 2) use a Number item in openHAB to receive it. Then you’re set!

In fact I just discover something new
Everything works if the string is preceded by a space
so
pi@raspberrypi ~ $ mosquitto_pub -u ‘MQTT’ -P ‘MQTT’ -t Home/RF/nb/000/3/10 -m “123.46”
Doesn’t work
but
pi@raspberrypi ~ $ mosquitto_pub -u ‘MQTT’ -P ‘MQTT’ -t Home/RF/nb/000/3/10 -m " 123.46"
is OK
Robert
The same with ON/OFF

pi@raspberrypi ~ $ mosquitto_pub -u ‘MQTT’ -P ‘MQTT’ -t Home/RF/nb/000/0/5 -m “ON” is NOK
pi@raspberrypi ~ $ mosquitto_pub -u ‘MQTT’ -P ‘MQTT’ -t Home/RF/nb/000/0/5 -m " ON" is OK

Now concerning numbers ans string, and IP address such as 192.168.0.254 is that a string or a number?
Robert

It would be a string, since it won’t parse as a number.

OK that looks to be the solution, all messages that I sent to OPENHAB that I consider to be a string are now preceded by a space.
For the time being all my problems are solved , the IP address one and the ON/OFF, by this little workaround.

What do you think, its is maybe something that should be documented somewhere!
Robert

By the way, this is the same issue I encountered when I wanted to set the state of a Location item using an MQTT in binding. MQTT will not give me a PointType state, which Location items accept, so I had to use the “proxy item rule” approach I mentioned earlier. If MQTT were to know what kind of Item it’s posting an update to, then it could be smart enough to construct an acceptable Type object for that item, without needing a rule like this:

import org.openhab.core.library.types.PointType

rule LocationUpdated
when
	Item Loc changed
then
	if (!Loc.state.toString.contains("undefined")) {
		LocPoint.postUpdate(new PointType(Loc.state.toString))
	}
end

One approach to improve this could be to add the item’s class (not the item itself) to the MqttItemConfig during processBindingConfiguration, and when it comes time to create a State from an incoming message, use the context provided by the item’s class to dynamically decide what kind of Type to post as an update. That way, if the incoming message is ON or 1.234 or 77.1234,-6.5432 or CLOSED, the binding would say, “so, it’s a StringItem I’m trying to update – I’ll just make a StringType and post that,” or, “so it’s a LocationItem I’m trying to update – I’ll construct a PointType and post that,” etc. You would of course use the Item.getAcceptedDataTypes() approach, not hardcoding a table, etc., ensure this isn’t a breaking change, etc.

  1. I would like to correct my previous statement as follow:
    Uppercase MQTT messages such as ON, OFF, OPEN, CLOSED, UP, DOWN used for a String Item should be preceded by a space or an alphabetical character to become for instance: " ON", " OFF", " OPEN"," CLOSED"," UP"," DOWN".
    All numeral value including special characters such as 1.1.1 or 1/1 or 1%1 +1.2 should also be preceded by a space or an alphabetical character to become for instance: " 1.1.1"," 1/1"," 1%1", " +1.2"
    All other alphabetical strings may be used has is.
  2. Sorry my understanding of OpenHab is very very limited so I do not exactly understand what should I do with your proxy item rule to solve this issue / feature.

Anyway I happy with this workaround, so thank you again for your help and support
Robert

If preceding the message string with a space works for you, then the MQTT binding will only ever post StringType updates to your String items, since it won’t match the other types first. For those that want to take advantage of the different kinds of state types that openHAB supports, this approach has some drawbacks. But if it works for you, hooray!

OK

I don’t say that I do want to only post String Items, but in particular case I would like that a StringType to be interpreted as a pure String.
I start to have a better understanding of the MQTT binding through the light of you information.
So I summarised it like this:
MQTT looks for special types: ON, OFF, OPEN, CLOSED, UP, DOWN and real numbers (xx.yy)
So if such types have to be considered as Strings they should be formatted to appear as strings, by for instance adding a leading space.
This looks to be more simple for me to understand.
Robert

That is about the size of it more or less, until and unless the MQTT binding can be made a little smarter to take into account the type of item it’s trying to update. In any case, no changes to the binding will be made that would break any existing uses of it, so you can continue doing what works for you without worry.

@watou Why is this frowned upon? The ItemRegistry doesn’t appear to be an internal interface.

I had thought about storing the item type but even that can change when items are redefined (Switch to String, for example). Looking up the item in the registry when doing the incoming message processing and using the item’s acceptable types for parsing the payload seems like a reasonable solution.

Well, often a binding needs the ItemRegistry to perform caching and update suppression, both problematic things for a binding to do, but I suppose it may have valid uses as well. I would be more concerned with potential performance issues of doing lookups by item name a lot, just to get the accepted types and commands.

Anyway, I had to flush the idea of a PR out of my head (insomnia), so I submitted a pull request for you and others to look over. I haven’t even tested it yet, but the idea is to use the existing mechanisms for determining item-specific acceptable types and commands, so that if the bound item is a String, messages like ON and OFF will come through just fine as strings. Or if it’s a Number, the incoming message will only possibly turn into the accepted types for Number items. Or in my earlier use case for Location items, the incoming message will only try to parse as a PointType. The binding would no longer have a hardcoded list of types to try; it instead defers to the lists kept with each kind of item.

The PR probably has issues, like I haven’t verified that the MQTT message bus binding will work properly with this change. But at least it’s small!

Please let me know your thoughts, @steve1, or anyone else who can provide helpful critiques. Thanks.

I have a test JAR available that matches the current state of this pull request and I would be very happy if others were to test it in their environments. I’ve tested both the MQTT Item and the MQTT Event Bus bindings on two of my openHAB servers (one at 1.7.1 and one a recent 1.8.0-SNAPHOT).

This is what should be different:

The two bindings (MQTT Item and MQTT Event Bus) determine the kind of openHAB item to which a message is intended, and will only convert the message into an update or command that is appropriate for that kind of item. This allows the following scenarios that are not currently possible:

  1. Send a decimal number to a String item.
  2. Send a string that looks like a lat,long to a Location item.
  3. Send ON, OFF, OPEN, CLOSED, etc. to a String item.
  4. Any other accepted combination that would otherwise fail with the current binding.

Prior to this pull request, there is a hardcoded list of types in the MQTT binding (ON/OFF, OPEN/CLOSED, UP/DOWN, something that can be parsed as a hue/saturation/brightness, a percentage, a decimal number, a date and then, lastly, a string), and which one is chosen is based on the first one that parses correctly. This can lead to problems, as described in this thread earlier.

Also, this pull request’s MQTT Message Bus binding will not put subscribed messages on the local openHAB message bus for items that do not exist in the local system. If you turn on DEBUG logging for the binding, you will see them being dropped, as they have nowhere to go.

I believe that this set of changes will not break any existing working configurations, but will allow more flexibility out of the MQTT bindings by dynamically accounting for items’ accepted types. I need you to try to prove me wrong!

@rlkoshak, @steve1, @tramlaan, @ben_jones12, and anyone else who could replace your current MQTT binding JAR with this one, I would appreciate it much. Testing should focus on 1) nothing breaks, and 2) the new flexibility works as advertised.

Thank you,
John

I’ll give it a try sometime this weekend or Monday and report back here with my findings.

Thanks, Rich.