Switch manager is a centralised component to handle button pushes for your wireless switches. This includes anything passed through the event bus or MQTT. The component relies on switch blueprints which is easily made to allow GUI configuration of your switches and their button pushes. This helps remove clutter from the automations view as they will be handled independently by this component.
I am happy to accept any pull requests for anyone who wishes to submit missing blueprint for switches from this repository as to help eliminate other users from having to build their own.
- Download the component
- Place the folder
custom_components/switch_manager
into theconfig/custom_components/
path of your home assistant installation - Restart Home Assistant
- Goto Config -> Integration then find and add Switch Manager
Once the integration has been loaded, a folder with blueprints will be created in your config/blueprints/switch_manager
home assistant path. You can add/create extra blueprints to this path.
In the side panel you goto Switch Manager. Next click Add Switch
and select the switch blueprint for the service/integration it's on (If you can't find your service and switch then see Blueprints below). The same switch can be defined multiple times but not for different services as they differ their event data's from one another.
Once you've selected the blueprint, you will be taken to the switch editor view.
There will be an identifier or mqtt topic input box up in the top left with a placeholder asking for the value for that key within the event data or mqtt topic.
You can either enter the identifier manually or use the button on the right then press a button on the switch to autofill the value. There is a posibility that an identifier from some other device for the event to be discovered if that device sent an event before your button push. If this is the case and the button helper isn't getting the right identifier then follow the next step to discover it manually.
If you have changed the default MQTT base topic for a service/integration and using a blueprint provided by Switch Manager then you will need to enter that topic manually as discovery will not work!
If you do not know the event value then goto Developer Tools -> Events and start listening for events (use * if you're unsure of the event type for your switch). Once you've started listening for events, push a button on your switch then stop the listener. View the data and you will find the event related to your switch. Inside that data you will find the identifier's value. Copy this value to the identifier's textbox on the switch editor page to bind.
If using a MQTT service then you can either download MQTT Explorer (preferred) or listen to all topics using the MQTT integration's listener. Goto Confiuration Menu -> Integrations -> MQTT -> Configure. Next listen to the topic #
(which mean all topics), after pressing a button you will see a topic representing this, this would be your MQTT topic for Switch Manager (you can cross reference the blueprint file with the mqtt data if you want to be sure).
Depending on the blueprint and the actions that your switch supports, you can select buttons by clicking on them from the image displayed and each button can have multiple actions eg tap, double tap and hold etc.
Navigation and usage should be pretty straight forward.
Remember to save before leaving the page when changes has been made! Once saved you can test to make sure all is working.
Sometimes you may want certain buttons or actions handled by the devices default handler. For example, a Zigbee device may already be bound to a certain light which also imo has better response, reliability and stability. To remind you of this, you could add a stop action with a description of why the button shouldn't be changed and being handled somehwere else. Then for other actions that aren't handled else where then you can handle them with this component. It's also fine to allow an external handler to handle the button push aswell as this component so a button could turn on the light handled via Zigbee and the component could start playing music based on the same switch action.
You can assign variables to the switch from the top right menu, these variables can be access through the blueprint conditions or action sequences.
The event or MQTT data can also be accessed inside your sequences via the data variable.
Blueprints are the heart of this component, once a blueprint is defined for a switch then it can be reused for all switches for that specific service and type. All blueprints are yaml defined and needs to be placed inside the config/blueprints/switch_manager
path eg config/blueprints/switch_manager/philips-hue-tap.yaml
. For a more user friendly experience and for switches with multiple buttons then a png file should be placed with the same name (case sensitive) eg a philips-hue-tap.yaml blueprint image would be config/blueprints/switch_manager/philips-hue-tap.png
.
File names should be defined as {service-name}-{switch-name-or-type}.yaml and all lower case. If you don't plan on posting your blueprint for others to use then it would be a good idea to prefix your file names with something unique like mycustom-{service-name}-{switch-name-or-type}.yaml. This way when you update the component with new blueprints then it won't overwrite your personal made ones if they happen to have the same file name.
- Only PNG files are currently supported.
- Images should not exceed 500px height or 800px width
- Images with transparent background are preferred
I tend to just google the device under the images tab. Next I will skim through til I find an image that has a flat perspective (top down) and is above 800px or 500px depending on the switches ratio. Next I will open the image in photoshop then mask out the background area with the shape tool. I then control click the layer to make only the visible selected which I then crop. Lastly I resize the image to be either 800px width or 500px height depending on which one has a greater value but I do not upscale if the image is below those sizes.
Once a blueprint file or image file has been created or edited then you will need to either call the switch_manager.reload service or restart Home Assistant for the changes to take effect.
Once a switch is saved, you can enable debugging through the hamburger menu up in the top right. List conditions will use what ever is in the data object (you do not need to add data to your keys) while Template conditions and sequence templates will need to access the data variable (eg data.{event_key} ).
Once enabled, open your browser dev console to view debugging output
The following tables shows how to structure a blueprint yaml file
View other blueprint files to get a grasp on how it's constructed if the following table is hard to understand.
Option | Values | Required | Details |
---|---|---|---|
name | string |
* | A friendly name for the switch |
service | string |
* | The service or integration that this switch relates to (matching services will be grouped when selecting a blueprint from gui) |
event_type | string |
* | Must match the event type through the event bus triggered by the switch (Monitor * events in developer tools if unsure of its value). Set this to mqtt if handling a mqtt message instead of an event (see mqtt) |
identifier_key | string |
* If not mqtt | The key in the event data that will uniquely identify a switch. |
mqtt_topic_format | string |
- | If event_type is mqtt, then this will give the user an understanding of what they should set their topic as. example: zigbee2mqtt/+/action. The MQTT topic here will also help with discovery (remember to use wildcard + where needed). Make sure you set this to the standard topic if planning on sharing blueprint and not a topic that you have customised yourself through the integration |
mqtt_sub_topics | bool |
- | Along with the original topic, sub topics will also be listened to and passed in for condition checking etc. If enabled then make sure the original topic doesn't use # wildcards or + at the end. Default is false |
buttons | list Button |
* | You will need to define a list of buttons even if the switch has only one or multiple. See Button for details on defining a button |
conditions | list Condition | string Template |
- | This optional list or Template allows the switch to only accept these conditions within the event data or mqtt payload. All conditions must evaluate to true to be valid. See Condition for details on defining a condition |
If there are more than 1 button on the switch then you should be using a png (even one button should have an image for better visualisation) and defining the buttons position with the x, y, width and height properties. This also can be expanded to being a circular shape or a svg path.
If a switch supports multiple button presses (so two buttons are pushed at the same time) then add another button with circle shape centered between the two buttons to indicate they're linked. Within the actions, the title should prefix both. See Xiaomi Double Key for an example.
You will need to save the switch before feedback will be displayed on the UI, this is due to needing backend processing of a switch which isn't created until it's been saved
if you want more control on positioning and look then you can open the image up in inkscape (with matching width and height values for the viewBox) then draw the paths for each button and copy the d attribute of that path then paste in the d property for the button in yaml. You would also set the shape as path
Single buttons will not render a graphic so if you do add a shape etc for a single button, it won't be shown and end up being redundant
- Shape
rect
uses x, y, width, height - Shape
circle
uses x, y, width - Shape
path
uses d
Option | Values | Required | Details |
---|---|---|---|
x | int px |
- | The x (left, right) position of the button from top left within the image. *not valid for shape: path |
y | int px |
- | The y (up, down) position of the button from top left within the image. *not valid for shape: path |
width | int px |
- | The width of the shape rect or circle. *not valid for shape: path |
height | int px |
- | Only valid for shape: rect. The height you want the rectangle to be |
d | string |
- | Only valid if shape: path. Using svg path format |
shape | rect|circle|path |
- | Default is rect (rectangle). |
actions | list Action |
* | Each button will have atleast one action. Each action would be the result of a tap, double tap or hold etc depending on what the switch supports. |
conditions | list Condition | string Template |
- | This optional list or Template allows the button to only accept conditions within the event data or mqtt payload. This can help scope down to where the button was pressed. All conditions must evaluate to true to be valid. See Condition for details on defining a condition. |
An action would be the result of a press/tap, whether its held down or if it was pressed twice etc (all depending on what the device and/or service supports). An action must contain a title at minimum. Conditions should be used to differentiate the actions for any button.
To unify switches added to Switch Manager, it makes sense to conform to a naming convention so the below dot points are some rules to go by
- All characters should be lowercase
- If mechanical button then the action should be press
- If touch button (as in there's no mechanical trigger) then the action should be tap (if unsure then resort to press)
- If action is double press/tap or triple press/tap and so on then the action should be press 2x / tap 2x or press 3x / tap 3x and so on
- If the button supports a hold/long and hold/long release then there should be an action for both hold and hold (released) do NOT use the wording long
- Do NOT use short or short release as this is generally a generic press
- In the case where a switch allows multiple buttons to be pushed then you can prefix each action with both so a dual button press would be both press and both press 2x etc. This makes it clear to a user that the button they have selected is actually for multiple buttons. See Xiaomi Double Key for an example
Actions should be ordered logically. This would be press -> press 2x -> press 3x -> hold -> hold (released) -> Then anything that is more unique like shake, viabrate and so on.
Option | Values | Required | Details |
---|---|---|---|
title | string |
* | Please read naming convention to better understand what title should be used |
conditions | list Condition | string Template |
- | This optional list or Template allows the action to only accept conditions within the event data or mqtt payload. This can help scope down to the kind of action if the button has multiple. All conditions must evaluate to true to be valid. See Condition for details on defining a condition. |
Conditions will traverse down the switch from root -> button -> action. The process of the heirachy will stop if the condition fails. Please use list over templates.
You can use Home Assistant generic condition template to validate a condition https://www.home-assistant.io/docs/configuration/templating/. Define the property conditions
as a string instead of an array. Lists are still preferred as rendering templates takes extra processing times. The event or mqtt data are passed in on the data variable. Switch defined variables can be accessed through the data.variables
object.
conditions: "{{ data.value == 'KeyPressed' and data.topic_basename == 'left_button' }}"
Conditions defined as a list evaluates the event/mqtt data. If the key doesn't exist then it also evaluates to false. Use dot notation for the key to traverse nested dictionaries. Switch defined variables can be accessed using the variables
key. All conditions must be true to be valid
Option | Values | Required | Details |
---|---|---|---|
key | string |
* | The key to match in the event data or mqtt payload |
value | string |
* | The value to match for the key |
conditions:
- key: value
value: KeyPressed
- key: group
value: 1
MQTT is handled differently to events and the incoming data is that of a payload... If a payload is not json formatted then it will be passed in as the key payload
containing the string. The payload itself is what the conditions will check against. Included in the data is topic and topic_basename as this can be useful for condtions where a topic is listened via #
or +
.
To help discover a switch when trying to discover from GUI then use a format for the topic in mqtt_topic_format
that will scope down to the best possibility. For zigbee2mqtt this is generally zigbee2mqtt/+/action
. The +
is a wild card saying to match a single level (so anything between the forward slash /
). For more information visit here. Sharing blueprints should be set to the default topic of the integration and not one that you have changed to.
If you want a condition on a payload that isn't json formatted then you would do as follows:
- key: payload
value: tap
Otherwise you will check against the payloads keys and values
The follow example is a blueprint for a Wallmote Quad which has 4 buttons with each button having 2 actions (tap and hold). This blueprint is also designed for the Z-Wave JS Integration and handles the event type zwave_js_value_notification
. With in that we set the identifier key to node_id
as this key is a way to distinguish which switch the event refers to. Further along we check from the root condition whether the event data has property: scene
otherwise the switch has no need to further proceed nor does the component process other child conditions. We do this again for the buttons and actions to scope down whether the incoming event should be handled by the switch and its buttons or actions.
Each button has a shape of a path as it was traced through inkscape, drawing the shapes whether be rect, circle or path allows GUI representation and allows to select individual buttons within the GUI switch editor.
You should wrap your conditon values in qoutes as 001 equates to an int which would end up being 1 and will not match a value of 001 within the event data.
name: Wallmote Quad
service: ZWave JS
event_type: zwave_js_value_notification
identifier_key: node_id
conditions:
- key: property
value: scene
buttons:
- shape: path
d: m 45.944466,2.0341694 h 176.769524 v 219.3817306 h -219.1028571 l 0,-177.048398 a 42.333333,42.333333 135 0 1 42.3333331,-42.3333326 z
conditions:
- key: property_key
value: '001'
actions:
- title: tap
conditions:
- key: value
value: KeyPressed
- title: hold
conditions:
- key: value
value: KeyHeldDown
- shape: path
d: m 222.78056,2.0572453 h 176.76953 a 42.333333,42.333333 45 0 1 42.33333,42.3333327 v 177.048392 h -219.10286 z
conditions:
- key: property_key
value: '002'
actions:
- title: tap
conditions:
- key: value
value: KeyPressed
- title: hold
conditions:
- key: value
value: KeyHeldDown
- shape: path
d: m 3.4383569,221.24492 h 219.1028631 v 219.38173 h -176.76953 a 42.333333,42.333333 45 0 1 -42.3333331,-42.33333 z
conditions:
- key: property_key
value: '003'
actions:
- title: tap
conditions:
- key: value
value: KeyPressed
- title: hold
conditions:
- key: value
value: KeyHeldDown
- shape: path
d: m 222.71397,221.28836 h 219.10286 v 177.0484 a 42.333333,42.333333 135 0 1 -42.33333,42.33333 l -176.76953,0 z
conditions:
- key: property_key
value: '004'
actions:
- title: tap
conditions:
- key: value
value: KeyPressed
- title: hold
conditions:
- key: value
value: KeyHeldDown
name: Sonoff SNZB 01
service: Zigbee2MQTT
event_type: mqtt
mqtt_topic_format: zigbee2mqtt/+/action
buttons:
- actions:
- title: press
conditions:
- key: payload
value: single
- title: press 2x
conditions:
- key: payload
value: double
- title: hold
conditions:
- key: payload
value: long
If by chance your switches are invalid because of a blueprint change, then this would generally mean a blueprint has added either more buttons or extra actions. We try to avoid this and as this integration is still in it's infancy stages there will be changes from time to time and while these changes happen, so does the rules in adding a blueprint to this repo (this should hopefully iron out these issues in the future). For now, you have two options when there's a blueprint mismatch. First you could delete the invalid switch and create it again, or you can go into the .storage folder and edit switch_manager then add the missing actions or buttons manually to match the number of buttons and actions on the blueprint...
I did contemplate updating the switches to match the buttons upon a migration method but found this to be dangerous as it would cause already set switches to call a sequence on the wrong button or action and I can not be sure someone hasn't hooked up a switch button to a bomb or who knows what ;). So for now I feel it's safer to invalidate a switch when there's a mismatch and hopefully this will not be a problem in the future when everything is set in stone.