I recently received a zigbee Xiaomi Mijia Wireless Switch, which can trigger on:
- Single click
- Double clicks
- Triple clicks
- Quadruple clicks
- Many clicks (anything over four clicks is sent as
many
) - Long press (hold)
- Long press (release)
It will also output the duration of the long press.
Here is how I integrated into openHAB, via zigbee2mqtt and Mosquitto.
Prerequisites
- Ensure the openHAB MQTT binding is installed (V2, not V1)
- My Mosquitto MQTT broker is setup as per default.
- Pair the device with zigbee2mqtt as described here.
- Ensure that you are able to pair devices by setting
permit_join
totrue
in configuration.yaml (usually in /opt/zigbee2mqtt/data)
- Ensure that you are able to pair devices by setting
- Once paired, adjust the zigbee2mqtt configuration.yaml (usually in /opt/zigbee2mqtt/data) to:
- Give the paired device a friendly name
- Turn on the experimental attribute output, which means zigbee2mqtt will send plain strings, rather than JSON strings.
Here is my configuration.yaml - your device ID is likely to be different. I have given my device the friendly name swButton
:
homeassistant: false
permit_join: true
mqtt:
base_topic: zigbee2mqtt
server: 'mqtt://localhost'
serial:
port: /dev/ttyACM0
disable_led: false
advanced:
log_level: error
availability_timeout: 5
devices:
'0x00158d0003d2bf4e':
friendly_name: swButton
experimental:
output: attribute
openHAB
MQTT bridge
I have a separate file which just contains the bridge Thing to my Mosquitto MQTT broker:
Bridge mqtt:broker:MosquittoMqttBroker "Mosquitto MQTT Broker" [
host="192.168.1.92",
secure=false,
port=1883,
clientID="OpenHAB2"
]
zigbee.things
//Mijia WXKG01LM button
Thing mqtt:topic:swButton "Mijia button" (mqtt:broker:MosquittoMqttBroker) {
Channels:
Type switch : availability "Reachable" [
stateTopic = "zigbee2mqtt/swButton/availability",
off="offline",
on="online"
]
Type number : battery "Battery level" [
stateTopic = "zigbee2mqtt/swButton/battery"
]
Type number : voltage "Battery voltage" [
stateTopic = "zigbee2mqtt/swButton/voltage"
]
Type number : linkquality "Link quality" [
stateTopic = "zigbee2mqtt/swButton/linkquality"
]
Type string : click "Click" [
stateTopic = "zigbee2mqtt/swButton/click"
]
Type number : click_duration "Click duration" [
stateTopic = "zigbee2mqtt/swButton/duration"
]
}
zigbee.items
Switch sButtonReachable "Zigbee button reachable" (gReachable) { channel="mqtt:topic:swButton:availability" }
Number nButtonBattery { channel="mqtt:topic:swButton:battery" }
Number nButtonVoltage { channel="mqtt:topic:swButton:voltage" }
Number nButtonLinkQuality { channel="mqtt:topic:swButton:linkquality" }
String strButtonClick { channel="mqtt:topic:swButton:click" }
Number nButtonClickDuration { channel="mqtt:topic:swButton:click_duration" }
sitemap
Text item=sButtonReachable label="Button switch [MAP(switch2online.map):%s]" icon="wallswitch" valuecolor=["ON"="green", "OFF"="red", "NULL"="red", "-"="red"]
Text item=nButtonBattery label="Battery [%.0f %%]" icon="battery"
Text item=nButtonVoltage label="Voltage [%.0f mV]" icon="battery"
Text item=nButtonLinkQuality label="Link quality [%.0f]" icon="qualityofservice"
Text item=strButtonClick label="Last click action [%s]"
Text item=nButtonClickDuration label="Last long click duration [%.0f]" icon="time"
The switch2online.map file contains the below, saved into the transform folder:
OFF=OFFLINE
ON=ONLINE
NULL=UNDEFINED
-=-
Example rule
The following rule triggers when the switch is pressed, and performs an action depending on the click type:
DSL
rule "Mijia button pressed"
when
Item strButtonClick received update
then
//Switch through the different options
switch strButtonClick.state {
case "single":
//Perform action on single click
sUpstairsHallwayLight.sendCommand(ON)
case "double":
//Perform action on double click
sUpstairsHallwayLight.sendCommand(OFF)
case "triple":
//Perform action on triple click
sRGB1.sendCommand(ON)
case "quadruple":
//Perform action on quadruple click
sRGB1.sendCommand(OFF)
case "many":
//Perform action on more than 4 clicks
sRGB2.sendCommand(ON)
case "long":
//Perform action on long press whilst still pressed
sRGB2.sendCommand(OFF)
case "long_release":{
//Perform action on long press when released
sUpstairsHallwayLight.sendCommand(ON)
if(nButtonClickDuration.state < 1000){
//Short long press
}
else if(nButtonClickDuration.state < 2000){
//Medium long press
}
else{
//Long long press
}
}
}
end
Jython
(I’m aware that the log entry could be sent before the IF statement, but there are understandable errors if I only have commented lines after each ELIF…)
from core.rules import rule
from core.triggers import when
'''
MIJIA SWITCH
Perform actions when the button is pressed
'''
@rule("Mijia switch pressed", description="Perform actions when the button is pressed")
@when("Item strButtonClick received update")
def action_mijia_switch_changed(event):
click_type = items["strButtonClick"].toString()
if click_type == "single" :
#Perform action on single click
action_mijia_switch_changed.log.info("{} click on the Mijia switch".format(click_type))
elif click_type == "double" :
#Perform action on double clicks
action_mijia_switch_changed.log.info("{} click on the Mijia switch".format(click_type))
elif click_type == "triple" :
#Perform action on triple clicks
action_mijia_switch_changed.log.info("{} click on the Mijia switch".format(click_type))
elif click_type == "quadruple" :
#Perform action on quadruple clicks
action_mijia_switch_changed.log.info("{} click on the Mijia switch".format(click_type))
elif click_type == "many" :
#Perform action on many clicks
action_mijia_switch_changed.log.info("{} click on the Mijia switch".format(click_type))
elif click_type == "long" :
#Perform action on long click hold
action_mijia_switch_changed.log.info("{} click on the Mijia switch".format(click_type))
elif click_type == "long_release" :
#Perform action on long click release
action_mijia_switch_changed.log.info("{} click on the Mijia switch".format(click_type))
click_duration = float(items["nButtonClickDuration"].toString())
if click_duration < 1000:
#Perform action on short long press
action_mijia_switch_changed.log.info("{} click duration on the Mijia switch".format(click_duration))
elif click_duration < 2000:
#Perform action on medium long press
action_mijia_switch_changed.log.info("{} click duration on the Mijia switch".format(click_duration))
else:
#Perform action on long long press
action_mijia_switch_changed.log.info("{} click duration on the Mijia switch".format(click_duration))
At this point in time, I am unsure of the units for long-click duration.