Newbie question - how do I find the identity and topic for an mqtt message

Its actually not that complicated particularly if you have lots of switches / sensors.

If all you want is the switches, put mqtt discovery on the HA you want the switches on.

Where the actually switches are, put statestream on and these automations. It will populate all the switches. (you can amend for lights) . The first automation makes the config topic in mqtt so mqtt discovery and auto create them. The second automation will actually control the switches by looking the set topic and actuating the switch.

automation mqtt_config_entity_creator_switch:
  alias: mqtt_config_entity_creator_switch
  trigger:
    - platform: mqtt
      topic: 'homeassistant/switch/#'
  condition:
    condition: template
    value_template:  "{{ trigger.topic.split('/')[3] == 'state' }}"   
  action:
    - service: mqtt.publish
      data_template:
        topic: "homeassistant/switch/{{ trigger.topic.split('/')[2] }}/config"
        payload: "{\"name\": \"{{ trigger.topic.split('/')[2]| replace('_', ' ') | title }}\", \"device_class\": \"{{ trigger.payload }}\", \"pl_off\":\"off\", \"pl_on\":\"on\",  \"command_topic\": \"homeassistant/switch/{{ trigger.topic.split('/')[2] }}/set\" }"
        retain: true
automation mqtt_command_switch:
  alias: mqtt_command_switch
  trigger:
    - platform: mqtt
      topic: 'homeassistant/switch/#'
  condition:
    condition: template
    value_template:  "{{ trigger.topic.split('/')[3] == 'set' }}"
  action:
    - service_template: 'switch.turn_{{trigger.payload | lower }}'
      data_template:
        entity_id: switch.{{ trigger.topic.split('/')[2] }}

What you will need to do is to create the mqtt statestream setup on both servers and for simplicity just name them hassbian1 & hassbian2 (drop the “master”/“slave” nomenclature)

then you will subscribe to the created topic for the “state” of the device and publish to a command topic that you create.

say that you want to turn on the pool light. you publish to the command topic “hassbian2/command/pool_light” with a payload of ‘on’. then in your hassbian2 you lkisten for that command topic/payload and use that to turn on the pool light. then after the light is on you would listen for the state change on the hassbian2 topic that gets auto created to set the displayed state in hassbian1.

yes, you should remove it. you aren’t going to be using eventstream, just statestream.

mqtt doesn’t use the entities themselves to interact with devices. EVERYTHING is a topic & payload. then you look at the topics and decide what to do based on the topic/payload combination. Most of the time that will be done thru an automation. Unless you create template devices in the server that directly reads/writes to/from the topics themselves.

Well, I have tried to work my way through your explanations. As I understand it:
When I switch on the In pool light (fibaro_system_fgs213_switch_switch_4) in hassbian 2 it sends a topic “hassbian2/switch/fibaro_system_fgs213_switch_switch_4/state” with the value “on”. This is picked up by hassbian1 and shows the “on” state for fibaro_system_fgs213_switch_switch_4 on it’s front page.

When I toggle the fibaro_system_fgs213_switch_switch_4 button on the front page of hassbian1, hassbian1 sends a topic “hassbian2/switch/fibaro_system_fgs213_switch_switch_4/set” with the value “off”. This is picked up by hassbian2 and triggers the fibaro_system_fgs213_switch_switch_4 to turn off.

On hassbian1 I have:
Removed mqtt_eventstream from configuration.yaml

Added in configuration.yaml:

mqtt_statestream:
  base_topic: hassbian2
  publish_attributes: true
  publish_timestamps: true
  include:
    entities:
      - switch.fibaro_system_fgs213_switch_switch_2
      - switch.fibaro_system_fgs213_switch_switch_4

On hassbian2 I have:
Removed mqtt_eventstream from configuration.yaml
Added in configuration.yaml:

mqtt_statestream:
  base_topic: hassbian2
  publish_attributes: true
  publish_timestamps: true
  include:
    entities:
      - switch.fibaro_system_fgs213_switch_switch_2
      - switch.fibaro_system_fgs213_switch_switch_4

Added in automations.yaml (of hassbian2):

automation mqtt_config_entity_creator_switch
automation mqtt_command_switch:

I changed the topics from “homeassistant/…” to “hassbian2/…” I hope that was correct.

In the hassbian2 log I can see:

Apr 24 23:13:43 hassbian2 hass[21249]: 2019-04-24 23:13:43 DEBUG (MainThread) [homeassistant.components.mqtt] Transmitting message on hassbian2/switch/fibaro_system_fgs213_switch_switch_4/state: off
Apr 24 23:13:43 hassbian2 hass[21249]: 2019-04-24 23:13:43 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on hassbian2/switch/fibaro_system_fgs213_switch_switch_4/state: b’off’

I don’t know if the “b” in "state: b’off’ is important.
I have also seen:

Apr 24 23:33:27 hassbian2 hass[22842]: 2019-04-24 23:33:27 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on hassbian2/switch/fibaro_system_fgs213_switch_switch_4/config: b’{“name”: “Fibaro System Fgs213 Switch Switch 4”, “device_class”: “off”, “pl_off”:“off”, “pl_on”:“on”, “command_topic”: “hassbian2/switch/fibaro_system_fgs213_switch_switch_4/set” }

So I assume the MQTT messages are working.

However, I cannot see on the States page of hassbian1 any sign of the Fibaro switches that exist on hassbian2. Do I need to add to hassbian1’s configuration.yaml something like:

switch:
  - platform: mqtt
    state_topic: "hassbian2/switch.fibaro_system_fgs213_switch_switch_4"
    command_topic: "hassbian2/switch.fibaro_system_fgs213_switch_switch_4/set"
    name: "In pool light"
    payload_on: "on"
    payload_off: "off"

Also I have noticed the following line in the log:

Apr 24 23:33:17 hassbian2 hass[22842]: 2019-04-24 23:33:17 DEBUG (MainThread) [homeassistant.components.mqtt] Subscribing to homeassistant/#

I think this is because I have “default_config:” in configuration.yaml of both hassbians. Do I need to turn this off?

Thank you very much for your support with this.

First, I would change the base topic in hassbian1 to “hassbian1” just to make it easier to keep things straight on where the source is.

Next the topics for the switch in hassbian1:

The state topic should be the exact same topic that hassbian2 sends back to tell what the state of the switch is. And you have that listed above… I think.

“hassbian2/switch/fibaro_system_fgs213_switch_switch_4/state”

The command topic should be any topic you want but I would create the topic to maintain consistency.

“hassbian1/switch.f/fibaro_system_fgs213_switch_switch_4/set”

I think that may work but you may have to create an automation in hassbian2 to trigger the switch on or off based on the set command received.

Maybe…:smile:

I’m doing this off the cuff without being able to test it.

  • You have two instances of Home Assistant: Hassbian1 and Hassbian2.
  • Hassbian2 communicates with, and controls, two zwave switches located in a shed.
  • You want Hassbian1 to be able to control the two zwave switches.

MQTT_Statestream publishes the states of one or more entities. We want to configure it on Hassbian2 so it publishes the states of the two zwave switches.

Hassbian2 configuration.yaml:

mqtt_statestream:
  base_topic: homeassistant
  include:
    entities:
      - switch.fibaro_system_fgs213_switch_switch_2
      - switch.fibaro_system_fgs213_switch_switch_4

Hassbian2 will now publish the states of the two zwave switches to topics in this format: base_topic/domain/entity/state.

So the two zwave switches will have their states published to these two topics:

  • homeassistant/switch/fibaro_system_fgs213_switch_switch_2/state
  • homeassistant/switch/fibaro_system_fgs213_switch_switch_4/state

Now we have to make Hassbian1 subscribe to the two topics. We do this by defining two MQTT Switch entities on Hassbian1.

On Hassbian1:

switch:
  - platform: mqtt
    name: "Switch 2"
    state_topic: "homeassistant/switch/fibaro_system_fgs213_switch_switch_2/state"
    command_topic: "homeassistant/switch/fibaro_system_fgs213_switch_switch_2/set"
    value_template: "{{ value | upper }}"

  - platform: mqtt
    name: "Switch 4"
    state_topic: "homeassistant/switch/fibaro_system_fgs213_switch_switch_4/state"
    command_topic: "homeassistant/switch/fibaro_system_fgs213_switch_switch_4/set"
    value_template: "{{ value | upper }}"

NOTE
The configuration of the two MQTT Switches is probably incomplete as shown. I believe they need a value_template to extract the state from the topic’s payload. However, I currently don’t have time to figure this out for you so just be aware that the configuration shown won’t work as-is.
Done.


Now Hassbian1 shows the state of the two zwave switches via the entities: switch.switch_2 and switch.switch_4. These two entities publish their states to topics that end with /set. The last step is to make Hassbian2 subscribe to the two command_topics.

On Hassbian2, we create two automations, one for each switch.

automation:
  - alias: control_switch_2
    trigger:
      - platform: mqtt
        topic: "homeassistant/switch/fibaro_system_fgs213_switch_switch_2/set"
    action:
      - service_template: "switch.turn_{{trigger.payload | lower}}"
        entity_id: switch.fibaro_system_fgs213_switch_switch_2

  - alias: control_switch_4
    trigger:
      - platform: mqtt
        topic: "homeassistant/switch/fibaro_system_fgs213_switch_switch_4/set"
    action:
      - service_template: "switch.turn_{{trigger.payload | lower}}"
        entity_id: switch.fibaro_system_fgs213_switch_switch_4

Here’s an overview of what we’ve done:

  • Hassbian2 uses MQTT_Statestream to publish the state of each zwave switch to a state topic.
  • Hassbian 1 has two MQTT Switches subscribed to the two state topics.
  • The two MQTT Switches publish their commands to two command topics.
  • Hassbian2 uses automations to subscribe to the command topics and update the state of its zwave switches.

Try it on your system and once you have it working, and understand how it works, you may wish to explore other solutions.

The solution I’ve described can become cumbersome to configure if there are many switches, lights, and sensors involved. That’s why RobDYI’s solution is worth investigating because it uses automations, that leverage MQTT Discovery, to simplify the configuration process. Alternately, there is a custom component, called home-assistant-remote, that uses WebSockets, instead of MQTT, to connect two instances of Home Assistant.

3 Likes

Hi @finity and @123, thank you for your erudite inputs. With your help I have at last understood what you have been trying to tell me!
On hassbian1 config.yaml:

mqtt_statestream:
  base_topic: hassbian1
  publish_attributes: true
  publish_timestamps: true
  include:
    entities:
      - switch.fibaro_system_fgs213_switch_switch_2
      - switch.fibaro_system_fgs213_switch_switch_4

  
switch:
  - platform: mqtt
    state_topic: "hassbian2/switch/fibaro_system_fgs213_switch_switch_4/state"
    command_topic: "hassbian1/switch/fibaro_system_fgs213_switch_switch_4/set"
    name: "In-pool light"
    payload_on: "on"
    payload_off: "off"

On hassbian2 in config.yaml I have:

mqtt_statestream:
  base_topic: hassbian2
  publish_attributes: true
  publish_timestamps: true
  include:
    entities:
      - switch.fibaro_system_fgs213_switch_switch_2
      - switch.fibaro_system_fgs213_switch_switch_4

and in hassbian2 automations.yaml I have:

- alias: Turn on In-pool light
  trigger:
    - platform: mqtt
      topic: 'hassbian1/switch/fibaro_system_fgs213_switch_switch_4/set'
      payload: 'on'
  action:
    - service: switch.turn_on
      entity_id: switch.fibaro_system_fgs213_switch_switch_4
      
- alias: Turn off In-pool light
  trigger:
    - platform: mqtt
      topic: 'hassbian1/switch/fibaro_system_fgs213_switch_switch_4/set'
      payload: 'off'
  action:
    - service: switch.turn_off
      entity_id: switch.fibaro_system_fgs213_switch_switch_4

RESULT: In hassbian1 the “In-pool light” entity shows when the light is on or off. And when I toggle the entity button in hassbian1 the light turns off in hassbian2.

Thank you so much for getting me to this stage. I have a long way to go to understand the templating that @123 has shown but I am really thrilled to have got to this understanding.

Maybe I misunderstood how your system is configured. You said these two zwave switches communicate with hassbian2:

switch.fibaro_system_fgs213_switch_switch_2
switch.fibaro_system_fgs213_switch_switch_4

If that’s true, I have no idea why you are configuring MQTT_Statestream on hassbian1:

Why do you have MQTT_Statestream running on both systems when the two zwave switches are communicating with only one system (hassbian2)?

@123, thank you for asking this. I am a complete beginner with all of this and I am picking up information from the various HA documents, not fully understanding them, and doing my best to make things work.
The two fibaro switches are controlled by hassbian2 (the Aeotec USB zwave stick is plugged into hassbian2). What I have achieved is to be able to turn on the two fibaro switches from hassbian1.

I’m now back at work so I don’t have access to configuring the hassbians, but when I get back home this evening I will remove the MQTT Statestream on hassbian1 and see if it will still work.

Thanks again!

Because you only want to control two zwave switches, another solution is to use a simple automation instead of MQTT Statestream.

On Hassbian1, create two MQTT Switches:

  - platform: mqtt
    name: "Switch 2"
    state_topic: "homeassistant/switch/fibaro_system_fgs213_switch_switch_2/state"
    command_topic: "homeassistant/switch/fibaro_system_fgs213_switch_switch_2/set"

  - platform: mqtt
    name: "Switch 4"
    state_topic: "homeassistant/switch/fibaro_system_fgs213_switch_switch_4/state"
    command_topic: "homeassistant/switch/fibaro_system_fgs213_switch_switch_4/set"

On Hassbian2, create two automations:

- alias: 'MQTT publish switch state'
  trigger:
    platform: state
    entity_id: 
      - switch.fibaro_system_fgs213_switch_switch_2
      - switch.fibaro_system_fgs213_switch_switch_4
  action:
    service: mqtt.publish
    data_template:
      topic: "homeassistant/switch/{{trigger.to_state.object_id}}/state"
      payload: "{{ trigger.to_state.state | upper }}"

- alias: 'MQTT subscribe switch command'
  trigger:
  - platform: mqtt
    topic: homeassistant/switch/fibaro_system_fgs213_switch_switch_2/set
  - platform: mqtt
    topic: homeassistant/switch/fibaro_system_fgs213_switch_switch_4/set
  action:
  - service_template: "switch.turn_{{trigger.payload | lower}}"
    data_template:
      entity_id: "switch.{{trigger.topic.split('/')[2]}}"
  • The first automation publishes the states of the two zwave switches.
  • The second automation subscribes to the command_topics of Hassbian1’s two MQTT Switches. The received payloads are used to turn the zwave switches on/off.

EDIT
Two corrections to the second automation:

  1. Added lower filter to service_template.
  2. Replaced trigger.payload.split with trigger.topic.split in data_template's entity_id.
1 Like

@123 thank you for simplifying this issue, your solution looks more elegant than if I did not use templating.
I have loaded your programming on to hassbian1 and hassbian2. I changed the topic base from “homeassistant” to “hassbian2” so that if I do add more secondary controllers in the future I can identify the individual commands.

Unfortunately I am not able to get the “MQTT subscribe switch command” automation to work. If I set it up as

- alias: MQTT subscribe switch command
  trigger:
    - platform: mqtt
      topic: 'hassbian2/switch/fibaro_system_fgs213_switch_switch_2/set'
    - platform: mqtt
      topic: 'hassbian2/switch/fibaro_system_fgs213_switch_switch_4/set'
  action:
     service: switch.turn_off
     data:
       entity_id: switch.fibaro_system_fgs213_switch_switch_4       

This will switch off fibaro_system_fgs213_switch_switch_4 (when it is on). So I know the trigger is working. I have also tried

  action:     
     service_template: "switch.turn_{{trigger.payload}}"
     data:
       entity_id: switch.fibaro_system_fgs213_switch_switch_4    

and

  action:
     service: switch.turn_off
     data_template:
       entity_id: "switch.{{trigger.payload.split('/')[2]}}"

But neither of these work. Is there a way I can test if the templates are resolving the correct outputs?
Thank you very much for your help.

Further tinkering:
Upper case OFF and ON do not work when expressed as “switch.turn_OFF” or “switch.turn_ON”

I messed up the white space for the two variations. With the correct white space:

  action:
     service_template: "switch.turn_{{trigger.payload | lower}}"
     data:
       entity_id: switch.fibaro_system_fgs213_switch_switch_4       

The above works, but the below does not:

  action:
     service: switch.turn_off
     data_template:
       entity_id: "switch.{{trigger.payload.split('/')[2]}}"

Correct. I was in a hurry and made two mistakes. Glad to hear you caught the first mistake and corrected it. The second mistake was I used trigger.payload.split instead of trigger.topic.split.

I’ve updated my original post with the corrections.

Great, that has worked. Very helpful, thank you very much for your explanation and patience.
Now that has been achieved I hope to be able to work out how to show the states of some input_select and input_booleans on hassbian1 that I have on hassbian2 that control the length of time the pool pump runs for!
Is there an instruction website that explains how to construct templates that you would recommend please?
TIA

If it works, I suggest you consider tagging it as a solution so others can find it easily.

The reference for Jinja2 is here but it’s purely a reference and not a tutorial.

There’s useful information in Home Assistant’s documentation:

I learned what I know by studying other people’s examples, notably from Petro, pnbruckner, Mariusthvdb, and others.