Hi guys, in light of learning more about jinja2 templating and webhook automation in Home Assistant I’ve created an webhook automation using some SwitchBot sensors that I bought that is efficient in responding to Switchbot Webhook API for asynchronous event like door open, motion on.
Others solution that I found online and in HA forum usually parse the webhook payload on the mqtt
sensor defined in configuration.yaml
, whereas the service that I did will did all the parsing at the Automation script instead. It will then set the right state (as a string instead of JSON payload) to a dynamic topic depending on the type of the Switchbot sensor. The mqtt
sensor defined in configuration.yaml
will just have to specify a topic to subscribe for a state and just compare the string inside that topic. This method doesn’t require any restart since no changes is done in configuration.yaml
.
Of course you could create a binary_sensor
in configuration.yaml
without having to use the webhook that periodially pool SwitchBot API for any status. In fact this is how I started, but then it’s not efficient since the event should be asynchronous, and that is exactly why Webhook is so important!
binary_sensor:
# for switchbot motion sensor
- platform: rest
name: "Motion Sensor Staircase Downstair"
device_class: motion
resource: !secret switchbot_staircase_downstair_motion_sensor_status_url
method: GET
scan_interval: 1
headers:
Authorization: !secret switchbot_api
Content-Type: "application/json"
value_template: "{{ value_json.body.moveDetected }}"
Devices Used
- Switchbot Hub Mini
- SwitchBot Door Contact Sensor
- SwitchBot Motion Sensor
- Amazon Alexa
Prerequisite
-
You need to install
MQTT
integration and created an Automation withWebhook
as trigger. I setup my MQTT broker as another VM in my unRAID server rather than an Add-on to simplify my workflow. -
Register the Webhook URL that you received from Home Assistant Cloud (NabuCasa) and call Switchbot API. Note I’m still using Switchbot API v1 to simplify token auth
curl
example to register your HA webhook URL to Switchbot API server
curl -H "Content-Type: application/json" -H "Authorization: <YOUR_SWITCHBOT_TOKEN>" -X POST https://api.switch-bot.com/v1.0/webhook/setupWebhook -d '{"action":"setupWebhook", "url": "https://hooks.nabu.casa/<AUTO_GENERATED_URL_FROM_NABUCASE>", "deviceList": "ALL"}'
You should receive the following response code 100
if it works
{"statusCode":100,"body":{},"message":"success"}
How the Webhook works
- Your Switchbot sensor detected a state change and sent a message to Switchbot Hub.
- Your Switchbot hub sent an update to Switchbot API server
- Switchbot API server call registered web hook pointed to your HA (routed via NabuCasa server)
- The webhook JSON payload is then sent to HA Automation for that registered webhook
- Parse JSON payload and construct the right topic that is subscribed by each sensor defined in
configuration.yaml
, and update the value of that state. To keep it simple, the value is a string, rather than a JSON body that yourmqtt sensor
defined atconfiguration.yaml
had to parse. - SEnd the payload to the MQTT server that you setup in HA
MQTT
integration. -
mqtt sensor
defined inconfiguration.yaml
update its state value based on the payload (string) payload received from a subscribed topic from MQTT server
Implementation
What the Script Does
- Alexa announce the notification depending on the sensor type, e.g.
door open
for Contact Sensor, andmotion on
for Motion Sensor. - The state is parsed from Switchbot Webhook JSON payload. The value depend on the sensor type, e.g.
on/off
for motion sensor andopen/close
for contact sensor. - An additional availability is parse, not needed for these kind of sensor but just to demonstrate you could do it too
- The JSON received from Switchbot Webhook API is sent to another topic for debugging purpose.
MQTT Topic Design
The topic uses the following hierarchy:
/<HOME_NAME>/<SENSOR_LOCATION>/<MANUFACTURER>/<SENSOR_TYPE>/<DEVICE_ID>/{state,availability,json}
For Contact Sensor
Note: My motion sensor device ID is C8F7D45BB07B
State change (open/close): /home/staircase/switchbot/contact/C8F7D45BB07B/state
Availability (online/offline): /home/staircase/switchbot/contact/C8F7D45BB07B/availability
Full JSON from Switchbot Webhook API: /home/staircase/switchbot/contact/C8F7D45BB07B/json
For Motion Sensor
Note: My motion sensor device ID is D7F9AC484301
State change (open/close): /home/staircase/switchbot/motion/D7F9AC484301/state
Availability (online/offline): /home/staircase/switchbot/motion/D7F9AC484301/availability
Full JSON from Switchbot Webhook API: /home/staircase/switchbot/motion/D7F9AC484301/json
Paste the following YAML to the Automation Webhook trigger. You may change the topic accordingly.
alias: Webhook - Receive switchbot webhook
description: ""
trigger:
- platform: webhook
webhook_id: motion-detected-staircase-downstair
condition: []
action:
- service: notify.alexa_media
data_template:
message: >-
{% if trigger.json.context.deviceType == 'WoContact' %}
{% if trigger.json.context.openState == 'open' %}
Door opened
{% else %}
Door closed
{% endif %}
{% elif trigger.json.context.deviceType == 'WoPresence' %}
{% if trigger.json.context.detectionState == 'DETECTED' %}
Motion sensor on
{% else %}
Motion sensor off
{% endif %}
{% endif %}
target: media_player.gary_s_echo_dot
data:
type: tts
# update entity state
- service: mqtt.publish
data_template:
# topic: /home/staircase/switchbot/motion/D7F9AC484301
# payload_template: "{{ trigger.json | tojson }}"
topic: >-
{% if trigger.json.context.deviceType == 'WoContact' %}
/home/staircase/switchbot/contact/{{ trigger.json.context.deviceMac }}/state
{% elif trigger.json.context.deviceType == 'WoPresence' %}
/home/staircase/switchbot/motion/{{ trigger.json.context.deviceMac }}/state
{% endif %}
payload: >-
{% if trigger.json.context.deviceType == 'WoContact' %}
{% if trigger.json.context.openState == 'open' %}
open
{% else %}
close
{% endif %}
{% elif trigger.json.context.deviceType == 'WoPresence' %}
{% if trigger.json.context.detectionState == 'DETECTED' %}
on
{% else %}
off
{% endif %}
{% endif %}
# update entity availability
- service: mqtt.publish
data_template:
# topic: /home/staircase/switchbot/motion/D7F9AC484301/status
topic: >-
{% if trigger.json.context.deviceType == 'WoContact' %}
/home/staircase/switchbot/contact/{{ trigger.json.context.deviceMac }}/availability
{% elif trigger.json.context.deviceType == 'WoPresence' %}
/home/staircase/switchbot/motion/{{ trigger.json.context.deviceMac }}/availability
{% endif %}
payload: online
# display raw json response from Switchbot API server
- service: mqtt.publish
data_template:
# topic: /home/staircase/switchbot/motion/D7F9AC484301/json
topic: >-
{% if trigger.json.context.deviceType == 'WoContact' %}
/home/staircase/switchbot/contact/{{ trigger.json.context.deviceMac }}/json
{% elif trigger.json.context.deviceType == 'WoPresence' %}
/home/staircase/switchbot/motion/{{ trigger.json.context.deviceMac }}/json
{% endif %}
payload: "{{ trigger.json }}"
mode: single
Paste the following to configuration.yaml
. Be sure to change the device ID to the one in your Switchbot Hub. You can run the following curl
command to get a list of device ID currently connected to your SwitchBot Hub Mini.
curl -H "Authorization:<SWITCHBOT_TOKEN>" https://api-switch-bot.com/v1.0/devices/
configuration.yaml
# uses the MQTT message payload as the sensor value.
mqtt:
binary_sensor:
- name: "Switchbot Motion Sensor Staircase Downstair"
unique_id: switchbot_D7F9AC484301
icon: mdi:motion-sensor
device_class: motion
state_topic: "/home/staircase/switchbot/motion/D7F9AC484301/state"
payload_on: "on"
payload_off: "off"
- name: "Switchbot Door Contact Sensor Living Room"
unique_id: switchbot_C8F7D45BB07B
icon: mdi:leak
device_class: door
state_topic: "/home/staircase/switchbot/contact/C8F7D45BB07B/state"
payload_on: "open"
payload_off: "close"
# availability:
# - topic: "/home/staircase/switchbot/contact/C8F7D45BB07B/availability"
# payload_available: "online"
# payload_not_available: "offline"
Check your configuration from Developer page, restart and profit!