[OBSOLETE] Device Handler for Aqara Wired Wall Switch

** This DTH is no longer supported **

Pls refer to Device Handler for Aqara 2 Gang Wired Wall Switch no Neutral for the latest supported version.


This is DTH for 86x86 Aqara Wired wall switch.

It comes in 4 variants.

Single Gang Neutral Required
Dual Gang Neutral Required
Single Gang Neutral NOT required
Dual Gang Neutral NOT required

Just to avoid confusion, this is what it looks like:

4 Likes

Step 1: Pairing.

Like most Aqara stuff, you need to extract the zigbee ID from the Hub catchall

From the example below, the zigbee ID you need is A8B2.

catchall: 0104 0000 01 01 0100 00 A8B2 00 04 115F 0A 01 01FF42296410016510006E20016F20000121E40C0328

Step 2: Assign the Aqara DTH to the newly created device

Step 3: Tie the 2nd input to a virtual switch handler. You can reuse the smartapp from my kudled DTH post

Note: The state of the buttons for the 2 gang switch will NEVER be able to be in sync. This is because smartthings masks the endpoint end when it returns the on/off status. Hence the DH will never know the on/off returned is for which button.

But you can certainly use it to explicitly send ON or OFF commands in conjunction with smartapps or other automations.

2 Likes

Device Handler


/**
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 *  Modified from DTH by a4refillpad
 
 *  10/2017 first release
 */

metadata {
    definition (name: "Aqara 2 Button Wired Wall Switch", namespace: "simic", author: "simic") {
        capability "Actuator"
        capability "Configuration"
        capability "Refresh"
        capability "Switch"
        capability "Temperature Measurement"
        
        command "on2"
        command "off2"
        
        attribute "switch2","ENUM", ["on","off"]
        
        attribute "lastCheckin", "string"
    }

    // simulator metadata
    simulator {
        // status messages
        status "on": "on/off: 1"
        status "off": "on/off: 0"

        // reply messages
        reply "zcl on-off on": "on/off: 1"
        reply "zcl on-off off": "on/off: 0"
    }

    tiles(scale: 2) {
        multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
            tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { 
                attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00a0dc", nextState:"turningOff"
                attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
                attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00a0dc", nextState:"turningOff"
                attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
            }
            
            
            
           	tileAttribute("device.lastCheckin", key: "SECONDARY_CONTROL") {
    			attributeState("default", label:'Last Update: ${currentValue}',icon: "st.Health & Wellness.health9")
		   	}
        }
        
        standardTile("switch2", "device.switch2", width: 2, height: 2, canChangeIcon: true) {
			state "off", label: '${name}', action: "on2", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
			state "on", label: '${name}', action: "off2", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		}

        valueTile("temperature", "device.temperature", width: 2, height: 2) {
			state("temperature", label:'${currentValue}°',
				backgroundColors:[
					[value: 31, color: "#153591"],
					[value: 44, color: "#1e9cbb"],
					[value: 59, color: "#90d2a7"],
					[value: 74, color: "#44b621"],
					[value: 84, color: "#f1d801"],
					[value: 95, color: "#d04e00"],
					[value: 96, color: "#bc2323"]
				]
			)
		}
        standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
            state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
        }
        main (["switch", "switch2", "temperature"])
        details(["switch", "switch2", "temperature", "refresh"])
    }
}

// Parse incoming device messages to generate events
def parse(String description) {
   log.debug "Parsing '${description}'"
   def value = zigbee.parse(description)?.text
   log.debug "Parse: $value"
   Map map = [:]
   
   if (description?.startsWith('catchall:')) {
		map = parseCatchAllMessage(description)
	}
	else if (description?.startsWith('read attr -')) {
		map = parseReportAttributeMessage(description)
	}
    else if (description?.startsWith('on/off: ')){
    	def resultMap = zigbee.getKnownDescription(description)
   		log.debug "${resultMap}"
        
        map = parseCustomMessage(description) 
    }

	log.debug "Parse returned $map"
    //  send event for heartbeat    
    def now = new Date()
    sendEvent(name: "lastCheckin", value: now)
    
	def results = map ? createEvent(map) : null
	return results;
}

private Map parseCatchAllMessage(String description) {
	Map resultMap = [:]
	def cluster = zigbee.parse(description)
	log.debug cluster
    
    if (cluster.clusterId == 0x0006 && cluster.command == 0x01){
    	def onoff = cluster.data[-1]
        if (onoff == 1)
        	resultMap = createEvent(name: "switch", value: "on")
        else if (onoff == 0)
            resultMap = createEvent(name: "switch", value: "off")
    }
    
	return resultMap
}

private Map parseReportAttributeMessage(String description) {
	Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
		def nameAndValue = param.split(":")
		map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
	}
	//log.debug "Desc Map: $descMap"
 
	Map resultMap = [:]

	if (descMap.cluster == "0001" && descMap.attrId == "0020") {
		resultMap = getBatteryResult(convertHexToInt(descMap.value / 2))
 	}
    if (descMap.cluster == "0002" && descMap.attrId == "0000") {
		resultMap = createEvent(name: "temperature", value: zigbee.parseHATemperatureValue("temperature: " + (convertHexToInt(descMap.value) / 2), "temperature: ", getTemperatureScale()), unit: getTemperatureScale())
		log.debug "Temperature Hex convert to ${resultMap.value}%"
    }
    else if (descMap.cluster == "0008" && descMap.attrId == "0000") {
    	resultMap = createEvent(name: "switch", value: "off")
    } 
	return resultMap
}

def off() {
    log.debug "off()"
	sendEvent(name: "switch", value: "off")
	"st cmd 0x${device.deviceNetworkId} 2 6 0 {}"
}

def on() {
   log.debug "on()"
	sendEvent(name: "switch", value: "on")
	"st cmd 0x${device.deviceNetworkId} 2 6 1 {}"
}

def off2() {
    log.debug "off2()"
	sendEvent(name: "switch2", value: "off")
	"st cmd 0x${device.deviceNetworkId} 3 6 0 {}"
}

def on2() {
   log.debug "on2()"
	sendEvent(name: "switch2", value: "on")
	"st cmd 0x${device.deviceNetworkId} 3 6 1 {}"
}

def refresh() {
	log.debug "refreshing"
    [
        "st rattr 0x${device.deviceNetworkId} 1 6 0", "delay 500",
        "st rattr 0x${device.deviceNetworkId} 1 6 0", "delay 250",
        "st rattr 0x${device.deviceNetworkId} 1 2 0", "delay 250",
        "st rattr 0x${device.deviceNetworkId} 1 1 0", "delay 250",
        "st rattr 0x${device.deviceNetworkId} 1 0 0"
    ]
}

private Map parseCustomMessage(String description) {
	def result
	if (description?.startsWith('on/off: ')) {
    	if (description == 'on/off: 0')
    		result = createEvent(name: "switch", value: "off")
    	else if (description == 'on/off: 1')
    		result = createEvent(name: "switch", value: "on")
	}
    
    return result
}

private Integer convertHexToInt(hex) {
	Integer.parseInt(hex,16)
}
3 Likes

Reserved post for future use

Two questions since I don´t get yet the whole logic in ST :slight_smile:

  1. what is the on/off button in the bottom left doing versus the light on/off button on top?

  2. “Step 3: Tie the 2nd input to a virtual switch handler. You can reuse the smartapp from my kudled DTH post” can you give an example what to use this for and give a brief guide how to do it?

1 Like
  1. I didnt clean up the code properly. but top button is switch 1
    small button is switch 2.

  2. I realised that my current code dont quite work with the kudled smartapp due different naming of variables.

Will find time during weekend to do the cleanup.

meanwhile for those developers that can do code, feel free to modify and share!

ANYBODY CAN HELP ME?
i need code for Aqara 1 Button Wired Wall Switch neutral wired and
Aqara 2 Button Wired Wall Switch no netral wired

Thanks for this. Mine finally arrived and is working nicely with your DTH.

Time permitting (ha!) I might have a play with the code and see what comes out :grin:

I have a single gang no neutral version of the one above and I had some issues with the DH above, so I created my own version. The issues were that the attribute ID was actually 2 not 1 and also double tapping on the switch when pressed.

Still don’t trust the temperature value (Mine is in celsius) but it’s coming back from the correct cluster and so I have also added a fix in the config to allow for an offset. Only one problem still exists - the colour of the temp tile is always red. Need to work this one through. EDIT: Fixed this. currentValue is in Fahrenheit! Fixed the display now

Any questions then please shout. I have one with a neutral connection as well but not tested it yet.

Thanks
John

6 Likes

Thumbs up!

Great to see the community chipping in!

How do you get to add the device? I have been reading a ton of posts about this, mentioning to use the catch-all approach to get the device ID, but I’m not being able to doing. Regardless of how many times or how long I press the buttons, there’s not catch all in the logs. How did you add yours?

Look for it in the hub logs. Not the live logging

I always looked for it in both places. It never comes up :frowning:

Press and hold the paddle switch for 5 sec while your hub is in Discovery mode.

You should see the blue led indicatiors at the bottom blink… That should reinitialize the switch and make it send th catch all again.

Don’t see it? Press and hold and try a few more times.

When u pair foreign devices with st. U have to be patient.

It took a while for mine to latch, I tried a few times over a few days. Depending on where it’s installed, signal strength may be an issue, especially for detection. I ended up moving my hub.

With these devices it sometimes just takes a few tries.

Don’t know if you managed to clean up your code, but I’m 90% of the way there:

/**
 *  Aqara Wall Switch Binder
 *  This app allows you to bind 3 Virtual On/Off Tiles to the 3 switchable outlets.
 *
 *  Author: jymbob - based on KUDLED handler by simic
 *  Date: 22/11/2017
 
 */
// Automatically generated. Make future change here.
definition(
    name: "Aqara Wall Switch Binder 1.1",
    namespace: "",
    author: "james.scholes@gmail.com",
    description: "This app allows you to bind 3 Virtual On/Off Tiles to the 3 switchable outlets.",
    category: "Convenience",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png")
preferences {
	section("Which Aqara Wall Switch is used?"){
		input "strip", "capability.Switch"
	}
	section("Select a Virtual Switch to bind to Outlet 1"){
		input "switch1", "capability.Switch", required: false
	}
    section("Select a Virtual Switch to bind to Outlet 2"){
		input "switch2", "capability.Switch", required: false
	}
    section("Select a Virtual Switch to bind to Outlet 3"){
		input "switch3", "capability.Switch", required: false
	}
}
def installed() {
	log.debug "Installed with settings: ${settings}"
    //subscribe(strip, "switch.on", MainSwitchOnOneHandler)
    //subscribe(strip, "switch.off", MainSwitchOffOneHandler)
    subscribe(strip, "switch2.on", MainSwitchOnTwoHandler)
    subscribe(strip, "switch2.off", MainSwitchOffTwoHandler)
    subscribe(strip, "switch3.on", MainSwitchOnThreeHandler)
    subscribe(strip, "switch3.off", MainSwitchOffThreeHandler)
	subscribe(switch1, "switch.on", switchOnOneHandler)
    subscribe(switch2, "switch.on", switchOnTwoHandler)
    subscribe(switch3, "switch.on", switchOnThreeHandler)
    subscribe(switch1, "switch.off", switchOffOneHandler)
    subscribe(switch2, "switch.off", switchOffTwoHandler)
    subscribe(switch3, "switch.off", switchOffThreeHandler)
}
def updated(settings) {
	log.debug "Updated with settings: ${settings}"
	unsubscribe()
	//subscribe(strip, "switch.on", MainSwitchOnOneHandler)
    //subscribe(strip, "switch.off", MainSwitchOffOneHandler)
    subscribe(strip, "switch2.on", MainSwitchOnTwoHandler)
    subscribe(strip, "switch2.off", MainSwitchOffTwoHandler)

    subscribe(strip, "switch3.on", MainSwitchOnThreeHandler)
    subscribe(strip, "switch3.off", MainSwitchOffThreeHandler)

    subscribe(switch1, "switch.on", switchOnOneHandler)
    subscribe(switch2, "switch.on", switchOnTwoHandler)
    subscribe(switch3, "switch.on", switchOnThreeHandler)
    subscribe(switch1, "switch.off", switchOffOneHandler)
    subscribe(switch2, "switch.off", switchOffTwoHandler)
    subscribe(switch3, "switch.off", switchOffThreeHandler)
   }
def MainSwitchOnOneHandler(evt) {
	log.debug "switch on"
	switch1.on()
}
def MainSwitchOffOneHandler(evt) {
	log.debug "switch off"
	switch1.off()
}
def MainSwitchOnTwoHandler(evt) {
	log.debug "switch on"
	switch2.on()
}
def MainSwitchOffTwoHandler(evt) {
	log.debug "switch off"
	switch2.off()
}
def MainSwitchOnThreeHandler(evt) {
	log.debug "switch on"
	switch3.on()
}
def MainSwitchOffThreeHandler(evt) {
	log.debug "switch off"
	switch3.off()
}
def switchOnOneHandler(evt) {
	log.debug "switch on1"
	strip.on()
}
def switchOnTwoHandler(evt) {
	log.debug "switch on2"
	strip.on2()
}
def switchOnThreeHandler(evt) {
	log.debug "switch on3"
	strip.on3()
}
def switchOffOneHandler(evt) {
	log.debug "switch off1"
	strip.off()
}
def switchOffTwoHandler(evt) {
	log.debug "switch off2"
	strip.off2()
}
def switchOffThreeHandler(evt) {
	log.debug "switch off3"
	strip.off3()
}

I’ve changed the commands to match the Aqara DTH, made each switch optional and disabled the response from the Aqara on changing switch1, as we can’t be sure which switch it refers to (otherwise you switch on virtual switch two, the smartapp receives an on and switches virtual switch one, then switches the other switch on)

I haven’t seen an Aqara 3-gang switch, but I’ve left the hooks in just in case they release one :wink:

Haven’t done much in the way of testing yet, as my switch is in the garage, and I can’t see the lights from here!

1 Like

I did move the hub as close as I could, probably just a couple of meters from the switch, but still no luck :frowning:

great job.

I’ve been busy at work, no time to cleanup… and i have given my Aqara switch away. :slight_smile:

My Kudled and Atsmart are working fine. No more place to install additional paddle switches. eeks

I added your HD to my 2 button Aqara switch and it comes up saying Tiles Missing…
any ideas ?

am i right in thinking one paddle is for a physical switch but the second paddle is virtual only?