How do you name your MQTT topics?

When I program devices with, say, Tasmota, the default topic names tend start with the general category followed by the devoce name, like

tele/shelly-045678/state and
cmnd/sonoff-045678/power etc

but it seemed more natural to me to put the device first, and just number types of device as I buy them rather than using MAC addresses, so things would begin

sonoff_s20_1/tele/...
sonoff_s20_1/cmnd/...

That kind of made sense because I wasn’t always quite sure where I was going to use them when I first programmed them. I would give them more useful names in Home Assistant once they were actually plugged in/connected up, or whatever.

Now, however, I’m tempted to go back and use topic names based on locations in the house:

upstairs/laundry/tumbledryer/stat
outside/garage/light/1/cmnd/power

etc, since a human-readable name is always going to be more useful…
(I wonder, as an aside, if the HA MQTT auto-discovery stuff would pick up the new topics for a device if I changed them, or whether I’d need to delete the devices and re-add them, or start editing the .storage directory?)

Anyway, how do you name yours? In a flattish structure? By device, by type? Or in a more hierarchical fashion? Or do you just use the defaults?

I guess this might be driven by the kinds of subscriptions you think a system is going to make, and how that maps onto the slightly limited wildcard options available in MQTT. Are you, or your HA system, more likely to want to subscribe to all the topics relating to the garage, or all the topics relating to commands sent to lights, or…?

Keen to get ideas before I do a big tidying exercise :slight_smile:

I use hierarchical topics, based on the device’s location in my home.

To automate my home, I use two home automation systems: Premise and Home Assistant. I started using Premise in 2008 and it continues to run all automation logic and integrate my home’s devices. Home Assistant is used to provide a UI and to integrate with devices Premise cannot. The two systems communicate via MQTT.

Just like Home Assistant, Premise allows me to define areas. However, it permits nested areas thereby allowing me to model my home as a hierarchy of areas and devices. The default name of the hierarchy’s root node is “Home”. Below that I’ve created House, Outside, and Shed.

  • Within House there are floors (First, Second, etc) with rooms (Living, Dining, etc) and the attached Garage.
  • Within Outside there are areas like Porch, Patio, etc.
Home
  - House
    + First
    + Second
    - Garage
      - WorkLight
  - Outside
    - Porch
      - Sconces
      - Fountain
    + Patio
    + FrontYard
    + BackYard
  + Shed

That means the ‘fully qualified’ name of WorkLight is:

Home/House/Garage/WorkLight

Premise’s hierarchical naming scheme makes it very easy to assign an MQTT topic to each device.

For example, a dimmable light has two key properties:

  1. PowerState
  2. Brightness

So the MQTT state_topic for WorkLight’s Powerstate is:

premise/home/house/garage/worklight/powerstate

The MQTT command_topic for WorkLight’s Powerstate is:

premise/command/home/house/garage/worklight/powerstate

It also allows other systems to selectively subscribe to topics. For example, if you only wanted to subscribe to devices on the first floor:

premise/home/house/first/+

What this scheme cannot support is the ability to subscribe to the topics of a particular type of device (like all lights or all doors). To support that, it would need the device’s type specified near the root node. I don’t have a need for that so it is not included in the topic.


For MQTT Discovery, here is an example of the topic and payload to make Home Assistant create an entity called light.garage_worklight:

Topic:

homeassistant/light/garage_worklight/config

Payload:

{
  "name": "Garage WorkLight",
  "unique_id": "home_house_garage_worklight",
  "cmd_t": "premise/command/home/house/garage/worklight/powerstate",
  "stat_t": "premise/home/house/garage/worklight/powerstate",
  "pl_on": "1",
  "pl_off": "0",
  "bri_scl": 100,
  "bri_stat_t": "premise/home/house/garage/worklight/brightness",
  "bri_cmd_t": "premise/command/home/house/garage/worklight/brightness",
  "on_cmd_type": "brightness"
}
2 Likes

Thanks for a detailed response. I like your scheme…

So I have 9 devices… 7 sonoff and 2 nodemcu… sonoff topic is just sonoff1… etc… But I use MQTT discovery and just refer to them as the switch name they get configured with. I have not done anything cute at all with anything else…

I bookmarked this post as a good philosophy to follow. https://tinkerman.cat/post/mqtt-topic-naming-convention

But in practice I just go with whatever the default topic is set. I haven’t found enough practical advantages to spend time on defining a structure myself.

2 Likes

FWIW, I have 127 MQTT topics representing all the properties of every device managed by Premise (includes 6 scenes).

Here’s a screenshot from MQTT Explorer showing the shed door’s sensor property (dooropened). The hierarchical structure, based on location, makes it easy to find a device’s topic(s) and payload(s).

Screenshot from 2020-02-07 08-53-06

Although I tend to assign all devices unique names, I could give them generic names without causing duplication. That’s because the hierarchical, location-based scheme ensures their ‘fully qualified’ names remain unique:

home/house/first/foyer/ceilinglight
home/house/second/hallway/ceilinglight
home/house/garage/door
home/shed/door

If I were to adopt the convention of ‘generic names’ then, for use with Home Assistant, I would combine the device’s generic name and its location (room) to uniquely identify it. It’s fairly easy to convert this string home/house/garage/door to this garage_door.

foyer_ceilinglight
hallway_ceilinglight
garage_door
shed_door

Another alternative, mentioned previously, is to include the device type in the topic. For example:

premise/status/light/home/house/garage/worklight/powerstate

I added the word status to differentiate it from command (you’ll understand why in a moment). Given this structure, we can subscribe to topics based on device-type and/or device-location.

All lights in the house:

premise/status/light/home/house/+

All doors on the first floor of the house:

premise/status/door/home/house/first/+

All devices in the garage:

premise/status/+/home/house/garage/+

The other extreme is a flat naming structure:

garage_worklight/powerstate
garage_worklight/brightness
garage_door/state
garage_side_door/state

This is a serviceable scheme provided you don’t need much flexibility (like subscribing to topics based on location or type) and don’t foresee managing more than a few dozen topics.

The real question is : how do you create a structure if you have a lot of different integrations that use mqtt ?

I have about 40 tasmotized shellies and sonoffs : they use devicename/topic
I have about 15 zigbee2mqtt devices (and more I still have to install) : they use zigbee2mqtt/devicename/topic
I have 2 rfbridges flashed with openmqttgateway : they use home/openmqttgateway(number)/code
I have a rfbridge using espRfLinkMQTT : here it is rflink/device
my sensors coming from rfbridges / rflink / self defined mqtt use sensor/devicename
ESPEasy uses ESP_Easy/

It is difficult to get a sensible naming strategy with all these different integrations.

Yes, though I like the idea of reflecting the origin or destination of the MQTT messages. With zigbee2mqtt, you aren’t addressing the devices directly; they need to be proxied through that gateway, so it seems sensible to me to group those together.

Similarly, if you have more than one home automation system as in the Premise discussions above, then it make make sense to divide the space.

But if the devices themselves are communicating directly with a shared broker and may be relevant to more than one system, it seems sensible to find another good way to group them.