Connecting multi-channel Items (using MQTT) – how is it intended to work?

  • Platform information:
    • openHABian
    • openHAB 2.4

I am trying to setup a connection between two openHABs (home and office) with the aim to be able to remotely control the thermostat in my office from an item on my home sitemap. But I am running into problems that I’ve been trying to solve since days now. I hope someone can help me!

My setup so far:

  1. I’ve installed the new MQTT binding on both openHABs, plus on the one at home, I’ve installed the Embedded MQTT Broker.
  2. On both openHABs, I’ve added an MQTT Broker, both connecting to the Embedded Broker at home.
  3. On both openHABs, I’ve added a Generic MQTT Thing, using the previously added MQTT Broker as their bridges.
  4. On the Generic MQTT Things, I’ve added a channel, with the state of the one being the command of the other. Looks like that:
Thing mqtt:topic:084b7bfa:officeWallthermostat  "MQTT New Office Wall Thermostat"
     (mqtt:broker:084b7bfa) @ "Office"
{
    Channels:
        Type number : set_temp "Set Temperature"
            [
                stateTopic = "generic/test/wallthermostat/setTemp/state",
                commandTopic = "generic/test/wallthermostat/setTemp/command"
            ]
}

On the other openHAB, state and command are reversed like this:

                stateTopic = "generic/test/wallthermostat/setTemp/command",
                commandTopic = "generic/test/wallthermostat/setTemp/state"

(Note that I played around with both PaperUI as well as configuration files, but the results are identical.)

Ob both ends, I then created an Item from these channels.

Now what works is that I can change the temperature on one side and the other Item follows almost instantly, and that works in both directions (tested in PaperUI > Control). If the state changes on one end, the new value gets send as a command to the other end. Seems perfect. Not sure, if this is the intended way to do it, though? But I couldn’t get it to work unless I reversed the topics.

As my next step, I’ve tried to connect the Item on the office OpenHAB with the real world thermostat Thing by adding the thermostat’s channel to the Item like so:

Number OfficeThermostat_SetTemperature "Office Set Temperature" (gOfficeThermostat) [ "TargetTemperature" ] {channel="max:wallthermostat:XEQ1633453:XKF0042762:set_temp", "channel="mqtt:topic:ca454cfb:set_temp"}

The problem I’m now having is that it does not update in all directions. I’ve played with the follow profile, but there’s always one direction that stops working:

  • Leaving all at profile default: when updating the thermostat, the local openHAB item gets updated, but not the remote one
  • Setting the MQ channel link to follow: changing the remote item updates neither the local item nor the thermostat itself
  • Setting the thermostat channel link to follow: changes at the thermostat are not reflected in the items
  • Setting both channel links to follow: changes at the thermostat as well as changes at the remote item do not propagate

The closest I can get is with both channel links set to default. Then everything works expect that changes a the thermostat are reflected in the local item, but do not propagate over MQ to the remote item. Any ideas?

One problem I have is that I’not sure what the follow profile actually does. The docs state:

The term “follow” in this case means that any state that is sent to an Item will be forwarded from this Item to any linked Channel with the follow Profile. It takes state updates on an Item and sends them as a command onto the Channel.

From that, I understand and would expect that when I link the MQTT items with profile follow, I change of state in one would send the new value as a command to the other, but that doesn’t seem to happen. With log level debug, I see:

2019-01-31 16:21:21.622 [DEBUG] [nal.handler.AbstractMQTTThingHandler] - Successfully published value 24.0 to topic generic/test/office/setTemperature/state

So the value is published as a new state, but not as a command. That’s why I finally reversed the state and the command topics between the two MQTT channels to make it work.

However, I admit I don’t understand what this says:

In the direction from the ThingHandler towards the Item, this Profile ignores state updates.

What does “in the direction from the ThingHandler” mean? Are these state updates from the physical device (like when I change the temperature at the thermostat itself)?

Btw, I also wondner why I get these log lines:

2019-01-31 16:19:00.342 [TRACE] [.MqttChannelStateDescriptionProvider] - Providing state description for channel max:bridge:NEQ1633453:free_mem

What is providing a state description to what (and what is a state description)? But that’s probably something different.

I would appreciate if someone could tell me if my approach is completely wrong? And give me some hint how to proceed?

Thanks for reading until here! :slight_smile:

UPDATE:

It seems I’ve found a work-around by using the variant with all profiles set to default. The (only) problem with that was that changes at the thermostat updated the local item, but not the remote one. So updates of the multi-channel item were obviously not passed on from one channel to the the other channel (nothing was logged).

I solved that with a rule:

var oldValue = null

rule "MQTT propagation"
when
	Item MQTTThing_MQTTOfficeSetTemperature received update
then
    if (oldValue != triggeringItem.state)   // to prevent an endless loop
    {
		logInfo(logname, "MQTT item resending update to {} (from {})", triggeringItem.state, oldValue)
		oldValue = triggeringItem.state
		triggeringItem.sendCommand(triggeringItem.state)
    }
end

However, I still think that either do I not properly understand how multi-channel items are supposed to work (especially with regard to the follow profile), or there is a bug somewhere that inhibits the proper update of changed values under certain circumstances?

I’ve made a series of tests. Maybe someone could help me understand the results.

The setup is as explained above:

Home Item ← → MQTT Thing channel ← → MQTT broker ← → MQTT Thing channel ← → Office Item ← → Thermostat Thing channel ← → Physical Thermostat

I’ve modified the profiles of both channels attached to the multi-channel Item Office Item, with the following results:

As you can see, none of the combinations work perfectly, with all profiles left at default still best…

In the general scheme of things,only commands sent to an Item get actioned by the channels/bindings of that Item.
State updates or changes are normally ignored by bindings.

The follow profile allows you to configure a channel to get force-fed updates as “simulated commands”.

MQTT is an unusual binding, in that it does allow for configuring to listen for updates as well as / instead of commands, and send an external message.
Whether that message gets turned into a command or an update at the other end, depends on the configuring at that end.

So you don’t strictly need follow profile for MQTT, it already has that capability.

I may well be wrong, but to me this seems contradictory to what the docs say (emphasis by me):

default : If you don’t specify any Profile, this Profile will be used. For State Channels, this means that states and commands are just propagated from the Channel to the Item and vice-versa without any changes.

Also, when I tried the profile follow on the MQTT channel, judging from the effect I saw as well as from what was logged, a state change from the other channel was not forwarded as a command over the MQTT channel, but still was sent as a new state. Since the docs state that follow causes state changes to be forwarded as command, to me that appears to be a possible bug.

Sorry to say that my work-around stopped working today. For some unknown reason, triggerItem is suddenly null when trying to use sendCommand on it?!? But it’s available in the lines before that??

[INFO ] [clipse.smarthome.model.script.mqtt#1] - MQTT item resending update to 22.5 (from 22.0)
[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'MQTT propagation work-around': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.sendCommand(org.eclipse.smarthome.core.items.Item,java.lang.String) on instance: null

I was talking about the general case, how commands and updates flow through channels. Profiles, which are completely optional, allow some workarounds to the general scheme. That’s what they’re for, tailoring.

I don’t think profile is needed here at all, folk have been linking OH instances with MQTT before profiles were invented.

Absolutely right. MQTT just passes messages. Whether it gets handled as a command or as an update at the receiving openHAB is up to the way you’ve configured the MQTT channel.

Here’s a relevant discussion. The nitty gritty is MQTT-1, but the principles are the same.

Let’s take a step back, to clarify your objectives.

On Office-OH you have an Item XX with a “max” channel.
Any commands you issue, say by using a UI of Office-OH, will get passed to the device by the max channel. It’s not clear if your device responds with an update for the Item, but even if it doesn’t autoupdate will take care of that.
In the normal course of events, a command to Item XX will get passed to the device, and the Item will get updated shortly after. So far, so ordinary.

On a remote Home-OH you have an Item ZZ to mirror the office Item. You want to use the Home-OH UI to send commands to the office, so with Item ZZ on the sitemap in the usual way, you send commands to local Item ZZ.

Home Item ZZ needs an MQTT channel that listens for commands only, and sends a message to the office. You don’t want to send updates this way at all. That’s a pretty ordinary configuration (using commandTopic)

Home Item ZZ will also get updated by the local commands triggering autoupdate. If it were me, I’d disable that and rely on the remote update we get later.

Now you have to listen out for those messages at Office-OH, by having an MQTT channel set up. The unusual part of this channel is that you’ll use postCommand to trigger a command to Item XX instead of the usual update.
The command should end up going to the device via ‘max’ channel, and shortly cause an Item XX update same as a locally issued command.

All we have to do now is feed updates back from Office-OH to Home-OH, just so that you can see what’s what from home. I believe you will use a different MQTT topic for this backchannel.
You’d want an MQTT channel that listens for Item XX state updates, again this not the ordinary usage. You could do this MQTT1, but unfortunately the feature doesn’t yet exist in MQTT2 channels.
There is however a workaround using an MQTT action in rule. You’d trigger the rule from Item XX update. See


and the note about using OH 2.5

I believe trying to make this part work using a follow profile, in an effort to convert state updates into commands on the same Item, is going to lead to looping. Because commands usually provoke an update.
If you wanted to avoid OH2.5, I think you would need an additional dummy Item at Office-OH. Use follow profile or rule to convert update of Item XX into commands for dummy Item, have an MQTT channel on dummy Item sending messages on command in the ordinary way. The state of this Item is of no real interest.

Once you are sending messages from Office-OH, the Home-OH needs an ordinary channel updating state (stateTopic). Home Item-ZZ will therefore have two MQTT channels, “command-out” and “state-in” effectively.

1 Like

@rossko57, thank you very much for your detailed answer. Sorry for the delay, I’ve been unforeseeably away during the last few days, but now I will work through everything you’ve written.