[RELEASE] Simple MQTT Client Driver

Download: GitHub - sethkinast/hubitat-simple-mqtt

This driver allows your hub to subscribe and publish to topics via an MQTT broker. Each topic is represented as a child device, which makes it easy to incorporate topics into Rule Machine, dashboards, and more.

The goal of this driver is to act as a simple bridge between Hubitat and other MQTT-speaking devices. The driver is not aware of what devices are on your hub and it does not attempt to publish their state changes. If your goal is to map all of your hub's devices to MQTT topics, you likely want to use a different driver like MQTT Link.

Topics

Instead of devices, this driver is built around MQTT topics. You can register as many topics as you want and performance will not be affected, as a single MQTT connection is shared by all child devices.

Once you register a topic, it appears as a child device under the MQTT client. This allows you to use the topic in several ways.

Publishing to the topic

Each topic has the Notification capability, which lets Hubitat send a notification to the topic. The notification is sent as the payload of an MQTT message to the topic.

Subscribing to the topic

Each topic acts as a Button, a Switch, and a Variable for use in Rule Machine or other apps.

  • Button: Any message received to the topic (even a null message) will fire a Button 1 pushed event. This event fires every time a message is received, even if the message is the same.
  • Switch: If the message is on, off, true, or false, the topic's switch will turn on or off.
    If the switch is already on, Hubitat doesn't treat turning it on again as a new event, which means you can repeatedly publish the state of your device without firing a rule over and over.
  • Variable: Any other message will be stored in the variable field on the device, allowing you to listen for a Custom Attribute change in Rule Machine, or display the variable on a dashboard. This allows you to track water or fuel levels, temperatures, and more.

Bidirectional communication

You can use the same topic to both send and receive. However, note that the device will also receive its OWN messages (until Hubitat supports MQTT v5).

For many use cases this is OK, but be careful not to create an infinite loop. If you need better support for this scenario, please open an issue to discuss.

Why another MQTT driver?

None of the existing ones did what I wanted, haha :slight_smile: Most of the existing generic drivers are designed to mirror the devices on your hub to MQTT. I wanted a simpler client that I could use to publish and subscribe to arbitrary topics.

This driver is tiny (200 LOC with the child device driver) and has no companion app. It's a very thin layer around existing Hubitat concepts (Notification, Button, Switch, and Variable), which makes it lightweight and pretty intuitive. It doesn't use custom commands, which makes it nicer to integrate into Rules. It is more resilient than some of the others at properly reconnecting to the broker if it loses connection.

There are lots of alternatives that are mostly focused on mapping your Hubitat devices to topics. Check some of them out to see if they suit your needs better!

Examples

Pause ad blocking on Pihole

I had a virtual Button in a dashboard that pauses the Pihole for 5 minutes. In the same Rule Machine rule, I can now also Listen for Button 1 pushed on hubitat/pause_pihole, and then use Rule Machine to POST to https://pi.hole/api/dns/blocking

Decide if it's a work-from-home day

In Rule Machine, trigger at 7am M-F. If my presence sensor is Present, send a Notification to hubitat/work_from_home, which other devices on my network are listening for (like the coffee machine and the air conditioner).

Monitor solar production

My solar monitoring system publishes the total energy produced that day to hubitat/solar_production. I can use the variable attribute on this topic to display the value in a dashboard.

Monitor heating oil tank

I have a smart oil gauge in my tank that broadcasts the oil level to hubitat/oilTankLevel. I can use the variable attribute and fire a rule when the level gets too low. Because I need to make a numeric comparison, I have to convert the string payload to a number (see example under Known limitations)

Known limitations

  • Sending a notification on a device also triggers its button push (see Bidirectional communication section above)
  • JSON payloads are received but not parsed, because only one string variable attribute is available. Parsing arbitrary payloads in a way that is useful requires more thought.
  • Changing the topic prefix does not update child devices since that would break existing automations.
  • Rule Machine does not support Momentary buttons, which is why you have to check "Button 1 pushed" in rules instead.
  • MQTT payloads are always strings. Rather than include logic in the driver to try to parse payloads and publish a bunch of different attributes, the variable of the topic is always a string. If your topic publishes numbers, use a rule like this in Rule Machine to convert it. (h/t @at9 and @bertabcd1234 for setting me onto this)

9 Likes

Thankyou for putting this together!

Perfect timing, as I just restored my energy monitoring MQTT Topic stream(s), and needed to pull some of them back into Hubitat and WatchTower.

Here's what that looks like, with a small number of the Topics coming from my EM (Brultech GEM):

The two graphs in the middle, for Solar and for the Kitchen Fridge, are sourced over MQTT from their respective breakers, whilst the more granular Consumption (Power) data is coming from INNR outlets.

... and yes, it's gloomy here today, hence the low Solar-generation :wink:

2 Likes

Awesome! The exact use case I was looking for when I wrote this driver!

I made tweaks to the Driver code, to better support my use-case (PowerMeter data) and the rules I needed to support my graphs, and the WT graphs themselves.

I needed to add my Solar circuits to find the total-solar and, with the data-as-strings, this was painful to do in RM.

The changes were basic:

Simple MQTT Topic

  • Add declaration for PowerMeter capability, similar to how you support Switch (etc)

Simple MQTT Client

  • Added support in the else case to test if the payload isNumber, and set the power value

You mentioned this in your Known limitations, so I haven't submitted a PR to change it (but can if you'd like).

The rest of the mods were isolated to my Watchtower [visual] tweaks. These also got simpler with the numeric Timeseries

The relevant parts now look like:

and Solar/Generation Summation rule is simply:

2 Likes

Yeah I struggled with a good agnostic way for this. Because I'm using numbers that aren't power (tank fill level, temperature)

I think just dumping into power is probably better for your fork rather than the driver but happy to hear more ideas! Strong typing doesn't play well with what we're doing and Hubitat doesn't use Generics haha

There's a fairly small list of numeric Capabilities defined for this platform, and a somewhat smaller list of ones natively "point-n-click" in the UI.

When I first looked, I was hoping for a variable_number as part of Variable, but no joy there.

Things like level/depth/distance being obv ones in the IoT space that are missing.

The Energy space is well covered, with ones like CurrentMeter, EnergyMeter, PowerMeter and VoltageMeasurement

If I needed the other Energy ones, I was planning to overload it a little and do something akin to this hack:

        } else if (parsedMessage.payload) {
            events += [name: 'variable', value: parsedMessage.payload]
            if (parsedMessage.payload.isNumber()) {
                val = parsedMessage.payload.toDouble()
                events += [name: 'power', value: val]
                events += [name: 'energy', value: val]
                events += [name: 'voltage', value: val]
                events += [name: 'amperage', value: val]
            }
        }

TemperatureMeasurement exists, but the water levels (except for a PCT-based one for something else) are broadly missing.

Ok, for now I'll leave it in my personal copy.

1 Like

I found this alternative version from @bravenel:

image

Which requires two variables per device, but would allow everything to happen in Rule Machine.

The other thing I considered was just, like you said, a variable_num, that would be set anytime the MQTT payload was numeric. It just felt a little dirty so I didn't include it in v1.

@bravenel, there isn't a one-liner version of these two rules I'm missing, is there? Assign device attribute (string) to rule variable (decimal) as decimal ?

1 Like

If you are using a device attribute, then RM is only going to offer up numeric/decimal attributes to assign to a decimal variable. So, yeah, it takes 2 steps.

1 Like