MQTT sub to obtain default value

I have built a ESP chip with relay, connected to a solenoid to control a garden sprinkler. It’s coded in Arduino IDE and simply uses MQTT for communication (eg: enable/disable, sending status, etc), The “Run every X hours” is controlled by OpenHAB itself (so the ESP subscribes to the topic, and OpenHAB will publish to the ESP that “X hours” has occurred and to run for a duration of Y minutes. OpenHAB also has an item for “Runtime in minutes” …

Fairly simple, with the main items as follows:

Items:

Number          sprinklerRunEvery               "Run every (hr) [%.0f]"              <flow>
Number          sprinklerDuration               "Run duration (min) [%.0f]"          <time>                                   { mqtt=">[mqttbroker:openhab/sprinkler/duration:command:*:${command}]" }`

Sitemap:

Setpoint item=sprinklerRunEvery minValue=1 maxValue=24 step=1
Setpoint item=sprinklerDuration minValue=1 maxValue=30 step=1

The problem is, when the ESP chip boots up, it subscribes to the MQTT “duration” topic above, however it does not get sent the default value that’s currently set for the duration. It will only get a call back if I click to increment or decrement the duration. What I need, is when the Arduino subscribes to the above topic, for OpenHAB to send it the current “duration” value. As mentioned, if I manually click in OpenHAB to say increment the set point, then OpenHAB updates the topic, which in turn I see the value get to the ESP chip via the debug console. I figured when something subscribes to an MQTT topic, it would get a call back with the current value in that topic.

I know this will be easy enough using “publish(mqttbroker…” within a rule, so when the “run every X hours” is due, then to publish the interval first, then publish to trigger the sprinkler on. However is there anyway for the ESP to pickup this value off OpenHAB as soon as it subscribes to the topic?

It is up to the Broker to send the “stored” MQTT message to the client (ESP) that will subscribe to the topic.
From OH2 side, try to set <broker_alias>.retain=true in your /etc/openhab2/services/mqtt.cfg file to see if this helps.

openHAB doesn’t know when a new client connects to the broker. You could setup a solution that the broker would notify OH2 on client connections and use this info to fire a rule (but that’s too complex versus the retain option).

Google shows for MQTT “Retain-Flag”

Sources:
i) https://www.hivemq.com/blog/mqtt-essentials-part-4-mqtt-publish-subscribe-unsubscribe
ii) https://www.hivemq.com/blog/mqtt-essentials-part-8-retained-messages
iii) http://www.steves-internet-guide.com/mqtt-retained-messages-example/

1 Like

Thanks Dim, retain flag in config file did the trick.

1 Like

Note this could cause some problems. That setting will cause ALL messages to ALL topics to be retained. So if you have an actuator (e.g. turn on a light, open a garage door opener, etc) the actuator will act as if it is seeing that command again. That is no big deal for something like a light, but you don’t want your garage door opener going up every time you lose power.

Clearly one can work around this but they need to know what is going on. My garage door opener was offline for months before I discovered why they kept going up when the RPi wired to them rebooted or lost network.

The key behavior is that it will send the last retained message when any client connects, even if that client has already received that message.

Indeed you are correct Rich…

Just found that when I rebooted OpenHAB, my front door just unlocked and my TV turned on!
Think I’ll turn the RetainFlag off and do this programmatically.

Cheers

Correct.
That would be a nice enhancement request: To set the retain flag on the item config level
Maybe I will raise a PR against the mqtt1 addon :slight_smile:

Note: Restarting OH2 would cause issues with the retained messages if rules are set up to fire on item states bound to mqtt topics that contain retained messages…
The most usual negative side-effect would be associated with the remote device rebooting and subscribing to the broker and receiving again the retained mqtt message

2 Likes

There are three things in that context:

  1. the broker can retain on topic level - but you have to configure the broker accordingly and I see no chance to trigger that from openHAB
  2. the message can contain a retain=true flag - but I can’t see on how we can address one single message in openHAB
  3. but - as you pointed out - we could add an attribute on item-level to retain messages sent from that specific item

ad 1)
I think we can’t do that directly - should be an HowTo on how to manipulate the Broker.

ad 2)
I don’t see a solution other than to have some configuration with “retained topics” in openHAB, which gets parsed before every MQTT publishing from OH - I feel overhead and perfomance issue

ad 3)
this would be the solution to-go! but we should think of the implications. I vote for retaining this specific item’s messages - either from a item-configuration perspective and from a eventbus-configuration. So, if the item gets published, it shouldn’t matter if it was from item-configuration or from eventbus-configuration. (MQTT-persistence already does that, doesn’t it?)

Option 4.

Create multiple broker configs in mqtt.cfg, one with retain and one without. Then use the desired broker in the Item config.

You will have to use a different clientID for the second broker config.

Example:

mosquitto.url=tcp://localhost:1883
mosquitto.clientId=openhab
mosquitto.user=user
mosquitto.pwd=password
mosquitto.retain=false

retain.url=tcp://localhost:1883
retain.clientId=openhabRetain
retain.user=user
retain.pwd=password
retain.retain=true

Given this workaround, I wonder if a PR is really needed.

In reference to 1, I don’t see anything in mosquitto.conf that would let me set the retain on a given topic. I didn’t look deeply into it though so I may have missed it. But any tutorial would be specific to the broker. There are several other viable brokers avaialble (HiveMQ, RabbitMQ, etc) and the instructions for those would be different.

2 would be more inline with how MQTT appears to be designed to work. It might make sense to do this for the publish action but I agree, I don;t think it is something we would want on the bindings. I just don’t see a case where we would need to do that at the Item level.

3 isn’t unreasonable and it would be my first thought. In addition to the retain the QOS should be supported as well.

But, given the devs are working furiously on MQTT 2, I wonder if we should stick to 4 for now. We can get there from here wihtout changes to the code.

3 Likes

that is a very, very good idea :slight_smile:

I read on this on hivemq the other day. But could be a specific solution.

Besides: option 4 is indeed genius.

I’ve often wondered if I should be using HiveMQ instead of Mosquitto. Every time I search for any information on MQTT I always end up on their site.

I wish I had thought of this before. I was helping someone with a QOS issue where it would have been really helpful to use a different QOS for different Items and I can’t find that thread anymore.

1 Like

I posted this elsewhere, however it may actually be an extension to my initial problem here. After setting retain to true, and then no longer wanting it and setting back to false, it seems that it still retains the settings and reinstates them. This is causing issues with sonoff devices rebooting continuously (after being sent a reboot command once, it seems to “stick” and repeat over and over)

If I sub to the topic:

pi@raspberrypi:~ $ mosquitto_sub -v -t openhab/sonoff/#
openhab/sonoff/pool/LWT Offline
openhab/sonoff/pool/cmnd/restart 1
openhab/sonoff/maintowelrail/LWT Offline
openhab/sonoff/maintowelrail/cmnd/POWER OFF
openhab/sonoff/maintowelrail/cmnd/restart 1

And then in another cmd window, publish restart as “0”, which of course adds the following to the bottom of the list:

openhab/sonoff/maintowelrail/cmnd/restart 0

And then I cancel and re-run the subscription, I get:

pi@raspberrypi:~ $ mosquitto_sub -v -t openhab/sonoff/#
openhab/sonoff/pool/LWT Offline
openhab/sonoff/pool/cmnd/restart 1
openhab/sonoff/maintowelrail/LWT Offline
openhab/sonoff/maintowelrail/cmnd/POWER OFF
openhab/sonoff/maintowelrail/cmnd/restart 1

Restart is back to 1 again. It doesn’t “save” the restart 0 at all. This constantly runs over and over, so every 3-4 seconds the sonoff device reboots. My default persistence is mysql.

(in fact, if I subscribe to openhab/#, I get about a dozen items displayed - from somewhere, I have no idea where. Not from mysql, as I dropped the database and recreated. I’ve renamed all other persistence files to .OLD and rebooted, and these dozen or so items still appear. HELP?!)

And one thing I don’t understand, is if I’m using mysql.persist as default, does that mean mqtt.persist is no longer used? Or does mqtt.persist save/restore MQTT related items, and mysql does everything else?

Also, here is the web console output from the sonoff, as you can see its been quite a number of reboots before I’ve noticed this!!! This page clears and it reboots over and over about 3-4 seconds in between each.

00:00:00 Cnfg: Load from flash at F6 and count 14238
00:00:00 APP: Bootcount 13516
00:00:00 APP: Project sonoff SonoffMainTowelRail (Topic maintowelrail, Fallback DVES_B4AE80, GroupTopic sonoffs) Version 5.5.1
00:00:00 Cnfg: Save (1648 bytes) to flash at F5 and count 14239
00:00:00 Wifi: Attempting connection...
00:00:00 Wifi: Patch issue 2186
00:00:00 Wifi: Connecting to AP1 iotbam in mode 11N as maintowelrail...
00:00:01 Wifi: Attempting connection...
00:00:02 Wifi: Attempting connection...
00:00:03 Wifi: Attempting connection...
00:00:04 Wifi: Attempting connection...
00:00:05 Wifi: Attempting connection...
00:00:06 Wifi: Connected
00:00:06 mDNS: Initialized
00:00:06 HTTP: Webserver active on maintowelrail.local with IP address 172.16.223.100
00:00:07 RTC: (UTC) Tue Feb 27 01:59:15 2018
00:00:07 RTC: (DST) Sun Mar 25 02:00:00 2018
00:00:07 RTC: (STD) Sun Oct 28 03:00:00 2018
02:59:16 MQTT: Attempting connection...
02:59:17 mDNS: Query done with 0 mqtt services found
02:59:17 MQTT: Connected
02:59:17 MQTT: openhab/sonoff/maintowelrail/LWT = Online (retained)
02:59:17 MQTT: openhab/sonoff/maintowelrail/cmnd/POWER = 
02:59:17 RSLT: DataCb Group 0, Index 1, Type POWER, Data OFF (OFF)
02:59:17 MQTT: openhab/sonoff/maintowelrail/RESULT = {"POWER":"OFF"}
02:59:17 MQTT: openhab/sonoff/maintowelrail/POWER = OFF
02:59:17 MQTT: openhab/sonoff/maintowelrail/INFO1 = {"Module":"Sonoff Basic", "Version":"5.5.1", "FallbackTopic":"DVES_B4AE80", "GroupTopic":"sonoffs"}
02:59:17 MQTT: openhab/sonoff/maintowelrail/INFO2 = {"WebserverMode":"Admin", "Hostname":"maintowelrail", "IPaddress":"172.16.223.100"}
02:59:17 MQTT: openhab/sonoff/maintowelrail/INFO3 = {"Started":"Software/System restart"}
02:59:17 RSLT: DataCb Group 0, Index 1, Type RESTART, Data 1 (1)
02:59:17 MQTT: openhab/sonoff/maintowelrail/RESULT = {"Restart":"Restarting"}

F!@#$king hell… I had persistence enabled in the /etc/mosquitto/mosquitto.conf file…

ARGH! Ignore this…!

Unfortunately, this is caused by the fact that the retain flag gets applied to individual messages. Any new messages you send after changing the retain flag in OH will no longer have the retain flag applied, but any messages you sent before changing the setting will still have that flag and those messages will still stick around.

Here is a link to a script (see the answers) that uses mosquitto_pub to clear out those retained messages. Essentially you need to publish a zero length retained message to the topic and that will clear them out.

The behavior you are seeing is not related to persistence nor MySQL.

mqtt.persist was kind of a poor man’s MQTT Event Bus implementation. It publishes Item’s state changes, updates, or commands (depending on how it is configured) just like MySQL saves these to the database. I think it came before the MQTT Event Bus and as far as I’m concerned its use should be considered deprecated. This also has nothing to do with the behavior you are seeing.

That could be a problem too. Glad that fixed it.

Thanks Rich.

So I have my mqsql persistence file as follows, however the entries, specifically “powermeter…” that I’m testing at the moment, do not restore when OpenHAB starts up. I have powermeter entries logging to RRD4J charts so i could do by code to say on startup, then read powermeteritem.maximumSince(now.MinusHours(24), “rrd4j”).state and set the item that way - but surely the persistence with the restore on startup setting should do the trick? I tried lowercase “items” instead of “Items” based on another post with someone having issues, however has made no difference.

// mysql persistence file
Strategies {
	everyMinute : "0 * * * * ?"
	default : everyChange
}
items {
	* : strategy = everyChange, everyDay
	Temperature*,Weather_Chart* : strategy = everyMinute, restoreOnStartup
	powermeter* : strategy = everyChange, restoreOnStartup
	sprinkler* : strategy = everyChange, restoreOnStartup
	main* : strategy = everyChange, restoreOnStartup
	alarm* : strategy = everyChange, restoreOnStartup
	hrv* : strategy = everyChange, restoreOnStartup
}
  • first of all, it’s Items (with a capital I).
  • second of all, please have a look in the logs after changing and saving the persist-file, it should’ve at least told you, that items error. so please post the log and we can have a look
  • third of all, if you didn’t have a Strategy defined for everyDay, the persistence can’t work, can it? Again: have a look in the logs - it tells you!
  • fourth of all, you really want to save every item on everyChange? even the ones, you won’t need persisted? My tipp would be to have the *-Strategy at least only everyDay. but that’s not relevant for your issue.

powermeter is a Group? If not that is the problem. The * is not a wild card. In this context, powermeter* means all members of the poweremeter Group, not all Items whose name starts with poweremeter.

Also, I use a capital I for Items in my .persist files.

1 Like

Ugh, no powermeter is not a group. And yes I thought it was a wildcard.

Suppose I should RTFM!

Thanks again!

Hmm, maybe spoke too soon. I’ve changed to group names, still no go. Values are not restored (for example, after I save my items file and openhab refreshes, or rebooting)

Here are my items:

/* Power Meter */
Number          powermeterState                  "Power Meter [MAP(status.map):%s]"	 <settings>         (gPowerMeter)                            { mqtt="<[mqttbroker:openhab/powermeter/status:state:default]" }
String          powermeterIPAddress              "Power Meter IP [%s]"               <network>          (gPowerMeter)                            { mqtt="<[mqttbroker:openhab/powermeter/ipaddress:state:default]" }
Number          powermeterCounter                "kWh counter (per 20 secs)"         <energy>                                                    { mqtt="<[mqttbroker:openhab/powermeter/counter:state:default]" }
Number          powermeterLoadkW                 "Current Load [%.3f kW]"            <energy>          
Number          powermeterDailykWh               "Daily Usage [%.3f kWh]"            <energy>           (gPowerMeter)
Number          powermeterMonthlykWh             "Monthly Usage [%.0f kWh]"          <energy>           (gPowerMeter)
Number			powermeter_Chart_Period_L        "Chart Period"                                         (gPowerMeter)
Number			powermeter_Chart_Period_D        "Chart Period"                                         (gPowerMeter)
Number			powermeter_Chart_Period_M        "Chart Period"                                         (gPowerMeter)

Here is my updated mysql.persist file:

// mysql persistence file
Strategies {
	everyMinute : "0 * * * * ?"
	everyHour : "0 0 * * * ?"
	everyDay  : "0 0 0 * * ?"	
	default = everyChange
}
Items {
	// * : strategy = everyChange, everyDay
	gWeather*,gWeather_Chart* : strategy = everyMinute, restoreOnStartup
	gPowerMeter* : strategy = everyChange, restoreOnStartup
	gSprinkler* : strategy = everyChange, restoreOnStartup
	gBathroom* : strategy = everyChange, restoreOnStartup
	gAlarm* : strategy = everyChange, restoreOnStartup
	gHRV* : strategy = everyChange, restoreOnStartup
}

I also have a rule that sets a proxy item to ON when startup occurs, and OFF once start up is complete, and other rules check that and don’t update - for example, power usage if the system is starting up (so as to not interfere with the incrementing of the power usage)

  1. What’s in the logs regarding the two problems (restoreOnStartup is not connected with your switch - unless that one is restored also)?
  2. does your mysql get populated at all?