I can get the temperature setpoint from a device but not change it (parse error)

I have a device (eq3 valve) that returns the temperature setpoint (temp field) and other fiels of its status altogether i a JSON status MQTT topic.
When yo want to change the setpoint you have to use another command topic and send the temp as raw format (string with the temperature in ºC).

I have created the thing and the channels and links to items and interface elements.
I can view and update other channels that are string like mode (auto or manual).
But when it comes to settemp (I configured it as a number in the channel) it fails.

I can see the setpoint temp pusblished by the device, but when I try to use a scale to change it it does not work.

In openHAB console it gives me an error:

 15:12:57.305 [ERROR] [rnal.common.AbstractInvocationHandler] - An error occurred while calling method 'ThingHandler.handleCommand()' on 'org.openhab.binding.mqtt.generic.internal.handler.GenericMQTTThingHandler@4e3bc25d': Parse Error
javax.measure.format.MeasurementParseException: Parse Error
        at tech.units.indriya.format.SimpleUnitFormat$DefaultFormat.check(SimpleUnitFormat.java:631) ~[bundleFile:2.1.2]
        at tech.units.indriya.format.SimpleUnitFormat$DefaultFormat.parseSingleUnit(SimpleUnitFormat.java:486) ~[bundleFile:2.1.2]
        at tech.units.indriya.format.SimpleUnitFormat$DefaultFormat.parseProductUnit(SimpleUnitFormat.java:505) ~[bundleFile:2.1.2]
        at tech.units.indriya.format.SimpleUnitFormat.parseObject(SimpleUnitFormat.java:293) ~[bundleFile:2.1.2]
        at tech.units.indriya.format.SimpleUnitFormat$DefaultFormat.parse(SimpleUnitFormat.java:834) ~[bundleFile:2.1.2]
        at tech.units.indriya.format.SimpleUnitFormat$DefaultFormat.parse(SimpleUnitFormat.java:829) ~[bundleFile:2.1.2]
        at tech.units.indriya.format.SimpleUnitFormat$DefaultFormat.parse(SimpleUnitFormat.java:825) ~[bundleFile:2.1.2]
        at tech.units.indriya.AbstractUnit.parse(AbstractUnit.java:219) ~[bundleFile:2.1.2]
        at org.openhab.core.library.types.QuantityType.toUnit(QuantityType.java:281) ~[bundleFile:?]
        at org.openhab.binding.mqtt.generic.values.NumberValue.update(NumberValue.java:116) ~[?:?]
        at org.openhab.binding.mqtt.generic.ChannelState.publishValue(ChannelState.java:334) ~[?:?]
        at org.openhab.binding.mqtt.generic.AbstractMQTTThingHandler.handleCommand(AbstractMQTTThingHandler.java:149) ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
        at org.openhab.core.internal.common.AbstractInvocationHandler.invokeDirect(AbstractInvocationHandler.java:154) [bundleFile:?]
        at org.openhab.core.internal.common.InvocationHandlerSync.invoke(InvocationHandlerSync.java:59) [bundleFile:?]
        at com.sun.proxy.$Proxy380.handleCommand(Unknown Source) [?:?]
        at org.openhab.core.thing.internal.profiles.ProfileCallbackImpl.handleCommand(ProfileCallbackImpl.java:80) [bundleFile:?]
        at org.openhab.core.thing.internal.profiles.SystemDefaultProfile.onCommandFromItem(SystemDefaultProfile.java:48) [bundleFile:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
        at org.openhab.core.internal.common.AbstractInvocationHandler.invokeDirect(AbstractInvocationHandler.java:154) [bundleFile:?]
        at org.openhab.core.internal.common.Invocation.call(Invocation.java:52) [bundleFile:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
        at java.lang.Thread.run(Thread.java:829) [?:?]

It seems the scale object sends the correct value and the item passes it corectly to the channel of the item, but when it tryes to parse it there is an error.

This is the configuration of the thing’s channel:

  - id: tempObjRadiadorSalaJuegos
    channelTypeUID: mqtt:number
    label: Temperatura objetivo Radiador sala de juegos
    description: ""
    configuration:
      postCommand: true
      unit: ºC
      min: 5
      qos: 2
      formatBeforePublish: "%.1f"
      max: 35
      commandTopic: cmnd/tasmotaSalaJuegos/EQ3/001A2215622D/settemp
      step: 0.1
      stateTopic: stat/EQ3/001A2215622D
      transformationPattern: JSONPATH:$.temp

I have defined it as a number and it reads it correctly from the JSON message.
The problem seems to be when the number needs to be converted to string again to send it to the command topic.

I have tried to use formatBeforrePublish: %.1f and %s and none works.

I am sure I am missing something, but could not find what is it.

As said this works correctly with other fields that are text fields.

I doubt you want the postCommand option.

What type of Item have you linked? What commands do you send that? (see your events.log) Do you want the MQTT payload to include the units symbol?

May be I am misunderstanding the use of these config in things channels.
I thought I should use a mqtt:number as it is a number, a tempertature and that the other min, max, step and format were defaults for components like scale, not to include it in the output message, and output was formated with formatBeforePublish.

No, I don’t want to add ºC to the temp field.
It is a EQ3 thermostatic valve. It sends a status message something like:

{
"cmd":"settemp",
"result":"ok",
"MAC":"001AXXXXXXX",
"tas":"tasmotaSalaJuegos",
"RSSI":-84,
"stattime":1639153880,
"temp":22.5,
"posn":100,
"mode":"manual",
"hassmode":"heat",
"boost":"inactive","
dst":"set",
"window":"closed",
"state":"unlocked",
"battery":"GOOD",
"holidayend":"00-00-00 00:00"
}

The command for changing settemp to 22.5 ºC should be:

cmnd/tasmotaSalaJuegos/EQ3/001A2215622D/settemp 22.5

So unit and min and max or step should be eliminated?

I would like that whenever the linked item state changes, the system sends a MQTT mesage to the valve to change the settime.
If it is not available in that moment it should receive the message later when it becomes available and just one message.

OK, so you have units and it sounds like you are trying to use the Scale transformation in a Profile, correct?

If so, I’m pretty sure that Scale doesn’t know nor understand units. This property

is telling the binding to append “°C” as the units before sending the value along, presumably to a Number:Temperature type Item. But the Scale is trying to intercept that value before it gets to the Item to modify it and Scale doesn’t handle units.

MQTT is one of the more powerful yet complicated binding OH has. I recommend taking a step back and simplify. First make sure you get the value and can pass it on to just a Number. Then make a Number:Temperature and see if that works. OH will likely interpret the units to be what ever is your system default, making specifying the units in the Channel unnecessary. without the units specified there Scale should work.

At least unit. Min and max shouldn’t be causing any problems here.

If what is not available in that moment? The binding? The clients subscribing to the topic?

It would be good to read up a bit on how MQTT works. OH is not sending a message to a valve nor any other device. It is publishing a message to an MQTT Topic on an MQTT Broker. Your valve subscribes to that topic. Thus, controlling things like how many times to deliver, whether the message is delivered to a client that isn’t connected when it reconnects, and stuff like that is handled by the QOS and “retained message” settings on both the publisher (i.e. in your Thing and Channel config) and the client.

All the options and what they mean is too big a topic for a forum reply. https://www.hivemq.com/mqtt-essentials/ is probably the best tutorial.

OK, I will delete the channel and recreate it step by step.

I had misunderstood the info about unit, I had understood it was there to tell openHAB what the unit in the MQQT msg was, when it was not present. But I see it is not, it is just to add that to the command message when the device requires it to be added.

I don’t understand well what “Is command” option (postCommand: true) is.
I will keep it disabled.

Yes I have read about MQTT and its basics, but I don’t understand it fully.
QOS 2 (as I understood it) is to be sure the command (write to a topic) will be received (read) by the devices just once and that they will receive it later, even if they are not online at that moment.
As changing the setpoint temperature should be acomplish by the device even if it is temporarily offline, it makes sense (to me) to enable that mode.
Is there something wrong with that?

Thanks for the tutorial, I will have a second look at MQTT concepts.

By the way:
How may I see the MQTT message openHAB is sending to the broker?

I am using MQTT Explorer and I can see the MQTT messages.
But I can see stat/xxxx/xxx messages and can send cmnd/EQ3/xxxx messages (it works when I send the message to settemp from MQTT explorer).

But I can not see any cmnd/EQ3/xxx message sent from openHAB, when I change the value in the slider.

In openHab console it says the value has changed from xx to yy and no error.
But it does not seem to send the MQTT message as it is not shown in explorer.

I had no problems with other (string) channels like “mode”.

No, I think you had it right in the first place. You just didn’t understand what the implications are to adding the unit to the Item was.

When you supplied the unit in the Channel config the processing was like this:

# Client sends 21 to the MQTT Broker
Client - 21 -> MQTT Broker

MQTT Broker - 21 -> MQTT Binding - 21 °C -> Link Profile Scale -> !ERROR

The Binding add °C to the value received from the broker. Why would you want to do that? Because when the Item that receives the state update is a Number:Temperature the °C tells OH what units the number is.

Theoretically, if you received a °F but wanted to have a °C you could change the State Description to show °C and it will convert the value for you. But there is a bug in MQTT Binding right now that makes that not work as expected.

And as you saw, when the binding added that °C to the value, it rendered Scale unable to process it because Scale doesn’t understand units.

Not necessarily. Also keep in mind that the QOS handles the communication between the client and the broker only. Setting QOS to 2 in OH will not guarantee that the end device receives the message with QOS 2. OH could send with QOS 2 and the device subscribe with QOS 0. And even with QOS 2 I don’t think it tries forever to deliver the message and I’m almost certain it loses the message if the broker restarts.

Typically, to handle cases where a client is offline when the message is sent retained messages are used. This causes the MQTT Broker to persist the message so even if the client was offline when the message was sent, the client will receive the message as soon as it reconnects (even if the MQTT broker itself went offline). That is probably what you need to be looking into.

As a rule of thumb, all topics that represent a state of something should be retained (unless that state is constantly updating like a once a minute temperature reading). All topics that represent a command to cause a device to do something should not be retained. Otherwise when you device reboots it will receive all those commands again.

In a typical home networking environment, there really is almost no practical difference between QOS 0, 1 or 2. Our networks are far more reliable than those for which MQTT was originally developed to operate in (i.e. oil pipeline sensor networks).

It depends on how the messages are sent but in general you need to correlate events that happen in OH with the arrival of a message seen in MQTTExplorer.

Remember, once the message gets to the MQTT Broker no one cares where it came from. Similarly no one cares where it’s going to. That’s the business of the publishers and subscribers. All the broker really cares about is that message “foo” was published to topic “bar”.

So you need to start at the beginning and work through the path.

You say you see the Item’s state change, but is that Item being commanded? An update only changes the state of an Item internal to OH. If you want to send that message out to the device (i.e. publish the MQTT message) you need to command the Item. By default interacting with an Item through the UI will issue commands. But in rules you have to use sendCommand instead of postUpdate.

If the Item is being commanded, do you see the commands in events.log? You should see commands, changes (if the command results in a changed state), and depending on how the Item is configured autoupdate predictions in events.log for every command sent to an Item.

If you see commands there then the next step is to get some debug logging from the MQTT binding (assuming that you’ve already verified that the Item is linked to the right channel). There are lots of ways to do this. One is to edit $OH_USERDATA/etc/log4j2.xml and add <Logger level="DEBUG" name="org.openhab.binding.MQTT"/> (at least I think that’s the name of the logger) to the bottom of the “Loggers” section. That will tell you everything the binding is doing.

If that seems to be OK, look through your MQTT topics in MQTTExplorer and double check the Channel config to make sure the topic name is correct. Maybe it’s publishing to the wrong topic.

1 Like

I thought SCALE transform did work with units (by dint of ignoring them). I don’t think any SCALE is involved here? Nevertheless if you get a numeric payload and shovel it into a plain Number Item, you don’t want any units.

OK, thanks I have understood it much better now (sorry for my english it is difficult for me to express correctly my ideas in english and I know sometimes it is difficult to understand what I mean).

So I had understood it well, and I could use min, max, step and unit to define the limits and unit to describe the content of the mqtt message to the channel.

But I was assuming the problem was when the MQTT output message was being formatted by the channel and it was not there, it is in the communication of that info to the scale component (due to the bug you are talking about).

So I will let it blank, as the unit of the measurement is ºC and that is the unit that should be displayed.

Now I have this layout for the channel and it seems to work, at leaste i could change the setpoint some times from openHAB:

  - id: tempObjRadiadorSalaJuegos
    channelTypeUID: mqtt:number
    label: Temperatura objetivo Radiador sala de juegos
    description: ""
    configuration:
      min: 5
      formatBeforePublish: "%.1f"
      max: 30
      commandTopic: cmnd/tasmotaSalaJuegos/EQ3/radiadorSalaJuegos/settemp
      step: 0.5
      stateTopic: stat/EQ3/radiadorSalaJuegos
      transformationPattern: JSONPATH:$.temp

It seems to work now, it sends the output formatted as 22.5 for example.

But it has some strange behaviour (it some times work and others returns to previous value) that I will explain later, first I want to do more tests in order to explain the problem correctly.

MQTT
I had mixed concepts about MQTT QOS and retain messages.
I now see that what I was trying to achieve was just retain message in order to be sure it reached the device.

But as you say then the device can received it twice, and in this case the MQTT device that receives the message is a TASMOTA ESP32 that transforms it to bluetooth messages to the end EQ3 valve.
And I think BLE is not reliable in that aspect, the device does not stablished connections with TASMOTA driver (as they are not paired), just broadcast messages and receives other messages when it becomes awaken again.

So I won’t mess up with QOS or retain for now, I will add retain fot messages if it is needed later.

I did not understand well the last part of your explanation.
The item is linked to the channel, and a slider has that item as its slider item, so If I understand it well, when I change the value in the slider, the item gets upadated and passes the value to the channel to send the MQTT command topic.

There is no active rule or script.

When I change the value in the slider, in console I can see that Item xxxx has changed from YY to ZZ and no error.

I see the cmnd/…/settemp MQTT message, but the value sometimes is updated and correct but not others.

When it fails it returns to the old value.

For example, the valve state indicates a 15º temp and slider reflects it correctly.

I change the temp in the slider to 10º and see the message in console stating the Item has been changed from 15º to 10º.

And few moments later, it says again that the item has been updated from 10º back to 15 and the slilder returns to 15.

I have an idea of what may be happening, but have to elaborate it better.

Well, in this case the unit of the incoming value is the same as the internal units used in openHAB and the units I want to display.

But of course it is important to have the correct units.

The unit of the valve might be ºF instead, and need to be converted to ºC as it seems to be the units openHAB expect.

The user may want to display the temperature in ºK and set that acorrdingly in the slider.

So the unit in the channel should reflect ºF and the system when receives the value will chan from ºF to ºC to save it as a number. The slider should convert from ºC to ºK to display it.

So, yes units are important when you want to display things in different units.

I have a problem with the fmiweather forecast thing, as in the precipitation intensity channel it is defined as number:Speed and nobody stablished the unit to be mm/h.
So when you display it is shown as km/h.

I don’t use it myself so I was just assuming since the error seemed to be coming from SCALE and was a parse error. Maybe I was wrong. It could be something else, maybe another side effect of the weird way MQTT binding handles units.

This is one place where using the right word/OH concept is important. In this case the Item is commanded.

There are two ways to interact with an Item’s state: commands and updates.

A command will go to the Item, through the Link and to the Binding and cause the binding to take action on the command (e.g. send the MQTT message). The Item does not change state in response to a command. Some commands have no equivalent state, for example you can command a Dimmer Item with INCREASE. MyDimmer.state will never be INCREASE though.

An update is how one changes the state of an Item. The binding never sees an update. It’s only seen by OH.

So how does an Item change state after a command? There are two options. By default, a little service in OH called “autoupdate” will see the command and attempt to predict what state the Item should become and update the Item to that value (e.g. add 5 to the current state of a Dimmer when an INCREASE command is received). Autoupdate is turned on by default by can and should be turned off if the Item is updated by the binding with new states in a timely manner. When autoupdate is off, the Item will never change state in response to a command until the device reports back that it’s in a new state.

So in this case, when you interact with an Item in the UI, it sends commands to that Item. And commands should go to the binding and out to the device.

See where? If you take one thing from my previous reply take this. You must look at both openhab.log and events.log to debug any problem you are having with OH. You can’t rely on the UI because the UI may be lying to you. You need to see what is actually happening with your Items and for that you need to look at events.log. That will show you changes, commands, and what autoupdate is doing.

You will never see errors in events.log. For errors you need to look at openhab.log.

MQTTExplorer will show you every message received, even if it’s the same message. When it is not correct, is it still receiving the message? Or is the message not sent at all?

In cases like this seeing the full set of events on the Item in events.log is going to be critical.

Did the device report a new state that’s the old value? This is starting to look less like an OH problem and more like your device isn’t actually changing to 15, or for some reason reverting back. When it does that it reports that state, as it should and OH updates accordingly.

If you ever actually need to do this come back and ask. It doesn’t work with MQTT right now as you would expect and you need a JavaScript transformation to handle it.

Or do math.

So go to that Item, add State Description metadata and set the pattern to %.1f mm/h. That sort of thing is kind of the whole point of units of measurement.

I was meaning that I was seeing in the console log, using log:tail command.

Yes, then it is a commanded item.

I expect that when the slider changes the associated item receive the new value and uses the liked channel to send the MQTT command topic.

The valve will answer (may be sometime later) with a state MQTT message on the status topic with the new state and the new setpoint temp (that should be the commanded one) and that should be interpreted by the channel as a state change and state of all items linked to them should be updated.
I this case there is only one item linked to the channel.

So all the item states should reflect the new value (if the valve has answered correctly) may be a bit later, as the valve some times take a little bit to answer (few seconds).

But after being changed, a bit later, the log reflects a message saying it has been changed again to the old value.
Here the valve and slilder indicated 17º.
Then I changed the slider to 14º and in this is the log afterwards:

19:43:46.883 [INFO ] [openhab.event.ItemCommandEvent       ] - Item 'tempObjRadiadorSalaJuegos' received command 14
19:43:46.887 [INFO ] [openhab.event.ItemStatePredictedEvent] - Item 'tempObjRadiadorSalaJuegos' predicted to become 14
19:43:46.929 [INFO ] [openhab.event.ItemStateChangedEvent  ] - Item 'tempObjRadiadorSalaJuegos' changed from 17 °C to 14 °C
19:43:50.719 [INFO ] [openhab.event.ItemStateChangedEvent  ] - Item 'tempObjRadiadorSalaJuegos' changed from 14 °C to 17 °C

In MQQT explorer the cmnd/tasmotaSalaJuegos/EQ3/radiadorSalaJuegos/settemp cotains 17.

But I think there are to commands sent, one first with 14º (that you have not time to see in mqtt explorer, as it polls values not that often) and a second one returning it to 17º.

But don’t understand why that happends.

The only think I can think of is that openHAB reads the state topic before the new answer is received and reads the previos temp 17º, and interprets it as a new change in value.

When I send the command topic to change settemp using MQTT explorer, all works as expected, and the slider shows the correct updated temperature, and the valves updates it correctly.

May be the problem is with autoupdate, as the valves responds with the value and the state is received in intervals (sent by the gateway which polls ble regularly).

But if i turn it off it may affect other devices … i will seek infor for autoupdate.

One of the key takeaways from my previous reply is that commands and updates are not the same. Commands never change the state of an Item. Only the binding, a rule, or autoupdate ever changes the state of an Item.

Given the behavior described it is critical you understand this.

Sometimes that is how it works. With MQTT that’s often how you want it to work.

However that’s not how it works by default. By default it works like this:

  1. UI sends command to Item
  2. Command is passed through the Link to the Binding
  3. In parallel:
    a. the binding publishes the message
    b. autoupdate predicts the new state for the Item and updates it accordingly
  4. Sometime later the device publishes a state message
  5. The binding receives the message and updates the Item with the new state

That looks like what is happening in your logs. You send 14 and OH guesses that the new state will be 14. However, four seconds later the device reports that it’s still actually set to 17.

So the problem lies in your device. Why did it not change to 14?

In the mean time, turn off autoupdate and the round trip will look like:

  1. UI sends command to Item
  2. Command is passed through the Link to the Binding
  3. the binding publishes the message
  4. Sometime later the device publishes a state message
  5. The binding receives the message and updates the Item with the new state

But in this case you will see that the Item never changes to 14. It will remain 17 because the device is never reporting that it changed.

That comes from your device.

You’ve got a Tasmota something between openHAB and the EQ3 valve, haven’t you? When does Tasmota send you updates -before the valve has done its thing?
I’m guessing Tasmota responds to commands with “this is the way it is right now” i.e. “old” status.
Is there another Tasmota topic telling you when the EQ3 really changes?

When I send the command topic manually using mqtt explorer it works perfectly.
The devices receives it and update the temp in the display, and a few seconds later I see the updated state topic in MQTT with the cmd=settemp result=ok and temp=14 all correct and openHAB receives the state update and updates the slider correctly reflecting new value.

Some commands are queued by the valve, meaning that it does not perform the tas inmediatly, and it answers with the state and result=“queue” and the updated value not changed yet. When the valve updates the value, it sends another state update with result=ok and the new value.

But it does not seem to be the case with settemp, as when I do it manually, allways answers with the new value and result=ok.

My guess is that when the command topic is sent, the state is read before the valve has answered with the new state.

I will try disabling autoupdate.

Thank you, I have done this and it works correctly, now it displays mm/h.
I did not know that item metadata could do such kind of things. Great!!

Yes there is a tasmota in between, it is the gateway to transform mqtt messages to ble and viceversa.

When I send mqtt command topic to the broker manually, the answer is {cmd: settemp, result:ok, temp: xx } being xx the correct value I sent to it.
So I don’t think there is a problem with that.

But some commands are queued, they are not executed inmediatly and then it responds with an state that is { cmd: commandGiven, result:queue, …} in that cases the state provides still the old values as it has not been stell changed.

Tasmota polls the devices from time to time and updates the state topics, in that case the state would be { cmd:poll, result:ok,…}

But as I said, settemp is not queued (when i send the topic command).

The problem is that i cannot see the messages sent directly to the broker, mqtt updates the topices from time to time and you may have miss some updates.

Again be careful with the way you think about this stuff.

OH doesn’t read the state topic. It is sent a message published to that topic when it’s published to that topic. If OH get’s a message and updates the state of an Item, it’s because something published a message to that topic. And at this point the only thing we know of that would publish to that topic is your Tasmota device.

There is a “History” field on the right. Click on the topic, open History and if the topic has a number it will present a chart showing the past states.

So it is not possible that it receives the old state if the tasmota (the valve gateway) has not sent a new state message.

Well will try to disable autoupdate and see if I can see the message topics send from openHAB and received by the tasmota and viceversa.

No, the, there is no command topic that sets the value to 14º, only 17.
openHAB seems that never sends the command changing the value changed in the slider, it detects the change in the item, and another change (I don’t know where it comes from) that returns it to the old value, 17.
And then it send a command topic asking for 17º, I have new topics with the same value each time I try to change the value.

So there is no message from the tasmota as the command changin to 14º seems that never have been sent.

Maybe you could show us these things, please.